--- title: "LoL Worlds: Swiss Stage to Top-Cut Bracket" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{LoL Worlds: Swiss Stage to Top-Cut Bracket} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` ```{r setup} library(bracketeer) ``` This vignette models a **League of Legends Worlds** style event: - A Swiss stage where all 16 teams compete over several rounds, - The top 8 advance to a single-elimination top-cut bracket. 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, - the auto-advance default, and - full inspection with `stage_status()`, `standings()`, and `winner()`. --- ## 1) Define the entrants ```{r teams} 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) ``` --- ## 2) Define the tournament Because the pipeline is a straight line, `from` is never written. The `single_elim` stage implicitly reads from `swiss` via `previous_stage()`. ```{r define} trn <- tournament(teams) |> swiss("open", rounds = 5) |> single_elim("top_cut", take = top_n(8)) ``` 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. --- ## 3) Preflight check (spec path) When reusing a format across multiple events, define a spec first and validate before building. ```{r spec-path} 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) ``` --- ## 4) Inspect the Swiss schedule ```{r swiss-schedule} stage_status(trn) open_ms <- matches(trn, "open") nrow(open_ms) # 5 rounds × 8 matches = 40 matches head(open_ms) ``` --- ## 5) Enter Swiss results 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. ```{r enter-swiss} 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. --- ## 6) Confirm advancement ```{r post-swiss} 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 bracket ``` --- ## 7) Run the top-cut bracket ```{r run-top-cut} cut_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)) } ``` --- ## 8) Outcomes ```{r outcomes} winner(trn) rankings(trn) routing_log(trn) ``` --- ## 9) Manual advance mode For tournament operations where stages advance on an explicit signal (e.g., after a broadcast break), use `auto_advance = FALSE`: ```{r manual} 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") ``` --- ## 10) Batch result entry `results()` accepts a data frame for entering multiple results at once. ```{r batch} round1 <- data.frame( match = matches(trn, "open")$id, score1 = rep(1L, 8), score2 = rep(0L, 8) ) trn <- trn |> results("open", round1) ```