AlgoJudge documentation0.1
Domain model

The model at a glance

The eleven concepts the Server stores, how they hang together, and the five things a reader gets wrong without being told.

Every concept below is defined from the model class that stores it, in AlgoJudge.Server/Database/Models/. Where a page states a rule as an invariant, the code enforces it.

The concepts

ConceptOne line
Activitya contest or a course: the outermost container, and the unit of enrolment
Seriesa group of problems inside an activity — a round, a week, a class
Problema library entry, with append-only content versions
AssignmentSeriesProblem: one problem attached to one series, with its own configuration
Submissionwhat a participant sent. It carries no verdict
EvaluationEvaluationJob, one attempt; Result, the outcome of one completed attempt
GroupActivityGroup: several people competing as one
Grantwhat a user may do within a scope — and, in an activity, the membership
Useran account, and the sessions it holds
Runnera registered evaluation worker
Filestored bytes, and the references that say what they are for

How they hang together

Read the chain from the right: a Result belongs to one EvaluationJob, which is one attempt at one Submission, which was sent against a SeriesProblem — an assignment, not a bare problem — in a Series of an Activity. Beside the series hang the activity's ActivityGroup rows and its Grant rows, which are its membership; the assignment points at a Problem, and the version of that problem's content an attempt was judged against is pinned onto the job and copied onto the result.

Five things that are easy to get wrong

A Submission does not carry a verdict. There is no verdict column, no state column and no score on it. Each attempt at evaluating it is an EvaluationJob; the whole attempt history is retained, and a rejudge adds one rather than replacing anything.

EvaluationJob is the job record and Result is not. The claim, the lease, the Runner, the delivery count and the failure reason live on the job. Result is the outcome of one completed job, one-to-one, and holds four values the Server reads — score, maximum, verdict, and the Runner build. The per-test rows and the compiler log are attachments, not columns.

A Submission belongs to a SeriesProblem, not to a Problem. The languages and limits it was judged under are properties of the assignment, so the assignment is what it points at. The same library problem may be assigned twice in one activity with different settings.

Problem.Type and ProblemVersion.Version are two different axes. Problem.Type versions the kind of problem and its renderer and handler contract — standard-io@1. ProblemVersion.Version versions this problem's content — its statement, its tests, its package.

A grant is not an access control list. An ACL hangs off a resource and lists who may touch that one thing. A grant hangs off a user and says what they may do within a scope. In an activity, the grant is the membership — there is no second table that could disagree about who is taking part.

Two more, while they are cheap

Group membership lives on the grant, not on the group. Grant.GroupId is nullable, and because the schema already holds one grant per user per activity, that column is the rule "at most one group".

The Server stores file references only. There is no statement entity and no statement column: content.md is a well-known FileReference.Name that the Client understands. The Server never reads it.

On this page