" . $content . "\n";
}
function spacer(string $classes = 'spacer', string $content = ' '): string
{
return li($classes, $content);
}
function team_text(array $team): string
{
return "" . $team['seed'] . " " . e($team['name']);
}
function team_li(array $team, string $classes): string
{
$full = $team['seed'] . ' ' . $team['name'];
return "
"
. team_text($team) . "\n";
}
/**
* The two outermost columns. Both teams in a matchup sit adjacent with no
* spacer between them; the spacer separates one matchup from the next.
*/
function seed_column(array $teams, string $side): string
{
$game = "game-$side";
$out = spacer();
foreach (array_chunk($teams, 2) as [$top, $bottom]) {
$out .= team_li($top, "$game game-top");
$out .= team_li($bottom, "$game game-bottom");
$out .= spacer();
}
return $out;
}
/**
* Rounds 1-4. Each pair of entries feeds one game in the next round, so they
* are joined by a bordered spacer. Round 3 fills that spacer with the region
* name via $labels, keyed by pair index.
*/
function round_column(array $entries, string $side, array $labels = []): string
{
$game = "game-$side";
$edge = $side === 'left' ? 'right' : 'left';
$out = spacer();
foreach (array_chunk($entries, 2) as $pair => [$top, $bottom]) {
$out .= team_li($top, "$game game-top");
$out .= isset($labels[$pair])
? spacer("$game spacer region region-$edge", e($labels[$pair]))
: spacer("$game spacer");
$out .= team_li($bottom, "$game game-bottom");
$out .= spacer();
}
return $out;
}
/** Final Four and championship columns hold a single entry, so nothing to pair. */
function single_column(array $team, string $classes): string
{
return spacer() . team_li($team, $classes) . spacer();
}
/** One column of the date band above the bracket. Null renders an empty column. */
function header_column(?array $round): string
{
if ($round === null) {
return '';
}
return li('', e($round['name'])) . li('', e($round['dates']));
}
/* -------------------------------------------------------------------------
Narrow-screen view. Below 800px the mirrored bracket is replaced by these:
a champion card, then the four regions stacked, then the Final Four. The
two are alternatives, never shown together. See style.css.
---------------------------------------------------------------------- */
/** Headline result. */
function champion_card(array $t): string
{
return " \n"
. "
Champion
\n"
. "
" . team_text($t['champion']) . "
\n"
. "
over " . team_text($t['runnerUp']) . "
\n"
. "
\n";
}
/** A section heading carrying the winner that came out of it. */
function panel_head(string $name, array $winner): string
{
return " " . e($name) . ""
. "" . team_text($winner) . "
\n";
}
/**
* A region as a four-column bracket: 16 seeds, then the winners of rounds 1-3.
* The fourth-round winner is the region champion, which goes in the heading
* rather than a fifth column — that is what lets this fit 320px.
*/
function region_panel(array $region): string
{
$columns = " \n"
. seed_column($region['rounds'][0], 'left') . "
\n";
for ($n = 1; $n <= 3; $n++) {
$columns .= " \n"
. round_column($region['rounds'][$n], 'left') . "
\n";
}
return " \n"
. panel_head($region['label'], $region['rounds'][4][0])
. " \n$columns
\n"
. " \n";
}
/** One game as a two-row card with the winner marked. */
function matchup_card(array $game): string
{
$rows = '';
foreach (['top', 'bottom'] as $slot) {
$won = $game[$slot] === $game['winner'];
$rows .= " "
. team_text($game[$slot]) . "
\n";
}
return " \n$rows
\n";
}
/**
* The Final Four and title game. Three games is too few to be worth a bracket,
* so they are cards instead.
*/
function final_four_panel(array $t, array $rounds): string
{
return " \n"
. panel_head('Final Four', $t['champion'])
. " " . e($rounds[4]['name']) . " " . e($rounds[4]['dates']) . "
\n"
. matchup_card($t['national'][5][0]) . matchup_card($t['national'][5][1])
. " " . e($rounds[5]['name']) . " " . e($rounds[5]['dates']) . "
\n"
. matchup_card($t['national'][6][0])
. " \n";
}