Files
SixFlagsSuperCalendar/scripts/debug.ts
T
josh 4652a92c29 refactor: hardcode API IDs and coaster lists, remove Playwright discovery
Embed Six Flags API IDs directly in the park registry and snapshot
coaster lists from park-meta.json into a TypeScript module. This
eliminates the Playwright-based discovery script, RCDB scraper, and
runtime dependency on park-meta.json — preparing for the backend
API transition.

- Add apiId field to Park type and all 24 park entries
- Create lib/coaster-data.ts with hardcoded coaster lists
- Update page components to use park.apiId and new getCoasterSet()
- Remove scripts/discover.ts, lib/scrapers/rcdb.ts, lib/park-meta.ts
- Remove data/park-meta.json from shared volume
- Remove playwright devDependency and discover npm script
- Simplify scripts/scrape.ts (no RCDB, no discovery checks)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-23 21:25:53 -04:00

130 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Debug a specific park + date to inspect raw API data and parsed output.
*
* Usage:
* npm run debug -- --park greatadventure --date 2026-07-04
*
* Output is printed to the terminal and saved to debug/{parkId}_{date}.txt
*/
import fs from "fs";
import path from "path";
import { PARKS } from "../lib/parks";
import { scrapeMonthRaw } from "../lib/scrapers/sixflags";
function arg(flag: string): string | undefined {
const i = process.argv.indexOf(flag);
return i !== -1 ? process.argv[i + 1] : undefined;
}
function fmt24(time: string): string {
const [h, m] = time.split(":").map(Number);
const period = h >= 12 ? "pm" : "am";
const h12 = h % 12 || 12;
return m === 0 ? `${h12}${period}` : `${h12}:${String(m).padStart(2, "0")}${period}`;
}
async function main() {
const parkId = arg("--park");
const dateStr = arg("--date");
if (!parkId || !dateStr) {
console.error("Usage: npm run debug -- --park <parkId> --date <YYYY-MM-DD>");
console.error("\nAvailable park IDs:");
for (const p of PARKS) console.error(` ${p.id.padEnd(24)} ${p.name}`);
process.exit(1);
}
const park = PARKS.find((p) => p.id === parkId);
if (!park) {
console.error(`Unknown park: "${parkId}"`);
process.exit(1);
}
const match = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})$/);
if (!match) {
console.error(`Invalid date: "${dateStr}" — expected YYYY-MM-DD`);
process.exit(1);
}
const [, yearStr, monthStr, dayStr] = match;
const year = parseInt(yearStr);
const month = parseInt(monthStr);
const day = parseInt(dayStr);
const lines: string[] = [];
const out = (...args: string[]) => {
const line = args.join(" ");
lines.push(line);
console.log(line);
};
out(`Park : ${park.name} (${park.id})`);
out(`API ID : ${park.apiId}`);
out(`Date : ${dateStr}`);
out(`Fetched : ${new Date().toISOString()}`);
out("");
out(`Fetching ${year}-${String(month).padStart(2, "0")} from API...`);
const raw = await scrapeMonthRaw(park.apiId, year, month);
const targetDate = `${String(month).padStart(2, "0")}/${String(day).padStart(2, "0")}/${year}`;
const dayData = raw.dates.find((d) => d.date === targetDate);
if (!dayData) {
console.error(`Date ${dateStr} not found in API response.`);
console.error(`Dates returned by API: ${raw.dates.map((d) => d.date).join(", ")}`);
process.exit(1);
}
// ── Raw API response ───────────────────────────────────────────────────────
out("");
out("── Raw API response ─────────────────────────────────────────");
out(JSON.stringify(dayData, null, 2));
// ── Parsed result ──────────────────────────────────────────────────────────
const operating =
dayData.operatings?.find((o: { operatingTypeName: string }) => o.operatingTypeName === "Park") ??
dayData.operatings?.[0];
const item = operating?.items?.[0];
const hoursLabel =
item?.timeFrom && item?.timeTo
? `${fmt24(item.timeFrom)} ${fmt24(item.timeTo)}`
: undefined;
const isBuyout = item?.isBuyout ?? false;
const isPassholderPreview = dayData.events?.some((e: { extEventName: string }) =>
e.extEventName.toLowerCase().includes("passholder preview")
) ?? false;
const isOpen = !dayData.isParkClosed && hoursLabel !== undefined && (!isBuyout || isPassholderPreview);
const specialType = isPassholderPreview ? "passholder_preview" : null;
out("");
out("── Parsed result ────────────────────────────────────────────");
out(` isParkClosed : ${dayData.isParkClosed}`);
out(` events : ${dayData.events?.length ?? 0} (${dayData.events?.map((e: { extEventName: string }) => e.extEventName).join(", ") || "none"})`);
out(` operatings : ${dayData.operatings?.length ?? 0} entr${dayData.operatings?.length === 1 ? "y" : "ies"}`);
if (operating) {
out(` selected : "${operating.operatingTypeName}" (${operating.items?.length ?? 0} item(s))`);
if (item) {
out(` timeFrom : ${item.timeFrom}${fmt24(item.timeFrom)}`);
out(` timeTo : ${item.timeTo}${fmt24(item.timeTo)}`);
out(` isBuyout : ${isBuyout}`);
}
}
out(` isPassholderPreview : ${isPassholderPreview}`);
out(` hoursLabel : ${hoursLabel ?? "(none)"}`);
out(` isOpen : ${isOpen}`);
out(` specialType : ${specialType ?? "(none)"}`)
// ── Write to file ──────────────────────────────────────────────────────────
const debugDir = path.join(process.cwd(), "debug");
fs.mkdirSync(debugDir, { recursive: true });
const outPath = path.join(debugDir, `${parkId}_${dateStr}.txt`);
fs.writeFileSync(outPath, lines.join("\n") + "\n");
console.log(`\nSaved to debug/${parkId}_${dateStr}.txt`);
}
main().catch((err) => {
console.error("Fatal:", err);
process.exit(1);
});