AlgoJudge documentation0.2
Domain model

Activity

A contest or a course — the outermost container, the unit of enrollment, and the owner of the limits the Server itself enforces.

An activity is the outermost container: a contest, a course, a practice set. It owns series, groups, questions, attachment rules, and the grants that are its membership.

Identity and type

FieldMeaning
Slughuman-readable alias used in URLs, for example AMMPZ-2019. Unique per installation, case-insensitively, and immutable once set. It is not an identifier — nothing references an activity by slug
Namewhat people see
Typediscriminator, name@version. Never interpreted by the Server
RankingTypewhich ranking the Client renders, for example icpc or points
TimeZoneIANA zone the activity's clock is kept in. Every instant in the schema is stored UTC; this is what a manager's "18:00" means when they type it, and what the Client names beside a reader's own clock. It is not what a reader sees

RankingType is deliberately separate from Type, and deliberately never branched on in the Server: the moment the Server reads it, adding a ranking format becomes a Server release.

Lifecycle

Two timestamps rather than two booleans, because since when is a question that gets asked and a flag cannot answer it.

FieldMeaning
PublishedAtwhen somebody decided this exists for the people taking part. Null means it is being prepared
ArchivedAtarchived: still readable, accepting nothing new — no submissions, no questions, no edits

Nothing opens while PublishedAt is null. The series scheduler skips the whole activity, so a copy of last year's course does not spring open the moment somebody duplicates it. Whoever may edit the activity still reaches it.

Publication is the whole activity, not each round. Hiding rounds one by one would allow a half-published copy that nobody chose and that reads, from outside, like a deliberate schedule.

Archiving is the ordinary way an activity ends. Deleting one destroys submissions participants may still want to look back at, which is why activity:delete is a separate permission and is not in the manager role.

Enrollment

FieldMeaning
EnrollmentRolesthe roles this activity's enrollments link to, in two slots: one for somebody taking part, one for somebody running it. A slot holds several roles, and an empty one means the installation's built-in participant or manager
JoinPolicyClosed, Password or Open. These are the three answers to self-enrollment; a manager may always enroll somebody by hand, which is what a grant is
JoinPasswordthe join code under Password
Unlistedhidden from the activity list of anybody not enrolled — reachable by its address and nothing else. Independent of the policy

Both slots are read by self-enrollment, by the grant an activity's creator is given, by a bulk of temporary accounts, and by an LTI rule aimed at a slot rather than at a named role. Only an installation's role or one of this activity's own may be named, and that is checked where they are written rather than by the foreign key. Without the slots an activity's own role could be created and never reach anybody: every automatic enrollment would land on the installation-wide one.

JoinPassword is a join code, not a credential. It authenticates nobody and belongs to the activity rather than to a person, so it is neither an end-user password nor an exception to the rule that those do not live in the Server. A manager reads it back on purpose: its whole use is to go in a link.

Limits the Server enforces

These are columns rather than entries in an opaque configuration document, because the Server is what rejects the request — it cannot police a value it does not read.

FieldDefaultMeaning
MaxUploadBytes8 MiBceiling on a participant upload
MaxAttachments1how many files one submission may carry
MaxSubmissionsPerProblemnullsubmissions one participant may make per problem; null is unlimited

An assignment may narrow all three. Time and memory limits are not here: they are the Runner's, and they only become knowable while the solution is running.

A limit is checked when it is set

The Server refuses a limit that cannot work, on all four write paths — the activity created, the activity edited, the assignment attached, the assignment edited. Stored instead, such a value is shown back to the manager and discovered to be impossible only by whoever tries to submit.

RefusedCode
maxUploadBytes of zero or less — it accepts nothing at allmaxUploadBytes.invalid
maxUploadBytes above the 8 MiB this Server accepts — nothing would ever reach itmaxUploadBytes.tooLarge
a negative maxAttachmentsmaxAttachments.invalid
maxSubmissions of zero or less — it lets nobody submitmaxSubmissions.invalid

The codes are prefixed activity. or assignment. by the path that refused.

Zero attachments is legal and zero submissions is not, which looks inconsistent and is not. A problem that accepts no attachments is a problem somebody meant to configure. A limit of zero submissions closes the problem while telling every participant they have no submissions left — a state nobody chooses on purpose, and one null already expresses properly. null means inherit, or no limit, and is always accepted.

Visibility

FieldMeaning
ScoreVisibilityEveryone, ParticipantOnly, ManagersOnly. Who sees scores — which also decides whether the ranking exists at all
ShowGroupMemberswhether a group's ranking row also names who is in it. Off by default
HideEndedSeriesProblemstake the problems of a finished series away rather than leaving them readable. Off by default

There is no second switch beside ScoreVisibility: a board turned on where nobody may see a score shows nothing, and the two settings would disagree.

Modules

Two parts of the product are optional per activity, and each is one boolean.

FieldDefaultWhat it turns on
HasQuestionsonquestions and announcements
HasPrintoutsoffasking for source to be printed

Off, a module is not an empty screen: the participant's navigation loses the entry entirely. A course that never answers questions should look like a course with no questions in it, not like one whose organizers are ignoring them.

The switch governs what may be added. Asking is refused with 403 and the code questions.disabled or printouts.disabled; what was already asked stays readable to the person who asked and to the managers, because turning a module off is not a way of destroying what it collected.

The two defaults differ on purpose. Questions cost nobody anything to leave on. Printing assumes a person standing at a printer, and an activity where nobody is would offer a button leading to a queue no one works.

Turning it back on returns the participant to exactly what they had.

Attachment rules

AttachmentRule is a table, one row per attachment name, keyed on the name within the submissionsource, log, details — never on the uploaded file name, which is main.cpp and differs per person.

A name with no rule is managers-only

The cost of being wrong here is asymmetric: an over-cautious default is one click, an under-cautious one leaks the tests during a contest. A Runner that starts attaching something new must not publish it by arriving.

Absent is not empty

An activity created with no attachmentVisibility gets the conventional three: source and details to the participant — their own work and its verdict — and log managers-only, because what a compiler says about a solution is the activity's to release. Sent as [], the field still means no rows at all. The default fills in for a creation that said nothing, not for one that said none.

The rule above is what makes the difference matter: an empty table leaves the author of a submission unable to read back their own source, which is not what leaving the field out was asking for. The panel's form names all three, and the default makes an activity created any other way match it. log is stored even though a missing row would say the same thing, because the editor draws one switch per row and a table with no rows offers a manager nothing to change.

Editing is the other way around: an edit that omits attachmentVisibility leaves the table as it stands, and one that sends it replaces every row — so an empty list there does empty the table.

Routing

RunnerTags says which Runners judge this activity's submissions, paired with theirs by the rule in Tags and routing. A series may override it, and usually should — that page says why a whole course is the wrong thing to pin.

Props

Props is free display metadata: opaque to the Server, never queried and never filtered on. Null means none — never {}.

On this page