MatchMakerTool is a set of .NET libraries and a command-line tool for running quiz tournaments that use ACME Quiz Match Maker result files. It can:
- Generate a schedule for six different tournament types, from a plain list of teams.
- Produce a results/standings report from a folder of Match Maker score files.
- Roll up several tournaments into a single multi-event summary.
Reports and schedules can be exported as HTML, Markdown, PDF, RTF, XML, and (for summaries) Excel.
| Project | Description |
|---|---|
Models |
Core domain types shared by every other project: Team, Church, Quizzer, Schedule, Round, Result, and the TournamentType enum. |
Scheduling |
Builds tournament schedules and generates rounds as results come in. Contains one *Tournament class per TournamentType, plus ITournamentRoundGenerator/TournamentRoundGeneratorFactory for round-by-round advancement. |
Reporting |
Loads Match Maker score files, computes team/quizzer standings and rankings, and exports schedule/summary reports. |
Tool |
The command-line application. Wraps Scheduling and Reporting behind the schedule, report, and summary verbs. |
Tool.Unity |
An in-progress Unity front end (not yet functional). |
*.Test |
Unit tests for the corresponding library project. |
dotnet build
dotnet testRun dotnet test (or dotnet build) from the repository root so it picks up
MatchMakerTool.slnx and discovers both test projects.
Build the tool, then invoke it directly or via dotnet run:
dotnet run --project Tool -- <verb> [options]Three verbs are available: schedule, report, and summary. Pass --help after
any verb (for example dotnet run --project Tool -- schedule --help) to see the
full, generated option list.
dotnet run --project Tool -- schedule -i participants.xml -o .\out -t RoundRobin -n 4| Option | Required | Description |
|---|---|---|
-i |
Yes | Path to an input schedule/participants XML file (teams, churches, quizzers). |
-o |
Yes | Output folder for the generated schedule files. |
-t |
No (default RoundRobin) |
The TournamentType to generate: RoundRobin, SingleElimination, DoubleElimination, TripleElimination, Swiss, or SwissWithTopCut. |
-n |
No | Number of rooms available. Only used for RoundRobin. |
-f |
No (default all) | Output formats to produce: any combination of Html, Markdown, Pdf, Rtf, Xml (XML is always produced in addition to whatever is requested). |
Important: the CLI only generates the initial state of the tournament:
- For
RoundRobin, the entire round-robin schedule is generated up front, since the full schedule is known in advance. - For every other tournament type, only the first round is generated. Teams are
seeded in ascending team-id order. Subsequent rounds depend on match results and
are not generated by the CLI — see Advancing a tournament
below for how a separate controller application generates them using the
Schedulinglibrary.
dotnet run --project Tool -- report -s .\scores -o .\out -r whse -n "Spring Quiz Meet" -t 8 -m 4 -a 2Reads every Schedule.*.xml / Results.*.xml pair produced by Match Maker from a
source folder, computes standings, and exports a report.
| Option | Required | Description |
|---|---|---|
-s |
Yes | Source folder containing the Match Maker score files. |
-o |
No (default .) |
Output folder for the report. |
-r |
No (default whse) |
Ranking procedure: an ordered sequence of tie-break letters, applied left to right — w win percentage, l total losses, h head-to-head, s average score, e average errors. |
-n |
No | Tournament name, used in report titles. |
-t |
No (default 0) |
Number of top-placing round-robin teams that advance, unchanged, into a single-elimination tournament. |
-m |
No (default 0) |
Number of alternate teams to form from quizzers who didn't advance, for a consolation round robin. |
-a |
No (default 0) |
Rooms available for the alternate-team round robin (0 runs every match simultaneously). |
-f |
No (default all) | Output formats: any combination of Excel, Html, Pdf, Rtf, Xml. |
Setting -t/-m also generates the elimination-tournament and alternate-team
artifacts alongside the base report.
dotnet run --project Tool -- summary -i .\event1,.\event2,.\event3 -o .\season-summary.xlsx| Option | Required | Description |
|---|---|---|
-i |
Yes | Comma-separated list of input report paths. |
-o |
Yes | Output path for the combined summary. |
All verbs accept -v/--verbose for detailed trace output.
MatchMaker.Models.TournamentType defines six formats. All of them are implemented
end to end in Scheduling, but the CLI's schedule verb only ever produces the
tournament's initial state (see above); a separate, longer-running controller
application is expected to drive a tournament to completion round by round using the
Scheduling library directly.
| Type | Elimination rule | CLI generates | Library supports full progression |
|---|---|---|---|
RoundRobin |
Never — every team plays every other team. | The complete schedule. | N/A — the schedule is complete from creation. |
SingleElimination |
Eliminated after 1 loss. | Round 1 only. | Yes |
DoubleElimination |
Eliminated after 2 losses. | Round 1 only. | Yes |
TripleElimination |
Eliminated after 3 losses. | Round 1 only. | Yes |
Swiss |
Never eliminated; ranked by standings after a fixed number of rounds. | Round 1 only. | Yes |
SwissWithTopCut |
Swiss stage, then single elimination among the top finishers. | Round 1 only. | Yes |
Every team plays every other team once. RoundRobinTournament.Create schedules all
matches across the requested number of rooms and returns the complete Schedule;
there is nothing further to generate.
A team is eliminated after a single loss. Round 1 pairs the seed list
strongest-vs-weakest (1 vs. n, 2 vs. n-1, ...). After each round,
EliminationTournament/SingleEliminationRoundGenerator re-pairs the surviving
teams the same way until one team remains.
A team is eliminated after 2 (double) or 3 (triple) losses. These share a single
internal engine, MultiLifeEliminationTournament, parameterized by the number of
lives. Rather than modeling separate winners/losers brackets (the Schedule/Round
model has no concept of a bracket), each round re-pairs all teams that have not yet
reached the loss limit, ordered by fewest losses first and then by the same
strongest-vs-weakest fold used in single elimination. In practice this reproduces the
usual double-elimination shape (surviving teams converge into a "grand final," with a
"bracket reset" if the team from the loss column wins it) without requiring bracket
bookkeeping in the data model.
Teams are never eliminated. Round 1 pairs the top half of the seed list against the
bottom half (1 vs. n/2+1, 2 vs. n/2+2, ...). Later rounds are paired from current
standings (wins descending, then team id ascending) using a greedy nearest-unplayed-
opponent search that avoids rematches when possible, falling back to a rematch only
if no unplayed opponent remains. The recommended number of rounds is
ceil(log2(teamCount)), computed on demand rather than stored, and SwissTournament
reports the tournament complete once that many rounds have been played.
Limitation: byes are not scored as wins in the simplified Swiss model (consistent with how byes are handled elsewhere in
Schedule).
Runs the Swiss system for its recommended number of rounds, then appends a single-elimination "top cut" bracket to the same schedule for the top-placing teams. The cut size is always the largest power of two that is at most half the field (with a minimum of 2), which guarantees the elimination bracket never needs a bye.
Once a tournament other than RoundRobin has been created (whether by the CLI or
otherwise), a controller application can advance it as results come in without
branching on the tournament type:
var generator = TournamentRoundGeneratorFactory.For(schedule.EffectiveType);
if (!generator.IsComplete(schedule, result))
{
var round = generator.CreateNextRound(schedule, result);
// round is null if the current round hasn't been fully resolved yet.
}ITournamentRoundGenerator is implemented for every TournamentType, so this is the
single entry point a live tournament controller needs for round generation; initial
schedule creation (room counts, seeding, and so on) remains type-specific and is
exposed directly on each *Tournament class (RoundRobinTournament.Create,
EliminationTournament.Create, DoubleEliminationTournament.Create,
TripleEliminationTournament.Create, SwissTournament.Create,
SwissWithTopCutTournament.Create).