Go to the first, previous, next, last section, table of contents.


Scheme definitions

In order to interpret a sporting tournament under the libtour engine, one has to write a tournament definition in the predefined format in the Scheme programming language.

The following three pieces of definition must be provided:

Defining a tournament module

To make a tournament definition suitable for the libtour engine, one has to write a file called `<tour-name>.scm' and put it in a directory where libtour will find it (for the `tourcli' CLI client, see section Quick start). The file has to define a Guile module, tour-defs <tour-name> and export the following variables:

<tour-name>:INFO
associative list for general information, TITLE key is required
<tour-name>:TEAMS
team definitions (see section Teams definition)
<tour-name>:TEAMS-FORMAT
format of team definitions (see section Teams definition)
<tour-name>:STAGES
stage definitions (see section Stages definition)
<tour-name>:WINNERS
tournament winner definitions (see section Winners definition)
<tour-name>:SCHEDULE
schedule definitions (see section Game schedule definition)
<tour-name>:SCHEDULE-FORMAT
format of schedule definitions (see section Game schedule definition)
<tour-name>:SCHEDULE-DATE
format of date/time field in schedule definition (see section Game schedule definition)
<tour-name>:SCHEDULE-HOME
position of the home team in the schedule (see section Game schedule definition)

The definitions are usually split into several files. For instance, here is a partial content of `fifawc2002.scm':

(define-module (fifawc2002))

(use-modules ((fifawc2002_rules))
             ((fifawc2002_teams)
              :renamer (symbol-prefix-proc 'fifawc2002:))
             ((fifawc2002_schedule)
              :renamer (symbol-prefix-proc 'fifawc2002:)))

;; definitions of INFO, STAGES, WINNERS omitted

(export fifawc2002:INFO fifawc2002:STAGES fifawc2002:WINNERS)
(re-export fifawc2002:TEAMS fifawc2002:TEAM-FORMAT
           fifawc2002:SCHEDULE fifawc2002:SCHEDULE-FORMAT
           fifawc2002:SCHEDULE-DATE fifawc2002:SCHEDULE-HOME)

The following sections describe contents of the exported variables.

Teams definition

An associative list pointed to by the <tour-name>:TEAMS variable binds global team IDs to the team descriptions.

<tour-name>:TEAMS :
'(("<TEAM-GLOBAL-ID-1" <team-description-list>) ...)

<team-description-list> is a list of strings as defined by the <tour-name>:TEAM-FORMAT variable. Only NAME of teams is required to be specified in <tour-name>:TEAM-FORMAT, this name will be returned as the team identifier in libtour queries.

For instance, team definitions for the 2003 Ice Hockey WC included in the libtour distribution, contains the following (trimmed for space):

(define ihwc2003:TEAMS
  '(("SVK" "Slovakia")      ; "SVK" is a global team ID
    ("RUS" "Russia")        ; "Russia" is a team name
                            ;   according to the TEAM-FORMAT
                            ;   definition below
    ("SWE" "Sweden")
    ...))

(define ihwc2003:TEAM-FORMAT
  '(NAME))

Stages definition

<tour-name>:STAGES variable exported by the tournament module contains a Scheme list where each list member describes one stage.

<tour-name>:STAGES :
(<stage-definition> ...)

<stage-definition>:
((ID . <string for the stage ID>)
 (NAME . <string for the stage name>)
 (STANDINGS-FIELDS . <standings-fields list>)
 (GAMERES-FIELDS . <gameres-fields list>)
 (RES-F . <game-result-interpretation-procedure>)
 (TEAMS . <teams-definition>)
 (GROUPS . <groups-definition>)
 (SUMMARY . <summary-definition>)
 (FILTERS . <filters-definition>))
 (MAX-POINTS . <max-points-definition>))

The ID string can be anything, by convention it is "S1" for the first stage, "S2" for the second etc. The NAME string usually denotes what the stage is called, "Preliminary", or "Quarterfinals".

MAX-POINTS defines maximum number of points a team can get in a game. If such information can be provided for this stage, the value must be an integer greater than zero. If, on the other hand, maximum points can't be defined, a false value #f shoud be used.

The rest of the keys are described in the following subsections.

Standings and Game result fields definitions

STANDINGS-FIELDS defines a list of column (or field) names for a team in a table of standings, like this:

'(GAMES WINS DRAWS LOSSES GOALS-FOR GOALS-AGAINST POINTS)

All the fields will contain integers. The following fields are required to be present: GAMES, and POINTS

GAMERES-FIELDS denotes the fields for a game result. It consists of a pair of lists, the names of the fields in the first and types of the fields in the second. For instance, if a game results can be described by three items, goals scored by the first team, goals scored by the second team, and whether the game ended in overtime, the game fields may be defined like following:

'((GF GA OT) int int bool)

int and bool are the only two supported types.

Game results interpretation procedure

A Scheme procedure placed under the RES-F key will be used by libtour for interpreting a game result. It expects an associative list as the sole argument, whose keys are the same as GAMERES-FIELDS. For instance, for the GAMERES-FIELDS shown above and the game in which the first team lost 2 to 3 in regulation time (OT is false), the argument will be

'((GF . 2) (GA . 3) (OT . 0))

The RES-F procedure should return a pair of associative lists that describe change of STANDINGS-FIELDS for each of the teams. Continuing our example, if a team is awarded two points for a win, and zero for a loss, the procedure can return the following:

'(                        ;;; first team list
  ((GAMES . 1)             ; increment game count by 1
   (LOSSES . 1)            ; increment loss count by 1
   (GOALS-FOR . 2)         ; first team scored 2 goals
   (GOALS-AGAINST . 3))    ; first team allowed 3 goals

  (GAMES . 1)             ;;; second team list
  (WINS . 1)               ; increment win count by 1
  (GOALS-FOR . 3)
  (GOALS-AGAINST . 2)
  (POINTS . 2))            ; second team earned 2 points

The return lists may contain an association pair for any of the fields found in the STANDINGS-FIELDS list even if their values haven't changed (such as (POINTS . 0) for the first team).

Note that values of the POINTS entry cannot exceed the value defined in MAX-POINTS for current stage (see section Stages definition).

mk-res-lists helper procedure defined in the (libtour common) module (see section common module) is useful when creating a resulting list.

Stage teams definition

The TEAMS definition is an associative list with team IDs local to stage (see section Structure of a tournament) as keys and procedures of no argument (thunks) that return global team IDs when called:

'(("TEAM-LOCAL-ID-1" . <thunk>) ...)

Team local IDs can be any strings, but it is convenient to give them somewhat meaningful names. For the first stage of a tournament teams are known in advance, therefore the TEAMS list might look like following:

`(("TEAM-LOCAL-ID-1" . ,(lambda () "TEAM-GLOBAL-ID-1"))
  ...)

