diff --git a/cli.ts b/cli.ts index 7f4b6fc..163d1ce 100644 --- a/cli.ts +++ b/cli.ts @@ -10,6 +10,8 @@ import { TabroomEntry, } from "./types.ts"; +import { overrides } from "./constants.ts"; + // Load auth const nsdaAuth = await Deno.readFile("./auth.txt").then((a) => new TextDecoder().decode(a) @@ -32,7 +34,7 @@ for (const row of dom.querySelectorAll("tr")) { .filter((n) => n.nodeName === "TD") .map((n) => n.textContent.trim()); // Skip invalid entries - if (!institution || !location || !entry || !code) continue; + if (!institution || !location || !entry || !code || entry === "Names TBA") continue; entries.push({ institution, @@ -46,10 +48,12 @@ for (const row of dom.querySelectorAll("tr")) { const nsdaSearchResults = await Promise .all( entries.map(async (e) => { + const override = overrides[e.entry]; + let nsdaLookup: NSDAMemberSearchResult[] = await fetch( `https://api.speechanddebate.org/v2/search?${ new URLSearchParams({ - q: e.entry, + q: override?.name ?? e.entry, type: "members", }).toString() }`, @@ -60,6 +64,17 @@ const nsdaSearchResults = await Promise }, ).then((r) => r.json()); + // Short circuit on overrides + if (override !== undefined) { + const result = nsdaLookup.find((e) => e.id === override.id); + if (result !== undefined) { + return { tabroom: e, nsdaSearchResult: result }; + } else { + console.error(`ID override failed for ${e.entry} (${override.id})!`); + return null; + } + } + // Do our best to filter the results down to one // Start by filtering anything but HS competitors and status === 1 // (status 2 appeared on a duplicate, so I assume that marks inactive entries?) @@ -69,10 +84,20 @@ const nsdaSearchResults = await Promise // Then, if that doesn't work, filter by state if (nsdaLookup.length > 1) { nsdaLookup = nsdaLookup.filter((ee) => - ee.school_state.toLowerCase() === + ee.school_state?.toLowerCase() === e.location.replace("/US", "").toLowerCase() ); } + // At this point, collapse equivelent results just in case we *have* found one result + if (nsdaLookup.length > 1) { + const collapsed: NSDAMemberSearchResult[] = []; + for (const entry of nsdaLookup) { + if (!collapsed.some((e) => e.id === entry.id)) { + collapsed.push(entry); + } + } + nsdaLookup = collapsed; + } // Finally, if none of the past filters worked, attempt a school filter let schoolFilterUsed = false; if (nsdaLookup.length > 1) { @@ -136,8 +161,8 @@ ${ Object.entries(nsdaLookups.reduce( (acc, l) => ({ ...acc, - [l.nsdaSearchResult.school_state]: - (acc[l.nsdaSearchResult.school_state] ?? 0) + 1, + [l.tabroom.location.replace("/US", "")]: + (acc[l.tabroom.location.replace("/US", "")] ?? 0) + 1, }), {} as Record, )).sort((a, b) => b[1] - a[1]).map(([state, n]) => "- " + state + ": " + n) @@ -170,7 +195,7 @@ const sheet = [ l.nsdaMemberLookup.first, l.nsdaMemberLookup.middle ?? "", l.nsdaMemberLookup.last, - l.nsdaSearchResult.school_state, + l.nsdaSearchResult.school_state ?? l.tabroom.location.replace("/US", ""), l.nsdaSearchResult.school_name, l.nsdaPointsLookup.filter((e) => e.category_id === 202 /* Extemporaneous speech event ID */ diff --git a/constants.ts b/constants.ts new file mode 100644 index 0000000..de6ceb5 --- /dev/null +++ b/constants.ts @@ -0,0 +1,9 @@ +export const overrides: Record< + string, + { name: string; id: number } | undefined +> = { + "Christopher Ramirez-Chavez": { + name: "Christopher Chavez", + id: 10847338, + }, +}; \ No newline at end of file diff --git a/types.ts b/types.ts index 6533709..9e7131e 100644 --- a/types.ts +++ b/types.ts @@ -7,7 +7,7 @@ export interface NSDAMemberSearchResult { status: number; realm: string; school_name: string; - school_state: string; + school_state: string | null; type: string; name: string; description: string;