Scoreboard Implementation - pc2ccs/pc2v9 GitHub Wiki

Overview

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.)

Standings Computation

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.

Standings Transformations

Transformations Overview

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.

Invoking Transformations

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().

Performing Transformations

See Scoreboard HTML Configuration and Scoreboard HTML Transformations for a details on how Scoreboard Transformations are specified and executed using XSL Transformations.

Module Details

ScoreboardModule

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 the algoFrozen instance of DefaultScoringAlgorithm to true. This provides ScoreboardModule with two instances of DefaultScoringAlgorithm: 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 method generateOutput(), passing to it the (private, complete) XML standings string, the location of the XSL directory, and the location of the (private) output HTML folder. The ScoreboardCommon.generateOutput() method uses these values to produce the HTML output for the (private) scoreboard pages.
  • invoke the scoreboardCommon method generateResults() method, passing to it the private XML standings string and the location of the XSL directory, along with the current contest model and controller. Method generateResults() 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 the algofrozen instance of DefaultScoringAlgorithm, obtaining from it a (filtered, public) view of the standings.
    • again invoke the scoreboardCommon method generateOutput(), passing to it the (public) XML standings string, the location of the XSL directory, and the location of the (public) output HTML folder. The ScoreboardCommon.generateOutput() method uses these values to produce the HTML output for the (public) scoreboard pages.

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.

ScoreboardView

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 method generateOutput(), passing to it the (private, complete) XML standings string obtained from the PropertyChangeEvent, along with the location of the XSL directory and the location of the (private) output HTML folder. The ScoreboardCommon.generateOutput() method uses these values to produce the HTML output for the (private) scoreboard pages.
  • invoke the scoreboardCommon method generateResults() method, passing to it the private XML standings string and the location of the XSL directory, along with the current contest model and controller. Method generateResults() 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 the algofrozen instance of DefaultScoringAlgorithm, obtaining from it a (filtered, public) view of the standings.
  • again invoke the scoreboardCommon method generateOutput(), passing to it the (public) XML standings string, the location of the XSL directory, and the location of the (public) output HTML folder. The ScoreboardCommon.generateOutput() method uses these values to produce the HTML output for the (public) scoreboard pages.

StandingsHTMLPane

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.

See Also