For the following stages the thunk will be called after the previous stage is compete. Here is an example of specifying the team that took the first place in group "A" in the previous stage:

`("PREV-STAGE-A-1" .
  ,(lambda () <code to determine the real team ID>))

The thunk has to throw a Guile error if it cannot determine the global team ID.

Groups definition

The GROUPS key in the stage definition list corresponds to an associative list of group definitions.

<group-definitions>:
(<group-definition> ...)

<group-definition>:
((ID . <string for the group ID>)
 (NAME . <string for the group name>)
 (DESCRIPTION . <string for the group description>) ;; optional
 (G-TEAMS . <stage-local team-IDs list>)
 (FORMULA . <playing formula specification>)
 (G-CMP-F . <teams-comparison-procedure>)
 (G-GAME-HERE-F . <game-belongs-to-this-group-procedure-or-spec>))

Like for a stage, the ID string can be anything unique, and NAME string usually describes what a group is, like "Group A", or "Semifinal Pair 1". The DESCRIPTION string is optional and can contain some additional information about the group; it is filled in by libtour for filtered groups (see section Filtered groups).

Group teams definition

The G-TEAMS is a list of team IDs (local to the stage). Team IDs for a group should be subset of the the keys in stage's TEAMS definition (see section Stage teams definition). A team may belong to more than one group within a stage.

Group formula definition

Group playing formula helps determine how many games should be played between the teams within a group and when the group becomes complete (see section Game results and formula). The following values are allowed for a formula definition:

'(ROUND <number>)
round robin with <number> of games to be played between each two teams
'(TEAM-GAMES <number>)
each team will play <number> of games (similar to round robin but the number of games between any two teams is not enforced)
'(PLAYOFF <number>)
for a group of two teams, games continue until one team has <number> of wins
'(NONE)
no formula, the group will accept any number of game results as long as they are accepted by at least one group with a non-"none" formula within the stage

Teams comparison procedure

The procedure defined under the G-CMP-F key in the group definition will be used by libtour for sorting teams within the group.

The procedure must accept five arguments: (1) tournament name, (2) stage ID, (3) group ID, and (4,5) team result lists of the two teams to be compared. The first three arguments are obvious. Each of the last two contains an associative list of team results (see section Standings and Game result fields definitions) plus a team ID (local to stage) association pair, for example:

'((GAMES . 10)                ;; these are STANDINGS-FIELDS
  (WINS . 7)
  (DRAWS . 1)
  (LOSSES . 2)
  (GOALS-FOR . 22)
  (GOALS-AGAINST . 7)
  (POINTS . 15)
  (ID . "<TEAM-LOCAL-ID>"))   ;; additional ID entry

The procedure must return 1 if the first team results are higher than the second's, -1 if opposite, and 0 if the teams appear to be equal.

An example of the sorting procedure below uses helper procedures from module (libtour common) (see section common module).

(define cmp-f
  (lambda (tour-name stage-id group-id t1 t2)
    (or
        ;; compare points
        (cmp-assoc-field-p 'POINTS t1 t2)

        ;; if points are equal, compare goal difference
        (cmp-assoc-field-diff-p 'GOALS-FOR 'GOALS-AGAINST t1 t2)

        ;; if goal differences are equal, see which team scored more
        (cmp-assoc-field-p 'GOALS-FOR t1 t2)

        ;; if equal, compare personal games for these two teams
        (cmp-two-teams-p c-tour-name
                         stage-id
                         (assoc-ref t1 'ID)
                         (assoc-ref t2 'ID)
                         ;; another cmp procedure
                         cmp-prelim-stage-personal-f
                          ;; consider only games between these two teams
                         'BOTH)
        0)))  ;; give up, the teams are equal

game-belongs-to-group procedure

To determine if a game belongs to a given group, another Scheme procedure should be supplied. For the two most common cases, however, libtour provides shortcuts so that a predefined Scheme symbol can be given instead of a procedure.

'BOTH
game belongs to the group if both teams that played belong to the group
'ANY
game belongs to the group if any team that played belong to the group
(lambda (game-alist) ...)
a procedure which returns a pair of boolean values for each team; it is (#f . #f) if none of the two teams' result should be recorded in this group (and therefore the game does not belong to this group), or one of (#t . #f), (#f . #t), (#t . #t) if only the first, or only the second, or both teams' results correspondingly should be recorded in this group.

If a procedure is supplied, it should expect a game associative list and be in the format defined by the SCHEDULE-FORMAT (see section Game schedule definition), for instance:

'((ID . 123)
  (DATE . "23.06.2003 15:00")
  (TEAM1 . "<TEAM-LOCAL-ID-1>")
  (TEAM2 . "<TEAM-LOCAL-ID-2>"))

As mentioned, the procedure should return a pair of boolean values.

Summary definition

A SUMMARY entry controls creation of a summary group for a stage (see section Summary group). If its value is #f, no summary group will be created. If it contains a procedure, a summary group will be created for the stage, and this procedure will be used for team comparison (like see section Teams comparison procedure) within this group.

Filters definition

A FILTERS entry in a stage definition defines what team and/or game filters are aplicable to this stage (see section Filtered groups). It contains an associative list with the following optional keys: TEAM-FILTERS, and GAME-FILTERS; the values are lists of filters:

((TEAM-FILTERS <team-filter-making-procedure> ...)
 (GAME-FILTERS <game-filter-making-procedure> ...))

If no filters can be applied, the list is empty.

Winners definition

Winners (or losers) are the teams that finished the tournament with some distinguishable result: won gold, or lost everything. Winners definition is very similar to the one for teams within a stage (see section Stage teams definition). The differences are:

  1. a string describing what the team won is used in the place of stage-local team ID
  2. if the team cannot be determined the thunk should return #f rather than throw error.

Here is an example of a Winners list:

(define <tour-name>:WINNERS
  '(("Gold" . <thunk>)
    ("Silver" . <thunk>)
    ("Bronze" . <thunk>)))

Game schedule definition

The <tour-name>:SCHEDULE variable contains a list in the form:

'(<stage-list> ...)

stage-list:
("stage-id" <entry> ...)

entry:
<game-definition> or <thunk>

where <game-definition> is a list of string members defined in tour-name:SCHEDULE-FORMAT, and <thunk> is a procedure of no arguments that returns a list of <game-definition>. The <thunk> list elements (if any) are run at the time the stage changes its state from "uninitialized" to "ready".

A <game-definition> may look like this:

'(("1" "31.05.02 20:30" "<place>"
   "<stage-local team ID 1>" "<stage-local team ID 2>"))

To allow loading stages with unknown schedule <entry> members are optional. Note, however, that a stage with no schedule can never become "complete".

tour-name:SCHEDULE-FORMAT variable defines the meaning of the list members. For the preceding example it would be:

'(ID DATE TIME PLACE TEAM1 TEAM2)

Note that ID, DATE, TEAM1, and TEAM2 fields are mandatory, any other -- optional. Games are not required to be sorted as the sorting is done internally by libtour.

Interestingly, you can also supply a game result along with the game's schedule entry. If the game list contains more items than there is in SCHEDULE-FORMAT list, the rest is assumed to contain the game result in the format according to GAMERES-FIELDS. If the game result specified in the schedule, the game will be read-only. This obscure feature allows to implement carry-forward games but can also be used for pre-setting game results in the schedule.

tour-name:SCHEDULE-DATE variable should be provided. It is a string that describes the format of the DATE field in game definitions. The format description style used is identical to the one of UNIX strptime(3) C function. For instance, a date "2001-11-12 18:30" would be have format "%Y-%m-%d %H:%M" Please see the corresponding man page for details.

tour-name:SCHEDULE-HOME variable notifies the position of the home team in the game definitions. The following values (integer type) are permitted:

-1
home/away notion has no meaning for this tournament
0
the team in TEAM1 field is the home team
1
the team in TEAM2 field is the home team


Go to the first, previous, next, last section, table of contents.