-
Notifications
You must be signed in to change notification settings - Fork 24
Scoreboard Implementation
As described at Scoreboard Viewing, PC² contains a variety of places where contest standings ("scoreboards") can be generated and viewed. Scoreboard information appears in three different forms:
- HTML files, of which there are two sets: one set containing the "public" scoreboard (that is, a set which reflects the standings taking into account any scoreboard freeze configured in the contest); and one set containing the "private" scoreboard (that is, the actual current standings without considering any scoreboard freeze).
- Standings listings which appear on a variety of PC² interactive displays such as the Admin and Scoreboard modules.
- Output files which contain exported standings data suitable for uploading and processing by external tools.
Each of the above types of standings information can be generated from a number of different locations in the PC² code. One such place is the class ScoreboardModule
, which is instantiated when a user logs into a scoreboard account specifying "--nogui" on the command line. Once it is running, ScoreboardModule
causes updates to the HTML scoreboard page files (both the public and private sets) whenever a potential-standings-changing event occurs. (Events which can potentially cause a standings change include changes in the problem set, account information, submission judgments, and certain other contest configuration items.)
ScoreboardModule
also updates the contents of several "export" files containing standings information whenever the contest standings change. The updated files always include results.xml
; if the contest has been "finalized" then ScoreboardModule
also outputs updated results.tsv
, scoreboard.tsv
, and scoreboard.json
files in a folder named results
. The standings data written to results.xml
and pc2export.dat
is always the current, actual standings (that is, the information in these exported files does not take any "scoreboard freeze preriod" into account).
Another class which generates both public and private HTML files is ScoreboardView
, which is displayed when an interactive login using a scoreboard account occurs. Any change in contest standings causes ScoreboardView
to automatically update both the public and private HTML pages. Like ScoreboardModule
, the ScoreboardView
class also updates the output files results.xml
and pc2export.dat
with the current standings whenever the standings change.
Other classes which show scoreboard information include class StandingsPane
, which displays the current scoreboard, updated whenever a standings-changing event occurs. (Note that the standings displayed by StandingsPane
are always the actual, current standings -- that is, this class ignores any "scoreboard freeze" period; the information displayed by StandingsPane
is always identical to that contained in the private HTML pages generated as described above.)
Classes which display a StandingsPane
include ScoreboardView
and AdministratorView
(the latter of which is displayed when a login using an administrator account occurs). Both of these "view" classes contain instances of class StandingsPane
which can be selected using the view's Standings tab.
The AdministratorView
class also contains an instance of class StandingsHTMLPane
, which uses HTML to display current standings and which similarly get updated whenever a standings-changing even occurs. (Note that, just as with the StandingsPane
class, StandingsHTMLPane
always displays the actual, current standings; do not confuse this with the HTML public/private set generated by ScoreboardModule
and ScoreboardView
classes.)
Regardless of where (or in what format) contest standings are displayed, PC² always computes the current standings by using a class named DefaultScoringAlgorithm
. This class provides a method getStandings()
which returns a (filtered) XML Document string representation of the current contest standings.
All components of the PC² system which display contest standings (whether in interactive displays, embedded in HTML page files, or contained within export data files) start by invoking method getStandings()
in an instance of DefaultScoringAlgorithm
.
The XML string returned by DefaultScoringAlgorithm.getStandings()
is filtered in the following ways. First, getStandings()
ignores
- contest problems which are marked as "hidden",
- teams which are marked as "Do not display on scoreboard", and
- submissions which have been marked by the Contest Administrator as "deleted".
In addition, a given instance of DefaultScoringAlgorithm
can be configured via method setObeyFreeze(boolean)
to specify whether the output produced by getStandings()
should take into account any configured "scoreboard freeze". If obeyFreeze is set to true, getStandings()
will treat any submissions which were received during the configured "freeze period" as still "Pending", and will adjust the generated XML output string accordingly.
getStandings()
ranks all teams (taking the above filtering rules into account) firstly according to number of problems solved, then secondarily within that category according to "penalty points" (computed by multiplying the number of "NO" runs on solved problems by the Penalty Points value specified in the contest configuration), and then thirdly within the second category according to earliest time of last solution. Any teams remaining tied at that point are listed alphabetically by team name. The resulting standings are then returned as an XML document string.
A number of PC² classes which use DefaultScoringAlgorithm
to obtain current contest standings use the XML standings returned by getStandings()
directly. Classes which operate like this include api.implementation.GenerateStandings
, exports.ccs.ResultsFile
, ui.StandingsPane
, and multiple classes in package core.report.
Many other PC² classes, however, take the XML document string which is returned by DefaultScoringAlgorithm.getStandings()
and apply XSL Transformations (XSLT) to it. These are transformations which are used, for example, to transform XML into some corresponding formatted HTML representation. XSL Transformations use XSL (eXtensible Stylesheet Language) style sheets to specify how a given XML document is to be transformed.
PC² classes which use XSLT and XSL style sheets to transform XML standings into HTML include ScoreboardModule
, ScoreboardView
, and StandingsHTMLPane
. The first two of these (which are the primary classes which generate the public and private HTML scoreboard pages) use class ScoreboardCommon
to perform the XSL transformation. (The exception is the class StandingsHTMLPane
; see below.)
The ScoreboardCommon
class contains a public method generateOutput()
, which receives (1) an XML document (String) containing the current standings, (2) the name of a directory (folder) containing XSL style sheets for each of the HTML scoreboard pages to be produced, and (3) the name of the directory where the transformed (output) HTML files are to be placed.
In other words, the ScoreboardModule
and ScoreboardView
classes fetch current standings from an instance of DefaultScoringAlgorithm
and pass the returned XML to an instance of ScoreboardCommon.generateOutput()
, along with specifications for where to find the XSL style sheet files defining the transformations and for where to put the transformed (HTML) result. The default location for the XSL files is the folder data/xsl
in the PC² installation folder. The output folder to which the transformed results are written is either the location specified by the configuration property for the JUDGE (private) HTML pages or the location specified by the configuration property for the PUBLIC pages (the choice is determined by the code which invokes ScoreboardCommon.generateOutput()
.
See Scoreboard HTML Configuration and Scoreboard HTML Transformations for a details on how Scoreboard Transformations are specified and executed using XSL Transformations.
Logging in to a scoreboard account and specifying --nogui on the command line instantiates a ScoreboardModule
. This class initializes itself with two instances of DefaultScoringAlgorithm
-- one named algo
for computing private (complete) standings and a second named algoFrozen
for computing public standings which respect any configured scoreboard freeze period. The class initialization also includes creating an instance of class ScoreboardCommon
which is used to perform most of the work which scoreboard computations have in common.
The class which instantiates the ScoreboardModule
is expected to invoke its setContestAndController()
method. This method in turn invokes method startScoreboard()
, which does the following:
- set the
obeyFreeze
flag in thealgoFrozen
instance ofDefaultScoringAlgorithm
to true. This providesScoreboardModule
with two instances ofDefaultScoringAlgorithm
: one to compute private (current, actual) standings and a second whose results take into account any "scoreboard freeze" period. - determine the location of
xslDir
, a directory containing XSL directives for transforming XML documents. - add listeners for contest events, including changes in contest time, accounts, problems, languages, submissions ("runs" in PC² terminology), and contest settings.
Once the above initialization is completed, ScoreboardModule
invokes local method generateOutput()
. This method first obtains the current scoring properties for the contest, then invokes getStandings()
in the algo
instance of DefaultScoringAlgorithm
, passing to it the current contest and scoring properties and getting back the XML for the (actual, complete, non-freeze-respecting) contest standings. This XML string is then passed to another local method named generateOutput(String)
, which does the following:
- obtain from the contest scoring properties the location (folder) where the "judges" (a.k.a. "private") HTML scoreboard pages should be stored.
- invoke the
scoreboardCommon
methodgenerateOutput()
, passing to it the (private, complete) XML standings string, the location of the XSL directory, and the location of the (private) output HTML folder. TheScoreboardCommon.generateOutput()
method uses these values to produce the HTML output for the (private) scoreboard pages. - invoke the
scoreboardCommon
methodgenerateResults()
method, passing to it the private XML standings string and the location of the XSL directory, along with the current contest model and controller. MethodgenerateResults()
uses this information to generate "results" information in the current folder (which results can subsequently be used for exporting current standings). - obtain from the scoring properties the location where the "public" HTML scoreboard pages should be stored. If the public HTML location is not empty and is not the same as the (previously-updated) private scoreboard location, the following is done:
- invoke method
getStandings()
in thealgofrozen
instance ofDefaultScoringAlgorithm
, obtaining from it a (filtered, public) view of the standings. - again invoke the
scoreboardCommon
methodgenerateOutput()
, passing to it the (public) XML standings string, the location of the XSL directory, and the location of the (public) output HTML folder. TheScoreboardCommon.generateOutput()
method uses these values to produce the HTML output for the (public) scoreboard pages.
- invoke method
ScoreboardModule.generateOutput()
is also invoked by the listeners which were added during ScoreboardModule
initialization; this is what causes contest standings (for example, the public and private HTML page files) to be updated when something changes in the contest.
Logging in to a scoreboard account without specifying the "--nogui' parameter creates an instance of the ScoreboardView
class. This class operates similar to -- but not precisely the same as -- the ScoreboardModule
class (the differences are because (1) the class presents several different views of scoring data in addition to standings (for example, it has options to display balloon colors and it provides support for testing printing and emailing of balloon messages); and (2) the classes were created at different times by different developers).
When a ScoreboardView
is instantiated it creates both a ScoreboardCommon
instance and a DefaultScoringAlgorithm
instance, much like the ScoreboardModule
class. The DefaultScoringAlgorithm
instance is named algoFrozen
, and like its counterpart in ScoreboardModule
it is used to compute current standings taking into account any scoreboard freeze period (the initialization portion of ScoreboardView
calls algoFrozen.setObeyFreeze(true)
).
The code which instantiates ScoreboardView
is responsible for calling that class's setContestAndController()
method, which (among other things) determines the location of the folder containing the XSL stylesheets to be used for applying XSL Transformations to scoreboard HTML pages. The default location for the XSL stylesheets, as with ScoreboardModule
, is ./data/xsl
. If ScoreboardView
is unable to read that folder then it defaults instead to a folder named xslDir
in the PC² installation home directory.
Among its other initialization steps, ScoreboardView
constructs an instance of class StandingsPane
and adds it to the ScoreboardView
GUI. It also attaches a PropertyChangeListener
to the StandingsPane
which listens for changes in the contest property standings
. When the StandingsPane
is constructed and initialized it registers listeners with the contest, listening for changes in accounts, problems, submissions (runs), and certain other contest properties. When changes occur in any of these, the corresponding registered listener invokes StandingsPane.refreshStandings()
.
The refreshStandings()
method in turn invokes method parseAndDisplay()
, which in turn constructs a new DefaultScoringAlgorithm
and uses it to obtain an XML standings string giving the current (actual, unfrozen) standings. (Note that this is one substantial difference between ScoreboardView
and ScoreboardModule
; the latter constructs a single instance of DefaultScoringAlgorithm
to compute the unfrozen standings, while the former re-constructs a new instance every time its refreshStandings()
method is invoked. This should probably be refactored at some point...) In any case, the XML string obtained from the new DefaultScoringAlgorithm
is first used to update the display table in the ScoreView
grid; it is then used to fire a new propertyChanged
event. This invokes the PropertyChangeListener
in ScoreboardView
, from where the XML standings string is then passed to the ScoreboardView
method generateOutput()
.
The ScoreboardView.generateOutput()
method operates almost identically to the same-named method in class ScoreboardModule
, doing the following things:
- obtain from the contest scoring properties the location (folder) where the "judges" (a.k.a. "private") HTML scoreboard pages should be stored.
- invoke the
scoreboardCommon
methodgenerateOutput()
, passing to it the (private, complete) XML standings string obtained from thePropertyChangeEvent
, along with the location of the XSL directory and the location of the (private) output HTML folder. TheScoreboardCommon.generateOutput()
method uses these values to produce the HTML output for the (private) scoreboard pages. - invoke the
scoreboardCommon
methodgenerateResults()
method, passing to it the private XML standings string and the location of the XSL directory, along with the current contest model and controller. MethodgenerateResults()
uses this information to generate "results" information in the current folder (which results can subsequently be used, for exporting current standings). - obtain from the scoring properties the location where the "public" HTML scoreboard pages should be stored.
- invoke method
getStandings()
in thealgofrozen
instance ofDefaultScoringAlgorithm
, obtaining from it a (filtered, public) view of the standings. - again invoke the
scoreboardCommon
methodgenerateOutput()
, passing to it the (public) XML standings string, the location of the XSL directory, and the location of the (public) output HTML folder. TheScoreboardCommon.generateOutput()
method uses these values to produce the HTML output for the (public) scoreboard pages.
When the AdministratorView
class is initialized (specifically, when AdministratorView.setContestAndController()
is invoked), it constructs a new StandingsHTMLPane()
and adds it to the Administrator view. The instance of StandingsHTMLPane()
is initialized with a style sheet specification of full.xsl
. Initialization also registers listeners which respond to changes in accounts, problems, submissions (runs), and various other contest properties by invoking StandingsHTMLPane.refreshStandings()
. Initialization also includes creation of an instance of DefaultScoringAlgorithm
.
When refreshStandings
is invoked (due to a change in one of the listened-for properties), it invokes DefaultScoringAlgorithm.getStandings()
to obtain the XML string for the (current, actual) contest standings. At this point, unlike ScoreboardModule
and ScoreboardView
(which use ScoreboardCommon
to process the standings), StandingsHTMLPane
invokes its own transformAndDisplay()
method, passing it the XML standings and the previously-specified style sheet name.
Method transformAndDisplay
constructs an instance of class core.util.XSLTransformer
and passes to it the XML standings string and the XSL style sheet to be used to transform the XML string into HTML. The returned (transformed) HTML is then passed to method viewHTML
, which writes the HTML to a temporary file and then uses that file to load the text area of the StandingsHTMLPane
.