Tournaments
A league can now run a tournament: a straight knockout, or a group stage feeding one. It sits beside your seasons rather than inside one, which is the whole point of it — the people who enter are not a division's roster, so you can run a night for anybody in the league.
What it does
Set one up, get a field, draw it. Add players yourself, or open entries and share a link that lets them enter themselves. Seed the draw at random or by recorded average. Everything after that looks after itself: winners move into the next round, and the two players who suddenly have a match against each other are told.
Match lengths change as the night goes on. Best of 3 in the groups, 5 in the bracket, 7 in the final is four numbers on the form. They are remembered as the semi-finals and the final rather than as round numbers, so they stay right if four more people enter and the bracket grows a round.
There is a full walkthrough in running a tournament.
The interesting part
Every fixture in this app used to be known the moment a schedule was drawn. A season's divisions are
drawn in full — all 2(n-1) rounds at once — because "every pair meets twice, home and away" is a
property of the schedule and not of any round, so a round drawn on its own could not be checked
against it.
A bracket looks like it forbids that. Round two's pairings depend on round one's results, so surely they have to be created as they are settled?
It turns out the two halves come apart. A field of sixteen is fifteen matches whatever happens in them. The shape is arithmetic and is known the moment the field closes; only the occupants are not. So the whole bracket is still written in one go, later rounds holding nobody, and each row points at the slot its winner will fill. Advancing somebody is then one update against that pointer rather than a search for the right row — and the final is simply the match that points at nothing, which is how the app knows the night is over.
The practical result is that you see the whole tournament the moment you draw it, rather than a first round and a promise.
Two things that are not what they look like
A walkover is not a bye. In a league division a bye means somebody is unopposed this round and the schedule carries on around them — nothing was played and nothing counts. In a bracket it means somebody is through, and everything below them depends on it. They share a word and almost nothing else, so they are kept in separate columns in separate tables. Getting that wrong would have corrupted every "matches played" count in the app.
Correcting a result can be refused. If you change who won a match whose winner has already played their next one, the app will not quietly rewrite the round above — it tells you which result to delete first. The alternative was an unwind that walks up the bracket clearing everything as it goes, which deletes results nobody asked it to touch. One extra click, and nothing is lost.