This vignette models a League of Legends Worlds style event:
This is the canonical linear chain pattern — two stages in sequence with no branching. It demonstrates:
swiss("open", rounds = 5) for a Swiss-system
stage,single_elim("top_cut", take = top_n(8)) reading from
the prior stage automatically (no from = needed),top_n(8) as the simplest flat routing selector,stage_status(),
standings(), and winner().teams <- c(
"Gen.G", "T1", "Hanwha Life", "Dplus KIA",
"BLG", "TES", "LNG", "JDG",
"G2", "Fnatic", "MAD Lions", "BDS",
"Cloud9", "Team Liquid", "FlyQuest", "100 Thieves"
)
length(teams)Because the pipeline is a straight line, from is never
written. The single_elim stage implicitly reads from
swiss via previous_stage().
This is the entire routing definition: 16 teams play a 5-round Swiss; the top 8 by Swiss standings advance to a single-elimination bracket.
When reusing a format across multiple events, define a spec first and validate before building.
worlds_spec <- spec() |>
swiss("open", rounds = 5) |>
single_elim("top_cut", take = top_n(8))
validate(worlds_spec, n = 16) # passes
# Build for this year's entrants
trn <- worlds_spec |> build(teams)stage_status(trn)
open_ms <- matches(trn, "open")
nrow(open_ms) # 5 rounds × 8 matches = 40 matches
head(open_ms)Round-by-round entry. Swiss schedules are generated round-by-round as results come in, so you’ll see new pending matches after each round.
for (i in seq_len(nrow(open_ms))) {
trn <- trn |> result("open", match = open_ms$id[i], score = c(1, 0))
# Refresh pending matches — Swiss generates each round dynamically.
open_ms <- matches(trn, "open")
}After the final Swiss result, the top-cut stage materializes automatically.
stage_status(trn)
# stage status complete total materialized
# open complete 40 40 TRUE
# top_cut active 0 7 TRUE
standings(trn, "open") # full Swiss standings, 1st through 16th
matches(trn, "top_cut") # 8-team bracketcut_ms <- matches(trn, "top_cut")
for (i in seq_len(nrow(cut_ms))) {
trn <- trn |> result("top_cut", match = cut_ms$id[i], score = c(1, 0))
}For tournament operations where stages advance on an explicit signal
(e.g., after a broadcast break), use
auto_advance = FALSE:
trn <- tournament(teams, auto_advance = FALSE) |>
swiss("open", rounds = 5) |>
single_elim("top_cut", take = top_n(8))
# ... enter all Swiss results ...
# Stage does not advance until you say so:
trn <- trn |> advance("open")