| 1 |
<?php |
| 2 |
/** |
| 3 |
* Markup helpers. |
| 4 |
* |
| 5 |
* The class names and their cascade order matter: the connector lines are drawn |
| 6 |
* by li.game-left/right (side border) and li.game-top/bottom (bottom border), |
| 7 |
* where game-top deliberately clears the side border. Keep them as-is. |
| 8 |
*/ |
| 9 |
|
| 10 |
function e(string $value): string |
| 11 |
{ |
| 12 |
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); |
| 13 |
} |
| 14 |
|
| 15 |
function li(string $classes, string $content): string |
| 16 |
{ |
| 17 |
return " <li class='" . $classes . "'>" . $content . "</li>\n"; |
| 18 |
} |
| 19 |
|
| 20 |
function spacer(string $classes = 'spacer', string $content = ' '): string |
| 21 |
{ |
| 22 |
return li($classes, $content); |
| 23 |
} |
| 24 |
|
| 25 |
function team_text(array $team): string |
| 26 |
{ |
| 27 |
return "<span class='seed-num'>" . $team['seed'] . "</span> " . e($team['name']); |
| 28 |
} |
| 29 |
|
| 30 |
function team_li(array $team, string $classes): string |
| 31 |
{ |
| 32 |
$full = $team['seed'] . ' ' . $team['name']; |
| 33 |
return " <li class='" . $classes . "' title='" . e($full) . "'>" |
| 34 |
. team_text($team) . "</li>\n"; |
| 35 |
} |
| 36 |
|
| 37 |
/** |
| 38 |
* The two outermost columns. Both teams in a matchup sit adjacent with no |
| 39 |
* spacer between them; the spacer separates one matchup from the next. |
| 40 |
*/ |
| 41 |
function seed_column(array $teams, string $side): string |
| 42 |
{ |
| 43 |
$game = "game-$side"; |
| 44 |
$out = spacer(); |
| 45 |
foreach (array_chunk($teams, 2) as [$top, $bottom]) { |
| 46 |
$out .= team_li($top, "$game game-top"); |
| 47 |
$out .= team_li($bottom, "$game game-bottom"); |
| 48 |
$out .= spacer(); |
| 49 |
} |
| 50 |
return $out; |
| 51 |
} |
| 52 |
|
| 53 |
/** |
| 54 |
* Rounds 1-4. Each pair of entries feeds one game in the next round, so they |
| 55 |
* are joined by a bordered spacer. Round 3 fills that spacer with the region |
| 56 |
* name via $labels, keyed by pair index. |
| 57 |
*/ |
| 58 |
function round_column(array $entries, string $side, array $labels = []): string |
| 59 |
{ |
| 60 |
$game = "game-$side"; |
| 61 |
$edge = $side === 'left' ? 'right' : 'left'; |
| 62 |
$out = spacer(); |
| 63 |
|
| 64 |
foreach (array_chunk($entries, 2) as $pair => [$top, $bottom]) { |
| 65 |
$out .= team_li($top, "$game game-top"); |
| 66 |
$out .= isset($labels[$pair]) |
| 67 |
? spacer("$game spacer region region-$edge", e($labels[$pair])) |
| 68 |
: spacer("$game spacer"); |
| 69 |
$out .= team_li($bottom, "$game game-bottom"); |
| 70 |
$out .= spacer(); |
| 71 |
} |
| 72 |
return $out; |
| 73 |
} |
| 74 |
|
| 75 |
/** Final Four and championship columns hold a single entry, so nothing to pair. */ |
| 76 |
function single_column(array $team, string $classes): string |
| 77 |
{ |
| 78 |
return spacer() . team_li($team, $classes) . spacer(); |
| 79 |
} |
| 80 |
|
| 81 |
/** One column of the date band above the bracket. Null renders an empty column. */ |
| 82 |
function header_column(?array $round): string |
| 83 |
{ |
| 84 |
if ($round === null) { |
| 85 |
return ''; |
| 86 |
} |
| 87 |
return li('', e($round['name'])) . li('', e($round['dates'])); |
| 88 |
} |
| 89 |
|
| 90 |
/* ------------------------------------------------------------------------- |
| 91 |
Narrow-screen view. Below 800px the mirrored bracket is replaced by these: |
| 92 |
a champion card, then the four regions stacked, then the Final Four. The |
| 93 |
two are alternatives, never shown together. See style.css. |
| 94 |
---------------------------------------------------------------------- */ |
| 95 |
|
| 96 |
/** Headline result. */ |
| 97 |
function champion_card(array $t): string |
| 98 |
{ |
| 99 |
return " <div class='champion-card'>\n" |
| 100 |
. " <div class='champion-label'>Champion</div>\n" |
| 101 |
. " <div class='champion-name'>" . team_text($t['champion']) . "</div>\n" |
| 102 |
. " <div class='champion-over'>over " . team_text($t['runnerUp']) . "</div>\n" |
| 103 |
. " </div>\n"; |
| 104 |
} |
| 105 |
|
| 106 |
/** A section heading carrying the winner that came out of it. */ |
| 107 |
function panel_head(string $name, array $winner): string |
| 108 |
{ |
| 109 |
return " <h2 class='panel-head'><span class='panel-name'>" . e($name) . "</span>" |
| 110 |
. "<span class='panel-winner'>" . team_text($winner) . "</span></h2>\n"; |
| 111 |
} |
| 112 |
|
| 113 |
/** |
| 114 |
* A region as a four-column bracket: 16 seeds, then the winners of rounds 1-3. |
| 115 |
* The fourth-round winner is the region champion, which goes in the heading |
| 116 |
* rather than a fifth column — that is what lets this fit 320px. |
| 117 |
*/ |
| 118 |
function region_panel(array $region): string |
| 119 |
{ |
| 120 |
$columns = " <ul class='round seed'>\n" |
| 121 |
. seed_column($region['rounds'][0], 'left') . " </ul>\n"; |
| 122 |
for ($n = 1; $n <= 3; $n++) { |
| 123 |
$columns .= " <ul class='round round-$n'>\n" |
| 124 |
. round_column($region['rounds'][$n], 'left') . " </ul>\n"; |
| 125 |
} |
| 126 |
|
| 127 |
return " <section class='region-panel'>\n" |
| 128 |
. panel_head($region['label'], $region['rounds'][4][0]) |
| 129 |
. " <div class='tournament mini'>\n$columns </div>\n" |
| 130 |
. " </section>\n"; |
| 131 |
} |
| 132 |
|
| 133 |
/** One game as a two-row card with the winner marked. */ |
| 134 |
function matchup_card(array $game): string |
| 135 |
{ |
| 136 |
$rows = ''; |
| 137 |
foreach (['top', 'bottom'] as $slot) { |
| 138 |
$won = $game[$slot] === $game['winner']; |
| 139 |
$rows .= " <div class='side" . ($won ? ' won' : '') . "'>" |
| 140 |
. team_text($game[$slot]) . "</div>\n"; |
| 141 |
} |
| 142 |
return " <div class='card'>\n$rows </div>\n"; |
| 143 |
} |
| 144 |
|
| 145 |
/** |
| 146 |
* The Final Four and title game. Three games is too few to be worth a bracket, |
| 147 |
* so they are cards instead. |
| 148 |
*/ |
| 149 |
function final_four_panel(array $t, array $rounds): string |
| 150 |
{ |
| 151 |
return " <section class='region-panel'>\n" |
| 152 |
. panel_head('Final Four', $t['champion']) |
| 153 |
. " <h3>" . e($rounds[4]['name']) . " <small>" . e($rounds[4]['dates']) . "</small></h3>\n" |
| 154 |
. matchup_card($t['national'][5][0]) . matchup_card($t['national'][5][1]) |
| 155 |
. " <h3>" . e($rounds[5]['name']) . " <small>" . e($rounds[5]['dates']) . "</small></h3>\n" |
| 156 |
. matchup_card($t['national'][6][0]) |
| 157 |
. " </section>\n"; |
| 158 |
} |
| 159 |
|