Skip to content

Commit

Permalink
First pass at tables for sharing logs with the teams
Browse files Browse the repository at this point in the history
This introduces the concept of a Session, which may or not map
exactly to an actual session of matches, that a given collection
of archives is used for. Running a Session then generates various
Artefacts which we want to share with the teams (logs, animations,
possibly other things). We assume that for some types of Artefact,
teams should only able to view those which relate to their robot.

With thanks to James for design discussion.

Co-Authored-By: James Seden Smith <[email protected]>
  • Loading branch information
PeterJCLaw and sedders123 committed Jan 8, 2021
1 parent 1a1d5e9 commit 86d2a02
Showing 1 changed file with 94 additions and 0 deletions.
94 changes: 94 additions & 0 deletions code_submitter/tables.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import enum

import sqlalchemy

metadata = sqlalchemy.MetaData()

# As a team member you upload your archives prior to their being used to
# simulate matches.
Archive = sqlalchemy.Table(
'archive',
metadata,
Expand All @@ -19,6 +23,8 @@
),
)

# As a team member you choose which of your uploaded archives is the one which
# should be used for simulating matches.
ChoiceHistory = sqlalchemy.Table(
'choice_history',
metadata,
Expand All @@ -34,3 +40,91 @@
server_default=sqlalchemy.func.now(),
),
)


# At the point of downloading the archives in order to run matches, you create a
# Session. The act of doing that will also create the required ChoiceForSession
# rows to record which items will be contained in the download.
Session = sqlalchemy.Table(
'session',
metadata,
sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),
sqlalchemy.Column('description', sqlalchemy.String, nullable=False),

sqlalchemy.Column('username', sqlalchemy.String, nullable=False),

sqlalchemy.Column(
'created',
sqlalchemy.DateTime(timezone=True),
nullable=False,
server_default=sqlalchemy.func.now(),
),
)

ChoiceForSession = sqlalchemy.Table(
'choice_for_session',
metadata,
sqlalchemy.Column(
'choice_id',
sqlalchemy.ForeignKey('choice_history.id'),
primary_key=True,
),
sqlalchemy.Column(
'session_id',
sqlalchemy.ForeignKey('session.id'),
primary_key=True,
),
)


# After matches have been simulated, there are a number of artefacts which
# should be shared with the teams.

class ArtefactType(enum.Enum):
Logs = 'logs'
Animations = 'animations'


Artefact = sqlalchemy.Table(
'artefact',
metadata,
sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),
sqlalchemy.Column('content', sqlalchemy.LargeBinary, nullable=False),
sqlalchemy.Column('type', sqlalchemy.Enum(ArtefactType), nullable=False),

# Compound foreign key to the ChoiceForSession. This provides a link to the
# team this artefact is availalbe to. When `choice_id` is null, this
# indicates that the artefact is available to all teams.
sqlalchemy.Column(
'choice_id',
sqlalchemy.ForeignKey('choice.id'),
nullable=True,
),
sqlalchemy.Column(
'session_id',
sqlalchemy.ForeignKey('session.id'),
nullable=False,
),
sqlalchemy.ForeignKeyConstraint(
('choice_id', 'session_id'),
('choice_for_session.choice_id', 'choice_for_session.session_id'),
# This foreign key constraint only applies when both fields are populated
match='SIMPLE',
),

sqlalchemy.Column(
'created',
sqlalchemy.DateTime(timezone=True),
nullable=False,
server_default=sqlalchemy.func.now(),
),
)

# Constrain session_id such that we only allow one globally-visible artefact
# per session. This is to prevent accidentally uploading everything as
# visible to everyone.
sqlalchemy.Index(
'unique_globally_visible_artefact_per_session',
unique=True,
sqlite_where=Artefact.c.choice_id.is_(None),
)

0 comments on commit 86d2a02

Please sign in to comment.