// Load the parsed board Attendance Zone Recommendations capacity blocks // (data/cities/miami/reference/parsed/mdcps_abc_book_.csv) → // enrollment_abc, fish_capacity_permanent_abc, utilization_permanent_pct_abc // under the block's current year, and projected_enrollment_y1 / _y2 under the // projected years. // Run: npx tsx scripts/loaders/miami/abc_book.ts [source_id] import fs from "node:fs"; import path from "node:path"; import { parse } from "csv-parse/sync"; import { requireSource, startDataLoad, finishDataLoad, schoolUniverse, upsertFacts, runMain, type Fact } from "./_lib"; const SCRIPT_PATH = "scripts/loaders/miami/abc_book.ts"; const PARSED = path.join(process.cwd(), "data", "cities", "miami", "reference", "parsed"); const num = (v: string | undefined): number | null => { if (v === undefined || v === "" || v === "nan") return null; const n = Number.parseFloat(v); return Number.isFinite(n) ? n : null; }; async function main() { const sourceId = process.argv[2] ?? "mdcps_abc_book_2026-27"; const { prov } = requireSource(sourceId); const gate = JSON.parse(fs.readFileSync(path.join(PARSED, `${sourceId}.gate.json`), "utf-8")) as { pass: boolean }; if (!gate.pass) throw new Error(`${sourceId}: parser gate did not pass`); const rows = parse(fs.readFileSync(path.join(PARSED, `${sourceId}.csv`), "utf-8"), { columns: true, skip_empty_lines: true }) as Record[]; const universe = await schoolUniverse(); const facts: Fact[] = []; let schools = 0; for (const r of rows) { if (!universe.has(r.school_number)) { console.warn(`[abc] ${r.school_number} ${r.school_name} not in directory`); continue; } schools++; const y0 = r.year_current; const e = num(r.enrollment_current), c = num(r.perm_fish_current), u = num(r.util_perm_current); if (e !== null) facts.push({ schoolNumber: r.school_number, year: y0, metricKey: "enrollment_abc", value: e }); if (c !== null) facts.push({ schoolNumber: r.school_number, year: y0, metricKey: "fish_capacity_permanent_abc", value: c }); if (u !== null) facts.push({ schoolNumber: r.school_number, year: y0, metricKey: "utilization_permanent_pct_abc", value: u, denominator: c }); const p1 = num(r.enrollment_proj1), p2 = num(r.enrollment_proj2); if (p1 !== null && r.year_proj1) facts.push({ schoolNumber: r.school_number, year: r.year_proj1, metricKey: "projected_enrollment_y1", value: p1 }); if (p2 !== null && r.year_proj2) facts.push({ schoolNumber: r.school_number, year: r.year_proj2, metricKey: "projected_enrollment_y2", value: p2 }); } const load = await startDataLoad({ sourceId, sourceUrl: prov.url, sha256: prov.sha256, bytes: prov.bytes, yearCovered: rows[0]?.year_current, scriptPath: SCRIPT_PATH, notes: `parsed capacity blocks (${rows.length} schools; arithmetic gate PASS)` }); const res = await upsertFacts(facts, load.id); await finishDataLoad(load.id, { inserted: res.written, updated: 0, suppressed: 0 }); console.log(`[abc] ${res.written} facts for ${schools} schools`); } runMain(main);