@wral/hsot-data 0.1.5 → 0.1.7
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 +31 -3
- package/dist/define.mjs +9 -8
- package/dist/define.standalone.js +823 -581
- package/dist/{hsot-boxscore-B_yZEV8T.js → hsot-school-search-31NEMjUb.js} +657 -415
- package/dist/index.mjs +9 -8
- package/package.json +1 -1
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { LitElement as
|
|
2
|
-
const
|
|
3
|
-
function
|
|
1
|
+
import { LitElement as te, html as i, css as b, nothing as p, svg as X } from "lit";
|
|
2
|
+
const ne = 50;
|
|
3
|
+
function le(a = {}) {
|
|
4
4
|
const e = Object.entries(a).filter(([, s]) => s != null && s !== "");
|
|
5
5
|
if (!e.length) return "";
|
|
6
6
|
const t = new URLSearchParams();
|
|
7
7
|
return e.forEach(([s, r]) => t.set(s, String(r))), `?${t.toString()}`;
|
|
8
8
|
}
|
|
9
|
-
function
|
|
9
|
+
function ce({ baseUrl: a, token: e = "", fetchFn: t } = {}) {
|
|
10
10
|
if (!a) throw new Error("createClient requires a baseUrl");
|
|
11
|
-
const s = a.replace(/\/+$/, ""), r = t || ((...
|
|
12
|
-
async function o(
|
|
13
|
-
const
|
|
14
|
-
e && (
|
|
15
|
-
const
|
|
16
|
-
if (!
|
|
17
|
-
const
|
|
18
|
-
throw
|
|
11
|
+
const s = a.replace(/\/+$/, ""), r = t || ((...n) => fetch(...n));
|
|
12
|
+
async function o(n) {
|
|
13
|
+
const h = { Accept: "application/json" };
|
|
14
|
+
e && (h.Authorization = `Bearer ${e}`);
|
|
15
|
+
const l = await r(`${s}${n}`, { headers: h });
|
|
16
|
+
if (!l.ok) {
|
|
17
|
+
const d = new Error(`api-hsot ${l.status} on ${n}`);
|
|
18
|
+
throw d.status = l.status, d;
|
|
19
19
|
}
|
|
20
|
-
return
|
|
21
|
-
}
|
|
22
|
-
async function n
|
|
23
|
-
const
|
|
24
|
-
let
|
|
25
|
-
for (let m = 0; m <
|
|
26
|
-
const f =
|
|
27
|
-
if (
|
|
20
|
+
return l.json();
|
|
21
|
+
}
|
|
22
|
+
async function c(n, h = {}) {
|
|
23
|
+
const l = [];
|
|
24
|
+
let d = null;
|
|
25
|
+
for (let m = 0; m < ne; m += 1) {
|
|
26
|
+
const f = le(d ? { ...h, cursor: d } : h), g = await o(`${n}${f}`);
|
|
27
|
+
if (l.push(...g.items || []), d = g.nextCursor || null, !d) break;
|
|
28
28
|
}
|
|
29
|
-
return { items:
|
|
29
|
+
return { items: l, total: l.length, nextCursor: null };
|
|
30
30
|
}
|
|
31
31
|
return {
|
|
32
|
-
listSchools: (
|
|
33
|
-
getSchool: (
|
|
34
|
-
listTeams: (
|
|
35
|
-
getTeam: (
|
|
36
|
-
listConferences: (
|
|
37
|
-
listPlayers: (
|
|
38
|
-
listRosters: (
|
|
39
|
-
listGames: (
|
|
40
|
-
getGame: (
|
|
41
|
-
listTournaments: (
|
|
42
|
-
listSeedings: (
|
|
43
|
-
listRankings: (
|
|
32
|
+
listSchools: (n) => c("/schools", n),
|
|
33
|
+
getSchool: (n) => o(`/schools/${n}`),
|
|
34
|
+
listTeams: (n) => c("/teams", n),
|
|
35
|
+
getTeam: (n) => o(`/teams/${n}`),
|
|
36
|
+
listConferences: (n) => c("/conferences", n),
|
|
37
|
+
listPlayers: (n) => c("/players", n),
|
|
38
|
+
listRosters: (n) => c("/rosters", n),
|
|
39
|
+
listGames: (n) => c("/games", n),
|
|
40
|
+
getGame: (n) => o(`/games/${n}`),
|
|
41
|
+
listTournaments: (n) => c("/tournaments", n),
|
|
42
|
+
listSeedings: (n, h) => c(`/tournaments/${n}/seedings`, h),
|
|
43
|
+
listRankings: (n) => c("/rankings", n),
|
|
44
44
|
listSports: () => o("/sports")
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
const
|
|
47
|
+
const H = {
|
|
48
48
|
game: "/{sport}/game/{id}/",
|
|
49
49
|
school: "/school/{id}/",
|
|
50
50
|
section: "/{sport}/{view}/"
|
|
@@ -54,56 +54,62 @@ function u(a, e) {
|
|
|
54
54
|
}
|
|
55
55
|
function D(a) {
|
|
56
56
|
return {
|
|
57
|
-
game: a.getAttribute("game-href") ||
|
|
58
|
-
school: a.getAttribute("school-href") ||
|
|
59
|
-
section: a.getAttribute("section-href") ||
|
|
57
|
+
game: a.getAttribute("game-href") || H.game,
|
|
58
|
+
school: a.getAttribute("school-href") || H.school,
|
|
59
|
+
section: a.getAttribute("section-href") || H.section
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
const T = (a) => a ? a.charAt(0).toUpperCase() + a.slice(1) : "";
|
|
63
|
-
function
|
|
63
|
+
function $(a, e) {
|
|
64
64
|
if (!a) return "TBD";
|
|
65
65
|
const [t, s, r] = String(a).split("-").map(Number);
|
|
66
66
|
return !t || !s || !r ? "TBD" : new Date(t, s - 1, r).toLocaleDateString("en-US", e || { weekday: "short", month: "short", day: "numeric" });
|
|
67
67
|
}
|
|
68
|
-
function
|
|
68
|
+
function M(a) {
|
|
69
69
|
if (!a) return "";
|
|
70
70
|
const [e, t] = String(a).split(":").map(Number);
|
|
71
71
|
if (Number.isNaN(e)) return "";
|
|
72
72
|
const s = e >= 12 ? "PM" : "AM";
|
|
73
73
|
return `${(e + 11) % 12 + 1}:${String(t || 0).padStart(2, "0")} ${s}`;
|
|
74
74
|
}
|
|
75
|
-
function
|
|
75
|
+
function de(a) {
|
|
76
76
|
return a ? `${Math.floor(a / 12)}-${a % 12}` : "·";
|
|
77
77
|
}
|
|
78
|
-
function
|
|
78
|
+
function L(a = /* @__PURE__ */ new Date()) {
|
|
79
79
|
const e = a.getFullYear();
|
|
80
80
|
return a.getMonth() >= 6 ? `${e}-${e + 1}` : `${e - 1}-${e}`;
|
|
81
81
|
}
|
|
82
|
-
function
|
|
82
|
+
function j(a = /* @__PURE__ */ new Date()) {
|
|
83
83
|
const e = (t) => String(t).padStart(2, "0");
|
|
84
84
|
return `${a.getFullYear()}-${e(a.getMonth() + 1)}-${e(a.getDate())}`;
|
|
85
85
|
}
|
|
86
|
-
function
|
|
86
|
+
function he(a, e = j()) {
|
|
87
|
+
const t = [...new Set((a || []).filter(Boolean))].sort();
|
|
88
|
+
if (!t.length || t.includes(e)) return e;
|
|
89
|
+
const s = t.filter((r) => r < e);
|
|
90
|
+
return s.length ? s[s.length - 1] : t[0];
|
|
91
|
+
}
|
|
92
|
+
function G(a) {
|
|
87
93
|
return a ? (a.abbr || a.name || "?").slice(0, 4).toUpperCase() : "?";
|
|
88
94
|
}
|
|
89
|
-
function
|
|
95
|
+
function E(a) {
|
|
90
96
|
if (!a || !/^#[0-9a-fA-F]{6}$/.test(a)) return "#FFFFFF";
|
|
91
97
|
const e = parseInt(a.slice(1), 16), t = e >> 16 & 255, s = e >> 8 & 255, r = e & 255;
|
|
92
98
|
return 0.299 * t + 0.587 * s + 0.114 * r > 150 ? "#0F1B33" : "#FFFFFF";
|
|
93
99
|
}
|
|
94
|
-
const
|
|
100
|
+
const me = (a) => {
|
|
95
101
|
const e = ["th", "st", "nd", "rd"], t = a % 100;
|
|
96
102
|
return a + (e[(t - 20) % 10] || e[t] || e[0]);
|
|
97
103
|
};
|
|
98
|
-
function
|
|
104
|
+
function se(a) {
|
|
99
105
|
if (a.state === "live") return { kind: "live", label: `Live · ${a.period || ""}`.replace(/ · $/, "") };
|
|
100
106
|
if (a.state === "final") {
|
|
101
107
|
const e = [];
|
|
102
108
|
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(" · ")}` : ""}` };
|
|
103
109
|
}
|
|
104
|
-
return a.state === "postponed" ? { kind: "warn", label: "Postponed" } : a.state === "canceled" ? { kind: "warn", label: "Canceled" } : { kind: "sched", label: `${
|
|
110
|
+
return a.state === "postponed" ? { kind: "warn", label: "Postponed" } : a.state === "canceled" ? { kind: "warn", label: "Canceled" } : { kind: "sched", label: `${$(a.date, { month: "short", day: "numeric" })} · ${M(a.time)}`.replace(/ · $/, "") };
|
|
105
111
|
}
|
|
106
|
-
const
|
|
112
|
+
const pe = /* @__PURE__ */ new Set(["game", "story", "page", "forum", "video", "gallery"]);
|
|
107
113
|
function x(a) {
|
|
108
114
|
let e = String(a || "").replace(/^[a-z][a-z0-9+.-]*:\/\/[^/#?]*/i, "");
|
|
109
115
|
const t = e.indexOf("#");
|
|
@@ -112,26 +118,26 @@ function x(a) {
|
|
|
112
118
|
let r = e.split("?")[0] + s;
|
|
113
119
|
return r = r.replace(/([^:])\/{2,}/g, "$1/").replace(/^\/{2,}/, "/"), r = r.replace(/^\/(?=#)/, ""), r.length > 1 && (r = r.replace(/\/+$/, "")), r.toLowerCase();
|
|
114
120
|
}
|
|
115
|
-
function
|
|
121
|
+
function ae() {
|
|
116
122
|
const a = globalThis.location;
|
|
117
123
|
if (!a) return "";
|
|
118
124
|
const e = (a.hash || "").startsWith("#/") ? a.hash : "";
|
|
119
125
|
return x((a.pathname || "") + e);
|
|
120
126
|
}
|
|
121
|
-
function
|
|
127
|
+
function fe(a, e, t) {
|
|
122
128
|
if (!t) return null;
|
|
123
129
|
const s = x(a);
|
|
124
130
|
if (!s) return null;
|
|
125
131
|
const r = x(u(e.game, { sport: t, id: "" })), o = x(u(e.school, { id: "" }));
|
|
126
132
|
if (s === r || s.startsWith(`${r}/`) || s === o || s.startsWith(`${o}/`)) return null;
|
|
127
|
-
const
|
|
128
|
-
if (s ===
|
|
129
|
-
if (!s.startsWith(`${
|
|
130
|
-
const
|
|
131
|
-
return
|
|
133
|
+
const c = x(u(e.section, { sport: t, view: "" }));
|
|
134
|
+
if (s === c) return "";
|
|
135
|
+
if (!s.startsWith(`${c}/`)) return null;
|
|
136
|
+
const n = s.slice(c.length + 1), h = n.split("/");
|
|
137
|
+
return h.length > 2 || h.some((l) => !/^[a-z][a-z-]*$/.test(l)) || pe.has(h[0]) ? null : n;
|
|
132
138
|
}
|
|
133
|
-
function
|
|
134
|
-
const s = (
|
|
139
|
+
function ue(a, e, t) {
|
|
140
|
+
const s = (c) => u(t.section, { sport: a, view: c }).replace(/([^:])\/{2,}/g, "$1/"), o = new Set((e || []).map((c) => c && c.gender).filter((c) => c === "boys" || c === "girls")).size === 2 ? [
|
|
135
141
|
{ label: "Boys Standings", href: s("boys/standings") },
|
|
136
142
|
{ label: "Girls Standings", href: s("girls/standings") }
|
|
137
143
|
] : [{ label: "Standings", href: s("standings") }];
|
|
@@ -143,28 +149,31 @@ function me(a, e, t) {
|
|
|
143
149
|
{ label: "Polls & Rankings", href: s("rankings") }
|
|
144
150
|
];
|
|
145
151
|
}
|
|
146
|
-
function
|
|
152
|
+
function ge(a, e = ae()) {
|
|
147
153
|
const t = x(e);
|
|
148
154
|
for (const s of a.querySelectorAll(':scope > a[slot="nav"]'))
|
|
149
155
|
t && x(s.getAttribute("href")) === t ? s.setAttribute("aria-current", "page") : s.removeAttribute("aria-current");
|
|
150
156
|
}
|
|
151
|
-
class
|
|
157
|
+
class y extends te {
|
|
152
158
|
static properties = {
|
|
153
159
|
api: { type: String },
|
|
154
160
|
refreshInterval: { type: Number, attribute: "refresh-interval" },
|
|
161
|
+
promoHref: { type: String, attribute: "promo-href" },
|
|
162
|
+
promoImage: { type: String, attribute: "promo-image" },
|
|
163
|
+
promoAlt: { type: String, attribute: "promo-alt" },
|
|
155
164
|
data: { state: !0 },
|
|
156
165
|
loading: { state: !0 },
|
|
157
166
|
error: { state: !0 }
|
|
158
167
|
};
|
|
159
168
|
constructor() {
|
|
160
|
-
super(), this.api = "", this.refreshInterval = 0, this.data = null, this.loading = !1, this.error = "", this._client = null, this._refreshId = null;
|
|
169
|
+
super(), this.api = "", this.refreshInterval = 0, this.promoHref = "", this.promoImage = "", this.promoAlt = "", this.data = null, this.loading = !1, this.error = "", this._client = null, this._refreshId = null;
|
|
161
170
|
}
|
|
162
171
|
/** Injected client wins; otherwise build a fetch client from the api attribute. */
|
|
163
172
|
set client(e) {
|
|
164
173
|
this._client = e, this.isConnected && this.load();
|
|
165
174
|
}
|
|
166
175
|
get client() {
|
|
167
|
-
return this._client ? this._client : this.api ?
|
|
176
|
+
return this._client ? this._client : this.api ? ce({ baseUrl: this.api }) : null;
|
|
168
177
|
}
|
|
169
178
|
connectedCallback() {
|
|
170
179
|
super.connectedCallback(), this._setupInterval();
|
|
@@ -176,7 +185,7 @@ class $ extends ae {
|
|
|
176
185
|
this.load();
|
|
177
186
|
}
|
|
178
187
|
updated(e) {
|
|
179
|
-
e.has("api") && e.get("api") !== void 0 && e.get("api") !== this.api && this.load(), e.has("refreshInterval") && this._setupInterval(),
|
|
188
|
+
e.has("api") && e.get("api") !== void 0 && e.get("api") !== this.api && this.load(), e.has("refreshInterval") && this._setupInterval(), ge(this);
|
|
180
189
|
}
|
|
181
190
|
async load() {
|
|
182
191
|
const e = this.client;
|
|
@@ -205,13 +214,13 @@ class $ extends ae {
|
|
|
205
214
|
this._refreshId && (clearInterval(this._refreshId), this._refreshId = null);
|
|
206
215
|
}
|
|
207
216
|
render() {
|
|
208
|
-
return this.error === "not-configured" ?
|
|
217
|
+
return this.error === "not-configured" ? i`<div class="error">This component needs an <code>api</code> attribute (the api-hsot public read-surface base URL) or an injected client.</div>` : this.error ? i`<div class="error">Unable to load right now. <button class="chip" @click=${() => this.load()}>Retry</button></div>` : this.data ? this.renderView() : i`<div class="loading" role="status">Loading…</div>`;
|
|
209
218
|
}
|
|
210
219
|
renderView() {
|
|
211
|
-
return
|
|
220
|
+
return i``;
|
|
212
221
|
}
|
|
213
222
|
}
|
|
214
|
-
const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])),
|
|
223
|
+
const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ve = b`
|
|
215
224
|
:host {
|
|
216
225
|
--hsot-red: var(--color-red, #D1232A);
|
|
217
226
|
--hsot-red-deep: var(--color-red-dark, #951C21);
|
|
@@ -249,7 +258,7 @@ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), fe = y`
|
|
|
249
258
|
outline-offset: 1px;
|
|
250
259
|
}
|
|
251
260
|
.mut { color: var(--hsot-gray-5); }
|
|
252
|
-
`,
|
|
261
|
+
`, be = b`
|
|
253
262
|
.band { background: var(--hsot-white); color: var(--hsot-black); }
|
|
254
263
|
.band .inner { max-width: 1366px; margin: 0 auto; padding: 1.1rem 1.25rem 0; }
|
|
255
264
|
.band h1, .band h2.bandtitle {
|
|
@@ -298,8 +307,29 @@ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), fe = y`
|
|
|
298
307
|
@media (max-width: 720px) {
|
|
299
308
|
.band h1, .band h2.bandtitle, .band.section h1, .band.section h2.bandtitle { font-size: 1.8rem; }
|
|
300
309
|
}
|
|
301
|
-
`,
|
|
310
|
+
`, $e = b`
|
|
302
311
|
.view { max-width: 1366px; margin: 0 auto; padding: 1.25rem; box-sizing: border-box; }
|
|
312
|
+
/* Optional right rail (slot="rail" light-DOM children): a divided 300px
|
|
313
|
+
column on desktop, stacked under the view content on smaller screens. */
|
|
314
|
+
.viewmain, .viewrail { min-width: 0; }
|
|
315
|
+
.view.withrail .viewrail {
|
|
316
|
+
margin-top: 2rem; padding-top: 2rem;
|
|
317
|
+
border-top: 1px solid var(--hsot-gray-2, #E5E3E1);
|
|
318
|
+
}
|
|
319
|
+
@media (min-width: 1200px) {
|
|
320
|
+
.view.withrail {
|
|
321
|
+
/* 332px = 300px rail content + the 2rem divider padding. */
|
|
322
|
+
display: grid; grid-template-columns: minmax(0, 1fr) 332px;
|
|
323
|
+
gap: 2rem; align-items: stretch;
|
|
324
|
+
}
|
|
325
|
+
.view.withrail .viewrail {
|
|
326
|
+
margin-top: 0; padding-top: 0; border-top: none;
|
|
327
|
+
padding-left: 2rem;
|
|
328
|
+
border-left: 1px solid var(--hsot-gray-2, #E5E3E1);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
.promo { text-align: center; margin: 0 0 1.1rem; }
|
|
332
|
+
.promo img { max-width: 100%; height: auto; display: inline-block; }
|
|
303
333
|
.toolbar { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin: 0 0 1.1rem; }
|
|
304
334
|
.toolbar .spacer { flex: 1; }
|
|
305
335
|
.asof { font-size: 0.8125rem; color: var(--hsot-gray-5); }
|
|
@@ -341,7 +371,7 @@ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), fe = y`
|
|
|
341
371
|
.error { padding: 1.2rem 1rem; color: var(--hsot-red-deep); font-size: 0.9rem; }
|
|
342
372
|
.note { font-size: 0.8125rem; color: var(--hsot-gray-5); margin: 0.6rem 0 0; }
|
|
343
373
|
.loading { padding: 1.2rem; color: var(--hsot-gray-5); font-family: var(--hsot-heading-font); }
|
|
344
|
-
`,
|
|
374
|
+
`, ye = b`
|
|
345
375
|
.pill {
|
|
346
376
|
display: inline-block; font-family: var(--hsot-heading-font); font-weight: 700;
|
|
347
377
|
font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.04em;
|
|
@@ -356,7 +386,7 @@ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), fe = y`
|
|
|
356
386
|
.pill.champ { background: var(--hsot-straw); color: #6b5900; }
|
|
357
387
|
@keyframes hsot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
|
|
358
388
|
@media (prefers-reduced-motion: reduce) { .pill.live { animation: none; } }
|
|
359
|
-
`,
|
|
389
|
+
`, we = b`
|
|
360
390
|
.tablewrap { overflow-x: auto; }
|
|
361
391
|
table.data { font-family: var(--hsot-heading-font); font-size: 14px; border-collapse: collapse; width: 100%; }
|
|
362
392
|
table.data th {
|
|
@@ -374,7 +404,7 @@ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), fe = y`
|
|
|
374
404
|
table.data tbody tr.rowlink:hover { background: var(--hsot-gray-1); }
|
|
375
405
|
table.data td.teamcell a { color: inherit; text-decoration: none; font-weight: 500; }
|
|
376
406
|
table.data td.teamcell a:hover { text-decoration: underline; }
|
|
377
|
-
`,
|
|
407
|
+
`, xe = b`
|
|
378
408
|
.swatch {
|
|
379
409
|
display: inline-flex; align-items: center; justify-content: center;
|
|
380
410
|
width: 26px; height: 26px; border-radius: 50%;
|
|
@@ -398,7 +428,7 @@ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), fe = y`
|
|
|
398
428
|
.dot.W { background: var(--hsot-win); }
|
|
399
429
|
.dot.L { background: var(--hsot-loss); }
|
|
400
430
|
.dot.T { background: var(--hsot-tie); }
|
|
401
|
-
`,
|
|
431
|
+
`, ke = b`
|
|
402
432
|
ul.gamelist { list-style: none; margin: 0; padding: 0; }
|
|
403
433
|
.gamelist li {
|
|
404
434
|
display: flex; align-items: center; gap: 0.7rem; padding: 0.55rem 1rem;
|
|
@@ -407,6 +437,14 @@ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), fe = y`
|
|
|
407
437
|
.gamelist li:last-child { border-bottom: none; }
|
|
408
438
|
.gamelist .d { width: 84px; flex: none; color: var(--hsot-gray-5); font-size: 0.8rem; }
|
|
409
439
|
.gamelist .res { width: 86px; flex: none; font-family: var(--hsot-heading-font); font-weight: 700; }
|
|
440
|
+
/* Per-team score block on the scoreboard, in the status pills' bubble shape. */
|
|
441
|
+
.gamelist .score {
|
|
442
|
+
display: inline-block; min-width: 1.15em; text-align: center;
|
|
443
|
+
background: var(--hsot-red); color: var(--hsot-white);
|
|
444
|
+
font-family: var(--hsot-heading-font); font-weight: 700; font-size: 0.8125rem;
|
|
445
|
+
line-height: 1.2; border-radius: var(--hsot-radius-md); padding: 0.14rem 0.4rem;
|
|
446
|
+
margin-left: 0.45rem; vertical-align: middle; font-variant-numeric: tabular-nums;
|
|
447
|
+
}
|
|
410
448
|
.gamelist .res .W { color: var(--hsot-win); }
|
|
411
449
|
.gamelist .res .L { color: var(--hsot-loss); }
|
|
412
450
|
.gamelist .res .T { color: var(--hsot-tie); }
|
|
@@ -415,77 +453,77 @@ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), fe = y`
|
|
|
415
453
|
.gamelist .opp a:hover { text-decoration: underline; }
|
|
416
454
|
.gamelist .where { color: var(--hsot-gray-5); font-size: 0.78rem; }
|
|
417
455
|
.gamelist a.box { font-size: 0.78rem; }
|
|
418
|
-
`, F = [
|
|
419
|
-
function
|
|
456
|
+
`, F = [ve, be, $e, ye, we, xe, ke];
|
|
457
|
+
function q(a) {
|
|
420
458
|
return a.state !== "final" ? null : a.forfeit && a.forfeit !== "none" ? a.forfeit : a.homeScore > a.awayScore ? "home" : a.awayScore > a.homeScore ? "away" : a.tiebreakWinner && a.tiebreakWinner !== "none" ? a.tiebreakWinner : "tie";
|
|
421
459
|
}
|
|
422
460
|
function z(a, e) {
|
|
423
|
-
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,
|
|
461
|
+
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, c) => String(o.date).localeCompare(String(c.date)));
|
|
424
462
|
for (const o of r) {
|
|
425
|
-
const
|
|
426
|
-
for (const
|
|
427
|
-
const
|
|
428
|
-
if (!
|
|
429
|
-
const
|
|
430
|
-
|
|
463
|
+
const c = q(o), n = o.gameType === "conference";
|
|
464
|
+
for (const h of ["home", "away"]) {
|
|
465
|
+
const l = h === "home" ? o.homeTeamId : o.awayTeamId;
|
|
466
|
+
if (!l) continue;
|
|
467
|
+
const d = s(l), m = h === "home" ? o.homeScore : o.awayScore, f = h === "home" ? o.awayScore : o.homeScore;
|
|
468
|
+
d.pf += m, d.pa += f;
|
|
431
469
|
let g = "T";
|
|
432
|
-
|
|
470
|
+
c === "tie" ? (d.t += 1, n && (d.ct += 1)) : c === h ? (d.w += 1, n && (d.cw += 1), g = "W") : (d.l += 1, n && (d.cl += 1), g = "L"), d.results.push({ gameId: o.id, date: o.date, mark: g, my: m, their: f, opp: h === "home" ? o.awayTeamId : o.homeTeamId, conf: n });
|
|
433
471
|
}
|
|
434
472
|
}
|
|
435
473
|
return t;
|
|
436
474
|
}
|
|
437
|
-
function
|
|
475
|
+
function N(a) {
|
|
438
476
|
if (!a || !a.length) return "";
|
|
439
477
|
const e = a[a.length - 1].mark;
|
|
440
478
|
let t = 0;
|
|
441
479
|
for (let s = a.length - 1; s >= 0 && a[s].mark === e; s -= 1) t += 1;
|
|
442
480
|
return e + t;
|
|
443
481
|
}
|
|
444
|
-
const
|
|
482
|
+
const Z = (a, e, t) => {
|
|
445
483
|
const s = a + e + t;
|
|
446
484
|
return s ? (a + t / 2) / s : 0;
|
|
447
|
-
},
|
|
485
|
+
}, J = (a) => a.toFixed(3).replace("0.", ".");
|
|
448
486
|
function w(a, e = !1) {
|
|
449
487
|
if (!a) return "0-0";
|
|
450
488
|
const t = e ? a.cw : a.w, s = e ? a.cl : a.l, r = e ? a.ct : a.t;
|
|
451
489
|
return `${t}-${s}${r ? `-${r}` : ""}`;
|
|
452
490
|
}
|
|
453
|
-
function
|
|
491
|
+
function re(a, e) {
|
|
454
492
|
return a.map((t) => {
|
|
455
493
|
const s = e[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] };
|
|
456
|
-
return { team: t, rec: s, confPct:
|
|
494
|
+
return { team: t, rec: s, confPct: Z(s.cw, s.cl, s.ct), overallPct: Z(s.w, s.l, s.t) };
|
|
457
495
|
}).sort((t, s) => s.confPct - t.confPct || s.overallPct - t.overallPct || s.rec.pf - s.rec.pa - (t.rec.pf - t.rec.pa));
|
|
458
496
|
}
|
|
459
|
-
function
|
|
497
|
+
function W(a, e) {
|
|
460
498
|
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;
|
|
461
499
|
}
|
|
462
|
-
function
|
|
500
|
+
function ee(a, e) {
|
|
463
501
|
const t = a[e];
|
|
464
502
|
return t && t.results.length ? t.results[t.results.length - 1] : null;
|
|
465
503
|
}
|
|
466
|
-
function
|
|
504
|
+
function Me(a, e, t, s = "") {
|
|
467
505
|
let r = null;
|
|
468
506
|
for (const o of a || [])
|
|
469
507
|
o.sport === e && (t && o.effectiveDate > t || s && o.gender && o.gender !== s || (!r || o.effectiveDate > r.effectiveDate) && (r = o));
|
|
470
508
|
return r;
|
|
471
509
|
}
|
|
472
|
-
function
|
|
510
|
+
function V(a, e, t, s, r) {
|
|
473
511
|
const o = e[t];
|
|
474
512
|
if (!o) return null;
|
|
475
|
-
const
|
|
476
|
-
for (const
|
|
477
|
-
if (
|
|
478
|
-
const
|
|
479
|
-
(!
|
|
480
|
-
}
|
|
481
|
-
let
|
|
482
|
-
for (const
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
return
|
|
513
|
+
const c = /* @__PURE__ */ new Map();
|
|
514
|
+
for (const h of a || []) {
|
|
515
|
+
if (h.sport !== s || r && h.effectiveDate > r || h.gender && o.gender !== h.gender && o.gender !== "coed") continue;
|
|
516
|
+
const l = h.gender || "", d = c.get(l);
|
|
517
|
+
(!d || h.effectiveDate > d.effectiveDate) && c.set(l, h);
|
|
518
|
+
}
|
|
519
|
+
let n = null;
|
|
520
|
+
for (const h of c.values()) {
|
|
521
|
+
const l = (h.teamIds || []).indexOf(t);
|
|
522
|
+
l !== -1 && (!n || h.effectiveDate > n.effectiveDate) && (n = { poll: h, rank: l + 1 });
|
|
523
|
+
}
|
|
524
|
+
return n ? n.rank : null;
|
|
487
525
|
}
|
|
488
|
-
function
|
|
526
|
+
function Te(a, e, t) {
|
|
489
527
|
if (!a) return { kind: "none", delta: 0 };
|
|
490
528
|
const s = (a.teamIds || []).indexOf(t) + 1;
|
|
491
529
|
if (!s) return { kind: "none", delta: 0 };
|
|
@@ -495,109 +533,121 @@ function we(a, e, t) {
|
|
|
495
533
|
const o = r - s;
|
|
496
534
|
return o > 0 ? { kind: "up", delta: o } : o < 0 ? { kind: "down", delta: -o } : { kind: "same", delta: 0 };
|
|
497
535
|
}
|
|
498
|
-
function
|
|
536
|
+
function Ie(a) {
|
|
499
537
|
return /^https?:\/\//i.test(String(a || ""));
|
|
500
538
|
}
|
|
501
|
-
function
|
|
539
|
+
function _(a, e) {
|
|
502
540
|
const t = a?.logoAssetId;
|
|
503
|
-
if (!
|
|
541
|
+
if (!Ie(t)) return "";
|
|
504
542
|
const s = Math.max(1, Math.round(e * 2)), r = t.includes("?") ? "&" : "?";
|
|
505
543
|
return `${t}${r}w=${s}&h=${s}&f=webp`;
|
|
506
544
|
}
|
|
507
|
-
function
|
|
508
|
-
const o =
|
|
509
|
-
return
|
|
545
|
+
function Y(a, e, { title: t, sub: s, teams: r }) {
|
|
546
|
+
const o = ae(), n = !!a.querySelector(':scope > a[slot="nav"]') || fe(o, e.hrefs, e.sport) !== null;
|
|
547
|
+
return i`
|
|
510
548
|
<div class="band section">
|
|
511
549
|
<div class="inner">
|
|
512
550
|
<h1>${t}</h1>
|
|
513
|
-
${s ?
|
|
551
|
+
${s ? i`<p class="sub">${s}</p>` : p}
|
|
514
552
|
</div>
|
|
515
|
-
${
|
|
553
|
+
${n ? i`
|
|
516
554
|
<nav class="sectionnav" aria-label="${T(e.sport)} section">
|
|
517
555
|
<div class="navrow">
|
|
518
556
|
<slot name="nav">
|
|
519
|
-
${
|
|
520
|
-
aria-current=${o && x(
|
|
557
|
+
${ue(e.sport, r, e.hrefs).map((h) => i`<a href=${h.href}
|
|
558
|
+
aria-current=${o && x(h.href) === o ? "page" : p}>${h.label}</a>`)}
|
|
521
559
|
</slot>
|
|
522
560
|
</div>
|
|
523
561
|
</nav>` : p}
|
|
524
562
|
</div>
|
|
525
563
|
`;
|
|
526
564
|
}
|
|
527
|
-
const
|
|
565
|
+
const S = (a, e) => {
|
|
528
566
|
const t = a.teamsById[e];
|
|
529
567
|
return t ? a.schoolsById[t.schoolId] : null;
|
|
530
|
-
},
|
|
568
|
+
}, I = (a, e) => S(a, e)?.name || "TBD", A = (a, e) => S(a, e)?.abbr || "TBD";
|
|
531
569
|
function C(a, e = 26) {
|
|
532
570
|
if (!a) return p;
|
|
533
|
-
const t =
|
|
571
|
+
const t = _(a, e);
|
|
534
572
|
if (t)
|
|
535
|
-
return
|
|
573
|
+
return i`<img class="swatch logo" aria-hidden="true" alt="" loading="lazy"
|
|
536
574
|
src=${t} style="width:${e}px;height:${e}px" />`;
|
|
537
|
-
const s = a.colorPrimary || "#030711", r =
|
|
538
|
-
return
|
|
575
|
+
const s = a.colorPrimary || "#030711", r = E(s);
|
|
576
|
+
return i`<span class="swatch" aria-hidden="true"
|
|
539
577
|
style="width:${e}px;height:${e}px;background:${s};color:${r};font-size:${Math.max(8, e * 0.28)}px"
|
|
540
|
-
>${
|
|
578
|
+
>${G(a)}</span>`;
|
|
541
579
|
}
|
|
542
|
-
function
|
|
543
|
-
const s =
|
|
544
|
-
return s ?
|
|
580
|
+
function K(a, e, t) {
|
|
581
|
+
const s = V(a.rankings, a.teamsById, e, a.sport, t);
|
|
582
|
+
return s ? i`<span class="rankbadge">#${s}</span>` : p;
|
|
545
583
|
}
|
|
546
|
-
function
|
|
547
|
-
const s =
|
|
548
|
-
return s ?
|
|
584
|
+
function U(a, e, t) {
|
|
585
|
+
const s = S(a, e);
|
|
586
|
+
return s ? i`${K(a, e, t)}<a href=${u(a.hrefs.school, { id: s.id })}>${s.name}</a>` : i`<span class="mut">TBD</span>`;
|
|
549
587
|
}
|
|
550
|
-
function
|
|
588
|
+
function Q(a, e, t = 5) {
|
|
551
589
|
const s = a.records[e];
|
|
552
|
-
if (!s || !s.results.length) return
|
|
590
|
+
if (!s || !s.results.length) return i`<span class="mut">·</span>`;
|
|
553
591
|
const r = s.results.slice(-1 * t);
|
|
554
|
-
return
|
|
555
|
-
${r.map((o) =>
|
|
556
|
-
title="${o.mark} ${o.my}-${o.their} vs ${
|
|
592
|
+
return i`<span class="dots" role="img" aria-label="last ${r.length} results">
|
|
593
|
+
${r.map((o) => i`<a class="dot ${o.mark}"
|
|
594
|
+
title="${o.mark} ${o.my}-${o.their} vs ${I(a, o.opp)}"
|
|
557
595
|
href=${u(a.hrefs.game, { sport: a.sport, id: o.gameId })}>${o.mark}</a>`)}
|
|
558
596
|
</span>`;
|
|
559
597
|
}
|
|
598
|
+
function B(a, e) {
|
|
599
|
+
return a.querySelector(':scope > [slot="rail"]') ? i`<div class="view withrail">
|
|
600
|
+
<div class="viewmain">${e}</div>
|
|
601
|
+
<aside class="viewrail"><slot name="rail"></slot></aside>
|
|
602
|
+
</div>` : i`<div class="view">${e}</div>`;
|
|
603
|
+
}
|
|
604
|
+
function P(a) {
|
|
605
|
+
if (!a.promoImage) return p;
|
|
606
|
+
const e = i`<img src=${a.promoImage} alt=${a.promoAlt || "Sponsor"}>`;
|
|
607
|
+
return i`<div class="promo">${a.promoHref ? i`<a href=${a.promoHref} target="_blank" rel="sponsored noopener">${e}</a>` : e}</div>`;
|
|
608
|
+
}
|
|
560
609
|
function R(a) {
|
|
561
|
-
const e =
|
|
562
|
-
return
|
|
610
|
+
const e = se(a);
|
|
611
|
+
return i`<span class="pill ${e.kind}">${e.label}</span>`;
|
|
563
612
|
}
|
|
564
|
-
function
|
|
565
|
-
if (!e) return
|
|
613
|
+
function oe(a, e, t) {
|
|
614
|
+
if (!e) return i`<span class="mut">·</span>`;
|
|
566
615
|
const s = e.homeTeamId === t ? e.awayTeamId : e.homeTeamId, r = e.homeTeamId === t ? "vs" : "at";
|
|
567
|
-
return
|
|
616
|
+
return i`${e.state === "live" ? i`<span class="pill live">Live</span> ` : i`${$(e.date, { month: "numeric", day: "numeric" })} `}${r} ${A(a, s)}`;
|
|
568
617
|
}
|
|
569
|
-
class
|
|
618
|
+
class Se extends y {
|
|
570
619
|
static styles = F;
|
|
571
620
|
static properties = {
|
|
572
|
-
|
|
621
|
+
...y.properties,
|
|
573
622
|
sport: { type: String },
|
|
574
623
|
season: { type: String },
|
|
575
624
|
date: { type: String }
|
|
576
625
|
};
|
|
577
626
|
constructor() {
|
|
578
|
-
super(), this.sport = "football", this.season = "", this.date = "";
|
|
627
|
+
super(), this.sport = "football", this.season = "", this.date = "", this._datePinned = !1;
|
|
579
628
|
}
|
|
580
629
|
connectedCallback() {
|
|
581
630
|
if (super.connectedCallback(), !this.date) {
|
|
582
631
|
const e = new URLSearchParams(globalThis.location?.search || "").get("date");
|
|
583
|
-
this.date = e
|
|
632
|
+
e && (this.date = e);
|
|
584
633
|
}
|
|
634
|
+
this._datePinned = !!this.date;
|
|
585
635
|
}
|
|
586
636
|
async fetchData(e) {
|
|
587
|
-
const t = this.season ||
|
|
637
|
+
const t = this.season || L(), [s, r, o, c, n] = await Promise.all([
|
|
588
638
|
e.listSchools(),
|
|
589
639
|
e.listTeams({ sport: this.sport }),
|
|
590
640
|
e.listConferences(),
|
|
591
641
|
e.listGames({ sport: this.sport, season: t }),
|
|
592
642
|
e.listRankings({ sport: this.sport })
|
|
593
643
|
]);
|
|
594
|
-
return {
|
|
644
|
+
return this._datePinned || (this.date = he(c.items.map((h) => h.date)), this._datePinned = !0), {
|
|
595
645
|
season: t,
|
|
596
646
|
schools: s.items,
|
|
597
647
|
teams: r.items,
|
|
598
648
|
conferences: o.items,
|
|
599
|
-
games:
|
|
600
|
-
rankings:
|
|
649
|
+
games: c.items,
|
|
650
|
+
rankings: n.items
|
|
601
651
|
};
|
|
602
652
|
}
|
|
603
653
|
get ctx() {
|
|
@@ -611,24 +661,30 @@ class ke extends $ {
|
|
|
611
661
|
}, this._ctxData = this.data), this._ctx;
|
|
612
662
|
}
|
|
613
663
|
renderView() {
|
|
614
|
-
const e = this.ctx, t = v(this.data.conferences), s = [...new Set(this.data.games.map((
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
664
|
+
const e = this.ctx, t = v(this.data.conferences), s = [...new Set(this.data.games.map((l) => l.date).filter(Boolean))].sort(), r = Number.MAX_SAFE_INTEGER, o = (l) => {
|
|
665
|
+
const d = [l.awayTeamId, l.homeTeamId].map((m) => V(e.rankings, e.teamsById, m, this.sport, l.date)).filter(Boolean);
|
|
666
|
+
return d.length ? Math.min(...d) : r;
|
|
667
|
+
}, c = this.data.games.filter((l) => l.date === this.date), n = new Map(c.map((l) => [l, o(l)]));
|
|
668
|
+
c.sort((l, d) => (l.state === "live" ? 0 : 1) - (d.state === "live" ? 0 : 1) || n.get(l) - n.get(d));
|
|
669
|
+
const h = /* @__PURE__ */ new Map();
|
|
670
|
+
return c.forEach((l) => {
|
|
671
|
+
const d = l.gameType === "conference" && l.conferenceId ? t[l.conferenceId]?.name || "Conference" : l.gameType === "playoff" ? "Playoffs" : l.gameType === "scrimmage" ? "Scrimmages" : "Nonconference";
|
|
672
|
+
h.has(d) || h.set(d, []), h.get(d).push(l);
|
|
673
|
+
}), i`
|
|
674
|
+
${Y(this, e, {
|
|
675
|
+
title: i`${T(this.sport)} scores & schedules`,
|
|
676
|
+
sub: i`${$(this.date, { weekday: "long", month: "long", day: "numeric", year: "numeric" })} · ${c.length} games`,
|
|
622
677
|
teams: this.data.teams
|
|
623
678
|
})}
|
|
624
|
-
|
|
679
|
+
${B(this, i`
|
|
680
|
+
${P(this)}
|
|
625
681
|
<div class="toolbar">
|
|
626
682
|
<label class="asof" for="datesel">Date</label>
|
|
627
|
-
<select id="datesel" @change=${(
|
|
628
|
-
this.date =
|
|
683
|
+
<select id="datesel" @change=${(l) => {
|
|
684
|
+
this.date = l.target.value;
|
|
629
685
|
}}>
|
|
630
|
-
${s.map((
|
|
631
|
-
${
|
|
686
|
+
${(s.includes(this.date) ? s : [...s, this.date].sort()).map((l) => i`<option value=${l} ?selected=${l === this.date}>
|
|
687
|
+
${$(l, { weekday: "short", month: "short", day: "numeric" })}${l === j() ? " · today" : ""}
|
|
632
688
|
</option>`)}
|
|
633
689
|
</select>
|
|
634
690
|
<button class="chip" ?disabled=${s.indexOf(this.date) <= 0}
|
|
@@ -642,35 +698,38 @@ class ke extends $ {
|
|
|
642
698
|
<span class="spacer"></span>
|
|
643
699
|
<span class="asof">Live games first · report a score to see it update here</span>
|
|
644
700
|
</div>
|
|
645
|
-
${
|
|
646
|
-
${[...
|
|
647
|
-
<div class="section-title">${
|
|
701
|
+
${c.length ? p : i`<p class="empty">No ${this.sport} games on this date.</p>`}
|
|
702
|
+
${[...h.entries()].map(([l, d]) => i`
|
|
703
|
+
<div class="section-title">${l}</div>
|
|
648
704
|
<div class="card"><ul class="gamelist">
|
|
649
|
-
${
|
|
705
|
+
${d.map((m) => this.renderGame(e, m))}
|
|
650
706
|
</ul></div>
|
|
651
707
|
`)}
|
|
652
|
-
|
|
708
|
+
`)}
|
|
653
709
|
`;
|
|
654
710
|
}
|
|
711
|
+
// Each team's score rides in a block beside its name (reader feedback:
|
|
712
|
+
// a lone score column on the far right read as detached from the teams).
|
|
713
|
+
// Scheduled games carry their start time on the status pill alone.
|
|
655
714
|
renderGame(e, t) {
|
|
656
|
-
const s = t.state === "final" || t.state === "live"
|
|
657
|
-
return
|
|
715
|
+
const s = t.state === "final" || t.state === "live";
|
|
716
|
+
return i`
|
|
658
717
|
<li>
|
|
659
718
|
${R(t)}
|
|
660
|
-
<span class="opp">${
|
|
661
|
-
|
|
719
|
+
<span class="opp">${U(e, t.awayTeamId, t.date)}${s ? i`<span class="score">${t.awayScore}</span>` : p}
|
|
720
|
+
at ${U(e, t.homeTeamId, t.date)}${s ? i`<span class="score">${t.homeScore}</span>` : p}</span>
|
|
662
721
|
<span class="where">${t.venue || ""}</span>
|
|
663
|
-
${t.broadcast ?
|
|
722
|
+
${t.broadcast ? i`<span class="pill class">${t.broadcast}</span>` : p}
|
|
664
723
|
<a class="box" href=${u(e.hrefs.game, { sport: this.sport, id: t.id })}>Box score →</a>
|
|
665
724
|
</li>
|
|
666
725
|
`;
|
|
667
726
|
}
|
|
668
727
|
}
|
|
669
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-scores") && globalThis.customElements.define("hsot-scores",
|
|
670
|
-
class
|
|
728
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-scores") && globalThis.customElements.define("hsot-scores", Se);
|
|
729
|
+
class Ce extends y {
|
|
671
730
|
static styles = F;
|
|
672
731
|
static properties = {
|
|
673
|
-
|
|
732
|
+
...y.properties,
|
|
674
733
|
sport: { type: String },
|
|
675
734
|
season: { type: String },
|
|
676
735
|
classFilter: { state: !0 },
|
|
@@ -680,7 +739,7 @@ class Te extends $ {
|
|
|
680
739
|
super(), this.sport = "football", this.season = "", this.classFilter = "All", this.query = "";
|
|
681
740
|
}
|
|
682
741
|
async fetchData(e) {
|
|
683
|
-
const t = this.season ||
|
|
742
|
+
const t = this.season || L(), [s, r, o, c, n] = await Promise.all([
|
|
684
743
|
e.listConferences({ active: !0 }),
|
|
685
744
|
e.listSchools(),
|
|
686
745
|
e.listTeams({ sport: this.sport }),
|
|
@@ -692,8 +751,8 @@ class Te extends $ {
|
|
|
692
751
|
conferences: s.items,
|
|
693
752
|
schools: r.items,
|
|
694
753
|
teams: o.items,
|
|
695
|
-
games:
|
|
696
|
-
rankings:
|
|
754
|
+
games: c.items,
|
|
755
|
+
rankings: n.items
|
|
697
756
|
};
|
|
698
757
|
}
|
|
699
758
|
get ctx() {
|
|
@@ -708,16 +767,17 @@ class Te extends $ {
|
|
|
708
767
|
}
|
|
709
768
|
renderView() {
|
|
710
769
|
const e = this.ctx, t = ["All", ...new Set(this.data.conferences.flatMap((r) => r.classifications || []))].slice(0, 9), s = this.data.conferences.filter((r) => r.active !== !1).filter((r) => this.classFilter === "All" || (r.classifications || []).includes(this.classFilter));
|
|
711
|
-
return
|
|
712
|
-
${
|
|
713
|
-
title:
|
|
714
|
-
sub:
|
|
770
|
+
return i`
|
|
771
|
+
${Y(this, e, {
|
|
772
|
+
title: i`${T(this.sport)} standings`,
|
|
773
|
+
sub: i`${this.data.season} season · every conference, computed live from reported results`,
|
|
715
774
|
teams: this.data.teams
|
|
716
775
|
})}
|
|
717
|
-
|
|
776
|
+
${B(this, i`
|
|
777
|
+
${P(this)}
|
|
718
778
|
<div class="toolbar">
|
|
719
779
|
<div role="group" aria-label="Classification filter">
|
|
720
|
-
${t.map((r) =>
|
|
780
|
+
${t.map((r) => i`<button class="chip ${this.classFilter === r ? "on" : ""}"
|
|
721
781
|
@click=${() => {
|
|
722
782
|
this.classFilter = r;
|
|
723
783
|
}}>${r}</button>`)}
|
|
@@ -727,21 +787,21 @@ class Te extends $ {
|
|
|
727
787
|
this.query = r.target.value;
|
|
728
788
|
}}>
|
|
729
789
|
<span class="spacer"></span>
|
|
730
|
-
<span class="asof">Records through ${
|
|
790
|
+
<span class="asof">Records through ${$(j(), { month: "long", day: "numeric" })} · conference games count toward both records · scrimmages toward neither</span>
|
|
731
791
|
</div>
|
|
732
792
|
${s.map((r) => this.renderConference(e, r))}
|
|
733
|
-
|
|
793
|
+
`)}
|
|
734
794
|
`;
|
|
735
795
|
}
|
|
736
796
|
renderConference(e, t) {
|
|
737
|
-
const s = this.data.teams.filter((
|
|
797
|
+
const s = this.data.teams.filter((c) => c.conferenceId === t.id);
|
|
738
798
|
if (!s.length) return p;
|
|
739
|
-
const r = this.query.trim().toLowerCase(), o =
|
|
740
|
-
return
|
|
799
|
+
const r = this.query.trim().toLowerCase(), o = re(s, e.records);
|
|
800
|
+
return i`
|
|
741
801
|
<div class="card">
|
|
742
802
|
<div class="card-head">
|
|
743
803
|
<h2>${t.name}</h2>
|
|
744
|
-
${(t.classifications || []).map((
|
|
804
|
+
${(t.classifications || []).map((c) => i`<span class="pill class">${c}</span>`)}
|
|
745
805
|
<span class="meta">${o.length} teams · membership derives from teams</span>
|
|
746
806
|
</div>
|
|
747
807
|
<div class="tablewrap"><table class="data">
|
|
@@ -751,44 +811,44 @@ class Te extends $ {
|
|
|
751
811
|
<th>Streak</th><th>Last 5</th><th>Next</th>
|
|
752
812
|
</tr></thead>
|
|
753
813
|
<tbody>
|
|
754
|
-
${o.map((
|
|
814
|
+
${o.map((c, n) => this.renderRow(e, c, n, r))}
|
|
755
815
|
</tbody>
|
|
756
816
|
</table></div>
|
|
757
817
|
</div>
|
|
758
818
|
`;
|
|
759
819
|
}
|
|
760
820
|
renderRow(e, t, s, r) {
|
|
761
|
-
const o = e.schoolsById[t.team.schoolId],
|
|
762
|
-
if (r && !
|
|
763
|
-
const
|
|
764
|
-
<span class="pill champ" title="${m.season} ${m.title} champion">★ ${m.season} ${m.title}</span>`),
|
|
821
|
+
const o = e.schoolsById[t.team.schoolId], c = o?.name || t.team.name || "TBD";
|
|
822
|
+
if (r && !c.toLowerCase().includes(r)) return p;
|
|
823
|
+
const n = t.rec.pf - t.rec.pa, h = W(this.data.games, t.team.id), l = (t.team.championships || []).map((m) => i`
|
|
824
|
+
<span class="pill champ" title="${m.season} ${m.title} champion">★ ${m.season} ${m.title}</span>`), d = () => {
|
|
765
825
|
location.href = u(e.hrefs.school, { id: t.team.schoolId });
|
|
766
826
|
};
|
|
767
|
-
return
|
|
827
|
+
return i`
|
|
768
828
|
<tr class="rowlink" @click=${(m) => {
|
|
769
|
-
m.target.closest("a") ||
|
|
829
|
+
m.target.closest("a") || d();
|
|
770
830
|
}}>
|
|
771
831
|
<td class="mut">${s + 1}</td>
|
|
772
832
|
<td class="teamcell">
|
|
773
|
-
${C(o)}${
|
|
774
|
-
<a href=${u(e.hrefs.school, { id: t.team.schoolId })}>${
|
|
833
|
+
${C(o)}${K(e, t.team.id, null)}
|
|
834
|
+
<a href=${u(e.hrefs.school, { id: t.team.schoolId })}>${c}</a> ${l}
|
|
775
835
|
</td>
|
|
776
836
|
<td class="num">${w(t.rec, !0)}</td>
|
|
777
|
-
<td class="num">${
|
|
837
|
+
<td class="num">${J(t.confPct)}</td>
|
|
778
838
|
<td class="num">${w(t.rec)}</td>
|
|
779
|
-
<td class="num">${
|
|
839
|
+
<td class="num">${J(t.overallPct)}</td>
|
|
780
840
|
<td class="num">${t.rec.pf}</td>
|
|
781
841
|
<td class="num">${t.rec.pa}</td>
|
|
782
|
-
<td class="num" style="color:${
|
|
783
|
-
<td>${
|
|
784
|
-
<td>${
|
|
785
|
-
<td>${
|
|
842
|
+
<td class="num" style="color:${n >= 0 ? "var(--hsot-win)" : "var(--hsot-loss)"}">${n > 0 ? "+" : ""}${n}</td>
|
|
843
|
+
<td>${N(t.rec.results) || "·"}</td>
|
|
844
|
+
<td>${Q(e, t.team.id)}</td>
|
|
845
|
+
<td>${oe(e, h, t.team.id)}</td>
|
|
786
846
|
</tr>
|
|
787
847
|
`;
|
|
788
848
|
}
|
|
789
849
|
}
|
|
790
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-standings") && globalThis.customElements.define("hsot-standings",
|
|
791
|
-
const
|
|
850
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-standings") && globalThis.customElements.define("hsot-standings", Ce);
|
|
851
|
+
const De = b`
|
|
792
852
|
.hero1 {
|
|
793
853
|
border-radius: var(--hsot-radius-md); color: var(--hsot-white);
|
|
794
854
|
padding: 1.3rem 1.4rem; display: flex; align-items: center; gap: 1.2rem;
|
|
@@ -805,10 +865,10 @@ const Se = y`
|
|
|
805
865
|
.delta.new { background: var(--hsot-straw); color: #6b5900; border-radius: var(--hsot-radius-xs); padding: 0.1rem 0.3rem; font-size: 0.7rem; }
|
|
806
866
|
.sparkline { vertical-align: middle; }
|
|
807
867
|
`;
|
|
808
|
-
class
|
|
809
|
-
static styles = [...F,
|
|
868
|
+
class Fe extends y {
|
|
869
|
+
static styles = [...F, De];
|
|
810
870
|
static properties = {
|
|
811
|
-
|
|
871
|
+
...y.properties,
|
|
812
872
|
sport: { type: String },
|
|
813
873
|
gender: { type: String },
|
|
814
874
|
season: { type: String },
|
|
@@ -823,20 +883,20 @@ class Ie extends $ {
|
|
|
823
883
|
e && (this.pollDate = e);
|
|
824
884
|
}
|
|
825
885
|
async fetchData(e) {
|
|
826
|
-
const t = this.season ||
|
|
886
|
+
const t = this.season || L(), [s, r, o, c, n] = await Promise.all([
|
|
827
887
|
e.listRankings({ sport: this.sport, ...this.gender ? { gender: this.gender } : {} }),
|
|
828
888
|
e.listSchools(),
|
|
829
889
|
e.listTeams({ sport: this.sport }),
|
|
830
890
|
e.listConferences(),
|
|
831
891
|
e.listGames({ sport: this.sport, season: t })
|
|
832
|
-
]),
|
|
892
|
+
]), h = s.items.filter((l) => !this.gender || !l.gender || l.gender === this.gender).sort((l, d) => d.effectiveDate.localeCompare(l.effectiveDate));
|
|
833
893
|
return {
|
|
834
894
|
season: t,
|
|
835
|
-
polls:
|
|
895
|
+
polls: h,
|
|
836
896
|
schools: r.items,
|
|
837
897
|
teams: o.items,
|
|
838
|
-
conferences:
|
|
839
|
-
games:
|
|
898
|
+
conferences: c.items,
|
|
899
|
+
games: n.items
|
|
840
900
|
};
|
|
841
901
|
}
|
|
842
902
|
get ctx() {
|
|
@@ -850,45 +910,46 @@ class Ie extends $ {
|
|
|
850
910
|
}, this._ctxData = this.data), this._ctx;
|
|
851
911
|
}
|
|
852
912
|
sparkline(e, t, s) {
|
|
853
|
-
const
|
|
913
|
+
const n = t.map((m, f) => {
|
|
854
914
|
const g = (m.teamIds || []).indexOf(e);
|
|
855
915
|
if (g === -1) return null;
|
|
856
|
-
const k = t.length === 1 ? 96 / 2 : f / (t.length - 1) * 90 + 3,
|
|
857
|
-
return { x: k, y:
|
|
858
|
-
}),
|
|
859
|
-
let
|
|
860
|
-
if (
|
|
861
|
-
m ?
|
|
862
|
-
}),
|
|
863
|
-
const
|
|
864
|
-
return
|
|
865
|
-
${
|
|
916
|
+
const k = t.length === 1 ? 96 / 2 : f / (t.length - 1) * 90 + 3, O = 3 + g / 24 * 20;
|
|
917
|
+
return { x: k, y: O };
|
|
918
|
+
}), h = [];
|
|
919
|
+
let l = [];
|
|
920
|
+
if (n.forEach((m) => {
|
|
921
|
+
m ? l.push(m) : l.length && (h.push(l), l = []);
|
|
922
|
+
}), l.length && h.push(l), !h.length) return p;
|
|
923
|
+
const d = n[s];
|
|
924
|
+
return i`<svg class="sparkline" width=${96} height=${26} viewBox="0 0 ${96} ${26}" role="img" aria-label="rank history">
|
|
925
|
+
${h.map((m) => X`<polyline fill="none" stroke="var(--hsot-red)" stroke-width="2"
|
|
866
926
|
points=${m.map((f) => `${f.x.toFixed(1)},${f.y.toFixed(1)}`).join(" ")}></polyline>`)}
|
|
867
|
-
${
|
|
927
|
+
${d ? X`<circle cx=${d.x.toFixed(1)} cy=${d.y.toFixed(1)} r="3" fill="var(--hsot-black)"></circle>` : p}
|
|
868
928
|
</svg>`;
|
|
869
929
|
}
|
|
870
930
|
movement(e, t, s) {
|
|
871
|
-
const r =
|
|
872
|
-
return r.kind === "up" ?
|
|
931
|
+
const r = Te(e, t, s);
|
|
932
|
+
return r.kind === "up" ? i`<span class="delta up">▲ ${r.delta}</span>` : r.kind === "down" ? i`<span class="delta down">▼ ${r.delta}</span>` : r.kind === "new" ? i`<span class="delta new">NEW</span>` : r.kind === "same" ? i`<span class="delta same">—</span>` : i`<span class="delta same">·</span>`;
|
|
873
933
|
}
|
|
874
934
|
renderView() {
|
|
875
935
|
const e = this.ctx, t = this.data.polls;
|
|
876
|
-
if (!t.length) return
|
|
877
|
-
const s = Math.max(0, t.findIndex((m) => m.effectiveDate === this.pollDate)), r = t[s] || t[0], o = t[s + 1] || null,
|
|
878
|
-
return
|
|
879
|
-
${
|
|
880
|
-
title:
|
|
881
|
-
sub:
|
|
936
|
+
if (!t.length) return i`<div class="view"><p class="empty">No ${this.sport} polls published yet this season.</p></div>`;
|
|
937
|
+
const s = Math.max(0, t.findIndex((m) => m.effectiveDate === this.pollDate)), r = t[s] || t[0], o = t[s + 1] || null, c = t.slice().reverse(), n = c.indexOf(r), h = v(this.data.conferences), l = (r.teamIds || [])[0], d = l ? S(e, l) : null;
|
|
938
|
+
return i`
|
|
939
|
+
${Y(this, e, {
|
|
940
|
+
title: i`${T(this.sport)} Top 25`,
|
|
941
|
+
sub: i`The HighSchoolOT poll · updated weekly · ${t.length} polls this season`,
|
|
882
942
|
teams: this.data.teams
|
|
883
943
|
})}
|
|
884
|
-
|
|
944
|
+
${B(this, i`
|
|
945
|
+
${P(this)}
|
|
885
946
|
<div class="toolbar">
|
|
886
947
|
<label class="asof" for="pollsel">Poll of</label>
|
|
887
948
|
<select id="pollsel" @change=${(m) => {
|
|
888
949
|
this.pollDate = m.target.value;
|
|
889
950
|
}}>
|
|
890
|
-
${t.map((m, f) =>
|
|
891
|
-
${
|
|
951
|
+
${t.map((m, f) => i`<option value=${m.effectiveDate} ?selected=${m === r}>
|
|
952
|
+
${$(m.effectiveDate, { month: "long", day: "numeric", year: "numeric" })}${f === 0 ? " · current" : ""}
|
|
892
953
|
</option>`)}
|
|
893
954
|
</select>
|
|
894
955
|
<button class="chip" ?disabled=${s >= t.length - 1}
|
|
@@ -902,65 +963,65 @@ class Ie extends $ {
|
|
|
902
963
|
<span class="spacer"></span>
|
|
903
964
|
<span class="asof">Movement vs. the previous poll · sparkline = season rank history</span>
|
|
904
965
|
</div>
|
|
905
|
-
${
|
|
966
|
+
${d ? this.renderHero(e, r, o, l, d, h) : p}
|
|
906
967
|
<div class="card"><div class="tablewrap"><table class="data">
|
|
907
968
|
<thead><tr>
|
|
908
969
|
<th class="num">Rk</th><th>Mvmt</th><th>Team</th><th class="num">Record</th>
|
|
909
970
|
<th>Conference</th><th>Last result</th><th>Next</th><th>Season</th>
|
|
910
971
|
</tr></thead>
|
|
911
972
|
<tbody>
|
|
912
|
-
${(r.teamIds || []).map((m, f) => f === 0 || !m ? p : this.renderRow(e, r, o,
|
|
973
|
+
${(r.teamIds || []).map((m, f) => f === 0 || !m ? p : this.renderRow(e, r, o, c, n, h, m, f + 1))}
|
|
913
974
|
</tbody>
|
|
914
975
|
</table></div></div>
|
|
915
976
|
<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>
|
|
916
|
-
|
|
977
|
+
`)}
|
|
917
978
|
`;
|
|
918
979
|
}
|
|
919
|
-
renderHero(e, t, s, r, o,
|
|
920
|
-
const
|
|
921
|
-
return
|
|
922
|
-
<div class="hero1" style="background:${
|
|
980
|
+
renderHero(e, t, s, r, o, c) {
|
|
981
|
+
const n = e.records[r], h = ee(e.records, r), l = c[e.teamsById[r]?.conferenceId], d = `linear-gradient(120deg, ${o.colorPrimary || "#030711"} 0%, var(--hsot-black) 85%)`;
|
|
982
|
+
return i`
|
|
983
|
+
<div class="hero1" style="background:${d}">
|
|
923
984
|
<div class="bigrank">#1</div>
|
|
924
985
|
${C(o, 64)}
|
|
925
986
|
<div>
|
|
926
987
|
<h2><a href=${u(e.hrefs.school, { id: o.id })}>${o.name} ${o.mascot || ""}</a></h2>
|
|
927
988
|
<div class="facts">
|
|
928
|
-
${w(
|
|
929
|
-
· streak ${
|
|
930
|
-
${
|
|
989
|
+
${w(n)} overall${l ? i` · ${w(n, !0)} ${l.name}` : p}
|
|
990
|
+
· streak ${N(n?.results) || "·"}
|
|
991
|
+
${h ? i` · last: ${h.mark} ${h.my}-${h.their} vs ${A(e, h.opp)}` : p}
|
|
931
992
|
${this.movement(t, s, r)}
|
|
932
993
|
</div>
|
|
933
994
|
</div>
|
|
934
995
|
</div>
|
|
935
996
|
`;
|
|
936
997
|
}
|
|
937
|
-
renderRow(e, t, s, r, o,
|
|
938
|
-
const
|
|
939
|
-
if (!
|
|
940
|
-
const
|
|
941
|
-
location.href = u(e.hrefs.school, { id:
|
|
998
|
+
renderRow(e, t, s, r, o, c, n, h) {
|
|
999
|
+
const l = S(e, n);
|
|
1000
|
+
if (!l) return p;
|
|
1001
|
+
const d = e.records[n], m = ee(e.records, n), f = W(this.data.games, n), g = c[e.teamsById[n]?.conferenceId], k = () => {
|
|
1002
|
+
location.href = u(e.hrefs.school, { id: l.id });
|
|
942
1003
|
};
|
|
943
|
-
return
|
|
944
|
-
<tr class="rowlink" @click=${(
|
|
945
|
-
|
|
1004
|
+
return i`
|
|
1005
|
+
<tr class="rowlink" @click=${(O) => {
|
|
1006
|
+
O.target.closest("a") || k();
|
|
946
1007
|
}}>
|
|
947
|
-
<td class="num" style="font-weight:700">${
|
|
948
|
-
<td>${this.movement(t, s,
|
|
949
|
-
<td class="teamcell">${C(
|
|
950
|
-
<span class="mut" style="font-size:0.78rem">${
|
|
951
|
-
<td class="num">${w(
|
|
1008
|
+
<td class="num" style="font-weight:700">${h}</td>
|
|
1009
|
+
<td>${this.movement(t, s, n)}</td>
|
|
1010
|
+
<td class="teamcell">${C(l)}<a href=${u(e.hrefs.school, { id: l.id })}>${l.name}</a>
|
|
1011
|
+
<span class="mut" style="font-size:0.78rem">${l.mascot || ""}</span></td>
|
|
1012
|
+
<td class="num">${w(d)}</td>
|
|
952
1013
|
<td class="mut">${g?.name || "Independent"}</td>
|
|
953
|
-
<td>${m ?
|
|
1014
|
+
<td>${m ? i`<a class="box" style="text-decoration:none" href=${u(e.hrefs.game, { sport: this.sport, id: m.gameId })}>
|
|
954
1015
|
<b style="color:${m.mark === "W" ? "var(--hsot-win)" : m.mark === "L" ? "var(--hsot-loss)" : "var(--hsot-tie)"}">${m.mark}</b>
|
|
955
|
-
${m.my}-${m.their} vs ${
|
|
956
|
-
<td>${
|
|
957
|
-
<td>${this.sparkline(
|
|
1016
|
+
${m.my}-${m.their} vs ${A(e, m.opp)}</a>` : i`<span class="mut">·</span>`}</td>
|
|
1017
|
+
<td>${oe(e, f, n)}</td>
|
|
1018
|
+
<td>${this.sparkline(n, r, o)}</td>
|
|
958
1019
|
</tr>
|
|
959
1020
|
`;
|
|
960
1021
|
}
|
|
961
1022
|
}
|
|
962
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-rankings") && globalThis.customElements.define("hsot-rankings",
|
|
963
|
-
const
|
|
1023
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-rankings") && globalThis.customElements.define("hsot-rankings", Fe);
|
|
1024
|
+
const ze = b`
|
|
964
1025
|
.schoolhero { color: var(--hsot-white); padding: 1.6rem 1.25rem 1.3rem; }
|
|
965
1026
|
.schoolhero .inner { max-width: 1366px; margin: 0 auto; display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap; }
|
|
966
1027
|
.schoolhero .crest {
|
|
@@ -985,10 +1046,10 @@ const Ce = y`
|
|
|
985
1046
|
.cols { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 1.25rem; }
|
|
986
1047
|
@media (max-width: 900px) { .cols { grid-template-columns: 1fr; } .schoolhero h1 { font-size: 1.9rem; } }
|
|
987
1048
|
`;
|
|
988
|
-
class
|
|
989
|
-
static styles = [...F,
|
|
1049
|
+
class Be extends y {
|
|
1050
|
+
static styles = [...F, ze];
|
|
990
1051
|
static properties = {
|
|
991
|
-
|
|
1052
|
+
...y.properties,
|
|
992
1053
|
schoolId: { type: String, attribute: "school-id" },
|
|
993
1054
|
sport: { type: String },
|
|
994
1055
|
season: { type: String },
|
|
@@ -1003,26 +1064,26 @@ class De extends $ {
|
|
|
1003
1064
|
e && !this.sport && (this.sport = e);
|
|
1004
1065
|
}
|
|
1005
1066
|
async fetchData(e) {
|
|
1006
|
-
const t = this.season ||
|
|
1007
|
-
|
|
1008
|
-
|
|
1067
|
+
const t = this.season || L(), s = await e.getSchool(this.schoolId), o = (await e.listTeams({ schoolId: this.schoolId })).items, c = o.find((k) => k.sport === (this.sport || "football")) || o[0] || null, [n, h, l, d, m, f, g] = await Promise.all([
|
|
1068
|
+
c ? e.listGames({ sport: c.sport, season: t }) : Promise.resolve({ items: [] }),
|
|
1069
|
+
c ? e.listTeams({ sport: c.sport }) : Promise.resolve({ items: [] }),
|
|
1009
1070
|
e.listSchools(),
|
|
1010
1071
|
e.listConferences(),
|
|
1011
|
-
|
|
1012
|
-
|
|
1072
|
+
c ? e.listRankings({ sport: c.sport }) : Promise.resolve({ items: [] }),
|
|
1073
|
+
c ? e.listRosters({ teamId: c.id }) : Promise.resolve({ items: [] }),
|
|
1013
1074
|
// teamId is the public surface's one players filter (roster
|
|
1014
1075
|
// membership) — never fetch the whole collection.
|
|
1015
|
-
|
|
1076
|
+
c ? e.listPlayers({ teamId: c.id }) : Promise.resolve({ items: [] })
|
|
1016
1077
|
]);
|
|
1017
1078
|
return {
|
|
1018
1079
|
season: t,
|
|
1019
1080
|
school: s,
|
|
1020
1081
|
teams: o,
|
|
1021
|
-
active:
|
|
1022
|
-
games:
|
|
1023
|
-
allTeams:
|
|
1024
|
-
schools:
|
|
1025
|
-
conferences:
|
|
1082
|
+
active: c,
|
|
1083
|
+
games: n.items,
|
|
1084
|
+
allTeams: h.items,
|
|
1085
|
+
schools: l.items,
|
|
1086
|
+
conferences: d.items,
|
|
1026
1087
|
rankings: m.items,
|
|
1027
1088
|
roster: f.items.find((k) => k.season === t) || null,
|
|
1028
1089
|
players: g.items
|
|
@@ -1043,61 +1104,61 @@ class De extends $ {
|
|
|
1043
1104
|
}
|
|
1044
1105
|
renderView() {
|
|
1045
1106
|
const { school: e, teams: t, active: s, season: r } = this.data;
|
|
1046
|
-
if (!e) return
|
|
1047
|
-
const o = this.ctx,
|
|
1048
|
-
return
|
|
1049
|
-
<div class="schoolhero" style="background:linear-gradient(115deg, ${e.colorPrimary || "#030711"} 0%, ${e.colorPrimary || "#030711"} 55%, var(--hsot-black) 100%);color:${
|
|
1107
|
+
if (!e) return i`<div class="view"><p class="empty">School not found.</p></div>`;
|
|
1108
|
+
const o = this.ctx, c = E(e.colorPrimary || "#030711"), n = (e.adm || [])[0], h = v(this.data.conferences), l = s ? h[s.conferenceId] : null;
|
|
1109
|
+
return i`
|
|
1110
|
+
<div class="schoolhero" style="background:linear-gradient(115deg, ${e.colorPrimary || "#030711"} 0%, ${e.colorPrimary || "#030711"} 55%, var(--hsot-black) 100%);color:${c}">
|
|
1050
1111
|
<div class="inner">
|
|
1051
|
-
${
|
|
1112
|
+
${_(e, 84) ? i`<img class="crest logo" alt="" loading="lazy" src=${_(e, 84)} />` : i`<div class="crest" style="background:${e.colorSecondary || "#7C7C7C"};color:${E(e.colorSecondary || "#7C7C7C")}">${G(e)}</div>`}
|
|
1052
1113
|
<div style="min-width:260px">
|
|
1053
1114
|
<h1>${e.name} <span class="mascot">${e.mascot || ""}</span></h1>
|
|
1054
1115
|
<div class="facts">
|
|
1055
|
-
${e.location ?
|
|
1056
|
-
${e.association ?
|
|
1057
|
-
${
|
|
1058
|
-
${
|
|
1059
|
-
${e.openingYear ?
|
|
1060
|
-
${e.areaCode ?
|
|
1061
|
-
${e.tagSlug ? l`<span><b>Tag</b>#${e.tagSlug}</span>` : p}
|
|
1116
|
+
${e.location ? i`<span><b>Location</b>${e.location}${e.county ? i` · ${e.county} County` : p}</span>` : p}
|
|
1117
|
+
${e.association ? i`<span><b>League</b>${e.association}${e.classification ? i` · ${e.classification}` : p}</span>` : p}
|
|
1118
|
+
${l ? i`<span><b>Conference</b>${l.name}</span>` : p}
|
|
1119
|
+
${n ? i`<span><b>Enrollment</b>${n.value.toLocaleString()} (${n.season} ADM)</span>` : p}
|
|
1120
|
+
${e.openingYear ? i`<span><b>Opened</b>${e.openingYear}</span>` : p}
|
|
1121
|
+
${e.areaCode ? i`<span><b>Area</b>${e.areaCode}</span>` : p}
|
|
1062
1122
|
</div>
|
|
1063
1123
|
</div>
|
|
1064
1124
|
</div>
|
|
1065
1125
|
</div>
|
|
1066
1126
|
<div class="band">
|
|
1067
1127
|
<nav class="tabs" aria-label="Teams">
|
|
1068
|
-
${t.map((
|
|
1069
|
-
m.preventDefault(), this.switchSport(
|
|
1070
|
-
}}>${
|
|
1128
|
+
${t.map((d) => d.id === s?.id ? i`<a class="on" href="#" @click=${(m) => m.preventDefault()}>${d.name}</a>` : i`<a href="#" @click=${(m) => {
|
|
1129
|
+
m.preventDefault(), this.switchSport(d.sport);
|
|
1130
|
+
}}>${d.name}</a>`)}
|
|
1071
1131
|
</nav>
|
|
1072
1132
|
</div>
|
|
1073
|
-
|
|
1074
|
-
${
|
|
1075
|
-
|
|
1133
|
+
${B(this, i`
|
|
1134
|
+
${P(this)}
|
|
1135
|
+
${s ? this.renderTeam(o, s, l, r) : i`<p class="empty">No teams recorded for this school yet.</p>`}
|
|
1136
|
+
`)}
|
|
1076
1137
|
`;
|
|
1077
1138
|
}
|
|
1078
1139
|
renderTeam(e, t, s, r) {
|
|
1079
|
-
const o = e.records[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] },
|
|
1080
|
-
return
|
|
1140
|
+
const o = e.records[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, c = o.w + o.l + o.t, n = s ? this.data.allTeams.filter((m) => m.conferenceId === s.id) : [], h = s ? re(n, e.records).findIndex((m) => m.team.id === t.id) + 1 : 0, l = V(e.rankings, e.teamsById, t.id, t.sport, null), d = this.data.games.filter((m) => m.homeTeamId === t.id || m.awayTeamId === t.id).sort((m, f) => String(m.date).localeCompare(String(f.date)));
|
|
1141
|
+
return i`
|
|
1081
1142
|
<div class="tiles">
|
|
1082
|
-
<div class="tile"><div class="k">Overall</div><div class="v">${w(o)}</div><div class="s">${
|
|
1143
|
+
<div class="tile"><div class="k">Overall</div><div class="v">${w(o)}</div><div class="s">${c} games played</div></div>
|
|
1083
1144
|
<div class="tile"><div class="k">${s?.name || "Conference"}</div><div class="v">${w(o, !0)}</div>
|
|
1084
|
-
<div class="s">${
|
|
1085
|
-
<div class="tile"><div class="k">Points</div><div class="v">${
|
|
1086
|
-
<div class="s">scored per game · ${
|
|
1087
|
-
<div class="tile"><div class="k">Streak</div><div class="v">${
|
|
1088
|
-
<div class="s">last 5: ${
|
|
1089
|
-
<div class="tile"><div class="k">HSOT Top 25</div><div class="v">${
|
|
1145
|
+
<div class="s">${h ? `${me(h)} of ${n.length}` : "·"}</div></div>
|
|
1146
|
+
<div class="tile"><div class="k">Points</div><div class="v">${c ? (o.pf / c).toFixed(1) : "0.0"}</div>
|
|
1147
|
+
<div class="s">scored per game · ${c ? (o.pa / c).toFixed(1) : "0.0"} allowed</div></div>
|
|
1148
|
+
<div class="tile"><div class="k">Streak</div><div class="v">${N(o.results) || "·"}</div>
|
|
1149
|
+
<div class="s">last 5: ${Q(e, t.id)}</div></div>
|
|
1150
|
+
<div class="tile"><div class="k">HSOT Top 25</div><div class="v">${l ? `#${l}` : "NR"}</div>
|
|
1090
1151
|
<div class="s"><a href=${u(e.hrefs.section, { sport: t.sport, view: "rankings" })}>full poll</a></div></div>
|
|
1091
1152
|
</div>
|
|
1092
|
-
${(t.championships || []).length ?
|
|
1153
|
+
${(t.championships || []).length ? i`
|
|
1093
1154
|
<div style="margin:-0.2rem 0 1rem;display:flex;gap:0.4rem;flex-wrap:wrap">
|
|
1094
|
-
${t.championships.map((m) =>
|
|
1155
|
+
${t.championships.map((m) => i`<span class="pill champ">★ ${m.season} ${m.title} champion${m.classification ? ` · ${m.classification}` : ""}${m.region ? ` · ${m.region}` : ""}</span>`)}
|
|
1095
1156
|
</div>` : p}
|
|
1096
1157
|
<div class="cols">
|
|
1097
1158
|
<div>
|
|
1098
1159
|
<div class="section-title">Schedule & results</div>
|
|
1099
1160
|
<div class="card">
|
|
1100
|
-
${
|
|
1161
|
+
${d.length ? i`<ul class="gamelist">${d.map((m) => this.renderGameRow(e, t, m))}</ul>` : i`<p class="empty">No ${t.sport} games recorded for ${r}.</p>`}
|
|
1101
1162
|
</div>
|
|
1102
1163
|
</div>
|
|
1103
1164
|
<div>
|
|
@@ -1108,21 +1169,21 @@ class De extends $ {
|
|
|
1108
1169
|
`;
|
|
1109
1170
|
}
|
|
1110
1171
|
renderGameRow(e, t, s) {
|
|
1111
|
-
const r = s.homeTeamId === t.id, o = r ? s.awayTeamId : s.homeTeamId,
|
|
1112
|
-
let
|
|
1172
|
+
const r = s.homeTeamId === t.id, o = r ? s.awayTeamId : s.homeTeamId, c = r ? s.homeScore : s.awayScore, n = r ? s.awayScore : s.homeScore;
|
|
1173
|
+
let h = i`<span class="mut">${M(s.time)}</span>`;
|
|
1113
1174
|
if (s.state === "final") {
|
|
1114
|
-
const
|
|
1115
|
-
|
|
1116
|
-
} else s.state === "live" && (
|
|
1117
|
-
const
|
|
1118
|
-
return
|
|
1175
|
+
const d = q(s), m = d === "tie" ? "T" : d === (r ? "home" : "away") ? "W" : "L";
|
|
1176
|
+
h = i`<span class=${m}>${m}</span> ${c}-${n}${s.finish === "overtime" ? i` <span class="mut">OT</span>` : p}${s.forfeit && s.forfeit !== "none" ? i` <span class="mut">FF</span>` : p}`;
|
|
1177
|
+
} else s.state === "live" && (h = i`<span style="color:var(--hsot-red)">${c}-${n}</span>`);
|
|
1178
|
+
const l = s.gameType === "conference" ? "Conf" : s.gameType === "nonconference" ? "Non-conf" : s.gameType === "playoff" ? `Playoff${s.label ? ` · ${s.label}` : ""}` : "Scrimmage";
|
|
1179
|
+
return i`
|
|
1119
1180
|
<li>
|
|
1120
|
-
<span class="d">${
|
|
1121
|
-
${R(s)}
|
|
1122
|
-
<span class="res">${
|
|
1123
|
-
<span class="opp">${r ? "vs" : "at"} ${
|
|
1124
|
-
<span class="pill type">${
|
|
1125
|
-
${s.broadcast ?
|
|
1181
|
+
<span class="d">${$(s.date)}</span>
|
|
1182
|
+
${se(s).kind === "sched" ? p : R(s)}
|
|
1183
|
+
<span class="res">${h}</span>
|
|
1184
|
+
<span class="opp">${r ? "vs" : "at"} ${U(e, o, s.date)}
|
|
1185
|
+
<span class="pill type">${l}</span>
|
|
1186
|
+
${s.broadcast ? i`<span class="pill class">${s.broadcast}</span>` : p}
|
|
1126
1187
|
</span>
|
|
1127
1188
|
<span class="where">${s.venue || ""}</span>
|
|
1128
1189
|
<a class="box" href=${u(e.hrefs.game, { sport: t.sport, id: s.id })}>Box score →</a>
|
|
@@ -1132,21 +1193,21 @@ class De extends $ {
|
|
|
1132
1193
|
renderRoster(e) {
|
|
1133
1194
|
const t = this.data.roster;
|
|
1134
1195
|
if (!t)
|
|
1135
|
-
return
|
|
1136
|
-
const s = v(this.data.players), r = t.entries.slice().sort((o,
|
|
1137
|
-
return
|
|
1196
|
+
return i`<p class="empty">Roster not published for ${e}.</p>`;
|
|
1197
|
+
const s = v(this.data.players), r = t.entries.slice().sort((o, c) => (o.number || 0) - (c.number || 0));
|
|
1198
|
+
return i`
|
|
1138
1199
|
<div class="tablewrap"><table class="data">
|
|
1139
1200
|
<thead><tr><th class="num">No.</th><th>Player</th><th>Pos</th><th>Class</th><th class="num">Ht</th><th class="num">Wt</th></tr></thead>
|
|
1140
1201
|
<tbody>
|
|
1141
1202
|
${r.map((o) => {
|
|
1142
|
-
const
|
|
1143
|
-
return
|
|
1203
|
+
const c = s[o.playerId];
|
|
1204
|
+
return c ? i`<tr>
|
|
1144
1205
|
<td class="num mut">${o.number ?? "·"}</td>
|
|
1145
|
-
<td style="font-weight:500">${
|
|
1206
|
+
<td style="font-weight:500">${c.firstName} ${c.lastName}</td>
|
|
1146
1207
|
<td>${o.position || "·"}</td>
|
|
1147
|
-
<td class="mut">${
|
|
1148
|
-
<td class="num">${
|
|
1149
|
-
<td class="num">${
|
|
1208
|
+
<td class="mut">${c.classOf || "·"}</td>
|
|
1209
|
+
<td class="num">${de(c.heightIn)}</td>
|
|
1210
|
+
<td class="num">${c.weightLb || "·"}</td>
|
|
1150
1211
|
</tr>` : p;
|
|
1151
1212
|
})}
|
|
1152
1213
|
</tbody>
|
|
@@ -1154,16 +1215,16 @@ class De extends $ {
|
|
|
1154
1215
|
`;
|
|
1155
1216
|
}
|
|
1156
1217
|
}
|
|
1157
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-school") && globalThis.customElements.define("hsot-school",
|
|
1158
|
-
const
|
|
1159
|
-
function
|
|
1218
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-school") && globalThis.customElements.define("hsot-school", Be);
|
|
1219
|
+
const Pe = "https://api.wral.com/search";
|
|
1220
|
+
function Ee(a) {
|
|
1160
1221
|
return a.map((e) => `uri:"${e}"`).join(" OR ");
|
|
1161
1222
|
}
|
|
1162
|
-
function
|
|
1163
|
-
const t = String(a ||
|
|
1223
|
+
function _e(a, e) {
|
|
1224
|
+
const t = String(a || Pe).replace(/\/+$/, ""), s = new URLSearchParams({ query: Ee(e), sort: "score", lang: "en" });
|
|
1164
1225
|
return `${t}/v1/query?${s}`;
|
|
1165
1226
|
}
|
|
1166
|
-
function
|
|
1227
|
+
function ie(a) {
|
|
1167
1228
|
try {
|
|
1168
1229
|
const e = new URL(a);
|
|
1169
1230
|
if (/(^|\.)smugmug\.com$/i.test(e.hostname)) {
|
|
@@ -1178,13 +1239,13 @@ function se(a) {
|
|
|
1178
1239
|
}
|
|
1179
1240
|
return { uri: a, title: a };
|
|
1180
1241
|
}
|
|
1181
|
-
async function
|
|
1182
|
-
const r = await ((...
|
|
1242
|
+
async function Ae(a, e, t) {
|
|
1243
|
+
const r = await ((...n) => fetch(...n))(_e(a, e));
|
|
1183
1244
|
if (!r.ok) throw new Error(`search answered ${r.status}`);
|
|
1184
|
-
const o = await r.json(),
|
|
1185
|
-
return e.map((
|
|
1245
|
+
const o = await r.json(), c = new Map((o.items || []).map((n) => [n.uri, n]));
|
|
1246
|
+
return e.map((n) => c.get(n) || ie(n));
|
|
1186
1247
|
}
|
|
1187
|
-
const
|
|
1248
|
+
const Re = b`
|
|
1188
1249
|
.breadcrumbs { font-size: 0.8125rem; margin: 0.9rem 0 0; color: var(--hsot-gray-5); }
|
|
1189
1250
|
.breadcrumbs a { text-decoration: none; }
|
|
1190
1251
|
.scorehead { display: grid; grid-template-columns: 1fr auto 1fr; gap: 1rem; align-items: center; padding: 1.4rem 1rem; }
|
|
@@ -1223,10 +1284,10 @@ const _e = y`
|
|
|
1223
1284
|
.cols { grid-template-columns: 1fr; }
|
|
1224
1285
|
}
|
|
1225
1286
|
`;
|
|
1226
|
-
class
|
|
1227
|
-
static styles = [...F,
|
|
1287
|
+
class Le extends y {
|
|
1288
|
+
static styles = [...F, Re];
|
|
1228
1289
|
static properties = {
|
|
1229
|
-
|
|
1290
|
+
...y.properties,
|
|
1230
1291
|
gameId: { type: String, attribute: "game-id" },
|
|
1231
1292
|
// The public site search that resolves Game.coverageUrls into cards
|
|
1232
1293
|
// (DEV-1236). Shared cross-stage by design — see the studio host's
|
|
@@ -1238,7 +1299,7 @@ class Re extends $ {
|
|
|
1238
1299
|
super(), this.gameId = "", this.searchApi = "";
|
|
1239
1300
|
}
|
|
1240
1301
|
async fetchData(e) {
|
|
1241
|
-
const t = await e.getGame(this.gameId), s = Array.isArray(t.coverageUrls) ? t.coverageUrls : [], [r, o,
|
|
1302
|
+
const t = await e.getGame(this.gameId), s = Array.isArray(t.coverageUrls) ? t.coverageUrls : [], [r, o, c, n, h, l] = await Promise.all([
|
|
1242
1303
|
e.listSchools(),
|
|
1243
1304
|
e.listTeams({ sport: t.sport }),
|
|
1244
1305
|
e.listConferences(),
|
|
@@ -1246,16 +1307,16 @@ class Re extends $ {
|
|
|
1246
1307
|
e.listGames({ sport: t.sport, season: t.season }),
|
|
1247
1308
|
// A search outage must not blank the box score — degrade to bare
|
|
1248
1309
|
// links (fetchCoverage already degrades per-URL index misses).
|
|
1249
|
-
s.length ?
|
|
1310
|
+
s.length ? Ae(this.searchApi, s).catch(() => s.map(ie)) : Promise.resolve([])
|
|
1250
1311
|
]);
|
|
1251
1312
|
return {
|
|
1252
1313
|
game: t,
|
|
1253
1314
|
schools: r.items,
|
|
1254
1315
|
teams: o.items,
|
|
1255
|
-
conferences:
|
|
1256
|
-
rankings:
|
|
1257
|
-
games:
|
|
1258
|
-
coverage:
|
|
1316
|
+
conferences: c.items,
|
|
1317
|
+
rankings: n.items,
|
|
1318
|
+
games: h.items,
|
|
1319
|
+
coverage: l
|
|
1259
1320
|
};
|
|
1260
1321
|
}
|
|
1261
1322
|
get ctx() {
|
|
@@ -1270,49 +1331,50 @@ class Re extends $ {
|
|
|
1270
1331
|
}
|
|
1271
1332
|
renderView() {
|
|
1272
1333
|
const e = this.data.game;
|
|
1273
|
-
if (!e) return
|
|
1274
|
-
const t = this.ctx, s = v(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,
|
|
1275
|
-
return
|
|
1276
|
-
|
|
1334
|
+
if (!e) return i`<div class="view"><p class="empty">Game not found.</p></div>`;
|
|
1335
|
+
const t = this.ctx, s = v(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, c = q(e), n = (d) => e.state === "final" && c !== d && c !== "tie" ? "opacity:0.45" : "", h = e.conferenceId ? s[e.conferenceId] : null, l = this.data.games.filter((d) => d.id !== e.id && d.state === "final" && d.gameType !== "scrimmage" && (d.homeTeamId === e.homeTeamId && d.awayTeamId === e.awayTeamId || d.homeTeamId === e.awayTeamId && d.awayTeamId === e.homeTeamId));
|
|
1336
|
+
return i`
|
|
1337
|
+
${B(this, i`
|
|
1338
|
+
${P(this)}
|
|
1277
1339
|
<p class="breadcrumbs">
|
|
1278
1340
|
<a href=${u(t.hrefs.section, { sport: e.sport, view: "scores" })}>${T(e.sport)}</a> /
|
|
1279
1341
|
<a href=${u(t.hrefs.section, { sport: e.sport, view: "scores" })}>Scores/Schedules</a> /
|
|
1280
|
-
${
|
|
1342
|
+
${I(t, e.awayTeamId)} at ${I(t, e.homeTeamId)}
|
|
1281
1343
|
</p>
|
|
1282
1344
|
<div class="card">
|
|
1283
1345
|
<div class="scorehead">
|
|
1284
1346
|
${this.teamBlock(t, e, e.awayTeamId, r, !1)}
|
|
1285
1347
|
<div class="mid">
|
|
1286
1348
|
<div class="bigscore">
|
|
1287
|
-
<span style=${
|
|
1349
|
+
<span style=${n("away")}>${e.awayScore}</span>
|
|
1288
1350
|
<span class="mut" style="font-size:1.6rem">–</span>
|
|
1289
|
-
<span style=${
|
|
1351
|
+
<span style=${n("home")}>${e.homeScore}</span>
|
|
1290
1352
|
</div>
|
|
1291
1353
|
<div class="status">${R(e)}</div>
|
|
1292
|
-
<div class="status">${
|
|
1293
|
-
${e.broadcast ?
|
|
1354
|
+
<div class="status">${$(e.date, { weekday: "short", month: "short", day: "numeric", year: "numeric" })}${e.state === "scheduled" && e.time ? i` · ${M(e.time)}` : p} · ${e.venue || "Venue TBD"}
|
|
1355
|
+
${e.broadcast ? i` · <span class="pill class">${e.broadcast}</span>` : p}</div>
|
|
1294
1356
|
<div class="status">
|
|
1295
|
-
<span class="pill type">${e.gameType === "conference" ? `${
|
|
1296
|
-
${e.label ?
|
|
1297
|
-
${(e.tags || []).map((
|
|
1357
|
+
<span class="pill type">${e.gameType === "conference" ? `${h?.name || "Conference"} game` : e.gameType}</span>
|
|
1358
|
+
${e.label ? i`<span class="pill type">Bracket ${e.label}</span>` : p}
|
|
1359
|
+
${(e.tags || []).map((d) => i`<span class="pill type">${d}</span>`)}
|
|
1298
1360
|
</div>
|
|
1299
1361
|
</div>
|
|
1300
1362
|
${this.teamBlock(t, e, e.homeTeamId, o, !0)}
|
|
1301
1363
|
</div>
|
|
1302
1364
|
${this.renderLineScore(e, r, o)}
|
|
1303
|
-
${e.notes ?
|
|
1365
|
+
${e.notes ? i`<p class="note" style="padding:0 1rem 0.9rem;text-align:center">${e.notes}</p>` : p}
|
|
1304
1366
|
</div>
|
|
1305
|
-
${(this.data.coverage || []).length ?
|
|
1367
|
+
${(this.data.coverage || []).length ? i`
|
|
1306
1368
|
<div class="section-title">Coverage</div>
|
|
1307
1369
|
<div class="covgrid">
|
|
1308
|
-
${this.data.coverage.map((
|
|
1309
|
-
<a class="card covcard" href=${
|
|
1310
|
-
${
|
|
1370
|
+
${this.data.coverage.map((d) => i`
|
|
1371
|
+
<a class="card covcard" href=${d.uri}>
|
|
1372
|
+
${d.image ? i`<img class="covimg" src=${d.image} alt="" loading="lazy" />` : p}
|
|
1311
1373
|
<div class="covbody">
|
|
1312
|
-
<div class="covtitle">${
|
|
1313
|
-
${
|
|
1314
|
-
${
|
|
1315
|
-
<div class="covmeta">${[
|
|
1374
|
+
<div class="covtitle">${d.videoDuration ? i`<span class="pill live" style="animation:none">Video</span> ` : p}${d.photos ? i`<span class="pill live" style="animation:none">Photos</span> ` : p}${d.title || d.uri}</div>
|
|
1375
|
+
${d.description ? i`<p class="covdesc">${d.description}</p>` : p}
|
|
1376
|
+
${d.author || d.publishedTime ? i`
|
|
1377
|
+
<div class="covmeta">${[d.author, d.publishedTime ? new Date(d.publishedTime).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) : ""].filter(Boolean).join(" · ")}</div>
|
|
1316
1378
|
` : p}
|
|
1317
1379
|
</div>
|
|
1318
1380
|
</a>
|
|
@@ -1320,29 +1382,29 @@ class Re extends $ {
|
|
|
1320
1382
|
</div>` : p}
|
|
1321
1383
|
<div class="section-title">Season context</div>
|
|
1322
1384
|
<div class="cols">
|
|
1323
|
-
${[[e.awayTeamId, r], [e.homeTeamId, o]].map(([
|
|
1385
|
+
${[[e.awayTeamId, r], [e.homeTeamId, o]].map(([d, m]) => this.renderContext(t, d, m))}
|
|
1324
1386
|
</div>
|
|
1325
|
-
${
|
|
1387
|
+
${l.length ? i`
|
|
1326
1388
|
<div class="section-title">Head to head this season</div>
|
|
1327
1389
|
<div class="card"><ul class="gamelist">
|
|
1328
|
-
${
|
|
1329
|
-
<span class="d">${
|
|
1330
|
-
<span class="opp">${
|
|
1331
|
-
<a class="box" href=${u(t.hrefs.game, { sport: e.sport, id:
|
|
1390
|
+
${l.map((d) => i`<li>
|
|
1391
|
+
<span class="d">${$(d.date)}</span>${R(d)}
|
|
1392
|
+
<span class="opp">${I(t, d.awayTeamId)} ${d.awayScore}, ${I(t, d.homeTeamId)} ${d.homeScore}</span>
|
|
1393
|
+
<a class="box" href=${u(t.hrefs.game, { sport: e.sport, id: d.id })}>Box score →</a>
|
|
1332
1394
|
</li>`)}
|
|
1333
1395
|
</ul></div>` : p}
|
|
1334
|
-
|
|
1396
|
+
`)}
|
|
1335
1397
|
`;
|
|
1336
1398
|
}
|
|
1337
1399
|
teamBlock(e, t, s, r, o) {
|
|
1338
|
-
if (!r) return
|
|
1339
|
-
const
|
|
1340
|
-
return
|
|
1400
|
+
if (!r) return i`<div class="teamblock ${o ? "right" : ""}"><div class="tname">TBD</div></div>`;
|
|
1401
|
+
const c = e.teamsById[s], n = e.records[s], h = _(r, 58);
|
|
1402
|
+
return i`
|
|
1341
1403
|
<div class="teamblock ${o ? "right" : ""}">
|
|
1342
|
-
${
|
|
1404
|
+
${h ? i`<img class="crest logo" alt="" loading="lazy" src=${h} />` : i`<span class="crest" style="background:${r.colorPrimary || "#030711"};color:${E(r.colorPrimary || "#030711")}">${G(r)}</span>`}
|
|
1343
1405
|
<div>
|
|
1344
|
-
<div class="tname">${
|
|
1345
|
-
<div class="trec">${r.mascot || ""} · ${w(
|
|
1406
|
+
<div class="tname">${K(e, s, t.date)}<a href=${u(e.hrefs.school, { id: r.id })}>${r.name}</a></div>
|
|
1407
|
+
<div class="trec">${r.mascot || ""} · ${w(n)}${c?.conferenceId ? i` · ${w(n, !0)} conf` : p}</div>
|
|
1346
1408
|
</div>
|
|
1347
1409
|
</div>
|
|
1348
1410
|
`;
|
|
@@ -1350,23 +1412,23 @@ class Re extends $ {
|
|
|
1350
1412
|
renderLineScore(e, t, s) {
|
|
1351
1413
|
const r = e.periodScores || [];
|
|
1352
1414
|
if (!r.length)
|
|
1353
|
-
return
|
|
1354
|
-
const o = Math.max(4, ...r.map((
|
|
1355
|
-
const m = r.find((f) => f.period ===
|
|
1356
|
-
return m ? m[
|
|
1357
|
-
},
|
|
1415
|
+
return i`<p class="empty" style="text-align:center">Period scoring will appear once the game starts.</p>`;
|
|
1416
|
+
const o = Math.max(4, ...r.map((l) => l.period)), c = (l) => l <= 4 ? String(l) : `OT${l > 5 ? l - 4 : ""}`, n = (l, d) => {
|
|
1417
|
+
const m = r.find((f) => f.period === d);
|
|
1418
|
+
return m ? m[l] : e.state === "final" ? 0 : "·";
|
|
1419
|
+
}, h = (l, d, m) => i`
|
|
1358
1420
|
<tr>
|
|
1359
|
-
<td class="teamcell">${C(
|
|
1360
|
-
${Array.from({ length: o }, (f, g) =>
|
|
1421
|
+
<td class="teamcell">${C(l, 20)}${l?.abbr || "TBD"}</td>
|
|
1422
|
+
${Array.from({ length: o }, (f, g) => i`<td class="num">${n(d, g + 1)}</td>`)}
|
|
1361
1423
|
<td class="num" style="font-weight:700">${m}</td>
|
|
1362
1424
|
</tr>`;
|
|
1363
|
-
return
|
|
1425
|
+
return i`
|
|
1364
1426
|
<div class="tablewrap" style="border-top:1px solid var(--hsot-gray-2)">
|
|
1365
1427
|
<table class="data" style="max-width:560px;margin:0.6rem auto 0.9rem">
|
|
1366
|
-
<thead><tr><th>Team</th>${Array.from({ length: o }, (
|
|
1428
|
+
<thead><tr><th>Team</th>${Array.from({ length: o }, (l, d) => i`<th class="num">${c(d + 1)}</th>`)}<th class="num">T</th></tr></thead>
|
|
1367
1429
|
<tbody>
|
|
1368
|
-
${
|
|
1369
|
-
${
|
|
1430
|
+
${h(t, "away", e.awayScore)}
|
|
1431
|
+
${h(s, "home", e.homeScore)}
|
|
1370
1432
|
</tbody>
|
|
1371
1433
|
</table>
|
|
1372
1434
|
</div>
|
|
@@ -1374,37 +1436,217 @@ class Re extends $ {
|
|
|
1374
1436
|
}
|
|
1375
1437
|
renderContext(e, t, s) {
|
|
1376
1438
|
if (!s) return p;
|
|
1377
|
-
const r = e.records[t], o =
|
|
1378
|
-
return
|
|
1439
|
+
const r = e.records[t], o = W(this.data.games, t);
|
|
1440
|
+
return i`
|
|
1379
1441
|
<div class="card ctxcard">
|
|
1380
1442
|
<div class="who">${C(s)}${s.name}</div>
|
|
1381
1443
|
<div class="row">
|
|
1382
|
-
<span>Last 5: ${
|
|
1383
|
-
<span>Streak: <b>${r ?
|
|
1444
|
+
<span>Last 5: ${Q(e, t)}</span>
|
|
1445
|
+
<span>Streak: <b>${r ? N(r.results) : "·"}</b></span>
|
|
1384
1446
|
<span>PF/PA: <b>${r ? `${r.pf} / ${r.pa}` : "·"}</b></span>
|
|
1385
|
-
<span>Next: ${o ?
|
|
1386
|
-
${o.homeTeamId === t ? "vs" : "at"} ${
|
|
1447
|
+
<span>Next: ${o ? i`${$(o.date, { month: "numeric", day: "numeric" })}
|
|
1448
|
+
${o.homeTeamId === t ? "vs" : "at"} ${A(e, o.homeTeamId === t ? o.awayTeamId : o.homeTeamId)}` : "·"}</span>
|
|
1387
1449
|
</div>
|
|
1388
1450
|
</div>
|
|
1389
1451
|
`;
|
|
1390
1452
|
}
|
|
1391
1453
|
}
|
|
1392
|
-
globalThis?.customElements && !globalThis.customElements.get("hsot-boxscore") && globalThis.customElements.define("hsot-boxscore",
|
|
1454
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-boxscore") && globalThis.customElements.define("hsot-boxscore", Le);
|
|
1455
|
+
const Ne = 250, Oe = 2;
|
|
1456
|
+
class He extends te {
|
|
1457
|
+
static properties = {
|
|
1458
|
+
api: { type: String },
|
|
1459
|
+
schoolHref: { type: String, attribute: "school-href" },
|
|
1460
|
+
limit: { type: Number },
|
|
1461
|
+
placeholder: { type: String },
|
|
1462
|
+
results: { state: !0 },
|
|
1463
|
+
open: { state: !0 },
|
|
1464
|
+
activeIndex: { state: !0 },
|
|
1465
|
+
searched: { state: !0 }
|
|
1466
|
+
};
|
|
1467
|
+
static styles = b`
|
|
1468
|
+
:host {
|
|
1469
|
+
display: block;
|
|
1470
|
+
position: relative;
|
|
1471
|
+
font-family: var(--font-family, sans-serif);
|
|
1472
|
+
}
|
|
1473
|
+
input {
|
|
1474
|
+
width: 100%;
|
|
1475
|
+
box-sizing: border-box;
|
|
1476
|
+
padding: 0.625rem 0.75rem;
|
|
1477
|
+
font-size: 1rem;
|
|
1478
|
+
font-family: inherit;
|
|
1479
|
+
color: var(--color-black, #000);
|
|
1480
|
+
background: var(--color-white, #fff);
|
|
1481
|
+
border: 1px solid var(--color-gray-4, #ccc);
|
|
1482
|
+
border-bottom: 3px solid var(--color-red, #b90100);
|
|
1483
|
+
border-radius: 2px;
|
|
1484
|
+
}
|
|
1485
|
+
input:focus {
|
|
1486
|
+
outline: 2px solid var(--color-red, #b90100);
|
|
1487
|
+
outline-offset: -1px;
|
|
1488
|
+
}
|
|
1489
|
+
ul {
|
|
1490
|
+
position: absolute;
|
|
1491
|
+
z-index: 10;
|
|
1492
|
+
left: 0;
|
|
1493
|
+
right: 0;
|
|
1494
|
+
margin: 0;
|
|
1495
|
+
padding: 0;
|
|
1496
|
+
list-style: none;
|
|
1497
|
+
max-height: 20rem;
|
|
1498
|
+
overflow-y: auto;
|
|
1499
|
+
background: var(--color-white, #fff);
|
|
1500
|
+
border: 1px solid var(--color-gray-4, #ccc);
|
|
1501
|
+
border-top: none;
|
|
1502
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
|
1503
|
+
}
|
|
1504
|
+
li {
|
|
1505
|
+
padding: 0.5rem 0.75rem;
|
|
1506
|
+
cursor: pointer;
|
|
1507
|
+
}
|
|
1508
|
+
li[aria-selected="true"], li:hover {
|
|
1509
|
+
background: var(--color-gray-1, #f9f9f9);
|
|
1510
|
+
}
|
|
1511
|
+
li .name {
|
|
1512
|
+
font-weight: 700;
|
|
1513
|
+
color: var(--color-black, #000);
|
|
1514
|
+
}
|
|
1515
|
+
li .where {
|
|
1516
|
+
display: block;
|
|
1517
|
+
font-size: 0.8rem;
|
|
1518
|
+
color: var(--color-gray-5, #666);
|
|
1519
|
+
}
|
|
1520
|
+
li.empty {
|
|
1521
|
+
cursor: default;
|
|
1522
|
+
color: var(--color-gray-5, #666);
|
|
1523
|
+
}
|
|
1524
|
+
li.empty:hover {
|
|
1525
|
+
background: none;
|
|
1526
|
+
}
|
|
1527
|
+
`;
|
|
1528
|
+
constructor() {
|
|
1529
|
+
super(), this.api = "https://api.highschoolot.com/hsot/v1/public", this.schoolHref = "/school/{id}/", this.limit = 10, this.placeholder = "Find Your School", this.results = [], this.open = !1, this.activeIndex = -1, this.searched = !1;
|
|
1530
|
+
}
|
|
1531
|
+
disconnectedCallback() {
|
|
1532
|
+
super.disconnectedCallback(), clearTimeout(this.debounceTimer), this.abortController?.abort();
|
|
1533
|
+
}
|
|
1534
|
+
onInput(e) {
|
|
1535
|
+
const t = e.target.value.trim();
|
|
1536
|
+
if (clearTimeout(this.debounceTimer), t.length < Oe) {
|
|
1537
|
+
this.abortController?.abort(), this.results = [], this.open = !1, this.searched = !1;
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
this.debounceTimer = setTimeout(() => this.search(t), Ne);
|
|
1541
|
+
}
|
|
1542
|
+
async search(e) {
|
|
1543
|
+
this.abortController?.abort(), this.abortController = new AbortController();
|
|
1544
|
+
try {
|
|
1545
|
+
const t = `${this.api}/schools?q=${encodeURIComponent(e)}&limit=${this.limit}`, s = await fetch(t, {
|
|
1546
|
+
signal: this.abortController.signal
|
|
1547
|
+
});
|
|
1548
|
+
if (!s.ok)
|
|
1549
|
+
return;
|
|
1550
|
+
const r = await s.json();
|
|
1551
|
+
this.results = r.items || [], this.activeIndex = -1, this.searched = !0, this.open = !0;
|
|
1552
|
+
} catch (t) {
|
|
1553
|
+
t.name !== "AbortError" && console.warn("school search failed", t);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
onKeyDown(e) {
|
|
1557
|
+
if (e.key === "Escape") {
|
|
1558
|
+
this.open = !1;
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
if (!(!this.open || !this.results.length))
|
|
1562
|
+
if (e.key === "ArrowDown")
|
|
1563
|
+
e.preventDefault(), this.activeIndex = (this.activeIndex + 1) % this.results.length;
|
|
1564
|
+
else if (e.key === "ArrowUp") {
|
|
1565
|
+
e.preventDefault();
|
|
1566
|
+
const t = this.results.length;
|
|
1567
|
+
this.activeIndex = (this.activeIndex - 1 + t) % t;
|
|
1568
|
+
} else e.key === "Enter" && (e.preventDefault(), this.go(this.results[this.activeIndex] || this.results[0]));
|
|
1569
|
+
}
|
|
1570
|
+
onBlur() {
|
|
1571
|
+
setTimeout(() => {
|
|
1572
|
+
this.open = !1;
|
|
1573
|
+
}, 150);
|
|
1574
|
+
}
|
|
1575
|
+
onFocus() {
|
|
1576
|
+
this.results.length && (this.open = !0);
|
|
1577
|
+
}
|
|
1578
|
+
go(e) {
|
|
1579
|
+
e && (globalThis.location.href = this.schoolHref.replace("{id}", e.id));
|
|
1580
|
+
}
|
|
1581
|
+
where(e) {
|
|
1582
|
+
return [e.location, e.county && `${e.county} County`].filter(Boolean).join(" — ");
|
|
1583
|
+
}
|
|
1584
|
+
renderOption(e, t) {
|
|
1585
|
+
const s = this.where(e), r = (o) => {
|
|
1586
|
+
o.preventDefault(), this.go(e);
|
|
1587
|
+
};
|
|
1588
|
+
return i`
|
|
1589
|
+
<li
|
|
1590
|
+
id="school-option-${t}"
|
|
1591
|
+
role="option"
|
|
1592
|
+
aria-selected="${t === this.activeIndex ? "true" : "false"}"
|
|
1593
|
+
@pointerdown="${r}"
|
|
1594
|
+
@mousemove="${() => {
|
|
1595
|
+
this.activeIndex = t;
|
|
1596
|
+
}}"
|
|
1597
|
+
>
|
|
1598
|
+
<span class="name">${e.name}</span>
|
|
1599
|
+
${s ? i`<span class="where">${s}</span>` : p}
|
|
1600
|
+
</li>
|
|
1601
|
+
`;
|
|
1602
|
+
}
|
|
1603
|
+
renderListbox() {
|
|
1604
|
+
const e = this.searched && !this.results.length, t = i`<li class="empty">No schools found</li>`;
|
|
1605
|
+
return i`
|
|
1606
|
+
<ul id="school-search-listbox" role="listbox" aria-label="Schools">
|
|
1607
|
+
${this.results.map((s, r) => this.renderOption(s, r))}
|
|
1608
|
+
${e ? t : p}
|
|
1609
|
+
</ul>
|
|
1610
|
+
`;
|
|
1611
|
+
}
|
|
1612
|
+
render() {
|
|
1613
|
+
const e = this.activeIndex >= 0 ? `school-option-${this.activeIndex}` : "";
|
|
1614
|
+
return i`
|
|
1615
|
+
<input
|
|
1616
|
+
type="text"
|
|
1617
|
+
role="combobox"
|
|
1618
|
+
aria-label="Find your school"
|
|
1619
|
+
aria-expanded="${this.open ? "true" : "false"}"
|
|
1620
|
+
aria-controls="school-search-listbox"
|
|
1621
|
+
aria-activedescendant="${e}"
|
|
1622
|
+
autocomplete="off"
|
|
1623
|
+
placeholder="${this.placeholder}"
|
|
1624
|
+
@input="${this.onInput}"
|
|
1625
|
+
@keydown="${this.onKeyDown}"
|
|
1626
|
+
@blur="${this.onBlur}"
|
|
1627
|
+
@focus="${this.onFocus}"
|
|
1628
|
+
>
|
|
1629
|
+
${this.open ? this.renderListbox() : p}
|
|
1630
|
+
`;
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
globalThis?.customElements && !globalThis.customElements.get("hsot-school-search") && globalThis.customElements.define("hsot-school-search", He);
|
|
1393
1634
|
export {
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1635
|
+
H as D,
|
|
1636
|
+
Le as H,
|
|
1637
|
+
Fe as a,
|
|
1638
|
+
Be as b,
|
|
1639
|
+
He as c,
|
|
1640
|
+
Se as d,
|
|
1641
|
+
Ce as e,
|
|
1642
|
+
z as f,
|
|
1643
|
+
ce as g,
|
|
1644
|
+
u as h,
|
|
1645
|
+
q as i,
|
|
1646
|
+
Me as j,
|
|
1647
|
+
N as k,
|
|
1648
|
+
Te as p,
|
|
1407
1649
|
w as r,
|
|
1408
|
-
|
|
1409
|
-
|
|
1650
|
+
re as s,
|
|
1651
|
+
V as t
|
|
1410
1652
|
};
|