@wral/hsot-data 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -4
- package/dist/client.mjs +49 -0
- package/dist/define.mjs +1 -1
- package/dist/define.standalone.js +1273 -1196
- package/dist/{hsot-brackets-D5cwGage.js → hsot-brackets-Bqk0gI3J.js} +679 -648
- package/dist/index.mjs +16 -15
- package/package.json +2 -1
|
@@ -1,122 +1,85 @@
|
|
|
1
|
-
import { LitElement as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const e = Object.entries(a).filter(([, s]) => s != null && s !== "");
|
|
5
|
-
if (!e.length) return "";
|
|
6
|
-
const t = new URLSearchParams();
|
|
7
|
-
return e.forEach(([s, o]) => t.set(s, String(o))), `?${t.toString()}`;
|
|
8
|
-
}
|
|
9
|
-
function we({ baseUrl: a, token: e = "", fetchFn: t } = {}) {
|
|
10
|
-
if (!a) throw new Error("createClient requires a baseUrl");
|
|
11
|
-
const s = a.replace(/\/+$/, ""), o = t || ((...i) => fetch(...i));
|
|
12
|
-
async function r(i) {
|
|
13
|
-
const h = { Accept: "application/json" };
|
|
14
|
-
e && (h.Authorization = `Bearer ${e}`);
|
|
15
|
-
const c = await o(`${s}${i}`, { headers: h });
|
|
16
|
-
if (!c.ok) {
|
|
17
|
-
const d = new Error(`api-hsot ${c.status} on ${i}`);
|
|
18
|
-
throw d.status = c.status, d;
|
|
19
|
-
}
|
|
20
|
-
return c.json();
|
|
21
|
-
}
|
|
22
|
-
async function l(i, h = {}) {
|
|
23
|
-
const c = [];
|
|
24
|
-
let d = null;
|
|
25
|
-
for (let m = 0; m < ye; m += 1) {
|
|
26
|
-
const f = $e(d ? { ...h, cursor: d } : h), u = await r(`${i}${f}`);
|
|
27
|
-
if (c.push(...u.items || []), d = u.nextCursor || null, !d) break;
|
|
28
|
-
}
|
|
29
|
-
return { items: c, total: c.length, nextCursor: null };
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
listSchools: (i) => l("/schools", i),
|
|
33
|
-
getSchool: (i) => r(`/schools/${i}`),
|
|
34
|
-
listTeams: (i) => l("/teams", i),
|
|
35
|
-
getTeam: (i) => r(`/teams/${i}`),
|
|
36
|
-
listConferences: (i) => l("/conferences", i),
|
|
37
|
-
listPlayers: (i) => l("/players", i),
|
|
38
|
-
listRosters: (i) => l("/rosters", i),
|
|
39
|
-
listGames: (i) => l("/games", i),
|
|
40
|
-
getGame: (i) => r(`/games/${i}`),
|
|
41
|
-
listTournaments: (i) => l("/tournaments", i),
|
|
42
|
-
listSeedings: (i, h) => l(`/tournaments/${i}/seedings`, h),
|
|
43
|
-
listEdges: (i, h) => l(`/tournaments/${i}/edges`, h),
|
|
44
|
-
listRankings: (i) => l("/rankings", i),
|
|
45
|
-
listSports: () => r("/sports")
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
const j = {
|
|
1
|
+
import { LitElement as le, html as n, css as w, nothing as p, svg as ee } from "lit";
|
|
2
|
+
import { createClient as ke } from "./client.mjs";
|
|
3
|
+
const E = {
|
|
49
4
|
game: "/{sport}/game/{id}/",
|
|
50
5
|
school: "/school/{id}/",
|
|
51
|
-
section: "/{sport}/{view}/"
|
|
6
|
+
section: "/{sport}/{view}/",
|
|
7
|
+
// The "Report a Score" page; {id} is the game being reported on, and
|
|
8
|
+
// reportHref() drops the parameter when there is none.
|
|
9
|
+
report: "/report-a-score/?game={id}"
|
|
52
10
|
};
|
|
53
11
|
function g(a, e) {
|
|
54
12
|
return String(a).replace(/\{(\w+)\}/g, (t, s) => e[s] !== void 0 && e[s] !== null ? String(e[s]) : t);
|
|
55
13
|
}
|
|
56
14
|
function z(a) {
|
|
57
15
|
return {
|
|
58
|
-
game: a.getAttribute("game-href") ||
|
|
59
|
-
school: a.getAttribute("school-href") ||
|
|
60
|
-
section: a.getAttribute("section-href") ||
|
|
16
|
+
game: a.getAttribute("game-href") || E.game,
|
|
17
|
+
school: a.getAttribute("school-href") || E.school,
|
|
18
|
+
section: a.getAttribute("section-href") || E.section,
|
|
19
|
+
report: a.getAttribute("report-href") || E.report
|
|
61
20
|
};
|
|
62
21
|
}
|
|
63
|
-
|
|
64
|
-
|
|
22
|
+
function ce(a, e = "") {
|
|
23
|
+
const t = g(a.report || E.report, { id: e || "" });
|
|
24
|
+
return e ? t : t.replace(/([?&])game=(?=&|$)/, "$1").replace(/[?&]$/, "").replace(/\?&/, "?");
|
|
25
|
+
}
|
|
26
|
+
const k = (a) => a ? a.charAt(0).toUpperCase() + a.slice(1) : "";
|
|
27
|
+
function x(a, e) {
|
|
65
28
|
if (!a) return "TBD";
|
|
66
|
-
const [t, s,
|
|
67
|
-
return !t || !s || !
|
|
29
|
+
const [t, s, r] = String(a).split("-").map(Number);
|
|
30
|
+
return !t || !s || !r ? "TBD" : new Date(t, s - 1, r).toLocaleDateString("en-US", e || { weekday: "short", month: "short", day: "numeric" });
|
|
68
31
|
}
|
|
69
|
-
function
|
|
32
|
+
function W(a) {
|
|
70
33
|
if (!a) return "";
|
|
71
34
|
const [e, t] = String(a).split(":").map(Number);
|
|
72
35
|
if (Number.isNaN(e)) return "";
|
|
73
36
|
const s = e >= 12 ? "PM" : "AM";
|
|
74
37
|
return `${(e + 11) % 12 + 1}:${String(t || 0).padStart(2, "0")} ${s}`;
|
|
75
38
|
}
|
|
76
|
-
function
|
|
39
|
+
function Se(a) {
|
|
77
40
|
return a ? `${Math.floor(a / 12)}-${a % 12}` : "·";
|
|
78
41
|
}
|
|
79
|
-
function
|
|
42
|
+
function Ie(a) {
|
|
80
43
|
return (Array.isArray(a?.positions) ? a.positions : String(a?.position ?? "").split(/[/,]/)).map((t) => String(t ?? "").trim()).filter(Boolean).join("/");
|
|
81
44
|
}
|
|
82
|
-
function
|
|
45
|
+
function _(a = /* @__PURE__ */ new Date()) {
|
|
83
46
|
const e = a.getFullYear();
|
|
84
47
|
return a.getMonth() >= 6 ? `${e}-${e + 1}` : `${e - 1}-${e}`;
|
|
85
48
|
}
|
|
86
|
-
function
|
|
49
|
+
function V(a = /* @__PURE__ */ new Date()) {
|
|
87
50
|
const e = (t) => String(t).padStart(2, "0");
|
|
88
51
|
return `${a.getFullYear()}-${e(a.getMonth() + 1)}-${e(a.getDate())}`;
|
|
89
52
|
}
|
|
90
|
-
function
|
|
53
|
+
function Te(a, e = V()) {
|
|
91
54
|
const t = [...new Set((a || []).filter(Boolean))].sort();
|
|
92
55
|
if (!t.length || t.includes(e)) return e;
|
|
93
|
-
const s = t.filter((
|
|
56
|
+
const s = t.filter((r) => r < e);
|
|
94
57
|
return s.length ? s[s.length - 1] : t[0];
|
|
95
58
|
}
|
|
96
|
-
function
|
|
59
|
+
function Y(a) {
|
|
97
60
|
return a ? (a.abbr || a.name || "?").slice(0, 4).toUpperCase() : "?";
|
|
98
61
|
}
|
|
99
|
-
function
|
|
62
|
+
function G(a) {
|
|
100
63
|
if (!a || !/^#[0-9a-fA-F]{6}$/.test(a)) return "#FFFFFF";
|
|
101
|
-
const e = parseInt(a.slice(1), 16), t = e >> 16 & 255, s = e >> 8 & 255,
|
|
102
|
-
return 0.299 * t + 0.587 * s + 0.114 *
|
|
64
|
+
const e = parseInt(a.slice(1), 16), t = e >> 16 & 255, s = e >> 8 & 255, r = e & 255;
|
|
65
|
+
return 0.299 * t + 0.587 * s + 0.114 * r > 150 ? "#0F1B33" : "#FFFFFF";
|
|
103
66
|
}
|
|
104
|
-
const
|
|
67
|
+
const Ce = (a) => {
|
|
105
68
|
const e = ["th", "st", "nd", "rd"], t = a % 100;
|
|
106
69
|
return a + (e[(t - 20) % 10] || e[t] || e[0]);
|
|
107
70
|
};
|
|
108
|
-
function
|
|
109
|
-
const t = (
|
|
110
|
-
const
|
|
111
|
-
return
|
|
112
|
-
}, s = t(a),
|
|
113
|
-
return s !== null &&
|
|
114
|
-
}
|
|
115
|
-
function
|
|
71
|
+
function te(a, e) {
|
|
72
|
+
const t = (o) => {
|
|
73
|
+
const i = /^\d+/.exec(String(o ?? ""));
|
|
74
|
+
return i ? Number(i[0]) : null;
|
|
75
|
+
}, s = t(a), r = t(e);
|
|
76
|
+
return s !== null && r !== null && s !== r ? r - s : s !== null && r === null ? -1 : s === null && r !== null ? 1 : String(a ?? "").localeCompare(String(e ?? ""), "en", { sensitivity: "base" });
|
|
77
|
+
}
|
|
78
|
+
function De(a, e) {
|
|
116
79
|
const t = (s) => String(s?.name ?? s ?? "");
|
|
117
80
|
return t(a).localeCompare(t(e), "en", { numeric: !0, sensitivity: "base" });
|
|
118
81
|
}
|
|
119
|
-
function
|
|
82
|
+
function de(a) {
|
|
120
83
|
if (a.state === "live") {
|
|
121
84
|
const e = [a.period, a.clock].filter(Boolean).join(" ");
|
|
122
85
|
return { kind: "live", label: e ? `Live · ${e}` : "Live" };
|
|
@@ -125,54 +88,65 @@ function le(a) {
|
|
|
125
88
|
const e = [];
|
|
126
89
|
return a.finish === "overtime" && e.push("OT"), a.finish === "shootout" && e.push("PK-SO"), a.forfeit && a.forfeit !== "none" && e.push("Forfeit"), { kind: "final", label: `Final${e.length ? ` · ${e.join(" · ")}` : ""}` };
|
|
127
90
|
}
|
|
128
|
-
return a.state === "postponed" ? { kind: "warn", label: "Postponed" } : a.state === "canceled" ? { kind: "warn", label: "Canceled" } : { kind: "sched", label: `${
|
|
91
|
+
return a.state === "postponed" ? { kind: "warn", label: "Postponed" } : a.state === "canceled" ? { kind: "warn", label: "Canceled" } : { kind: "sched", label: `${x(a.date, { month: "short", day: "numeric" })} · ${W(a.time)}`.replace(/ · $/, "") };
|
|
92
|
+
}
|
|
93
|
+
const Be = ["boys", "girls"];
|
|
94
|
+
function he(a, e) {
|
|
95
|
+
return e ? a ? a.gender === e || a.gender === "coed" : !1 : !0;
|
|
129
96
|
}
|
|
130
|
-
|
|
131
|
-
|
|
97
|
+
function me(a, e) {
|
|
98
|
+
return e ? (a || []).filter((t) => he(t, e)) : a || [];
|
|
99
|
+
}
|
|
100
|
+
function q(a) {
|
|
101
|
+
const e = new Set((a || []).map((t) => t && t.gender));
|
|
102
|
+
return Be.filter((t) => e.has(t));
|
|
103
|
+
}
|
|
104
|
+
const Fe = (a) => q(a).length === 2, ze = /* @__PURE__ */ new Set(["game", "story", "page", "forum", "video", "gallery"]);
|
|
105
|
+
function I(a) {
|
|
132
106
|
let e = String(a || "").replace(/^[a-z][a-z0-9+.-]*:\/\/[^/#?]*/i, "");
|
|
133
107
|
const t = e.indexOf("#");
|
|
134
108
|
let s = "";
|
|
135
109
|
t !== -1 && (s = e.slice(t).split("?")[0], e = e.slice(0, t));
|
|
136
|
-
let
|
|
137
|
-
return
|
|
110
|
+
let r = e.split("?")[0] + s;
|
|
111
|
+
return r = r.replace(/([^:])\/{2,}/g, "$1/").replace(/^\/{2,}/, "/"), r = r.replace(/^\/(?=#)/, ""), r.length > 1 && (r = r.replace(/\/+$/, "")), r.toLowerCase();
|
|
138
112
|
}
|
|
139
|
-
function
|
|
113
|
+
function pe() {
|
|
140
114
|
const a = globalThis.location;
|
|
141
115
|
if (!a) return "";
|
|
142
116
|
const e = (a.hash || "").startsWith("#/") ? a.hash : "";
|
|
143
|
-
return
|
|
117
|
+
return I((a.pathname || "") + e);
|
|
144
118
|
}
|
|
145
|
-
function
|
|
119
|
+
function Pe(a, e, t) {
|
|
146
120
|
if (!t) return null;
|
|
147
|
-
const s =
|
|
121
|
+
const s = I(a);
|
|
148
122
|
if (!s) return null;
|
|
149
|
-
const
|
|
150
|
-
if (s ===
|
|
151
|
-
const
|
|
152
|
-
if (s ===
|
|
153
|
-
if (!s.startsWith(`${
|
|
154
|
-
const
|
|
155
|
-
return h.length > 2 || h.some((
|
|
156
|
-
}
|
|
157
|
-
function
|
|
158
|
-
const s = (
|
|
123
|
+
const r = I(g(e.game, { sport: t, id: "" })), o = I(g(e.school, { id: "" }));
|
|
124
|
+
if (s === r || s.startsWith(`${r}/`) || s === o || s.startsWith(`${o}/`)) return null;
|
|
125
|
+
const i = I(g(e.section, { sport: t, view: "" }));
|
|
126
|
+
if (s === i) return "";
|
|
127
|
+
if (!s.startsWith(`${i}/`)) return null;
|
|
128
|
+
const d = s.slice(i.length + 1), h = d.split("/");
|
|
129
|
+
return h.length > 2 || h.some((l) => !/^[a-z][a-z-]*$/.test(l)) || ze.has(h[0]) ? null : d;
|
|
130
|
+
}
|
|
131
|
+
function Ee(a, e, t) {
|
|
132
|
+
const s = (o) => g(t.section, { sport: a, view: o }).replace(/([^:])\/{2,}/g, "$1/"), r = Fe(e) ? [
|
|
159
133
|
{ label: "Boys Standings", href: s("boys/standings") },
|
|
160
134
|
{ label: "Girls Standings", href: s("girls/standings") }
|
|
161
135
|
] : [{ label: "Standings", href: s("standings") }];
|
|
162
136
|
return [
|
|
163
|
-
{ label: `${
|
|
137
|
+
{ label: `${k(a)} Home`, href: s("") },
|
|
164
138
|
{ label: "Scores/Schedule", href: s("scores") },
|
|
165
139
|
{ label: "Playoff Brackets", href: s("brackets") },
|
|
166
140
|
...r,
|
|
167
141
|
{ label: "Polls & Rankings", href: s("rankings") }
|
|
168
142
|
];
|
|
169
143
|
}
|
|
170
|
-
function
|
|
171
|
-
const t =
|
|
144
|
+
function Ae(a, e = pe()) {
|
|
145
|
+
const t = I(e);
|
|
172
146
|
for (const s of a.querySelectorAll(':scope > a[slot="nav"]'))
|
|
173
|
-
t &&
|
|
147
|
+
t && I(s.getAttribute("href")) === t ? s.setAttribute("aria-current", "page") : s.removeAttribute("aria-current");
|
|
174
148
|
}
|
|
175
|
-
class
|
|
149
|
+
class $ extends le {
|
|
176
150
|
static properties = {
|
|
177
151
|
api: { type: String },
|
|
178
152
|
refreshInterval: { type: Number, attribute: "refresh-interval" },
|
|
@@ -191,7 +165,7 @@ class y extends ie {
|
|
|
191
165
|
this._client = e, this.isConnected && this.load();
|
|
192
166
|
}
|
|
193
167
|
get client() {
|
|
194
|
-
return this._client ? this._client : this.api ?
|
|
168
|
+
return this._client ? this._client : this.api ? ke({ baseUrl: this.api }) : null;
|
|
195
169
|
}
|
|
196
170
|
connectedCallback() {
|
|
197
171
|
super.connectedCallback(), this._setupInterval();
|
|
@@ -203,7 +177,7 @@ class y extends ie {
|
|
|
203
177
|
this.load();
|
|
204
178
|
}
|
|
205
179
|
updated(e) {
|
|
206
|
-
e.has("api") && e.get("api") !== void 0 && e.get("api") !== this.api && this.load(), e.has("refreshInterval") && this._setupInterval(),
|
|
180
|
+
e.has("api") && e.get("api") !== void 0 && e.get("api") !== this.api && this.load(), e.has("refreshInterval") && this._setupInterval(), Ae(this);
|
|
207
181
|
}
|
|
208
182
|
async load() {
|
|
209
183
|
const e = this.client;
|
|
@@ -238,7 +212,7 @@ class y extends ie {
|
|
|
238
212
|
return n``;
|
|
239
213
|
}
|
|
240
214
|
}
|
|
241
|
-
const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])),
|
|
215
|
+
const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), _e = w`
|
|
242
216
|
:host {
|
|
243
217
|
--hsot-red: var(--color-red, #D1232A);
|
|
244
218
|
--hsot-red-deep: var(--color-red-dark, #951C21);
|
|
@@ -276,7 +250,7 @@ const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ze = $`
|
|
|
276
250
|
outline-offset: 1px;
|
|
277
251
|
}
|
|
278
252
|
.mut { color: var(--hsot-gray-5); }
|
|
279
|
-
`,
|
|
253
|
+
`, Ne = w`
|
|
280
254
|
.band { background: var(--hsot-white); color: var(--hsot-black); }
|
|
281
255
|
.band .inner { max-width: 1366px; margin: 0 auto; padding: 1.1rem 1.25rem 0; }
|
|
282
256
|
.band h1, .band h2.bandtitle {
|
|
@@ -325,7 +299,7 @@ const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ze = $`
|
|
|
325
299
|
@media (max-width: 720px) {
|
|
326
300
|
.band h1, .band h2.bandtitle, .band.section h1, .band.section h2.bandtitle { font-size: 1.8rem; }
|
|
327
301
|
}
|
|
328
|
-
`,
|
|
302
|
+
`, Re = w`
|
|
329
303
|
.view { max-width: 1366px; margin: 0 auto; padding: 1.25rem; box-sizing: border-box; }
|
|
330
304
|
/* Optional right rail (slot="rail" light-DOM children): a divided 300px
|
|
331
305
|
column on desktop, stacked under the view content on smaller screens. */
|
|
@@ -389,7 +363,7 @@ const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ze = $`
|
|
|
389
363
|
.error { padding: 1.2rem 1rem; color: var(--hsot-red-deep); font-size: 0.9rem; }
|
|
390
364
|
.note { font-size: 0.8125rem; color: var(--hsot-gray-5); margin: 0.6rem 0 0; }
|
|
391
365
|
.loading { padding: 1.2rem; color: var(--hsot-gray-5); font-family: var(--hsot-heading-font); }
|
|
392
|
-
`,
|
|
366
|
+
`, Ge = w`
|
|
393
367
|
.pill {
|
|
394
368
|
display: inline-block; font-family: var(--hsot-heading-font); font-weight: 700;
|
|
395
369
|
font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.04em;
|
|
@@ -404,7 +378,7 @@ const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ze = $`
|
|
|
404
378
|
.pill.champ { background: var(--hsot-straw); color: #6b5900; }
|
|
405
379
|
@keyframes hsot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
|
|
406
380
|
@media (prefers-reduced-motion: reduce) { .pill.live { animation: none; } }
|
|
407
|
-
`,
|
|
381
|
+
`, Me = w`
|
|
408
382
|
.tablewrap { overflow-x: auto; }
|
|
409
383
|
table.data { font-family: var(--hsot-heading-font); font-size: 14px; border-collapse: collapse; width: 100%; }
|
|
410
384
|
table.data th {
|
|
@@ -422,7 +396,7 @@ const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ze = $`
|
|
|
422
396
|
table.data tbody tr.rowlink:hover { background: var(--hsot-gray-1); }
|
|
423
397
|
table.data td.teamcell a { color: inherit; text-decoration: none; font-weight: 500; }
|
|
424
398
|
table.data td.teamcell a:hover { text-decoration: underline; }
|
|
425
|
-
`,
|
|
399
|
+
`, Le = w`
|
|
426
400
|
.swatch {
|
|
427
401
|
display: inline-flex; align-items: center; justify-content: center;
|
|
428
402
|
width: 26px; height: 26px; border-radius: 50%;
|
|
@@ -446,7 +420,7 @@ const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ze = $`
|
|
|
446
420
|
.dot.W { background: var(--hsot-win); }
|
|
447
421
|
.dot.L { background: var(--hsot-loss); }
|
|
448
422
|
.dot.T { background: var(--hsot-tie); }
|
|
449
|
-
`,
|
|
423
|
+
`, Oe = w`
|
|
450
424
|
ul.gamelist { list-style: none; margin: 0; padding: 0; }
|
|
451
425
|
.gamelist li {
|
|
452
426
|
display: flex; align-items: center; gap: 0.7rem; padding: 0.55rem 1rem;
|
|
@@ -496,183 +470,183 @@ const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ze = $`
|
|
|
496
470
|
.gamelist .ff { color: var(--hsot-gray-5); font-size: 0.78rem; font-style: italic; }
|
|
497
471
|
.gamelist .where { color: var(--hsot-gray-5); font-size: 0.78rem; }
|
|
498
472
|
.gamelist a.box { font-size: 0.78rem; }
|
|
499
|
-
`, P = [
|
|
500
|
-
function
|
|
473
|
+
`, P = [_e, Ne, Re, Ge, Me, Le, Oe];
|
|
474
|
+
function H(a) {
|
|
501
475
|
return a.state !== "final" ? null : a.forfeit === "home" ? "away" : a.forfeit === "away" || a.homeScore > a.awayScore ? "home" : a.awayScore > a.homeScore ? "away" : a.tiebreakWinner && a.tiebreakWinner !== "none" ? a.tiebreakWinner : "tie";
|
|
502
476
|
}
|
|
503
|
-
function
|
|
477
|
+
function He(a) {
|
|
504
478
|
return a && (a.forfeit === "home" || a.forfeit === "away") ? a.forfeit : null;
|
|
505
479
|
}
|
|
506
|
-
function
|
|
507
|
-
const t = {}, s = (
|
|
508
|
-
for (const
|
|
509
|
-
const
|
|
480
|
+
function N(a, e) {
|
|
481
|
+
const t = {}, s = (o) => (t[o] = t[o] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, t[o]), r = a.filter((o) => o.state === "final" && o.gameType !== "scrimmage" && (!e || o.date <= e)).sort((o, i) => String(o.date).localeCompare(String(i.date)));
|
|
482
|
+
for (const o of r) {
|
|
483
|
+
const i = H(o), d = o.gameType === "conference";
|
|
510
484
|
for (const h of ["home", "away"]) {
|
|
511
|
-
const
|
|
512
|
-
if (!
|
|
513
|
-
const
|
|
514
|
-
|
|
485
|
+
const l = h === "home" ? o.homeTeamId : o.awayTeamId;
|
|
486
|
+
if (!l) continue;
|
|
487
|
+
const c = s(l), m = h === "home" ? o.homeScore : o.awayScore, f = h === "home" ? o.awayScore : o.homeScore;
|
|
488
|
+
c.pf += m, c.pa += f;
|
|
515
489
|
let u = "T";
|
|
516
|
-
|
|
490
|
+
i === "tie" ? (c.t += 1, d && (c.ct += 1)) : i === h ? (c.w += 1, d && (c.cw += 1), u = "W") : (c.l += 1, d && (c.cl += 1), u = "L"), c.results.push({ gameId: o.id, date: o.date, mark: u, my: m, their: f, opp: h === "home" ? o.awayTeamId : o.homeTeamId, conf: d });
|
|
517
491
|
}
|
|
518
492
|
}
|
|
519
493
|
return t;
|
|
520
494
|
}
|
|
521
|
-
function
|
|
495
|
+
function U(a) {
|
|
522
496
|
if (!a || !a.length) return "";
|
|
523
497
|
const e = a[a.length - 1].mark;
|
|
524
498
|
let t = 0;
|
|
525
499
|
for (let s = a.length - 1; s >= 0 && a[s].mark === e; s -= 1) t += 1;
|
|
526
500
|
return e + t;
|
|
527
501
|
}
|
|
528
|
-
const
|
|
502
|
+
const se = (a, e, t) => {
|
|
529
503
|
const s = a + e + t;
|
|
530
504
|
return s ? (a + t / 2) / s : 0;
|
|
531
|
-
},
|
|
532
|
-
function
|
|
505
|
+
}, ae = (a) => a.toFixed(3).replace("0.", ".");
|
|
506
|
+
function S(a, e = !1) {
|
|
533
507
|
if (!a) return "0-0";
|
|
534
|
-
const t = e ? a.cw : a.w, s = e ? a.cl : a.l,
|
|
535
|
-
return `${t}-${s}${
|
|
508
|
+
const t = e ? a.cw : a.w, s = e ? a.cl : a.l, r = e ? a.ct : a.t;
|
|
509
|
+
return `${t}-${s}${r ? `-${r}` : ""}`;
|
|
536
510
|
}
|
|
537
|
-
function
|
|
511
|
+
function fe(a, e) {
|
|
538
512
|
return a.map((t) => {
|
|
539
513
|
const s = e[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] };
|
|
540
|
-
return { team: t, rec: s, confPct:
|
|
514
|
+
return { team: t, rec: s, confPct: se(s.cw, s.cl, s.ct), overallPct: se(s.w, s.l, s.t) };
|
|
541
515
|
}).sort((t, s) => s.confPct - t.confPct || s.overallPct - t.overallPct || s.rec.pf - s.rec.pa - (t.rec.pf - t.rec.pa));
|
|
542
516
|
}
|
|
543
|
-
function
|
|
517
|
+
function K(a, e) {
|
|
544
518
|
return a.filter((t) => (t.homeTeamId === e || t.awayTeamId === e) && (t.state === "scheduled" || t.state === "live") && t.gameType !== "scrimmage").sort((t, s) => String(t.date).localeCompare(String(s.date)))[0] || null;
|
|
545
519
|
}
|
|
546
|
-
function
|
|
520
|
+
function re(a, e) {
|
|
547
521
|
const t = a[e];
|
|
548
522
|
return t && t.results.length ? t.results[t.results.length - 1] : null;
|
|
549
523
|
}
|
|
550
|
-
function
|
|
551
|
-
let
|
|
552
|
-
for (const
|
|
553
|
-
|
|
554
|
-
return
|
|
524
|
+
function It(a, e, t, s = "") {
|
|
525
|
+
let r = null;
|
|
526
|
+
for (const o of a || [])
|
|
527
|
+
o.sport === e && (t && o.effectiveDate > t || s && o.gender && o.gender !== s || (!r || o.effectiveDate > r.effectiveDate) && (r = o));
|
|
528
|
+
return r;
|
|
555
529
|
}
|
|
556
|
-
function Q(a, e, t, s,
|
|
557
|
-
const
|
|
558
|
-
if (!
|
|
559
|
-
const
|
|
530
|
+
function Q(a, e, t, s, r) {
|
|
531
|
+
const o = e[t];
|
|
532
|
+
if (!o) return null;
|
|
533
|
+
const i = /* @__PURE__ */ new Map();
|
|
560
534
|
for (const h of a || []) {
|
|
561
|
-
if (h.sport !== s ||
|
|
562
|
-
const
|
|
563
|
-
(!
|
|
535
|
+
if (h.sport !== s || r && h.effectiveDate > r || h.gender && o.gender !== h.gender && o.gender !== "coed") continue;
|
|
536
|
+
const l = h.gender || "", c = i.get(l);
|
|
537
|
+
(!c || h.effectiveDate > c.effectiveDate) && i.set(l, h);
|
|
564
538
|
}
|
|
565
|
-
let
|
|
566
|
-
for (const h of
|
|
567
|
-
const
|
|
568
|
-
|
|
539
|
+
let d = null;
|
|
540
|
+
for (const h of i.values()) {
|
|
541
|
+
const l = (h.teamIds || []).indexOf(t);
|
|
542
|
+
l !== -1 && (!d || h.effectiveDate > d.effectiveDate) && (d = { poll: h, rank: l + 1 });
|
|
569
543
|
}
|
|
570
|
-
return
|
|
544
|
+
return d ? d.rank : null;
|
|
571
545
|
}
|
|
572
|
-
function
|
|
546
|
+
function Ue(a, e, t) {
|
|
573
547
|
if (!a) return { kind: "none", delta: 0 };
|
|
574
548
|
const s = (a.teamIds || []).indexOf(t) + 1;
|
|
575
549
|
if (!s) return { kind: "none", delta: 0 };
|
|
576
550
|
if (!e) return { kind: "same", delta: 0 };
|
|
577
|
-
const
|
|
578
|
-
if (!
|
|
579
|
-
const
|
|
580
|
-
return
|
|
551
|
+
const r = (e.teamIds || []).indexOf(t) + 1;
|
|
552
|
+
if (!r) return { kind: "new", delta: 0 };
|
|
553
|
+
const o = r - s;
|
|
554
|
+
return o > 0 ? { kind: "up", delta: o } : o < 0 ? { kind: "down", delta: -o } : { kind: "same", delta: 0 };
|
|
581
555
|
}
|
|
582
|
-
function
|
|
556
|
+
function je(a) {
|
|
583
557
|
return /^https?:\/\//i.test(String(a || ""));
|
|
584
558
|
}
|
|
585
|
-
function
|
|
586
|
-
if (!
|
|
559
|
+
function ue(a, { w: e, h: t } = {}) {
|
|
560
|
+
if (!je(a)) return "";
|
|
587
561
|
const s = [];
|
|
588
562
|
e && s.push(`w=${Math.max(1, Math.round(e))}`), t && s.push(`h=${Math.max(1, Math.round(t))}`), s.push("f=webp");
|
|
589
|
-
const
|
|
590
|
-
return `${a}${
|
|
563
|
+
const r = a.includes("?") ? "&" : "?";
|
|
564
|
+
return `${a}${r}${s.join("&")}`;
|
|
591
565
|
}
|
|
592
566
|
function M(a, e) {
|
|
593
567
|
const t = e * 2;
|
|
594
|
-
return
|
|
568
|
+
return ue(a?.logoAssetId, { w: t, h: t });
|
|
595
569
|
}
|
|
596
|
-
function
|
|
597
|
-
return
|
|
570
|
+
function qe(a, e) {
|
|
571
|
+
return ue(a?.photoAssetId, { w: e * 2 });
|
|
598
572
|
}
|
|
599
|
-
function
|
|
600
|
-
const
|
|
573
|
+
function j(a, e, { title: t, sub: s, teams: r }) {
|
|
574
|
+
const o = pe(), d = !!a.querySelector(':scope > a[slot="nav"]') || Pe(o, e.hrefs, e.sport) !== null;
|
|
601
575
|
return n`
|
|
602
576
|
<div class="band section">
|
|
603
577
|
<div class="inner">
|
|
604
578
|
<h1>${t}</h1>
|
|
605
579
|
${s ? n`<p class="sub">${s}</p>` : p}
|
|
606
580
|
</div>
|
|
607
|
-
${
|
|
608
|
-
<nav class="sectionnav" aria-label="${
|
|
581
|
+
${d ? n`
|
|
582
|
+
<nav class="sectionnav" aria-label="${k(e.sport)} section">
|
|
609
583
|
<div class="navrow">
|
|
610
584
|
<slot name="nav">
|
|
611
|
-
${
|
|
612
|
-
aria-current=${
|
|
585
|
+
${Ee(e.sport, r, e.hrefs).map((h) => n`<a href=${h.href}
|
|
586
|
+
aria-current=${o && I(h.href) === o ? "page" : p}>${h.label}</a>`)}
|
|
613
587
|
</slot>
|
|
614
588
|
</div>
|
|
615
589
|
</nav>` : p}
|
|
616
590
|
</div>
|
|
617
591
|
`;
|
|
618
592
|
}
|
|
619
|
-
const
|
|
593
|
+
const T = (a, e) => {
|
|
620
594
|
const t = a.teamsById[e];
|
|
621
595
|
return t ? a.schoolsById[t.schoolId] : null;
|
|
622
|
-
}, F = (a, e) =>
|
|
623
|
-
function
|
|
596
|
+
}, F = (a, e) => T(a, e)?.name || "TBD", L = (a, e) => T(a, e)?.abbr || "TBD";
|
|
597
|
+
function C(a, e = 26) {
|
|
624
598
|
if (!a) return p;
|
|
625
599
|
const t = M(a, e);
|
|
626
600
|
if (t)
|
|
627
601
|
return n`<img class="swatch logo" aria-hidden="true" alt="" loading="lazy"
|
|
628
602
|
src=${t} style="width:${e}px;height:${e}px" />`;
|
|
629
|
-
const s = a.colorPrimary || "#030711",
|
|
603
|
+
const s = a.colorPrimary || "#030711", r = G(s);
|
|
630
604
|
return n`<span class="swatch" aria-hidden="true"
|
|
631
|
-
style="width:${e}px;height:${e}px;background:${s};color:${
|
|
632
|
-
>${
|
|
605
|
+
style="width:${e}px;height:${e}px;background:${s};color:${r};font-size:${Math.max(8, e * 0.28)}px"
|
|
606
|
+
>${Y(a)}</span>`;
|
|
633
607
|
}
|
|
634
|
-
function
|
|
608
|
+
function X(a, e, t) {
|
|
635
609
|
const s = Q(a.rankings, a.teamsById, e, a.sport, t);
|
|
636
610
|
return s ? n`<span class="rankbadge">#${s}</span>` : p;
|
|
637
611
|
}
|
|
638
|
-
function
|
|
639
|
-
const s =
|
|
640
|
-
return s ? n`${
|
|
612
|
+
function O(a, e, t) {
|
|
613
|
+
const s = T(a, e);
|
|
614
|
+
return s ? n`${X(a, e, t)}<a href=${g(a.hrefs.school, { id: s.id })}>${s.name}</a>` : n`<span class="mut">TBD</span>`;
|
|
641
615
|
}
|
|
642
|
-
function
|
|
616
|
+
function Z(a, e, t = 5) {
|
|
643
617
|
const s = a.records[e];
|
|
644
618
|
if (!s || !s.results.length) return n`<span class="mut">·</span>`;
|
|
645
|
-
const
|
|
646
|
-
return n`<span class="dots" role="img" aria-label="last ${
|
|
647
|
-
${
|
|
648
|
-
title="${
|
|
649
|
-
href=${g(a.hrefs.game, { sport: a.sport, id:
|
|
619
|
+
const r = s.results.slice(-1 * t);
|
|
620
|
+
return n`<span class="dots" role="img" aria-label="last ${r.length} results">
|
|
621
|
+
${r.map((o) => n`<a class="dot ${o.mark}"
|
|
622
|
+
title="${o.mark} ${o.my}-${o.their} vs ${F(a, o.opp)}"
|
|
623
|
+
href=${g(a.hrefs.game, { sport: a.sport, id: o.gameId })}>${o.mark}</a>`)}
|
|
650
624
|
</span>`;
|
|
651
625
|
}
|
|
652
|
-
function
|
|
626
|
+
function D(a, e) {
|
|
653
627
|
return a.querySelector(':scope > [slot="rail"]') ? n`<div class="view withrail">
|
|
654
628
|
<div class="viewmain">${e}</div>
|
|
655
629
|
<aside class="viewrail"><slot name="rail"></slot></aside>
|
|
656
630
|
</div>` : n`<div class="view">${e}</div>`;
|
|
657
631
|
}
|
|
658
|
-
function
|
|
632
|
+
function B(a) {
|
|
659
633
|
if (!a.promoImage) return p;
|
|
660
634
|
const e = n`<img src=${a.promoImage} alt=${a.promoAlt || "Sponsor"}>`;
|
|
661
635
|
return n`<div class="promo">${a.promoHref ? n`<a href=${a.promoHref} target="_blank" rel="sponsored noopener">${e}</a>` : e}</div>`;
|
|
662
636
|
}
|
|
663
637
|
function A(a) {
|
|
664
|
-
const e =
|
|
638
|
+
const e = de(a);
|
|
665
639
|
return n`<span class="pill ${e.kind}">${e.label}</span>`;
|
|
666
640
|
}
|
|
667
|
-
function
|
|
641
|
+
function ge(a, e, t) {
|
|
668
642
|
if (!e) return n`<span class="mut">·</span>`;
|
|
669
|
-
const s = e.homeTeamId === t ? e.awayTeamId : e.homeTeamId,
|
|
670
|
-
return n`${e.state === "live" ? n`<span class="pill live">Live</span> ` : n`${
|
|
643
|
+
const s = e.homeTeamId === t ? e.awayTeamId : e.homeTeamId, r = e.homeTeamId === t ? "vs" : "at";
|
|
644
|
+
return n`${e.state === "live" ? n`<span class="pill live">Live</span> ` : n`${x(e.date, { month: "numeric", day: "numeric" })} `}${r} ${L(a, s)}`;
|
|
671
645
|
}
|
|
672
|
-
class
|
|
646
|
+
class We extends $ {
|
|
673
647
|
static styles = P;
|
|
674
648
|
static properties = {
|
|
675
|
-
|
|
649
|
+
...$.properties,
|
|
676
650
|
sport: { type: String },
|
|
677
651
|
season: { type: String },
|
|
678
652
|
date: { type: String }
|
|
@@ -688,57 +662,57 @@ class He extends y {
|
|
|
688
662
|
this._datePinned = !!this.date;
|
|
689
663
|
}
|
|
690
664
|
async fetchData(e) {
|
|
691
|
-
const t = this.season ||
|
|
665
|
+
const t = this.season || _(), [s, r, o, i, d] = await Promise.all([
|
|
692
666
|
e.listSchools(),
|
|
693
667
|
e.listTeams({ sport: this.sport }),
|
|
694
668
|
e.listConferences(),
|
|
695
669
|
e.listGames({ sport: this.sport, season: t }),
|
|
696
670
|
e.listRankings({ sport: this.sport })
|
|
697
671
|
]);
|
|
698
|
-
return this._datePinned || (this.date =
|
|
672
|
+
return this._datePinned || (this.date = Te(i.items.map((h) => h.date)), this._datePinned = !0), {
|
|
699
673
|
season: t,
|
|
700
674
|
schools: s.items,
|
|
701
|
-
teams:
|
|
702
|
-
conferences:
|
|
703
|
-
games:
|
|
704
|
-
rankings:
|
|
675
|
+
teams: r.items,
|
|
676
|
+
conferences: o.items,
|
|
677
|
+
games: i.items,
|
|
678
|
+
rankings: d.items
|
|
705
679
|
};
|
|
706
680
|
}
|
|
707
681
|
get ctx() {
|
|
708
682
|
return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
|
|
709
683
|
teamsById: b(this.data.teams),
|
|
710
684
|
schoolsById: b(this.data.schools),
|
|
711
|
-
records:
|
|
685
|
+
records: N(this.data.games),
|
|
712
686
|
rankings: this.data.rankings,
|
|
713
687
|
hrefs: z(this),
|
|
714
688
|
sport: this.sport
|
|
715
689
|
}, this._ctxData = this.data), this._ctx;
|
|
716
690
|
}
|
|
717
691
|
renderView() {
|
|
718
|
-
const e = this.ctx, t = b(this.data.conferences), s = [...new Set(this.data.games.map((
|
|
719
|
-
const
|
|
720
|
-
return
|
|
721
|
-
},
|
|
722
|
-
|
|
692
|
+
const e = this.ctx, t = b(this.data.conferences), s = [...new Set(this.data.games.map((l) => l.date).filter(Boolean))].sort(), r = Number.MAX_SAFE_INTEGER, o = (l) => {
|
|
693
|
+
const c = [l.awayTeamId, l.homeTeamId].map((m) => Q(e.rankings, e.teamsById, m, this.sport, l.date)).filter(Boolean);
|
|
694
|
+
return c.length ? Math.min(...c) : r;
|
|
695
|
+
}, i = this.data.games.filter((l) => l.date === this.date), d = new Map(i.map((l) => [l, o(l)]));
|
|
696
|
+
i.sort((l, c) => (l.state === "live" ? 0 : 1) - (c.state === "live" ? 0 : 1) || d.get(l) - d.get(c));
|
|
723
697
|
const h = /* @__PURE__ */ new Map();
|
|
724
|
-
return
|
|
725
|
-
const
|
|
726
|
-
h.has(
|
|
698
|
+
return i.forEach((l) => {
|
|
699
|
+
const c = l.gameType === "conference" && l.conferenceId ? t[l.conferenceId]?.name || "Conference" : l.gameType === "playoff" ? "Playoffs" : l.gameType === "scrimmage" ? "Scrimmages" : "Nonconference";
|
|
700
|
+
h.has(c) || h.set(c, []), h.get(c).push(l);
|
|
727
701
|
}), n`
|
|
728
|
-
${
|
|
729
|
-
title: n`${
|
|
730
|
-
sub: n`${
|
|
702
|
+
${j(this, e, {
|
|
703
|
+
title: n`${k(this.sport)} scores & schedules`,
|
|
704
|
+
sub: n`${x(this.date, { weekday: "long", month: "long", day: "numeric", year: "numeric" })} · ${i.length} games`,
|
|
731
705
|
teams: this.data.teams
|
|
732
706
|
})}
|
|
733
|
-
${
|
|
734
|
-
${
|
|
707
|
+
${D(this, n`
|
|
708
|
+
${B(this)}
|
|
735
709
|
<div class="toolbar">
|
|
736
710
|
<label class="asof" for="datesel">Date</label>
|
|
737
|
-
<select id="datesel" @change=${(
|
|
738
|
-
this.date =
|
|
711
|
+
<select id="datesel" @change=${(l) => {
|
|
712
|
+
this.date = l.target.value;
|
|
739
713
|
}}>
|
|
740
|
-
${(s.includes(this.date) ? s : [...s, this.date].sort()).map((
|
|
741
|
-
${
|
|
714
|
+
${(s.includes(this.date) ? s : [...s, this.date].sort()).map((l) => n`<option value=${l} ?selected=${l === this.date}>
|
|
715
|
+
${x(l, { weekday: "short", month: "short", day: "numeric" })}${l === V() ? " · today" : ""}
|
|
742
716
|
</option>`)}
|
|
743
717
|
</select>
|
|
744
718
|
<button class="chip" ?disabled=${s.indexOf(this.date) <= 0}
|
|
@@ -750,13 +724,13 @@ class He extends y {
|
|
|
750
724
|
this.date = s[s.indexOf(this.date) + 1];
|
|
751
725
|
}}>Next →</button>
|
|
752
726
|
<span class="spacer"></span>
|
|
753
|
-
<span class="asof">Live games first · report a score to see it update here</span>
|
|
727
|
+
<span class="asof">Live games first · <a href=${ce(e.hrefs)}>report a score</a> to see it update here</span>
|
|
754
728
|
</div>
|
|
755
|
-
${
|
|
756
|
-
${[...h.entries()].map(([
|
|
757
|
-
<div class="section-title">${
|
|
729
|
+
${i.length ? p : n`<p class="empty">No ${this.sport} games on this date.</p>`}
|
|
730
|
+
${[...h.entries()].map(([l, c]) => n`
|
|
731
|
+
<div class="section-title">${l}</div>
|
|
758
732
|
<div class="card"><ul class="gamelist">
|
|
759
|
-
${
|
|
733
|
+
${c.map((m) => this.renderGame(e, m))}
|
|
760
734
|
</ul></div>
|
|
761
735
|
`)}
|
|
762
736
|
`)}
|
|
@@ -766,12 +740,12 @@ class He extends y {
|
|
|
766
740
|
// a lone score column on the far right read as detached from the teams).
|
|
767
741
|
// Scheduled games carry their start time on the status pill alone.
|
|
768
742
|
renderGame(e, t) {
|
|
769
|
-
const s = t.state === "final" || t.state === "live",
|
|
743
|
+
const s = t.state === "final" || t.state === "live", r = (i, d, h = p) => n`<span class="side">${O(e, i, t.date)}${s ? n`<span class="score">${d}</span>` : p}${h}</span>`, o = He(t);
|
|
770
744
|
return n`
|
|
771
745
|
<li>
|
|
772
746
|
${A(t)}
|
|
773
|
-
<span class="opp matchup">${
|
|
774
|
-
${
|
|
747
|
+
<span class="opp matchup">${r(t.awayTeamId, t.awayScore, n`<span class="at">at</span>`)}${r(t.homeTeamId, t.homeScore)}</span>
|
|
748
|
+
${o ? n`<span class="ff">${F(e, o === "home" ? t.homeTeamId : t.awayTeamId)} forfeited</span>` : p}
|
|
775
749
|
<span class="where">${t.venue || ""}</span>
|
|
776
750
|
${t.broadcast ? n`<span class="pill class">${t.broadcast}</span>` : p}
|
|
777
751
|
<a class="box" href=${g(e.hrefs.game, { sport: this.sport, id: t.id })}>Box score →</a>
|
|
@@ -779,84 +753,116 @@ class He extends y {
|
|
|
779
753
|
`;
|
|
780
754
|
}
|
|
781
755
|
}
|
|
782
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-scores") && globalThis.customElements.define("hsot-scores",
|
|
783
|
-
class
|
|
756
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-scores") && globalThis.customElements.define("hsot-scores", We);
|
|
757
|
+
class Ve extends $ {
|
|
784
758
|
static styles = P;
|
|
785
759
|
static properties = {
|
|
786
|
-
|
|
760
|
+
...$.properties,
|
|
787
761
|
sport: { type: String },
|
|
762
|
+
gender: { type: String },
|
|
788
763
|
season: { type: String },
|
|
789
764
|
classFilter: { state: !0 },
|
|
790
|
-
query: { state: !0 }
|
|
765
|
+
query: { state: !0 },
|
|
766
|
+
pickedGender: { state: !0 }
|
|
791
767
|
};
|
|
792
768
|
constructor() {
|
|
793
|
-
super(), this.sport = "football", this.season = "", this.classFilter = "All", this.query = "";
|
|
769
|
+
super(), this.sport = "football", this.gender = "", this.season = "", this.classFilter = "All", this.query = "", this.pickedGender = "";
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* The side the table shows: the pinned `gender`, else the reader's pick,
|
|
773
|
+
* else the first side fielded. '' only for a sport with one side, where
|
|
774
|
+
* there is nothing to scope.
|
|
775
|
+
*/
|
|
776
|
+
get viewGender() {
|
|
777
|
+
if (this.gender) return this.gender;
|
|
778
|
+
const e = q(this.data?.teams);
|
|
779
|
+
return e.length < 2 ? "" : e.includes(this.pickedGender) ? this.pickedGender : e[0];
|
|
794
780
|
}
|
|
795
781
|
async fetchData(e) {
|
|
796
|
-
const t = this.season ||
|
|
782
|
+
const t = this.season || _(), [s, r, o, i, d] = await Promise.all([
|
|
797
783
|
e.listConferences({ active: !0 }),
|
|
798
784
|
e.listSchools(),
|
|
785
|
+
// Deliberately NOT gender-filtered: the sub-nav decides whether to
|
|
786
|
+
// offer Boys/Girls standings from the sides the sport fields, so it
|
|
787
|
+
// needs the whole sport. The table filters below.
|
|
799
788
|
e.listTeams({ sport: this.sport }),
|
|
789
|
+
// Games carry no gender (it lives on the team they are played by),
|
|
790
|
+
// so this stays the sport's season. Records key off team ids, and a
|
|
791
|
+
// team only appears in its own side's games.
|
|
800
792
|
e.listGames({ sport: this.sport, season: t }),
|
|
801
|
-
e.listRankings({ sport: this.sport })
|
|
793
|
+
e.listRankings({ sport: this.sport, ...this.gender ? { gender: this.gender } : {} })
|
|
802
794
|
]);
|
|
803
795
|
return {
|
|
804
796
|
season: t,
|
|
805
797
|
conferences: s.items,
|
|
806
|
-
schools:
|
|
807
|
-
teams:
|
|
808
|
-
games:
|
|
809
|
-
rankings:
|
|
798
|
+
schools: r.items,
|
|
799
|
+
teams: o.items,
|
|
800
|
+
games: i.items,
|
|
801
|
+
rankings: d.items
|
|
810
802
|
};
|
|
811
803
|
}
|
|
812
804
|
get ctx() {
|
|
813
|
-
return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
|
|
805
|
+
return (!this._ctx || this._ctxData !== this.data || this._ctxGender !== this.viewGender) && (this._ctx = {
|
|
814
806
|
teamsById: b(this.data.teams),
|
|
815
807
|
schoolsById: b(this.data.schools),
|
|
816
|
-
records:
|
|
808
|
+
records: N(this.data.games),
|
|
817
809
|
rankings: this.data.rankings,
|
|
818
810
|
hrefs: z(this),
|
|
819
|
-
sport: this.sport
|
|
820
|
-
|
|
811
|
+
sport: this.sport,
|
|
812
|
+
// The teams this view stands for — one side of a gendered
|
|
813
|
+
// sport, or all of them when the sport fields only one.
|
|
814
|
+
teams: me(this.data.teams, this.viewGender)
|
|
815
|
+
}, this._ctxData = this.data, this._ctxGender = this.viewGender), this._ctx;
|
|
821
816
|
}
|
|
822
817
|
renderView() {
|
|
823
|
-
const e = this.ctx, t = ["All", ...[...new Set(this.data.conferences.flatMap((
|
|
818
|
+
const e = this.ctx, t = this.viewGender, s = this.gender ? [] : q(this.data.teams), r = ["All", ...[...new Set(this.data.conferences.flatMap((i) => i.classifications || []))].sort(te)].slice(0, 9), o = this.data.conferences.filter((i) => i.active !== !1).filter((i) => this.classFilter === "All" || (i.classifications || []).includes(this.classFilter)).sort(De);
|
|
824
819
|
return n`
|
|
825
|
-
${
|
|
826
|
-
title: n`${
|
|
820
|
+
${j(this, e, {
|
|
821
|
+
title: n`${t ? `${k(t)} ` : ""}${k(this.sport)} standings`,
|
|
827
822
|
sub: n`${this.data.season} season · every conference, computed live from reported results`,
|
|
823
|
+
// The WHOLE sport, not this view's side: the sub-nav offers the
|
|
824
|
+
// Boys/Girls split only when both are fielded, and a
|
|
825
|
+
// gender-scoped list would always look like one side.
|
|
828
826
|
teams: this.data.teams
|
|
829
827
|
})}
|
|
830
|
-
${
|
|
831
|
-
${
|
|
828
|
+
${D(this, n`
|
|
829
|
+
${B(this)}
|
|
832
830
|
<div class="toolbar">
|
|
831
|
+
${s.length === 2 ? n`
|
|
832
|
+
<div role="group" aria-label="Boys or girls standings">
|
|
833
|
+
${s.map((i) => n`<button class="chip ${t === i ? "on" : ""}"
|
|
834
|
+
aria-pressed=${t === i ? "true" : "false"}
|
|
835
|
+
@click=${() => {
|
|
836
|
+
this.pickedGender = i;
|
|
837
|
+
}}>${k(i)}</button>`)}
|
|
838
|
+
</div>` : p}
|
|
833
839
|
<div role="group" aria-label="Classification filter">
|
|
834
|
-
${
|
|
840
|
+
${r.map((i) => n`<button class="chip ${this.classFilter === i ? "on" : ""}"
|
|
835
841
|
@click=${() => {
|
|
836
|
-
this.classFilter =
|
|
837
|
-
}}>${
|
|
842
|
+
this.classFilter = i;
|
|
843
|
+
}}>${i}</button>`)}
|
|
838
844
|
</div>
|
|
839
845
|
<input type="search" placeholder="Find a school…" aria-label="Find a school"
|
|
840
|
-
.value=${this.query} @input=${(
|
|
841
|
-
this.query =
|
|
846
|
+
.value=${this.query} @input=${(i) => {
|
|
847
|
+
this.query = i.target.value;
|
|
842
848
|
}}>
|
|
843
849
|
<span class="spacer"></span>
|
|
844
|
-
<span class="asof">Records through ${
|
|
850
|
+
<span class="asof">Records through ${x(V(), { month: "long", day: "numeric" })} · conference games count toward both records · scrimmages toward neither</span>
|
|
845
851
|
</div>
|
|
846
|
-
${
|
|
852
|
+
${o.map((i) => this.renderConference(e, i))}
|
|
847
853
|
`)}
|
|
848
854
|
`;
|
|
849
855
|
}
|
|
850
856
|
renderConference(e, t) {
|
|
851
|
-
const s =
|
|
857
|
+
const s = e.teams.filter((i) => i.conferenceId === t.id);
|
|
852
858
|
if (!s.length) return p;
|
|
853
|
-
const
|
|
859
|
+
const r = this.query.trim().toLowerCase(), o = fe(s, e.records);
|
|
854
860
|
return n`
|
|
855
861
|
<div class="card">
|
|
856
862
|
<div class="card-head">
|
|
857
863
|
<h2>${t.name}</h2>
|
|
858
|
-
${[...t.classifications || []].sort(
|
|
859
|
-
<span class="meta">${
|
|
864
|
+
${[...t.classifications || []].sort(te).map((i) => n`<span class="pill class">${i}</span>`)}
|
|
865
|
+
<span class="meta">${o.length} teams · membership derives from teams</span>
|
|
860
866
|
</div>
|
|
861
867
|
<div class="tablewrap"><table class="data">
|
|
862
868
|
<thead><tr>
|
|
@@ -865,43 +871,43 @@ class Ue extends y {
|
|
|
865
871
|
<th>Streak</th><th>Last 5</th><th>Next</th>
|
|
866
872
|
</tr></thead>
|
|
867
873
|
<tbody>
|
|
868
|
-
${
|
|
874
|
+
${o.map((i, d) => this.renderRow(e, i, d, r))}
|
|
869
875
|
</tbody>
|
|
870
876
|
</table></div>
|
|
871
877
|
</div>
|
|
872
878
|
`;
|
|
873
879
|
}
|
|
874
|
-
renderRow(e, t, s,
|
|
875
|
-
const
|
|
876
|
-
if (
|
|
877
|
-
const
|
|
880
|
+
renderRow(e, t, s, r) {
|
|
881
|
+
const o = e.schoolsById[t.team.schoolId], i = o?.name || t.team.name || "TBD";
|
|
882
|
+
if (r && !i.toLowerCase().includes(r)) return p;
|
|
883
|
+
const d = t.rec.pf - t.rec.pa, h = K(this.data.games, t.team.id), l = () => {
|
|
878
884
|
location.href = g(e.hrefs.school, { id: t.team.schoolId });
|
|
879
885
|
};
|
|
880
886
|
return n`
|
|
881
|
-
<tr class="rowlink" @click=${(
|
|
882
|
-
|
|
887
|
+
<tr class="rowlink" @click=${(c) => {
|
|
888
|
+
c.target.closest("a") || l();
|
|
883
889
|
}}>
|
|
884
890
|
<td class="mut">${s + 1}</td>
|
|
885
891
|
<td class="teamcell">
|
|
886
|
-
${
|
|
887
|
-
<a href=${g(e.hrefs.school, { id: t.team.schoolId })}>${
|
|
892
|
+
${C(o)}${X(e, t.team.id, null)}
|
|
893
|
+
<a href=${g(e.hrefs.school, { id: t.team.schoolId })}>${i}</a>
|
|
888
894
|
</td>
|
|
889
|
-
<td class="num">${
|
|
890
|
-
<td class="num">${
|
|
891
|
-
<td class="num">${
|
|
892
|
-
<td class="num">${
|
|
895
|
+
<td class="num">${S(t.rec, !0)}</td>
|
|
896
|
+
<td class="num">${ae(t.confPct)}</td>
|
|
897
|
+
<td class="num">${S(t.rec)}</td>
|
|
898
|
+
<td class="num">${ae(t.overallPct)}</td>
|
|
893
899
|
<td class="num">${t.rec.pf}</td>
|
|
894
900
|
<td class="num">${t.rec.pa}</td>
|
|
895
|
-
<td class="num" style="color:${
|
|
896
|
-
<td>${
|
|
897
|
-
<td>${
|
|
898
|
-
<td>${
|
|
901
|
+
<td class="num" style="color:${d >= 0 ? "var(--hsot-win)" : "var(--hsot-loss)"}">${d > 0 ? "+" : ""}${d}</td>
|
|
902
|
+
<td>${U(t.rec.results) || "·"}</td>
|
|
903
|
+
<td>${Z(e, t.team.id)}</td>
|
|
904
|
+
<td>${ge(e, h, t.team.id)}</td>
|
|
899
905
|
</tr>
|
|
900
906
|
`;
|
|
901
907
|
}
|
|
902
908
|
}
|
|
903
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-standings") && globalThis.customElements.define("hsot-standings",
|
|
904
|
-
const
|
|
909
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-standings") && globalThis.customElements.define("hsot-standings", Ve);
|
|
910
|
+
const Ye = w`
|
|
905
911
|
.hero1 {
|
|
906
912
|
border-radius: var(--hsot-radius-md); color: var(--hsot-white);
|
|
907
913
|
padding: 1.3rem 1.4rem; display: flex; align-items: center; gap: 1.2rem;
|
|
@@ -918,10 +924,10 @@ const je = $`
|
|
|
918
924
|
.delta.new { background: var(--hsot-straw); color: #6b5900; border-radius: var(--hsot-radius-xs); padding: 0.1rem 0.3rem; font-size: 0.7rem; }
|
|
919
925
|
.sparkline { vertical-align: middle; }
|
|
920
926
|
`;
|
|
921
|
-
class
|
|
922
|
-
static styles = [...P,
|
|
927
|
+
class Ke extends $ {
|
|
928
|
+
static styles = [...P, Ye];
|
|
923
929
|
static properties = {
|
|
924
|
-
|
|
930
|
+
...$.properties,
|
|
925
931
|
sport: { type: String },
|
|
926
932
|
gender: { type: String },
|
|
927
933
|
season: { type: String },
|
|
@@ -936,73 +942,73 @@ class qe extends y {
|
|
|
936
942
|
e && (this.pollDate = e);
|
|
937
943
|
}
|
|
938
944
|
async fetchData(e) {
|
|
939
|
-
const t = this.season ||
|
|
945
|
+
const t = this.season || _(), [s, r, o, i, d] = await Promise.all([
|
|
940
946
|
e.listRankings({ sport: this.sport, ...this.gender ? { gender: this.gender } : {} }),
|
|
941
947
|
e.listSchools(),
|
|
942
948
|
e.listTeams({ sport: this.sport }),
|
|
943
949
|
e.listConferences(),
|
|
944
950
|
e.listGames({ sport: this.sport, season: t })
|
|
945
|
-
]), h = s.items.filter((
|
|
951
|
+
]), h = s.items.filter((l) => !this.gender || !l.gender || l.gender === this.gender).sort((l, c) => c.effectiveDate.localeCompare(l.effectiveDate));
|
|
946
952
|
return {
|
|
947
953
|
season: t,
|
|
948
954
|
polls: h,
|
|
949
|
-
schools:
|
|
950
|
-
teams:
|
|
951
|
-
conferences:
|
|
952
|
-
games:
|
|
955
|
+
schools: r.items,
|
|
956
|
+
teams: o.items,
|
|
957
|
+
conferences: i.items,
|
|
958
|
+
games: d.items
|
|
953
959
|
};
|
|
954
960
|
}
|
|
955
961
|
get ctx() {
|
|
956
962
|
return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
|
|
957
963
|
teamsById: b(this.data.teams),
|
|
958
964
|
schoolsById: b(this.data.schools),
|
|
959
|
-
records:
|
|
965
|
+
records: N(this.data.games),
|
|
960
966
|
rankings: this.data.polls,
|
|
961
967
|
hrefs: z(this),
|
|
962
968
|
sport: this.sport
|
|
963
969
|
}, this._ctxData = this.data), this._ctx;
|
|
964
970
|
}
|
|
965
971
|
sparkline(e, t, s) {
|
|
966
|
-
const
|
|
972
|
+
const d = t.map((m, f) => {
|
|
967
973
|
const u = (m.teamIds || []).indexOf(e);
|
|
968
974
|
if (u === -1) return null;
|
|
969
|
-
const
|
|
970
|
-
return { x:
|
|
975
|
+
const y = t.length === 1 ? 96 / 2 : f / (t.length - 1) * 90 + 3, v = 3 + u / 24 * 20;
|
|
976
|
+
return { x: y, y: v };
|
|
971
977
|
}), h = [];
|
|
972
|
-
let
|
|
973
|
-
if (
|
|
974
|
-
m ?
|
|
975
|
-
}),
|
|
976
|
-
const
|
|
978
|
+
let l = [];
|
|
979
|
+
if (d.forEach((m) => {
|
|
980
|
+
m ? l.push(m) : l.length && (h.push(l), l = []);
|
|
981
|
+
}), l.length && h.push(l), !h.length) return p;
|
|
982
|
+
const c = d[s];
|
|
977
983
|
return n`<svg class="sparkline" width=${96} height=${26} viewBox="0 0 ${96} ${26}" role="img" aria-label="rank history">
|
|
978
|
-
${h.map((m) =>
|
|
984
|
+
${h.map((m) => ee`<polyline fill="none" stroke="var(--hsot-red)" stroke-width="2"
|
|
979
985
|
points=${m.map((f) => `${f.x.toFixed(1)},${f.y.toFixed(1)}`).join(" ")}></polyline>`)}
|
|
980
|
-
${
|
|
986
|
+
${c ? ee`<circle cx=${c.x.toFixed(1)} cy=${c.y.toFixed(1)} r="3" fill="var(--hsot-black)"></circle>` : p}
|
|
981
987
|
</svg>`;
|
|
982
988
|
}
|
|
983
989
|
movement(e, t, s) {
|
|
984
|
-
const
|
|
985
|
-
return
|
|
990
|
+
const r = Ue(e, t, s);
|
|
991
|
+
return r.kind === "up" ? n`<span class="delta up">▲ ${r.delta}</span>` : r.kind === "down" ? n`<span class="delta down">▼ ${r.delta}</span>` : r.kind === "new" ? n`<span class="delta new">NEW</span>` : r.kind === "same" ? n`<span class="delta same">—</span>` : n`<span class="delta same">·</span>`;
|
|
986
992
|
}
|
|
987
993
|
renderView() {
|
|
988
994
|
const e = this.ctx, t = this.data.polls;
|
|
989
995
|
if (!t.length) return n`<div class="view"><p class="empty">No ${this.sport} polls published yet this season.</p></div>`;
|
|
990
|
-
const s = Math.max(0, t.findIndex((m) => m.effectiveDate === this.pollDate)),
|
|
996
|
+
const s = Math.max(0, t.findIndex((m) => m.effectiveDate === this.pollDate)), r = t[s] || t[0], o = t[s + 1] || null, i = t.slice().reverse(), d = i.indexOf(r), h = b(this.data.conferences), l = (r.teamIds || [])[0], c = l ? T(e, l) : null;
|
|
991
997
|
return n`
|
|
992
|
-
${
|
|
993
|
-
title: n`${
|
|
998
|
+
${j(this, e, {
|
|
999
|
+
title: n`${k(this.sport)} Top 25`,
|
|
994
1000
|
sub: n`The HighSchoolOT poll · updated weekly · ${t.length} polls this season`,
|
|
995
1001
|
teams: this.data.teams
|
|
996
1002
|
})}
|
|
997
|
-
${
|
|
998
|
-
${
|
|
1003
|
+
${D(this, n`
|
|
1004
|
+
${B(this)}
|
|
999
1005
|
<div class="toolbar">
|
|
1000
1006
|
<label class="asof" for="pollsel">Poll of</label>
|
|
1001
1007
|
<select id="pollsel" @change=${(m) => {
|
|
1002
1008
|
this.pollDate = m.target.value;
|
|
1003
1009
|
}}>
|
|
1004
|
-
${t.map((m, f) => n`<option value=${m.effectiveDate} ?selected=${m ===
|
|
1005
|
-
${
|
|
1010
|
+
${t.map((m, f) => n`<option value=${m.effectiveDate} ?selected=${m === r}>
|
|
1011
|
+
${x(m.effectiveDate, { month: "long", day: "numeric", year: "numeric" })}${f === 0 ? " · current" : ""}
|
|
1006
1012
|
</option>`)}
|
|
1007
1013
|
</select>
|
|
1008
1014
|
<button class="chip" ?disabled=${s >= t.length - 1}
|
|
@@ -1016,65 +1022,65 @@ class qe extends y {
|
|
|
1016
1022
|
<span class="spacer"></span>
|
|
1017
1023
|
<span class="asof">Movement vs. the previous poll · sparkline = season rank history</span>
|
|
1018
1024
|
</div>
|
|
1019
|
-
${
|
|
1025
|
+
${c ? this.renderHero(e, r, o, l, c, h) : p}
|
|
1020
1026
|
<div class="card"><div class="tablewrap"><table class="data">
|
|
1021
1027
|
<thead><tr>
|
|
1022
1028
|
<th class="num">Rk</th><th>Mvmt</th><th>Team</th><th class="num">Record</th>
|
|
1023
1029
|
<th>Conference</th><th>Last result</th><th>Next</th><th>Season</th>
|
|
1024
1030
|
</tr></thead>
|
|
1025
1031
|
<tbody>
|
|
1026
|
-
${(
|
|
1032
|
+
${(r.teamIds || []).map((m, f) => f === 0 || !m ? p : this.renderRow(e, r, o, i, d, h, m, f + 1))}
|
|
1027
1033
|
</tbody>
|
|
1028
1034
|
</table></div></div>
|
|
1029
1035
|
<p class="note">Ranks elsewhere on the site resolve the poll in effect on the game date, so past box scores keep the ranks they were played under.</p>
|
|
1030
1036
|
`)}
|
|
1031
1037
|
`;
|
|
1032
1038
|
}
|
|
1033
|
-
renderHero(e, t, s,
|
|
1034
|
-
const
|
|
1039
|
+
renderHero(e, t, s, r, o, i) {
|
|
1040
|
+
const d = e.records[r], h = re(e.records, r), l = i[e.teamsById[r]?.conferenceId], c = `linear-gradient(120deg, ${o.colorPrimary || "#030711"} 0%, var(--hsot-black) 85%)`;
|
|
1035
1041
|
return n`
|
|
1036
|
-
<div class="hero1" style="background:${
|
|
1042
|
+
<div class="hero1" style="background:${c}">
|
|
1037
1043
|
<div class="bigrank">#1</div>
|
|
1038
|
-
${
|
|
1044
|
+
${C(o, 64)}
|
|
1039
1045
|
<div>
|
|
1040
|
-
<h2><a href=${g(e.hrefs.school, { id:
|
|
1046
|
+
<h2><a href=${g(e.hrefs.school, { id: o.id })}>${o.name} ${o.mascot || ""}</a></h2>
|
|
1041
1047
|
<div class="facts">
|
|
1042
|
-
${
|
|
1043
|
-
· streak ${
|
|
1048
|
+
${S(d)} overall${l ? n` · ${S(d, !0)} ${l.name}` : p}
|
|
1049
|
+
· streak ${U(d?.results) || "·"}
|
|
1044
1050
|
${h ? n` · last: ${h.mark} ${h.my}-${h.their} vs ${L(e, h.opp)}` : p}
|
|
1045
|
-
${this.movement(t, s,
|
|
1051
|
+
${this.movement(t, s, r)}
|
|
1046
1052
|
</div>
|
|
1047
1053
|
</div>
|
|
1048
1054
|
</div>
|
|
1049
1055
|
`;
|
|
1050
1056
|
}
|
|
1051
|
-
renderRow(e, t, s,
|
|
1052
|
-
const
|
|
1053
|
-
if (!
|
|
1054
|
-
const
|
|
1055
|
-
location.href = g(e.hrefs.school, { id:
|
|
1057
|
+
renderRow(e, t, s, r, o, i, d, h) {
|
|
1058
|
+
const l = T(e, d);
|
|
1059
|
+
if (!l) return p;
|
|
1060
|
+
const c = e.records[d], m = re(e.records, d), f = K(this.data.games, d), u = i[e.teamsById[d]?.conferenceId], y = () => {
|
|
1061
|
+
location.href = g(e.hrefs.school, { id: l.id });
|
|
1056
1062
|
};
|
|
1057
1063
|
return n`
|
|
1058
|
-
<tr class="rowlink" @click=${(
|
|
1059
|
-
|
|
1064
|
+
<tr class="rowlink" @click=${(v) => {
|
|
1065
|
+
v.target.closest("a") || y();
|
|
1060
1066
|
}}>
|
|
1061
1067
|
<td class="num" style="font-weight:700">${h}</td>
|
|
1062
|
-
<td>${this.movement(t, s,
|
|
1063
|
-
<td class="teamcell">${
|
|
1064
|
-
<span class="mut" style="font-size:0.78rem">${
|
|
1065
|
-
<td class="num">${
|
|
1068
|
+
<td>${this.movement(t, s, d)}</td>
|
|
1069
|
+
<td class="teamcell">${C(l)}<a href=${g(e.hrefs.school, { id: l.id })}>${l.name}</a>
|
|
1070
|
+
<span class="mut" style="font-size:0.78rem">${l.mascot || ""}</span></td>
|
|
1071
|
+
<td class="num">${S(c)}</td>
|
|
1066
1072
|
<td class="mut">${u?.name || "Independent"}</td>
|
|
1067
1073
|
<td>${m ? n`<a class="box" style="text-decoration:none" href=${g(e.hrefs.game, { sport: this.sport, id: m.gameId })}>
|
|
1068
1074
|
<b style="color:${m.mark === "W" ? "var(--hsot-win)" : m.mark === "L" ? "var(--hsot-loss)" : "var(--hsot-tie)"}">${m.mark}</b>
|
|
1069
1075
|
${m.my}-${m.their} vs ${L(e, m.opp)}</a>` : n`<span class="mut">·</span>`}</td>
|
|
1070
|
-
<td>${
|
|
1071
|
-
<td>${this.sparkline(
|
|
1076
|
+
<td>${ge(e, f, d)}</td>
|
|
1077
|
+
<td>${this.sparkline(d, r, o)}</td>
|
|
1072
1078
|
</tr>
|
|
1073
1079
|
`;
|
|
1074
1080
|
}
|
|
1075
1081
|
}
|
|
1076
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-rankings") && globalThis.customElements.define("hsot-rankings",
|
|
1077
|
-
const
|
|
1082
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-rankings") && globalThis.customElements.define("hsot-rankings", Ke);
|
|
1083
|
+
const Qe = w`
|
|
1078
1084
|
.schoolhero { color: var(--hsot-white); padding: 1.6rem 1.25rem 1.3rem; }
|
|
1079
1085
|
.schoolhero .inner { max-width: 1366px; margin: 0 auto; display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap; }
|
|
1080
1086
|
.schoolhero .crest {
|
|
@@ -1128,77 +1134,83 @@ const We = $`
|
|
|
1128
1134
|
table.data.roster .sub { display: block; font-weight: 400; font-size: 0.78rem; color: var(--hsot-gray-5); }
|
|
1129
1135
|
}
|
|
1130
1136
|
`;
|
|
1131
|
-
class
|
|
1132
|
-
static styles = [...P,
|
|
1137
|
+
class Xe extends $ {
|
|
1138
|
+
static styles = [...P, Qe];
|
|
1133
1139
|
static properties = {
|
|
1134
|
-
|
|
1140
|
+
...$.properties,
|
|
1135
1141
|
schoolId: { type: String, attribute: "school-id" },
|
|
1136
1142
|
sport: { type: String },
|
|
1143
|
+
gender: { type: String },
|
|
1137
1144
|
season: { type: String },
|
|
1138
1145
|
activeTeamId: { state: !0 }
|
|
1139
1146
|
};
|
|
1140
1147
|
constructor() {
|
|
1141
|
-
super(), this.schoolId = "", this.sport = "", this.season = "", this.activeTeamId = "";
|
|
1148
|
+
super(), this.schoolId = "", this.sport = "", this.gender = "", this.season = "", this.activeTeamId = "";
|
|
1142
1149
|
}
|
|
1143
1150
|
connectedCallback() {
|
|
1144
1151
|
super.connectedCallback();
|
|
1145
|
-
const e = new URLSearchParams(globalThis.location?.search || "").get("sport");
|
|
1146
|
-
|
|
1152
|
+
const e = new URLSearchParams(globalThis.location?.search || ""), t = e.get("sport"), s = e.get("gender");
|
|
1153
|
+
t && !this.sport && (this.sport = t), s && !this.gender && (this.gender = s);
|
|
1147
1154
|
}
|
|
1148
1155
|
async fetchData(e) {
|
|
1149
|
-
const t = this.season ||
|
|
1150
|
-
|
|
1151
|
-
|
|
1156
|
+
const t = this.season || _(), s = await e.getSchool(this.schoolId), o = (await e.listTeams({ schoolId: this.schoolId })).items, i = this.sport || "football", d = o.find((v) => v.id === this.activeTeamId) || o.find((v) => v.sport === i && he(v, this.gender)) || o.find((v) => v.sport === i) || o[0] || null, [h, l, c, m, f, u, y] = await Promise.all([
|
|
1157
|
+
d ? e.listGames({ sport: d.sport, season: t }) : Promise.resolve({ items: [] }),
|
|
1158
|
+
d ? e.listTeams({ sport: d.sport }) : Promise.resolve({ items: [] }),
|
|
1152
1159
|
e.listSchools(),
|
|
1153
1160
|
e.listConferences(),
|
|
1154
|
-
|
|
1155
|
-
|
|
1161
|
+
d ? e.listRankings({ sport: d.sport }) : Promise.resolve({ items: [] }),
|
|
1162
|
+
d ? e.listRosters({ teamId: d.id }) : Promise.resolve({ items: [] }),
|
|
1156
1163
|
// teamId is the public surface's one players filter (roster
|
|
1157
1164
|
// membership) — never fetch the whole collection.
|
|
1158
|
-
|
|
1165
|
+
d ? e.listPlayers({ teamId: d.id }) : Promise.resolve({ items: [] })
|
|
1159
1166
|
]);
|
|
1160
1167
|
return {
|
|
1161
1168
|
season: t,
|
|
1162
1169
|
school: s,
|
|
1163
|
-
teams:
|
|
1164
|
-
active:
|
|
1165
|
-
games:
|
|
1166
|
-
allTeams:
|
|
1170
|
+
teams: o,
|
|
1171
|
+
active: d,
|
|
1172
|
+
games: h.items,
|
|
1173
|
+
allTeams: l.items,
|
|
1167
1174
|
schools: c.items,
|
|
1168
|
-
conferences:
|
|
1169
|
-
rankings:
|
|
1170
|
-
roster:
|
|
1171
|
-
players:
|
|
1175
|
+
conferences: m.items,
|
|
1176
|
+
rankings: f.items,
|
|
1177
|
+
roster: u.items.find((v) => v.season === t) || null,
|
|
1178
|
+
players: y.items
|
|
1172
1179
|
};
|
|
1173
1180
|
}
|
|
1174
1181
|
get ctx() {
|
|
1175
1182
|
return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
|
|
1176
1183
|
teamsById: b(this.data.allTeams.length ? this.data.allTeams : this.data.teams),
|
|
1177
1184
|
schoolsById: b(this.data.schools),
|
|
1178
|
-
records:
|
|
1185
|
+
records: N(this.data.games),
|
|
1179
1186
|
rankings: this.data.rankings,
|
|
1180
1187
|
hrefs: z(this),
|
|
1181
1188
|
sport: this.data.active?.sport || "football"
|
|
1182
1189
|
}, this._ctxData = this.data), this._ctx;
|
|
1183
1190
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1191
|
+
/**
|
|
1192
|
+
* Open a team's tab. The team id is what selects it — sport alone is
|
|
1193
|
+
* ambiguous on a gendered sport — with sport and gender kept in step so
|
|
1194
|
+
* the rest of the view and a shared ?sport=&gender= link agree with it.
|
|
1195
|
+
*/
|
|
1196
|
+
switchTeam(e) {
|
|
1197
|
+
e && (this.activeTeamId = e.id, this.sport = e.sport, this.gender = e.gender || "", this.load());
|
|
1186
1198
|
}
|
|
1187
1199
|
renderView() {
|
|
1188
|
-
const { school: e, teams: t, active: s, season:
|
|
1200
|
+
const { school: e, teams: t, active: s, season: r } = this.data;
|
|
1189
1201
|
if (!e) return n`<div class="view"><p class="empty">School not found.</p></div>`;
|
|
1190
|
-
const
|
|
1202
|
+
const o = this.ctx, i = G(e.colorPrimary || "#030711"), d = (e.adm || [])[0], h = b(this.data.conferences), l = s ? h[s.conferenceId] : null;
|
|
1191
1203
|
return n`
|
|
1192
|
-
<div class="schoolhero" style="background:linear-gradient(115deg, ${e.colorPrimary || "#030711"} 0%, ${e.colorPrimary || "#030711"} 55%, var(--hsot-black) 100%);color:${
|
|
1204
|
+
<div class="schoolhero" style="background:linear-gradient(115deg, ${e.colorPrimary || "#030711"} 0%, ${e.colorPrimary || "#030711"} 55%, var(--hsot-black) 100%);color:${i}">
|
|
1193
1205
|
<div class="inner">
|
|
1194
|
-
${M(e, 84) ? n`<img class="crest logo" alt="" loading="lazy" src=${M(e, 84)} />` : n`<div class="crest" style="background:${e.colorSecondary || "#7C7C7C"};color:${
|
|
1206
|
+
${M(e, 84) ? n`<img class="crest logo" alt="" loading="lazy" src=${M(e, 84)} />` : n`<div class="crest" style="background:${e.colorSecondary || "#7C7C7C"};color:${G(e.colorSecondary || "#7C7C7C")}">${Y(e)}</div>`}
|
|
1195
1207
|
<div style="min-width:260px">
|
|
1196
1208
|
<h1>${e.name} <span class="mascot">${e.mascot || ""}</span></h1>
|
|
1197
1209
|
<div class="facts">
|
|
1198
1210
|
${e.location ? n`<span><b>Location</b>${e.location}${e.county ? n` · ${e.county} County` : p}</span>` : p}
|
|
1199
1211
|
${e.association ? n`<span><b>League</b>${e.association}${e.classification ? n` · ${e.classification}` : p}</span>` : p}
|
|
1200
|
-
${
|
|
1201
|
-
${
|
|
1212
|
+
${l ? n`<span><b>Conference</b>${l.name}</span>` : p}
|
|
1213
|
+
${d ? n`<span><b>Enrollment</b>${d.value.toLocaleString()} (${d.season} ADM)</span>` : p}
|
|
1202
1214
|
${e.openingYear ? n`<span><b>Opened</b>${e.openingYear}</span>` : p}
|
|
1203
1215
|
${e.areaCode ? n`<span><b>Area</b>${e.areaCode}</span>` : p}
|
|
1204
1216
|
</div>
|
|
@@ -1207,29 +1219,29 @@ class Ve extends y {
|
|
|
1207
1219
|
</div>
|
|
1208
1220
|
<div class="band">
|
|
1209
1221
|
<nav class="tabs" aria-label="Teams">
|
|
1210
|
-
${t.map((
|
|
1211
|
-
m.preventDefault(), this.
|
|
1212
|
-
}}>${
|
|
1222
|
+
${t.map((c) => c.id === s?.id ? n`<a class="on" href="#" aria-current="page" @click=${(m) => m.preventDefault()}>${c.name}</a>` : n`<a href="#" @click=${(m) => {
|
|
1223
|
+
m.preventDefault(), this.switchTeam(c);
|
|
1224
|
+
}}>${c.name}</a>`)}
|
|
1213
1225
|
</nav>
|
|
1214
1226
|
</div>
|
|
1215
|
-
${
|
|
1216
|
-
${
|
|
1217
|
-
${s ? this.renderTeam(
|
|
1227
|
+
${D(this, n`
|
|
1228
|
+
${B(this)}
|
|
1229
|
+
${s ? this.renderTeam(o, s, l, r) : n`<p class="empty">No teams recorded for this school yet.</p>`}
|
|
1218
1230
|
`)}
|
|
1219
1231
|
`;
|
|
1220
1232
|
}
|
|
1221
|
-
renderTeam(e, t, s,
|
|
1222
|
-
const
|
|
1233
|
+
renderTeam(e, t, s, r) {
|
|
1234
|
+
const o = e.records[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, i = o.w + o.l + o.t, d = s ? me(this.data.allTeams.filter((m) => m.conferenceId === s.id), t.gender) : [], h = s ? fe(d, e.records).findIndex((m) => m.team.id === t.id) + 1 : 0, l = Q(e.rankings, e.teamsById, t.id, t.sport, null), c = this.data.games.filter((m) => m.homeTeamId === t.id || m.awayTeamId === t.id).sort((m, f) => String(m.date).localeCompare(String(f.date)));
|
|
1223
1235
|
return n`
|
|
1224
1236
|
<div class="tiles">
|
|
1225
|
-
<div class="tile"><div class="k">Overall</div><div class="v">${
|
|
1226
|
-
<div class="tile"><div class="k">${s?.name || "Conference"}</div><div class="v">${
|
|
1227
|
-
<div class="s">${h ? `${
|
|
1228
|
-
<div class="tile"><div class="k">Points</div><div class="v">${
|
|
1229
|
-
<div class="s">scored per game · ${
|
|
1230
|
-
<div class="tile"><div class="k">Streak</div><div class="v">${
|
|
1231
|
-
<div class="s">last 5: ${
|
|
1232
|
-
<div class="tile"><div class="k">HSOT Top 25</div><div class="v">${
|
|
1237
|
+
<div class="tile"><div class="k">Overall</div><div class="v">${S(o)}</div><div class="s">${i} games played</div></div>
|
|
1238
|
+
<div class="tile"><div class="k">${s?.name || "Conference"}</div><div class="v">${S(o, !0)}</div>
|
|
1239
|
+
<div class="s">${h ? `${Ce(h)} of ${d.length}` : "·"}</div></div>
|
|
1240
|
+
<div class="tile"><div class="k">Points</div><div class="v">${i ? (o.pf / i).toFixed(1) : "0.0"}</div>
|
|
1241
|
+
<div class="s">scored per game · ${i ? (o.pa / i).toFixed(1) : "0.0"} allowed</div></div>
|
|
1242
|
+
<div class="tile"><div class="k">Streak</div><div class="v">${U(o.results) || "·"}</div>
|
|
1243
|
+
<div class="s">last 5: ${Z(e, t.id)}</div></div>
|
|
1244
|
+
<div class="tile"><div class="k">HSOT Top 25</div><div class="v">${l ? `#${l}` : "NR"}</div>
|
|
1233
1245
|
<div class="s"><a href=${g(e.hrefs.section, { sport: t.sport, view: "rankings" })}>full poll</a></div></div>
|
|
1234
1246
|
</div>
|
|
1235
1247
|
${(t.championships || []).length ? n`
|
|
@@ -1240,31 +1252,31 @@ class Ve extends y {
|
|
|
1240
1252
|
<div>
|
|
1241
1253
|
<div class="section-title">Schedule & results</div>
|
|
1242
1254
|
<div class="card">
|
|
1243
|
-
${
|
|
1255
|
+
${c.length ? n`<ul class="gamelist">${c.map((m) => this.renderGameRow(e, t, m))}</ul>` : n`<p class="empty">No ${t.sport} games recorded for ${r}.</p>`}
|
|
1244
1256
|
</div>
|
|
1245
1257
|
</div>
|
|
1246
1258
|
<div>
|
|
1247
|
-
<div class="section-title">Roster · ${
|
|
1248
|
-
<div class="card">${this.renderRoster(t,
|
|
1259
|
+
<div class="section-title">Roster · ${r}</div>
|
|
1260
|
+
<div class="card">${this.renderRoster(t, r)}</div>
|
|
1249
1261
|
</div>
|
|
1250
1262
|
</div>
|
|
1251
1263
|
`;
|
|
1252
1264
|
}
|
|
1253
1265
|
renderGameRow(e, t, s) {
|
|
1254
|
-
const
|
|
1255
|
-
let h = n`<span class="mut">${
|
|
1266
|
+
const r = s.homeTeamId === t.id, o = r ? s.awayTeamId : s.homeTeamId, i = r ? s.homeScore : s.awayScore, d = r ? s.awayScore : s.homeScore;
|
|
1267
|
+
let h = n`<span class="mut">${W(s.time)}</span>`;
|
|
1256
1268
|
if (s.state === "final") {
|
|
1257
|
-
const
|
|
1258
|
-
h = n`<span class=${m}>${m}</span> ${
|
|
1259
|
-
} else s.state === "live" && (h = n`<span style="color:var(--hsot-red)">${
|
|
1260
|
-
const
|
|
1269
|
+
const c = H(s), m = c === "tie" ? "T" : c === (r ? "home" : "away") ? "W" : "L";
|
|
1270
|
+
h = n`<span class=${m}>${m}</span> ${i}-${d}${s.finish === "overtime" ? n` <span class="mut">OT</span>` : p}${s.forfeit && s.forfeit !== "none" ? n` <span class="mut">FF</span>` : p}`;
|
|
1271
|
+
} else s.state === "live" && (h = n`<span style="color:var(--hsot-red)">${i}-${d}</span>`);
|
|
1272
|
+
const l = s.gameType === "conference" ? "Conf" : s.gameType === "nonconference" ? "Non-conf" : s.gameType === "playoff" ? `Playoff${s.label ? ` · ${s.label}` : ""}` : "Scrimmage";
|
|
1261
1273
|
return n`
|
|
1262
1274
|
<li>
|
|
1263
|
-
<span class="d">${
|
|
1264
|
-
${
|
|
1275
|
+
<span class="d">${x(s.date)}</span>
|
|
1276
|
+
${de(s).kind === "sched" ? p : A(s)}
|
|
1265
1277
|
<span class="res">${h}</span>
|
|
1266
|
-
<span class="opp">${
|
|
1267
|
-
<span class="pill type">${
|
|
1278
|
+
<span class="opp">${r ? "vs" : "at"} ${O(e, o, s.date)}
|
|
1279
|
+
<span class="pill type">${l}</span>
|
|
1268
1280
|
${s.broadcast ? n`<span class="pill class">${s.broadcast}</span>` : p}
|
|
1269
1281
|
</span>
|
|
1270
1282
|
<span class="where">${s.venue || ""}</span>
|
|
@@ -1276,25 +1288,25 @@ class Ve extends y {
|
|
|
1276
1288
|
const s = this.data.roster;
|
|
1277
1289
|
if (!s)
|
|
1278
1290
|
return n`<p class="empty">Roster not published for ${t}.</p>`;
|
|
1279
|
-
const
|
|
1291
|
+
const r = qe(s, 560), o = this.data.school?.name || "", i = b(this.data.players), d = s.entries.slice().sort((l, c) => (l.number || 0) - (c.number || 0)), h = d.some((l) => i[l.playerId]?.college);
|
|
1280
1292
|
return n`
|
|
1281
|
-
${
|
|
1282
|
-
alt="${
|
|
1293
|
+
${r ? n`<img class="rosterphoto" src=${r} loading="lazy" decoding="async"
|
|
1294
|
+
alt="${o} ${e.name} ${t} team photo" />` : p}
|
|
1283
1295
|
<div class="tablewrap"><table class="data roster">
|
|
1284
1296
|
<thead><tr><th class="num">No.</th><th>Player</th><th class="pos">Pos</th><th class="cls">Class</th><th class="num">Ht</th><th class="num">Wt</th>${h ? n`<th>College</th>` : p}</tr></thead>
|
|
1285
1297
|
<tbody>
|
|
1286
|
-
${
|
|
1287
|
-
const
|
|
1288
|
-
if (!
|
|
1289
|
-
const m =
|
|
1298
|
+
${d.map((l) => {
|
|
1299
|
+
const c = i[l.playerId];
|
|
1300
|
+
if (!c) return p;
|
|
1301
|
+
const m = Ie(l), f = [m, c.classOf].filter(Boolean).join(" · ") || "·";
|
|
1290
1302
|
return n`<tr>
|
|
1291
|
-
<td class="num mut">${
|
|
1292
|
-
<td class="player" style="font-weight:500">${
|
|
1303
|
+
<td class="num mut">${l.number ?? "·"}</td>
|
|
1304
|
+
<td class="player" style="font-weight:500">${c.firstName} ${c.lastName}<span class="sub">${f}</span></td>
|
|
1293
1305
|
<td class="pos">${m || "·"}</td>
|
|
1294
|
-
<td class="cls mut">${
|
|
1295
|
-
<td class="num">${
|
|
1296
|
-
<td class="num">${
|
|
1297
|
-
${h ? n`<td class="college">${
|
|
1306
|
+
<td class="cls mut">${c.classOf || "·"}</td>
|
|
1307
|
+
<td class="num">${Se(c.heightIn)}</td>
|
|
1308
|
+
<td class="num">${c.weightLb || "·"}</td>
|
|
1309
|
+
${h ? n`<td class="college">${c.college || "·"}</td>` : p}
|
|
1298
1310
|
</tr>`;
|
|
1299
1311
|
})}
|
|
1300
1312
|
</tbody>
|
|
@@ -1302,8 +1314,8 @@ class Ve extends y {
|
|
|
1302
1314
|
`;
|
|
1303
1315
|
}
|
|
1304
1316
|
}
|
|
1305
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-school") && globalThis.customElements.define("hsot-school",
|
|
1306
|
-
const
|
|
1317
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-school") && globalThis.customElements.define("hsot-school", Xe);
|
|
1318
|
+
const ve = {
|
|
1307
1319
|
football: ["quarters", 4],
|
|
1308
1320
|
flag_football: ["quarters", 4],
|
|
1309
1321
|
basketball: ["quarters", 4],
|
|
@@ -1314,57 +1326,57 @@ const pe = {
|
|
|
1314
1326
|
softball: ["innings", 7],
|
|
1315
1327
|
volleyball: ["sets", 3]
|
|
1316
1328
|
};
|
|
1317
|
-
function
|
|
1318
|
-
return (
|
|
1329
|
+
function be(a) {
|
|
1330
|
+
return (ve[a] || ["quarters", 4])[0];
|
|
1319
1331
|
}
|
|
1320
|
-
function
|
|
1321
|
-
return (
|
|
1332
|
+
function J(a) {
|
|
1333
|
+
return (ve[a] || ["quarters", 4])[1];
|
|
1322
1334
|
}
|
|
1323
|
-
function
|
|
1324
|
-
const t =
|
|
1335
|
+
function Ze(a, e) {
|
|
1336
|
+
const t = be(a), s = J(a);
|
|
1325
1337
|
if (e <= s || t === "innings" || t === "sets") return String(e);
|
|
1326
|
-
const
|
|
1327
|
-
return `OT${
|
|
1338
|
+
const r = e - s;
|
|
1339
|
+
return `OT${r > 1 ? r : ""}`;
|
|
1328
1340
|
}
|
|
1329
|
-
function
|
|
1341
|
+
function Je(a, e) {
|
|
1330
1342
|
const t = String(a ?? "").trim();
|
|
1331
1343
|
let s;
|
|
1332
|
-
return (s = /^(\d+)Q$/i.exec(t)) || (s = /^(\d+)H$/i.exec(t)) ? Number(s[1]) : /^half$/i.test(t) ?
|
|
1344
|
+
return (s = /^(\d+)Q$/i.exec(t)) || (s = /^(\d+)H$/i.exec(t)) ? Number(s[1]) : /^half$/i.test(t) ? be(e) === "halves" ? 1 : 2 : (s = /^(\d*)OT(\d*)$/i.exec(t)) ? J(e) + Number(s[1] || s[2] || 1) : (s = /^[TB](\d+)$/i.exec(t)) || (s = /^(\d+)(?:st|nd|rd|th)\s*set$/i.exec(t)) || (s = /^set\s*(\d+)$/i.exec(t)) ? Number(s[1]) : null;
|
|
1333
1345
|
}
|
|
1334
1346
|
const R = (a) => Number.isInteger(a) && a >= 0 ? a : null;
|
|
1335
|
-
function
|
|
1347
|
+
function et(a) {
|
|
1336
1348
|
const e = Array.isArray(a?.scoringPlays) ? a.scoringPlays : [];
|
|
1337
1349
|
if (!e.length) return null;
|
|
1338
1350
|
const t = a.sport, s = /* @__PURE__ */ new Map();
|
|
1339
1351
|
for (const m of e) {
|
|
1340
|
-
const f =
|
|
1341
|
-
if (!f || u === null ||
|
|
1342
|
-
const
|
|
1343
|
-
|
|
1352
|
+
const f = Je(m?.period, t), u = R(m?.homeScore), y = R(m?.awayScore);
|
|
1353
|
+
if (!f || u === null || y === null) return null;
|
|
1354
|
+
const v = s.get(f) || { home: 0, away: 0 };
|
|
1355
|
+
v.home = Math.max(v.home, u), v.away = Math.max(v.away, y), s.set(f, v);
|
|
1344
1356
|
}
|
|
1345
|
-
const
|
|
1346
|
-
let
|
|
1347
|
-
for (let m = 1; m <=
|
|
1348
|
-
const f = s.get(m) ||
|
|
1349
|
-
(u < 0 ||
|
|
1357
|
+
const r = Math.max(...s.keys()), o = [];
|
|
1358
|
+
let i = !0, d = { home: 0, away: 0 };
|
|
1359
|
+
for (let m = 1; m <= r; m += 1) {
|
|
1360
|
+
const f = s.get(m) || d, u = f.home - d.home, y = f.away - d.away;
|
|
1361
|
+
(u < 0 || y < 0) && (i = !1), o.push({ period: m, home: Math.max(u, 0), away: Math.max(y, 0) }), d = { home: Math.max(f.home, d.home), away: Math.max(f.away, d.away) };
|
|
1350
1362
|
}
|
|
1351
|
-
const h = R(a.homeScore) ?? 0,
|
|
1352
|
-
return
|
|
1363
|
+
const h = R(a.homeScore) ?? 0, l = R(a.awayScore) ?? 0, c = i && d.home === h && d.away === l;
|
|
1364
|
+
return i = i && d.home <= h && d.away <= l, { periods: o, reconciled: c, consistent: i };
|
|
1353
1365
|
}
|
|
1354
|
-
function
|
|
1366
|
+
function tt(a) {
|
|
1355
1367
|
if (Array.isArray(a?.periodScores) && a.periodScores.length) return a.periodScores;
|
|
1356
|
-
const e =
|
|
1368
|
+
const e = et(a);
|
|
1357
1369
|
return e ? a.state === "final" ? e.reconciled ? e.periods : null : e.consistent ? e.periods : null : null;
|
|
1358
1370
|
}
|
|
1359
|
-
const
|
|
1360
|
-
function
|
|
1371
|
+
const st = "https://api.wral.com/search";
|
|
1372
|
+
function at(a) {
|
|
1361
1373
|
return a.map((e) => `uri:"${e}"`).join(" OR ");
|
|
1362
1374
|
}
|
|
1363
|
-
function
|
|
1364
|
-
const t = String(a ||
|
|
1375
|
+
function rt(a, e) {
|
|
1376
|
+
const t = String(a || st).replace(/\/+$/, ""), s = new URLSearchParams({ query: at(e), sort: "score", lang: "en" });
|
|
1365
1377
|
return `${t}/v1/query?${s}`;
|
|
1366
1378
|
}
|
|
1367
|
-
function
|
|
1379
|
+
function ye(a) {
|
|
1368
1380
|
try {
|
|
1369
1381
|
const e = new URL(a);
|
|
1370
1382
|
if (/(^|\.)smugmug\.com$/i.test(e.hostname)) {
|
|
@@ -1379,13 +1391,13 @@ function ue(a) {
|
|
|
1379
1391
|
}
|
|
1380
1392
|
return { uri: a, title: a };
|
|
1381
1393
|
}
|
|
1382
|
-
async function
|
|
1383
|
-
const
|
|
1384
|
-
if (!
|
|
1385
|
-
const
|
|
1386
|
-
return e.map((
|
|
1394
|
+
async function ot(a, e, t) {
|
|
1395
|
+
const r = await ((...d) => fetch(...d))(rt(a, e));
|
|
1396
|
+
if (!r.ok) throw new Error(`search answered ${r.status}`);
|
|
1397
|
+
const o = await r.json(), i = new Map((o.items || []).map((d) => [d.uri, d]));
|
|
1398
|
+
return e.map((d) => i.get(d) || ye(d));
|
|
1387
1399
|
}
|
|
1388
|
-
const
|
|
1400
|
+
const nt = w`
|
|
1389
1401
|
.breadcrumbs { font-size: 0.8125rem; margin: 0.9rem 0 0; color: var(--hsot-gray-5); }
|
|
1390
1402
|
.breadcrumbs a { text-decoration: none; }
|
|
1391
1403
|
.scorehead { display: grid; grid-template-columns: 1fr auto 1fr; gap: 1rem; align-items: center; padding: 1.4rem 1rem; }
|
|
@@ -1428,6 +1440,9 @@ const st = $`
|
|
|
1428
1440
|
table.plays-table td.play { white-space: normal; min-width: 12rem; }
|
|
1429
1441
|
/* Game notes are typed with line breaks the desk means to keep. */
|
|
1430
1442
|
.gamenote { padding: 0 1rem 0.9rem; text-align: center; white-space: pre-line; }
|
|
1443
|
+
/* The embed's way out to everything it drops (Coverage, season context,
|
|
1444
|
+
head to head) — the data page still renders all of it. */
|
|
1445
|
+
.fullbox { margin: 0.9rem 0 0; text-align: center; font-size: 0.875rem; }
|
|
1431
1446
|
.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
|
|
1432
1447
|
.ctxcard { padding: 0.85rem 1rem; }
|
|
1433
1448
|
.ctxcard .who { font-family: var(--hsot-heading-font); font-weight: 700; margin-bottom: 0.4rem; }
|
|
@@ -1438,22 +1453,28 @@ const st = $`
|
|
|
1438
1453
|
.cols { grid-template-columns: 1fr; }
|
|
1439
1454
|
}
|
|
1440
1455
|
`;
|
|
1441
|
-
class
|
|
1442
|
-
static styles = [...P,
|
|
1456
|
+
class it extends $ {
|
|
1457
|
+
static styles = [...P, nt];
|
|
1443
1458
|
static properties = {
|
|
1444
|
-
|
|
1459
|
+
...$.properties,
|
|
1445
1460
|
gameId: { type: String, attribute: "game-id" },
|
|
1446
1461
|
// The public site search that resolves Game.coverageUrls into cards
|
|
1447
1462
|
// (DEV-1236). Shared cross-stage by design — see the studio host's
|
|
1448
1463
|
// registry — so the prod default is right everywhere; the attribute
|
|
1449
1464
|
// exists for the same reason the href templates do.
|
|
1450
|
-
searchApi: { type: String, attribute: "search-api" }
|
|
1465
|
+
searchApi: { type: String, attribute: "search-api" },
|
|
1466
|
+
// Story pages embed the box score in the article column, where the page
|
|
1467
|
+
// chrome (breadcrumbs, the report-a-score line) and the cross-links
|
|
1468
|
+
// (Coverage, Season context, head-to-head) belong to the data page, not
|
|
1469
|
+
// the recap. `embed` keeps the score head, line score and scoring plays,
|
|
1470
|
+
// and links out to the full box score for the rest.
|
|
1471
|
+
embed: { type: Boolean }
|
|
1451
1472
|
};
|
|
1452
1473
|
constructor() {
|
|
1453
|
-
super(), this.gameId = "", this.searchApi = "";
|
|
1474
|
+
super(), this.gameId = "", this.searchApi = "", this.embed = !1;
|
|
1454
1475
|
}
|
|
1455
1476
|
async fetchData(e) {
|
|
1456
|
-
const t = await e.getGame(this.gameId), s = Array.isArray(t.coverageUrls) ? t.coverageUrls : [], [
|
|
1477
|
+
const t = await e.getGame(this.gameId), s = Array.isArray(t.coverageUrls) ? t.coverageUrls : [], [r, o, i, d, h, l] = await Promise.all([
|
|
1457
1478
|
e.listSchools(),
|
|
1458
1479
|
e.listTeams({ sport: t.sport }),
|
|
1459
1480
|
e.listConferences(),
|
|
@@ -1461,23 +1482,25 @@ class at extends y {
|
|
|
1461
1482
|
e.listGames({ sport: t.sport, season: t.season }),
|
|
1462
1483
|
// A search outage must not blank the box score — degrade to bare
|
|
1463
1484
|
// links (fetchCoverage already degrades per-URL index misses).
|
|
1464
|
-
|
|
1485
|
+
// The embed drops the Coverage grid, so it skips the search
|
|
1486
|
+
// round-trip entirely rather than fetching cards it will not render.
|
|
1487
|
+
s.length && !this.embed ? ot(this.searchApi, s).catch(() => s.map(ye)) : Promise.resolve([])
|
|
1465
1488
|
]);
|
|
1466
1489
|
return {
|
|
1467
1490
|
game: t,
|
|
1468
|
-
schools:
|
|
1469
|
-
teams:
|
|
1470
|
-
conferences:
|
|
1471
|
-
rankings:
|
|
1491
|
+
schools: r.items,
|
|
1492
|
+
teams: o.items,
|
|
1493
|
+
conferences: i.items,
|
|
1494
|
+
rankings: d.items,
|
|
1472
1495
|
games: h.items,
|
|
1473
|
-
coverage:
|
|
1496
|
+
coverage: l
|
|
1474
1497
|
};
|
|
1475
1498
|
}
|
|
1476
1499
|
get ctx() {
|
|
1477
1500
|
return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
|
|
1478
1501
|
teamsById: b(this.data.teams),
|
|
1479
1502
|
schoolsById: b(this.data.schools),
|
|
1480
|
-
records:
|
|
1503
|
+
records: N(this.data.games),
|
|
1481
1504
|
rankings: this.data.rankings,
|
|
1482
1505
|
hrefs: z(this),
|
|
1483
1506
|
sport: this.data.game.sport
|
|
@@ -1486,50 +1509,59 @@ class at extends y {
|
|
|
1486
1509
|
renderView() {
|
|
1487
1510
|
const e = this.data.game;
|
|
1488
1511
|
if (!e) return n`<div class="view"><p class="empty">Game not found.</p></div>`;
|
|
1489
|
-
const t = this.ctx, s = b(this.data.conferences),
|
|
1512
|
+
const t = this.ctx, s = b(this.data.conferences), r = t.teamsById[e.awayTeamId] ? t.schoolsById[t.teamsById[e.awayTeamId].schoolId] : null, o = t.teamsById[e.homeTeamId] ? t.schoolsById[t.teamsById[e.homeTeamId].schoolId] : null, i = H(e), d = (c) => e.state === "final" && i !== c && i !== "tie" ? "opacity:0.45" : "", h = e.conferenceId ? s[e.conferenceId] : null, l = this.data.games.filter((c) => c.id !== e.id && c.state === "final" && c.gameType !== "scrimmage" && (c.homeTeamId === e.homeTeamId && c.awayTeamId === e.awayTeamId || c.homeTeamId === e.awayTeamId && c.awayTeamId === e.homeTeamId));
|
|
1490
1513
|
return n`
|
|
1491
|
-
${
|
|
1492
|
-
${
|
|
1493
|
-
|
|
1494
|
-
<
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1514
|
+
${D(this, n`
|
|
1515
|
+
${B(this)}
|
|
1516
|
+
${this.embed ? p : n`
|
|
1517
|
+
<p class="breadcrumbs">
|
|
1518
|
+
<a href=${g(t.hrefs.section, { sport: e.sport, view: "scores" })}>${k(e.sport)}</a> /
|
|
1519
|
+
<a href=${g(t.hrefs.section, { sport: e.sport, view: "scores" })}>Scores/Schedules</a> /
|
|
1520
|
+
${F(t, e.awayTeamId)} at ${F(t, e.homeTeamId)}
|
|
1521
|
+
</p>`}
|
|
1498
1522
|
<div class="card">
|
|
1499
1523
|
<div class="scorehead">
|
|
1500
|
-
${this.teamBlock(t, e, e.awayTeamId,
|
|
1524
|
+
${this.teamBlock(t, e, e.awayTeamId, r, !1)}
|
|
1501
1525
|
<div class="mid">
|
|
1502
1526
|
<div class="bigscore">
|
|
1503
|
-
<span style=${
|
|
1527
|
+
<span style=${d("away")}>${e.awayScore}</span>
|
|
1504
1528
|
<span class="mut" style="font-size:1.6rem">–</span>
|
|
1505
|
-
<span style=${
|
|
1529
|
+
<span style=${d("home")}>${e.homeScore}</span>
|
|
1506
1530
|
</div>
|
|
1507
1531
|
<div class="status">${A(e)}</div>
|
|
1508
|
-
<div class="status">${
|
|
1532
|
+
<div class="status">${x(e.date, { weekday: "short", month: "short", day: "numeric", year: "numeric" })}${e.state === "scheduled" && e.time ? n` · ${W(e.time)}` : p} · ${e.venue || "Venue TBD"}
|
|
1509
1533
|
${e.broadcast ? n` · <span class="pill class">${e.broadcast}</span>` : p}</div>
|
|
1510
1534
|
<div class="status">
|
|
1511
1535
|
<span class="pill type">${e.gameType === "conference" ? `${h?.name || "Conference"} game` : e.gameType}</span>
|
|
1512
1536
|
${e.label ? n`<span class="pill type">Bracket ${e.label}</span>` : p}
|
|
1513
|
-
${(e.tags || []).map((
|
|
1537
|
+
${(e.tags || []).map((c) => n`<span class="pill type">${c}</span>`)}
|
|
1514
1538
|
</div>
|
|
1539
|
+
${this.embed ? p : n`
|
|
1540
|
+
<div class="status">
|
|
1541
|
+
<a href=${ce(t.hrefs, e.id)}>Report a score for this game</a>
|
|
1542
|
+
</div>`}
|
|
1515
1543
|
</div>
|
|
1516
|
-
${this.teamBlock(t, e, e.homeTeamId,
|
|
1544
|
+
${this.teamBlock(t, e, e.homeTeamId, o, !0)}
|
|
1517
1545
|
</div>
|
|
1518
|
-
${this.renderLineScore(e,
|
|
1519
|
-
${this.renderScoringPlays(e,
|
|
1546
|
+
${this.renderLineScore(e, r, o)}
|
|
1547
|
+
${this.renderScoringPlays(e, r, o)}
|
|
1520
1548
|
${e.notes ? n`<p class="note gamenote">${e.notes}</p>` : p}
|
|
1521
1549
|
</div>
|
|
1550
|
+
${this.embed ? n`
|
|
1551
|
+
<p class="fullbox">
|
|
1552
|
+
<a href=${g(t.hrefs.game, { sport: e.sport, id: e.id })}>Full box score →</a>
|
|
1553
|
+
</p>` : n`
|
|
1522
1554
|
${(this.data.coverage || []).length ? n`
|
|
1523
1555
|
<div class="section-title">Coverage</div>
|
|
1524
1556
|
<div class="covgrid">
|
|
1525
|
-
${this.data.coverage.map((
|
|
1526
|
-
<a class="card covcard" href=${
|
|
1527
|
-
${
|
|
1557
|
+
${this.data.coverage.map((c) => n`
|
|
1558
|
+
<a class="card covcard" href=${c.uri}>
|
|
1559
|
+
${c.image ? n`<img class="covimg" src=${c.image} alt="" loading="lazy" />` : p}
|
|
1528
1560
|
<div class="covbody">
|
|
1529
|
-
<div class="covtitle">${
|
|
1530
|
-
${
|
|
1531
|
-
${
|
|
1532
|
-
<div class="covmeta">${[
|
|
1561
|
+
<div class="covtitle">${c.videoDuration ? n`<span class="pill live" style="animation:none">Video</span> ` : p}${c.photos ? n`<span class="pill live" style="animation:none">Photos</span> ` : p}${c.title || c.uri}</div>
|
|
1562
|
+
${c.description ? n`<p class="covdesc">${c.description}</p>` : p}
|
|
1563
|
+
${c.author || c.publishedTime ? n`
|
|
1564
|
+
<div class="covmeta">${[c.author, c.publishedTime ? new Date(c.publishedTime).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) : ""].filter(Boolean).join(" · ")}</div>
|
|
1533
1565
|
` : p}
|
|
1534
1566
|
</div>
|
|
1535
1567
|
</a>
|
|
@@ -1537,50 +1569,50 @@ class at extends y {
|
|
|
1537
1569
|
</div>` : p}
|
|
1538
1570
|
<div class="section-title">Season context</div>
|
|
1539
1571
|
<div class="cols">
|
|
1540
|
-
${[[e.awayTeamId,
|
|
1572
|
+
${[[e.awayTeamId, r], [e.homeTeamId, o]].map(([c, m]) => this.renderContext(t, c, m))}
|
|
1541
1573
|
</div>
|
|
1542
|
-
${
|
|
1574
|
+
${l.length ? n`
|
|
1543
1575
|
<div class="section-title">Head to head this season</div>
|
|
1544
1576
|
<div class="card"><ul class="gamelist">
|
|
1545
|
-
${
|
|
1546
|
-
<span class="d">${
|
|
1547
|
-
<span class="opp">${F(t,
|
|
1548
|
-
<a class="box" href=${g(t.hrefs.game, { sport: e.sport, id:
|
|
1577
|
+
${l.map((c) => n`<li>
|
|
1578
|
+
<span class="d">${x(c.date)}</span>${A(c)}
|
|
1579
|
+
<span class="opp">${F(t, c.awayTeamId)} ${c.awayScore}, ${F(t, c.homeTeamId)} ${c.homeScore}</span>
|
|
1580
|
+
<a class="box" href=${g(t.hrefs.game, { sport: e.sport, id: c.id })}>Box score →</a>
|
|
1549
1581
|
</li>`)}
|
|
1550
|
-
</ul></div>` : p}
|
|
1582
|
+
</ul></div>` : p}`}
|
|
1551
1583
|
`)}
|
|
1552
1584
|
`;
|
|
1553
1585
|
}
|
|
1554
|
-
teamBlock(e, t, s,
|
|
1555
|
-
if (!
|
|
1556
|
-
const
|
|
1586
|
+
teamBlock(e, t, s, r, o) {
|
|
1587
|
+
if (!r) return n`<div class="teamblock ${o ? "right" : ""}"><div class="tname">TBD</div></div>`;
|
|
1588
|
+
const i = e.teamsById[s], d = e.records[s], h = M(r, 58);
|
|
1557
1589
|
return n`
|
|
1558
|
-
<div class="teamblock ${
|
|
1559
|
-
${h ? n`<img class="crest logo" alt="" loading="lazy" src=${h} />` : n`<span class="crest" style="background:${
|
|
1590
|
+
<div class="teamblock ${o ? "right" : ""}">
|
|
1591
|
+
${h ? n`<img class="crest logo" alt="" loading="lazy" src=${h} />` : n`<span class="crest" style="background:${r.colorPrimary || "#030711"};color:${G(r.colorPrimary || "#030711")}">${Y(r)}</span>`}
|
|
1560
1592
|
<div>
|
|
1561
|
-
<div class="tname">${
|
|
1562
|
-
<div class="trec">${
|
|
1593
|
+
<div class="tname">${X(e, s, t.date)}<a href=${g(e.hrefs.school, { id: r.id })}>${r.name}</a></div>
|
|
1594
|
+
<div class="trec">${r.mascot || ""} · ${S(d)}${i?.conferenceId ? n` · ${S(d, !0)} conf` : p}</div>
|
|
1563
1595
|
</div>
|
|
1564
1596
|
</div>
|
|
1565
1597
|
`;
|
|
1566
1598
|
}
|
|
1567
1599
|
renderLineScore(e, t, s) {
|
|
1568
|
-
const
|
|
1569
|
-
if (!
|
|
1600
|
+
const r = tt(e);
|
|
1601
|
+
if (!r)
|
|
1570
1602
|
return e.state === "scheduled" ? n`<p class="empty" style="text-align:center">Period scoring will appear once the game starts.</p>` : p;
|
|
1571
|
-
const
|
|
1572
|
-
const m =
|
|
1573
|
-
return m ? m[
|
|
1574
|
-
}, h = (
|
|
1603
|
+
const o = Math.max(J(e.sport), ...r.map((l) => l.period)), i = (l) => Ze(e.sport, l), d = (l, c) => {
|
|
1604
|
+
const m = r.find((f) => f.period === c);
|
|
1605
|
+
return m ? m[l] : e.state === "final" ? 0 : "·";
|
|
1606
|
+
}, h = (l, c, m) => n`
|
|
1575
1607
|
<tr>
|
|
1576
|
-
<td class="teamcell">${
|
|
1577
|
-
${Array.from({ length:
|
|
1608
|
+
<td class="teamcell">${C(l, 20)}${l?.abbr || "TBD"}</td>
|
|
1609
|
+
${Array.from({ length: o }, (f, u) => n`<td class="num">${d(c, u + 1)}</td>`)}
|
|
1578
1610
|
<td class="num" style="font-weight:700">${m}</td>
|
|
1579
1611
|
</tr>`;
|
|
1580
1612
|
return n`
|
|
1581
1613
|
<div class="tablewrap" style="border-top:1px solid var(--hsot-gray-2)">
|
|
1582
1614
|
<table class="data" style="max-width:560px;margin:0.6rem auto 0.9rem">
|
|
1583
|
-
<thead><tr><th>Team</th>${Array.from({ length:
|
|
1615
|
+
<thead><tr><th>Team</th>${Array.from({ length: o }, (l, c) => n`<th class="num">${i(c + 1)}</th>`)}<th class="num">T</th></tr></thead>
|
|
1584
1616
|
<tbody>
|
|
1585
1617
|
${h(t, "away", e.awayScore)}
|
|
1586
1618
|
${h(s, "home", e.homeScore)}
|
|
@@ -1590,9 +1622,9 @@ class at extends y {
|
|
|
1590
1622
|
`;
|
|
1591
1623
|
}
|
|
1592
1624
|
renderScoringPlays(e, t, s) {
|
|
1593
|
-
const
|
|
1594
|
-
if (!
|
|
1595
|
-
const
|
|
1625
|
+
const r = Array.isArray(e.scoringPlays) ? e.scoringPlays : [];
|
|
1626
|
+
if (!r.length) return p;
|
|
1627
|
+
const o = (i) => [i.period, i.clock].filter(Boolean).join(" ");
|
|
1596
1628
|
return n`
|
|
1597
1629
|
<div class="plays">
|
|
1598
1630
|
<div class="plays-title">Scoring plays</div>
|
|
@@ -1603,11 +1635,11 @@ class at extends y {
|
|
|
1603
1635
|
<th class="num">${t?.abbr || "Away"}</th><th class="num">${s?.abbr || "Home"}</th>
|
|
1604
1636
|
</tr></thead>
|
|
1605
1637
|
<tbody>
|
|
1606
|
-
${
|
|
1607
|
-
<td class="when">${
|
|
1608
|
-
<td class="play">${
|
|
1609
|
-
<td class="num">${
|
|
1610
|
-
<td class="num">${
|
|
1638
|
+
${r.map((i) => n`<tr>
|
|
1639
|
+
<td class="when">${o(i) || "·"}</td>
|
|
1640
|
+
<td class="play">${i.description || "·"}</td>
|
|
1641
|
+
<td class="num">${i.awayScore}</td>
|
|
1642
|
+
<td class="num">${i.homeScore}</td>
|
|
1611
1643
|
</tr>`)}
|
|
1612
1644
|
</tbody>
|
|
1613
1645
|
</table>
|
|
@@ -1617,24 +1649,24 @@ class at extends y {
|
|
|
1617
1649
|
}
|
|
1618
1650
|
renderContext(e, t, s) {
|
|
1619
1651
|
if (!s) return p;
|
|
1620
|
-
const
|
|
1652
|
+
const r = e.records[t], o = K(this.data.games, t);
|
|
1621
1653
|
return n`
|
|
1622
1654
|
<div class="card ctxcard">
|
|
1623
|
-
<div class="who">${
|
|
1655
|
+
<div class="who">${C(s)}${s.name}</div>
|
|
1624
1656
|
<div class="row">
|
|
1625
|
-
<span>Last 5: ${
|
|
1626
|
-
<span>Streak: <b>${
|
|
1627
|
-
<span>PF/PA: <b>${
|
|
1628
|
-
<span>Next: ${
|
|
1629
|
-
${
|
|
1657
|
+
<span>Last 5: ${Z(e, t)}</span>
|
|
1658
|
+
<span>Streak: <b>${r ? U(r.results) : "·"}</b></span>
|
|
1659
|
+
<span>PF/PA: <b>${r ? `${r.pf} / ${r.pa}` : "·"}</b></span>
|
|
1660
|
+
<span>Next: ${o ? n`${x(o.date, { month: "numeric", day: "numeric" })}
|
|
1661
|
+
${o.homeTeamId === t ? "vs" : "at"} ${L(e, o.homeTeamId === t ? o.awayTeamId : o.homeTeamId)}` : "·"}</span>
|
|
1630
1662
|
</div>
|
|
1631
1663
|
</div>
|
|
1632
1664
|
`;
|
|
1633
1665
|
}
|
|
1634
1666
|
}
|
|
1635
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-boxscore") && globalThis.customElements.define("hsot-boxscore",
|
|
1636
|
-
const
|
|
1637
|
-
class
|
|
1667
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-boxscore") && globalThis.customElements.define("hsot-boxscore", it);
|
|
1668
|
+
const lt = 250, ct = 2;
|
|
1669
|
+
class dt extends le {
|
|
1638
1670
|
static properties = {
|
|
1639
1671
|
api: { type: String },
|
|
1640
1672
|
schoolHref: { type: String, attribute: "school-href" },
|
|
@@ -1645,7 +1677,7 @@ class nt extends ie {
|
|
|
1645
1677
|
activeIndex: { state: !0 },
|
|
1646
1678
|
searched: { state: !0 }
|
|
1647
1679
|
};
|
|
1648
|
-
static styles =
|
|
1680
|
+
static styles = w`
|
|
1649
1681
|
:host {
|
|
1650
1682
|
display: block;
|
|
1651
1683
|
position: relative;
|
|
@@ -1714,11 +1746,11 @@ class nt extends ie {
|
|
|
1714
1746
|
}
|
|
1715
1747
|
onInput(e) {
|
|
1716
1748
|
const t = e.target.value.trim();
|
|
1717
|
-
if (clearTimeout(this.debounceTimer), t.length <
|
|
1749
|
+
if (clearTimeout(this.debounceTimer), t.length < ct) {
|
|
1718
1750
|
this.abortController?.abort(), this.results = [], this.open = !1, this.searched = !1;
|
|
1719
1751
|
return;
|
|
1720
1752
|
}
|
|
1721
|
-
this.debounceTimer = setTimeout(() => this.search(t),
|
|
1753
|
+
this.debounceTimer = setTimeout(() => this.search(t), lt);
|
|
1722
1754
|
}
|
|
1723
1755
|
async search(e) {
|
|
1724
1756
|
this.abortController?.abort(), this.abortController = new AbortController();
|
|
@@ -1728,8 +1760,8 @@ class nt extends ie {
|
|
|
1728
1760
|
});
|
|
1729
1761
|
if (!s.ok)
|
|
1730
1762
|
return;
|
|
1731
|
-
const
|
|
1732
|
-
this.results =
|
|
1763
|
+
const r = await s.json();
|
|
1764
|
+
this.results = r.items || [], this.activeIndex = -1, this.searched = !0, this.open = !0;
|
|
1733
1765
|
} catch (t) {
|
|
1734
1766
|
t.name !== "AbortError" && console.warn("school search failed", t);
|
|
1735
1767
|
}
|
|
@@ -1763,15 +1795,15 @@ class nt extends ie {
|
|
|
1763
1795
|
return [e.location, e.county && `${e.county} County`].filter(Boolean).join(" — ");
|
|
1764
1796
|
}
|
|
1765
1797
|
renderOption(e, t) {
|
|
1766
|
-
const s = this.where(e),
|
|
1767
|
-
|
|
1798
|
+
const s = this.where(e), r = (o) => {
|
|
1799
|
+
o.preventDefault(), this.go(e);
|
|
1768
1800
|
};
|
|
1769
1801
|
return n`
|
|
1770
1802
|
<li
|
|
1771
1803
|
id="school-option-${t}"
|
|
1772
1804
|
role="option"
|
|
1773
1805
|
aria-selected="${t === this.activeIndex ? "true" : "false"}"
|
|
1774
|
-
@pointerdown="${
|
|
1806
|
+
@pointerdown="${r}"
|
|
1775
1807
|
@mousemove="${() => {
|
|
1776
1808
|
this.activeIndex = t;
|
|
1777
1809
|
}}"
|
|
@@ -1785,7 +1817,7 @@ class nt extends ie {
|
|
|
1785
1817
|
const e = this.searched && !this.results.length, t = n`<li class="empty">No schools found</li>`;
|
|
1786
1818
|
return n`
|
|
1787
1819
|
<ul id="school-search-listbox" role="listbox" aria-label="Schools">
|
|
1788
|
-
${this.results.map((s,
|
|
1820
|
+
${this.results.map((s, r) => this.renderOption(s, r))}
|
|
1789
1821
|
${e ? t : p}
|
|
1790
1822
|
</ul>
|
|
1791
1823
|
`;
|
|
@@ -1811,111 +1843,111 @@ class nt extends ie {
|
|
|
1811
1843
|
`;
|
|
1812
1844
|
}
|
|
1813
1845
|
}
|
|
1814
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-school-search") && globalThis.customElements.define("hsot-school-search",
|
|
1815
|
-
function
|
|
1816
|
-
const t = new Map(a.map((h) => [h.id, h])), s = /* @__PURE__ */ new Map(),
|
|
1846
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-school-search") && globalThis.customElements.define("hsot-school-search", dt);
|
|
1847
|
+
function $e(a, e) {
|
|
1848
|
+
const t = new Map(a.map((h) => [h.id, h])), s = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
|
|
1817
1849
|
for (const h of e || [])
|
|
1818
|
-
h.outcome === "winner" && (s.has(h.targetGameId) || s.set(h.targetGameId, []), s.get(h.targetGameId).push(h),
|
|
1819
|
-
const
|
|
1820
|
-
function
|
|
1821
|
-
const
|
|
1822
|
-
if (!
|
|
1823
|
-
const m = [...s.get(h) || []].sort((f, u) =>
|
|
1824
|
-
return { game:
|
|
1850
|
+
h.outcome === "winner" && (s.has(h.targetGameId) || s.set(h.targetGameId, []), s.get(h.targetGameId).push(h), r.has(h.sourceGameId) || r.set(h.sourceGameId, []), r.get(h.sourceGameId).push(h));
|
|
1851
|
+
const o = a.filter((h) => !r.has(h.id)), i = (h) => h.targetSlot === "home" ? 0 : 1;
|
|
1852
|
+
function d(h) {
|
|
1853
|
+
const l = t.get(h);
|
|
1854
|
+
if (!l) return null;
|
|
1855
|
+
const m = [...s.get(h) || []].sort((f, u) => i(f) - i(u)).map((f) => d(f.sourceGameId)).filter(Boolean);
|
|
1856
|
+
return { game: l, children: m, bracketGroup: l.bracketGroup };
|
|
1825
1857
|
}
|
|
1826
|
-
return
|
|
1858
|
+
return o.length === 1 ? d(o[0].id) : o.map((h) => d(h.id));
|
|
1827
1859
|
}
|
|
1828
|
-
function
|
|
1860
|
+
function we(a, e = [], t = 0) {
|
|
1829
1861
|
if (!a) return e;
|
|
1830
1862
|
e[t] || (e[t] = []), e[t].push(a.game);
|
|
1831
|
-
for (const s of a.children || [])
|
|
1863
|
+
for (const s of a.children || []) we(s, e, t + 1);
|
|
1832
1864
|
return e;
|
|
1833
1865
|
}
|
|
1834
|
-
const
|
|
1835
|
-
function
|
|
1836
|
-
const s =
|
|
1837
|
-
return
|
|
1866
|
+
const ht = (a) => Math.max(1, Math.round(Math.log2(a || 2)));
|
|
1867
|
+
function mt({ round: a, perGroup: e, groupCount: t = 1 }) {
|
|
1868
|
+
const s = ht(e), o = (t === 4 ? s + 2 : t === 2 ? s + 1 : s) - a;
|
|
1869
|
+
return o === 0 ? t > 1 ? "Championship" : "Final" : o === 1 ? "Semifinal" : `Round ${a}`;
|
|
1838
1870
|
}
|
|
1839
|
-
function
|
|
1871
|
+
function pt(a) {
|
|
1840
1872
|
if (!a || !a.length) return "setup";
|
|
1841
1873
|
const e = Math.max(...a.map((s) => s.round ?? 0)), t = a.filter((s) => (s.round ?? 0) === e);
|
|
1842
1874
|
return t.length && t.every((s) => s.state === "final") ? "complete" : a.some((s) => s.state !== "scheduled" || s.homeScore || s.awayScore || s.round === 1 && (s.homeTeamId || s.awayTeamId)) ? "active" : "setup";
|
|
1843
1875
|
}
|
|
1844
|
-
function
|
|
1876
|
+
function ft(a, e) {
|
|
1845
1877
|
const t = a?.groupNames || [];
|
|
1846
1878
|
if (t.length >= 2) {
|
|
1847
|
-
const
|
|
1848
|
-
return (e || []).some((
|
|
1879
|
+
const r = t.map((o) => ({ key: o, name: o }));
|
|
1880
|
+
return (e || []).some((o) => o.bracketGroup === "Championship") && r.push({ key: "Championship", name: "Championship" }), r;
|
|
1849
1881
|
}
|
|
1850
|
-
const s = [...new Set((e || []).map((
|
|
1882
|
+
const s = [...new Set((e || []).map((r) => r.bracketGroup).filter(Boolean))];
|
|
1851
1883
|
return [{ key: null, name: s.length === 1 ? s[0] : "Bracket" }];
|
|
1852
1884
|
}
|
|
1853
|
-
const
|
|
1885
|
+
const ut = (a, e) => e?.key == null ? [...a || []] : (a || []).filter((t) => t.bracketGroup === e.key), oe = (a) => {
|
|
1854
1886
|
const e = /(\d+)\s*$/.exec(a.label || "");
|
|
1855
1887
|
return e ? Number(e[1]) : 1 / 0;
|
|
1856
|
-
},
|
|
1857
|
-
function
|
|
1858
|
-
if (a.every((
|
|
1859
|
-
const t =
|
|
1860
|
-
for (const
|
|
1861
|
-
const
|
|
1862
|
-
|
|
1863
|
-
}
|
|
1864
|
-
return (
|
|
1865
|
-
}
|
|
1866
|
-
function
|
|
1867
|
-
const s =
|
|
1888
|
+
}, ne = (a, e) => oe(a) - oe(e) || String(a.id).localeCompare(String(e.id));
|
|
1889
|
+
function gt(a, e) {
|
|
1890
|
+
if (a.every((r) => Number.isInteger(r.round))) return (r) => r.round;
|
|
1891
|
+
const t = $e(a, e), s = /* @__PURE__ */ new Map();
|
|
1892
|
+
for (const r of Array.isArray(t) ? t : [t]) {
|
|
1893
|
+
const o = we(r), i = o.length - 1;
|
|
1894
|
+
o.forEach((d, h) => d.forEach((l) => s.set(l.id, i - h + 1)));
|
|
1895
|
+
}
|
|
1896
|
+
return (r) => Number.isInteger(r.round) ? r.round : s.get(r.id) || 1;
|
|
1897
|
+
}
|
|
1898
|
+
function vt(a, e, t) {
|
|
1899
|
+
const s = ut(a, t);
|
|
1868
1900
|
if (!s.length) return [];
|
|
1869
|
-
const
|
|
1870
|
-
for (const
|
|
1871
|
-
const
|
|
1872
|
-
|
|
1873
|
-
}
|
|
1874
|
-
const
|
|
1875
|
-
for (const
|
|
1876
|
-
|
|
1877
|
-
const
|
|
1901
|
+
const r = gt(a || [], e || []), o = /* @__PURE__ */ new Map();
|
|
1902
|
+
for (const l of s) {
|
|
1903
|
+
const c = r(l);
|
|
1904
|
+
o.has(c) || o.set(c, []), o.get(c).push(l);
|
|
1905
|
+
}
|
|
1906
|
+
const i = /* @__PURE__ */ new Map();
|
|
1907
|
+
for (const l of e || [])
|
|
1908
|
+
l.outcome === "winner" && (i.has(l.targetGameId) || i.set(l.targetGameId, []), i.get(l.targetGameId).push(l.sourceGameId));
|
|
1909
|
+
const d = [];
|
|
1878
1910
|
let h = null;
|
|
1879
|
-
for (const
|
|
1880
|
-
let
|
|
1911
|
+
for (const l of [...o.keys()].sort((c, m) => c - m)) {
|
|
1912
|
+
let c = [...o.get(l)];
|
|
1881
1913
|
if (h) {
|
|
1882
1914
|
const m = (f) => {
|
|
1883
|
-
const u = (
|
|
1915
|
+
const u = (i.get(f.id) || []).map((y) => h.get(y)).filter((y) => y !== void 0);
|
|
1884
1916
|
return u.length ? Math.min(...u) : 1 / 0;
|
|
1885
1917
|
};
|
|
1886
|
-
|
|
1918
|
+
c.sort((f, u) => m(f) - m(u) || ne(f, u));
|
|
1887
1919
|
} else
|
|
1888
|
-
|
|
1889
|
-
h = new Map(
|
|
1920
|
+
c.sort(ne);
|
|
1921
|
+
h = new Map(c.map((m, f) => [m.id, f])), d.push({ round: l, games: c });
|
|
1890
1922
|
}
|
|
1891
|
-
return
|
|
1923
|
+
return d;
|
|
1892
1924
|
}
|
|
1893
|
-
function
|
|
1894
|
-
const s = a[`${e}TeamId`] || null,
|
|
1895
|
-
return { teamId: s, seed:
|
|
1925
|
+
function bt(a, e, t) {
|
|
1926
|
+
const s = a[`${e}TeamId`] || null, r = (t || []).find((i) => i.gameId === a.id && i.slot === e), o = a[`${e}Seed`] ?? r?.seed ?? null;
|
|
1927
|
+
return { teamId: s, seed: o, bye: !s && !!r?.isBye };
|
|
1896
1928
|
}
|
|
1897
|
-
function
|
|
1898
|
-
const e =
|
|
1929
|
+
function xe(a) {
|
|
1930
|
+
const e = H(a);
|
|
1899
1931
|
return e === "home" || e === "away" ? e : null;
|
|
1900
1932
|
}
|
|
1901
|
-
function
|
|
1902
|
-
const t =
|
|
1933
|
+
function yt(a, e) {
|
|
1934
|
+
const t = $e(a || [], e || []);
|
|
1903
1935
|
if (!t || Array.isArray(t)) return null;
|
|
1904
|
-
const s =
|
|
1936
|
+
const s = xe(t.game);
|
|
1905
1937
|
return s && t.game[`${s}TeamId`] || null;
|
|
1906
1938
|
}
|
|
1907
|
-
const
|
|
1908
|
-
function
|
|
1939
|
+
const ie = { active: 0, setup: 1, complete: 2 };
|
|
1940
|
+
function $t(a, { id: e, param: t } = {}) {
|
|
1909
1941
|
const s = a || [];
|
|
1910
1942
|
if (!s.length) return null;
|
|
1911
|
-
for (const
|
|
1912
|
-
if (!
|
|
1913
|
-
const
|
|
1914
|
-
if (
|
|
1943
|
+
for (const r of [e, t]) {
|
|
1944
|
+
if (!r) continue;
|
|
1945
|
+
const o = s.find((i) => i.id === r);
|
|
1946
|
+
if (o) return o;
|
|
1915
1947
|
}
|
|
1916
|
-
return [...s].sort((
|
|
1948
|
+
return [...s].sort((r, o) => (ie[r.status] ?? 3) - (ie[o.status] ?? 3) || String(r.name || "").localeCompare(String(o.name || "")))[0];
|
|
1917
1949
|
}
|
|
1918
|
-
const
|
|
1950
|
+
const wt = w`
|
|
1919
1951
|
.bracket { display: flex; gap: 1rem; align-items: stretch; overflow-x: auto; padding-bottom: 0.5rem; }
|
|
1920
1952
|
.round { flex: 0 0 250px; display: flex; flex-direction: column; min-width: 0; }
|
|
1921
1953
|
.roundhead {
|
|
@@ -1961,10 +1993,10 @@ const vt = $`
|
|
|
1961
1993
|
.champ .tname a { color: inherit; text-decoration: none; font-weight: 700; }
|
|
1962
1994
|
@media (max-width: 720px) { .round { flex-basis: 215px; } }
|
|
1963
1995
|
`;
|
|
1964
|
-
class
|
|
1965
|
-
static styles = [P,
|
|
1996
|
+
class xt extends $ {
|
|
1997
|
+
static styles = [P, wt];
|
|
1966
1998
|
static properties = {
|
|
1967
|
-
|
|
1999
|
+
...$.properties,
|
|
1968
2000
|
sport: { type: String },
|
|
1969
2001
|
season: { type: String },
|
|
1970
2002
|
tournamentId: { type: String, attribute: "tournament-id" },
|
|
@@ -1975,24 +2007,24 @@ class bt extends y {
|
|
|
1975
2007
|
super(), this.sport = "football", this.season = "", this.tournamentId = "", this.picked = "", this.group = null;
|
|
1976
2008
|
}
|
|
1977
2009
|
async fetchData(e) {
|
|
1978
|
-
const t = this.season ||
|
|
1979
|
-
if (!
|
|
1980
|
-
const [
|
|
1981
|
-
e.listSeedings(
|
|
1982
|
-
e.listEdges(
|
|
1983
|
-
e.listGames({ tournamentId:
|
|
2010
|
+
const t = this.season || _(), s = (await e.listTournaments({ sport: this.sport, season: t })).items, r = new URLSearchParams(globalThis.location?.search || "").get("tournament"), o = $t(s, { id: this.picked || this.tournamentId, param: r });
|
|
2011
|
+
if (!o) return { season: t, tournaments: s, tournament: null };
|
|
2012
|
+
const [i, d, h, l, c] = await Promise.all([
|
|
2013
|
+
e.listSeedings(o.id),
|
|
2014
|
+
e.listEdges(o.id),
|
|
2015
|
+
e.listGames({ tournamentId: o.id }),
|
|
1984
2016
|
e.listSchools(),
|
|
1985
2017
|
e.listTeams({ sport: this.sport })
|
|
1986
2018
|
]);
|
|
1987
2019
|
return {
|
|
1988
2020
|
season: t,
|
|
1989
2021
|
tournaments: s,
|
|
1990
|
-
tournament:
|
|
1991
|
-
seedings:
|
|
1992
|
-
edges:
|
|
2022
|
+
tournament: o,
|
|
2023
|
+
seedings: i.items,
|
|
2024
|
+
edges: d.items,
|
|
1993
2025
|
games: h.items,
|
|
1994
|
-
schools:
|
|
1995
|
-
teams:
|
|
2026
|
+
schools: l.items,
|
|
2027
|
+
teams: c.items
|
|
1996
2028
|
};
|
|
1997
2029
|
}
|
|
1998
2030
|
get ctx() {
|
|
@@ -2018,46 +2050,46 @@ class bt extends y {
|
|
|
2018
2050
|
}
|
|
2019
2051
|
}
|
|
2020
2052
|
renderView() {
|
|
2021
|
-
const e = this.data, t = this.ctx, s =
|
|
2022
|
-
title: n`${
|
|
2053
|
+
const e = this.data, t = this.ctx, s = j(this, t, {
|
|
2054
|
+
title: n`${k(this.sport)} playoff brackets`,
|
|
2023
2055
|
sub: e.tournament ? n`${e.tournament.name} · ${e.season} season` : n`${e.season} season`,
|
|
2024
2056
|
teams: e.teams
|
|
2025
2057
|
});
|
|
2026
2058
|
if (!e.tournament)
|
|
2027
|
-
return n`${s}${
|
|
2028
|
-
${
|
|
2059
|
+
return n`${s}${D(this, n`
|
|
2060
|
+
${B(this)}
|
|
2029
2061
|
<div class="card"><div class="empty">No ${this.sport} brackets have been published for the ${e.season} season yet.</div></div>
|
|
2030
2062
|
`)}`;
|
|
2031
|
-
const
|
|
2063
|
+
const r = ft(e.tournament, e.games), o = r.find((m) => m.key === this.group) || r[0], i = (e.tournament.groupNames || []).length >= 2 ? e.tournament.groupNames.length : 1, d = (Number(e.tournament.size) || 0) / i, h = vt(e.games, e.edges, o), l = pt(e.games), c = yt(e.games, e.edges);
|
|
2032
2064
|
return n`
|
|
2033
2065
|
${s}
|
|
2034
|
-
${
|
|
2035
|
-
${
|
|
2066
|
+
${D(this, n`
|
|
2067
|
+
${B(this)}
|
|
2036
2068
|
<div class="toolbar">
|
|
2037
2069
|
${e.tournaments.length > 1 ? n`
|
|
2038
2070
|
<div role="group" aria-label="Tournament">
|
|
2039
2071
|
${e.tournaments.map((m) => n`<button class="chip ${m.id === e.tournament.id ? "on" : ""}"
|
|
2040
2072
|
@click=${() => this.pick(m.id)}>${m.name}</button>`)}
|
|
2041
2073
|
</div>` : p}
|
|
2042
|
-
${
|
|
2074
|
+
${r.length > 1 ? n`
|
|
2043
2075
|
<div role="tablist" aria-label="Bracket group">
|
|
2044
|
-
${
|
|
2045
|
-
aria-selected=${m.key ===
|
|
2076
|
+
${r.map((m) => n`<button class="chip ${m.key === o.key ? "on" : ""}" role="tab"
|
|
2077
|
+
aria-selected=${m.key === o.key ? "true" : "false"}
|
|
2046
2078
|
@click=${() => {
|
|
2047
2079
|
this.group = m.key;
|
|
2048
2080
|
}}>${m.name}</button>`)}
|
|
2049
2081
|
</div>` : p}
|
|
2050
2082
|
<span class="spacer"></span>
|
|
2051
|
-
<span class="pill ${
|
|
2083
|
+
<span class="pill ${l === "complete" ? "final" : l === "active" ? "class" : "type"}">${l === "complete" ? "Complete" : l === "active" ? "In progress" : "Bracket set"}</span>
|
|
2052
2084
|
<span class="asof">${e.tournament.size}-team ${String(e.tournament.format || "").replace(/_/g, " ")}</span>
|
|
2053
2085
|
</div>
|
|
2054
|
-
${
|
|
2055
|
-
${T(
|
|
2086
|
+
${c ? n`<div class="champ"><span class="pill champ">Champion</span>
|
|
2087
|
+
${C(T(t, c), 26)}<span class="tname">${O(t, c)}</span></div>` : p}
|
|
2056
2088
|
${h.length ? n`
|
|
2057
|
-
<div class="bracket" role="region" aria-label="${
|
|
2089
|
+
<div class="bracket" role="region" aria-label="${o.name} bracket">
|
|
2058
2090
|
${h.map((m) => n`
|
|
2059
2091
|
<section class="round">
|
|
2060
|
-
<h3 class="roundhead">${
|
|
2092
|
+
<h3 class="roundhead">${mt({ round: m.round, perGroup: d, groupCount: i })}</h3>
|
|
2061
2093
|
<div class="games">${m.games.map((f) => this.renderMatchup(t, f))}</div>
|
|
2062
2094
|
</section>`)}
|
|
2063
2095
|
</div>` : n`<div class="card"><div class="empty">This bracket has no games yet.</div></div>`}
|
|
@@ -2080,41 +2112,40 @@ class bt extends y {
|
|
|
2080
2112
|
`;
|
|
2081
2113
|
}
|
|
2082
2114
|
renderSlot(e, t, s) {
|
|
2083
|
-
const { teamId:
|
|
2115
|
+
const { teamId: r, seed: o, bye: i } = bt(t, s, this.data.seedings), d = xe(t), h = t.state === "live" || t.state === "final";
|
|
2084
2116
|
return n`
|
|
2085
|
-
<div class="slot ${
|
|
2086
|
-
<span class="seed">${
|
|
2087
|
-
${
|
|
2117
|
+
<div class="slot ${d ? d === s ? "winner" : "loser" : ""}">
|
|
2118
|
+
<span class="seed">${o ?? ""}</span>
|
|
2119
|
+
${r ? n`${C(T(e, r), 22)}<span class="tname">${O(e, r, t.date)}</span>` : i ? n`<span class="tname bye">Bye</span>` : n`<span class="tname mut">TBD</span>`}
|
|
2088
2120
|
${h ? n`<span class="score">${t[`${s}Score`] ?? 0}</span>` : p}
|
|
2089
2121
|
</div>
|
|
2090
2122
|
`;
|
|
2091
2123
|
}
|
|
2092
2124
|
}
|
|
2093
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-brackets") && globalThis.customElements.define("hsot-brackets",
|
|
2125
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-brackets") && globalThis.customElements.define("hsot-brackets", xt);
|
|
2094
2126
|
export {
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
ve as w
|
|
2127
|
+
E as D,
|
|
2128
|
+
it as H,
|
|
2129
|
+
xt as a,
|
|
2130
|
+
Ke as b,
|
|
2131
|
+
Xe as c,
|
|
2132
|
+
dt as d,
|
|
2133
|
+
We as e,
|
|
2134
|
+
Ve as f,
|
|
2135
|
+
ft as g,
|
|
2136
|
+
$e as h,
|
|
2137
|
+
yt as i,
|
|
2138
|
+
N as j,
|
|
2139
|
+
pt as k,
|
|
2140
|
+
g as l,
|
|
2141
|
+
H as m,
|
|
2142
|
+
It as n,
|
|
2143
|
+
mt as o,
|
|
2144
|
+
Ue as p,
|
|
2145
|
+
vt as q,
|
|
2146
|
+
S as r,
|
|
2147
|
+
fe as s,
|
|
2148
|
+
U as t,
|
|
2149
|
+
Q as u,
|
|
2150
|
+
we as v
|
|
2120
2151
|
};
|