Skip to content

v2.0.0

Choose a tag to compare

@github-actions github-actions released this 13 Sep 12:36
· 670 commits to main since this release

Bracket Creator 2.0.0

A major release. The draw engine was rebuilt: pool qualifiers now land in the knockout the way the European Kendo Championships draws them, pools and knockout-only brackets keep dojo-mates apart, and byes go to the competitors who have earned them. Every competitor is now identified by a participant id rather than by name, and numbered by their position in the draw. The elimination stage is called knockout everywhere, matching the vocabulary of the rulebooks operators read. Around that, the live tournament app was hardened for real venues: a result entered on a tablet with no signal is never silently thrown away, a write the server refuses says so on screen, and every score editor follows results recorded on other devices.

It is 2.0.0 rather than 1.2.0 because several of these changes are not backwards compatible. The same roster and settings produce a different draw than 1.x did, some configurations 1.x accepted are now refused, the on-disk data format and parts of the HTTP API changed shape, and one CLI command was renamed. Existing tournament-data folders are migrated automatically when 2.0 starts, but read the upgrade notes below before moving a live event across.

Upgrading from 1.x

Finish an in-progress event on the version it started on, and upgrade between events. The format rename and its data migration are not meant to be applied mid-tournament (#413). Once 2.0 has written to a data folder, do not go back to 1.x on it: a 1.x binary reading a knockout bracket saved by 2.0 shows blank scores (#389). After upgrading, reload any admin console or viewer tab that was left open, since an already-loaded console keeps the previous front-end and sends a settings field that 2.0 refuses (#413).

Migrated automatically when 2.0 opens an existing data folder

  • Competitions stored as format: playoffs or status: playoffs are read as knockout, and the retired match duration keys are folded onto the knockout duration. The conversion happens in memory on every read, and a best-effort startup pass rewrites the files. A config.md whose id: disagrees with its folder name is skipped and logged rather than rewritten (#413)
  • Whole-minute match durations are converted to seconds; the old keys are dropped on the next save (#365)
  • A competition with no competitor number prefix is given one derived from its name, and a pooled competition's existing draw is numbered under it (#416)
  • Seed rows gain the dojo and the participant id; pool, pool match and bracket rows gain participant ids; team members move into a squad of their own with member ids. Rows are repaired only where the name resolves to exactly one competitor. Anything that cannot be resolved is left untouched and named in the data-issues notice on the competition Overview (#389, #416)
  • Hantei results and knockout scores stored in the 1.x shape are converted to the new result record on load (#389)
  • A competition already drawn under 1.x keeps resolving its live bracket correctly: the old placement is replayed for it, so pool winners are not written into the wrong knockout slots (#384)

What behaves differently

  • Draws differ from 1.x. Pool assignment, knockout placement, bye allocation and dojo separation all changed (see Draws and seeding below), so regenerating a published draw will not reproduce it. The example workbooks were regenerated (#384, #408)
  • A competition that draws a bracket (Knockout only, or Pools + Knockout) must be assigned 1, 2, 4, 8 or 16 shiai-jo. A competition stored with any other count still loads, runs and keeps its results, but Generate draw and Start competition stay disabled until its shiai-jo are reassigned. League and Swiss are exempt. A tournament now holds at most 16 shiai-jo, down from 26; one stored with more keeps loading, but its next change to the shiai-jo list is refused until the count is 16 or fewer (#384)
  • Seeding must be complete before a draw. Ranks 1 to N must all be set; a gap blocks the draw with the missing ranks named. Seeds also require a competitor list to exist, so an archive that carries a seeds file but no participants file no longer imports (#384, #416)
  • Every competitor needs a name and a dojo, on every path (command line, legacy web UI, archive import and the app). A 1.x roster with a blank dojo still loads so it can be repaired, but the app refuses changes to it and refuses to draw it until the dojo is filled in (#408, #415, #416)
  • Team names must be unique even across dojos, because a team's name is its identity in results. Two members of one team can no longer share a name (#383, #416)
  • Competitor numbers belong to draw positions. Nothing is shown before the draw; after it, a pooled competition is numbered pool by pool (K1 to K4 are the first pool) and a knockout-only competition by bracket position. A knockout-only competition drawn by 1.x shows no numbers until its draw is regenerated. The provisional registration-order numbers in the check-in list are gone (#416)
  • Manual pool rank overrides recorded under 1.x are not read. Re-record them through the chusen flow, which stores them against participant ids (#416)
  • Format and competition type can no longer be changed once a competition has started (#403)
  • Kachinuki encounters now end only when the operator ends them, daihyosen is not offered in kachinuki, and the FIK five-person lineup rule is no longer enforced (#379)

Command line

  • create-playoffs is now create-knockout. The old name still works as an alias, so existing scripts keep running (#413)
  • Every run now numbers competitors. When --number-prefix is omitted the prefix is derived from --title-prefix, or K when that is also omitted, so pass a distinct -n per competition. The Data sheet gains a Player Number column and its first column is headed Entry order (#416)
  • --courts accepts only 1, 2, 4, 8 or 16 (#384)
  • Rows with an empty name or no dojo, and an out-of-range --pool-winners, are rejected up front (#415, #416)

HTTP API and integrations

  • The format and status value playoffs is now knockout, and playoffMatchDurationSeconds is now knockoutMatchDurationSeconds; sending the old duration key returns a 400 naming its replacement. The whole-minute poolMatchDuration, playoffMatchDuration and matchDuration fields are removed. Archives exported by 1.x still import (#365, #413)
  • The legacy web UI's tournamentType form value accepts knockout only (#413)
  • PUT /api/competitions/{id}/schedule and GET /api/viewer/schedule are removed (#389)
  • Knockout matches carry ipponsA/ipponsB and hansokuA/hansokuB like every other result, and a hantei is recorded as an Ht mark in the winner's ippons. decidedByHantei and the bracket scoreA/scoreB strings are no longer returned, though older clients may still send them (#389)
  • A match write the server refuses returns HTTP 200 with {"applied": false, "reason": "superseded"} or "clock_skew". Corrections no longer bypass the last-write-wins check (#402)
  • PUT .../seeds, generate-draw and start return 400 for an incomplete seeding (#384). League tie-break selection takes teamIds, and rank overrides are addressed by participant id (#416)
  • Exporting a Swiss competition to Excel returns 422 instead of an empty workbook (#412)

Highlights since v1.1.0

Draws and seeding

  • Knockout draws follow the European Kendo Championships construction: each shiai-jo owns one contiguous block of the bracket, pool winners stay in their own block, runners-up cross to the partner shiai-jo, and each shiai-jo's tree pages are a subtree its officials can run on their own. The decoded 34th EKC reference draws reproduce exactly (#384)
  • Byes go to seeded pools first in seed order, then to oversized pools, then by pool order, instead of wherever the tree left an odd slot (#384)
  • A pool's qualifiers are kept apart: two can only meet in the final, three or more land in different quarters (#384)
  • New Knockout qualifiers setting for pools sized by minimum players: Standard, Oversized send +1 (a larger pool sends one extra qualifier, who always fights in round one), and Fit the knockout (pools cut so winners plus drafted second places fill the bracket with no byes). Settings shows a live preview such as "34 pools -> 36 qualifiers -> 64-slot knockout (28 byes)". Also available as --extra-qualifiers (#384)
  • Pools spread each dojo across the draw: competitors are placed one at a time down the knockout tree the competition will build, seeds first, then a single exchange pass tidies the result. A dojo with more members than there are pools no longer piles into the first pools (#408)
  • Knockout-only draws now keep dojo-mates out of the first round. Measured on 16 competitors from four dojos of four: every first-round match was intra-dojo before, none after, with no seed moved (#408)
  • A half-typed seeding stays visible, names the ranks still to set, and blocks the draw with the reason on screen. Seeds of competitors who did not check in no longer shift the remaining seeds into the wrong half (#384)
  • With more seeds than pools, an extra seed takes the next pool holding no seed and no dojo-mate, and is never moved afterwards (#416)
  • A competition must name at least one shiai-jo; clearing every shiai-jo is refused instead of silently substituting the first one (#384)
  • Draws on large fields are many times faster: seeding a 256-entrant knockout took about 28 seconds before and now takes well under a second on typical rosters (#408, #416)
  • Competitors tied on every criterion now enter the knockout in a stable order (#370)

Competitor numbers and identity

  • A competition always has a number prefix. Leave it blank and the app derives one from the competition name, never one that could collide with another competition's tags. The prefix is capped at three characters and can be changed in any status: saving renumbers every competitor in place and warns that printed tags must be reprinted (#416)
  • Every competitor gets a participant id when the list is applied, shown beside the row. Results, standings, withdrawals and renames resolve by id, so a name or dojo can be corrected after the draw without results moving to someone else (#416)
  • Same-name competitors from different dojos are separate people throughout: they no longer share a standings row in leagues, Swiss or tie-breaks, and can no longer block each other from starting a match (#408, #416)
  • Team squads: each member has an identity and a label such as T10.1, shown on the scoring rows, viewer, TV display, streaming overlay and the Kachinuki Detail sheet. Squads are managed from competition Settings, and a replacement member can be added mid-tournament (#416)
  • Applying the participant list takes the console to the Overview (or to Scores for a running competition) instead of back to the dashboard (#416)

Scoring and score-sheet marks

  • Scores follow the FIK paper score sheet. The centre of a score only ever shows vs, X (tie), (E) (encho) or (DH) (daihyosen); results such as Ht, Kiken and Fus. sit beside the competitor they name. Points are shown as waza letters, never digits, and a default win shows its points as maru (#376)
  • The hantei Ht sits in the winner's next free slot rather than in the centre, and a pool hantei now survives a restart (#383, #389)
  • Encho is no longer capped: the operator records however many periods were fought (#376)
  • A hansoku point the operator struck is no longer deleted on save, and the Excel score sheet shows the hansoku triangle again, now on pool rows and team bout rows too (#401)
  • Pool matches keep who recorded a decision and why, the encho record and the modification time across a restart (#383)
  • Swiss standings now use flags for engi and IV/IL/IT/PW/PL for team competitions, with matching columns in the table (#377)
  • Saving Settings no longer clears the engi flag or blocks every later save, and engi matches opened from the competition page get the flag editor (#374)
  • Swiss matches appear on the competition page Overview, the status badge names the format, and rounds read "Round 1" instead of an internal id (#410)
  • The viewer schedule no longer shows a dash between competitors for an auto-completed bye (#382)

Kachinuki

  • Kachinuki is operator-led: Record bout keeps the winner on and adds the next pairing, End match decides the encounter from the last bout, a knockout tie offers Encho on the same pair, and Add next bout manually, Reopen match and Remove this bout recover from mistakes. Both exhaustion and a defeated taisho work as win rules (#379)
  • The bouts already fought show as read-only team-sheet rows above the current bout, and M/K/D/T/H (Shift for Aka) score from the keyboard (#379)
  • Schedule estimates for kachinuki competitions show a best, average and worst case (#379)
  • A bout between two same-named fighters is decided by member id, and renaming a member mid-encounter no longer puts someone who already lost back in the queue (#416)

Running tournaments live

  • The court console can correct any completed match in place with a Correct button, even while the next match is running on that shiai-jo (#379)
  • The armed finish button now reads "Tap again to finish", so a match is not left unfinalised by a missed second tap (#379)
  • Match durations are entered as m:ss (for example 2:30), between 1:00 and 60:00, and changing a duration never invalidates a generated draw (#365)
  • Competition create and Settings offer the same controls in the same order, including Format, Competition type and Round-robin shape on Settings, and the per-phase durations on create. Four mismatches between the two screens were fixed along the way (#403)
  • Joint third place is its own setting for every format except Swiss, instead of a side effect of the Naginata flag (#412)
  • The team editor follows bouts scored on another device row by row, without overwriting rows the operator is editing, and both editors adopt a hantei recorded elsewhere (#389, #404)
  • Scoring two pool bouts in quick succession no longer injects a phantom tie-break bout or stalls knockout advancement (#369)
  • A hand-edited, unreadable team result no longer wipes that encounter on the next score entry. The console says which file is broken and where, and an unreadable bracket can be moved aside from the Overview (#399)
  • Withdrawing a seeded competitor through a roster replace now works (#400)
  • The app front-end is cached by the browser, so reloading a page within five minutes makes no requests at all, and live updates cost less per connected viewer (#363, #383)

Reliability on flaky Wi-Fi

  • Only a confirmed write empties the offline outbox. Server errors keep retrying and show Not saving, an expired password shows Sign in to save, a password reset from another device parks unsent results until the next sign-in, signing out with unsent results asks first, and queued results now last 12 hours instead of 6 (#398)
  • A result the server discards because a newer one is already stored now says so on every surface, with advice not to re-enter it (#402)
  • Device clocks are kept in step with the server, and a device whose clock runs ahead is refused instead of silently overwriting newer results. It resyncs and asks the operator to enter the result again (#402)

Excel export and printing

  • The blank-template export renders every tree page (any competition on two or more shiai-jo was missing half its draw), fills the Elimination Matches sheet, no longer clips pool labels, and no longer prints a near-blank extra page per tree page (#368)
  • A knockout-only competition's blank-template export includes its bracket (#370)
  • Exported sheets name the shiai-jo a competition actually uses (a competition on C and D prints C and D) and follow bouts the operator moved to another shiai-jo (#384)
  • Both export types share one pipeline, so the blank template and the results workbook can no longer disagree. The print booklet lists any competition it had to skip, and print --fail-on-skip-all exits non-zero when nothing was printed (#412)
  • --third-place-match adds a bronze match on create-pools and create-knockout (#412)
  • Tags of four or five characters print whole, a multi-character prefix prints above the number, the QR code is larger and no longer overlaps the number, Names to Print fits one A3 landscape page, and knockout-only exports include tags and Names to Print (#416)

Documentation

  • New organiser pages on the knockout draw and the pool draw, with an interactive walk-through of how the pool draw places each competitor, and a competitor numbers section (#384, #408)
  • A site-wide language review corrected eight wrong claims, including a create-pools example that failed (#415)

Fixes and security

  • Competition file paths are checked to stay inside the tournament folder (#416)
  • Public self-registration no longer shows a walk-up another competitor's error, and the duplicate-registration message explains the name-plus-dojo rule (#415, #416)
  • A binary built without the front-end bundle (for example via go install) logs a warning at startup (#415)
  • Go toolchain updated to 1.26.6, clearing six standard library vulnerabilities, then to 1.27.1 (#385, #409)
  • Development-only JavaScript and docs dependency advisories cleared, and the frontend linter moved to oxlint (#364, #371, #390)

Dependencies and toolchain

Install: docker run -p 8080:8080 -v "$PWD/tournament-data:/tournament-data" ghcr.io/gitrgoliveira/bracket-creator-mobile:latest, or see the install guide for Homebrew, Linux packages, and binaries.

Full Changelog: v1.1.0...v2.0.0