diff --git a/app/routes/admin.sports.$id.tsx b/app/routes/admin.sports.$id.tsx
index de0dde1..4c7ff9b 100644
--- a/app/routes/admin.sports.$id.tsx
+++ b/app/routes/admin.sports.$id.tsx
@@ -22,7 +22,7 @@ import {
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
-import { SIMULATOR_TYPES } from "~/services/simulations/registry";
+import { SIMULATOR_TYPES, getSimulatorInfo } from "~/services/simulations/registry";
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
return [{ title: `${data?.sport?.name ?? "Sport"} - Brackt Admin` }];
@@ -205,14 +205,11 @@ export default function EditSport({ loaderData, actionData }: Route.ComponentPro
No simulator
- F1 Standings Model
- IndyCar Standings Model
- Golf Qualifying Points Model
- Bracket Monte Carlo
- UCL Bracket Monte Carlo
- NCAAM Bracket Monte Carlo
- NCAAW Bracket Monte Carlo
- NBA Playoff Monte Carlo
+ {SIMULATOR_TYPES.map((type) => (
+
+ {getSimulatorInfo(type)?.name ?? type}
+
+ ))}
diff --git a/app/services/simulations/nhl-simulator.ts b/app/services/simulations/nhl-simulator.ts
new file mode 100644
index 0000000..e296af3
--- /dev/null
+++ b/app/services/simulations/nhl-simulator.ts
@@ -0,0 +1,572 @@
+/**
+ * NHL Playoff Simulator
+ *
+ * Monte Carlo simulation of the NHL playoffs including seeding projection
+ * for the current season (2025-26).
+ *
+ * Algorithm:
+ * 1. Load all participants for the sports season from DB
+ * 2. Match participant names to hardcoded team data (Elo + seeding probabilities)
+ * 3. For each simulation:
+ * a. For each conference, draw division placements (1st/2nd/3rd per division)
+ * and two wildcard teams using weighted probability distributions
+ * b. Build the NHL bracket:
+ * - Higher-Elo division winner faces WC2; other division winner faces WC1
+ * - Each division's 2nd vs 3rd seeds play each other
+ * c. Simulate 4 rounds of best-of-7 series:
+ * Round 1 (Wild Card): m0=topDiv1st/WC2, m1=otherDiv1st/WC1,
+ * m2=topDiv2nd/3rd, m3=otherDiv2nd/3rd
+ * Round 2 (Div Finals): m0w vs m2w, m1w vs m3w
+ * Round 3 (Conf Finals): two division-final winners per conference
+ * Stanley Cup Final: East champ vs West champ
+ * 4. Track placement counts per scoring tier
+ * 5. Convert counts to probability distributions
+ *
+ * Win probability (Elo, PARITY_FACTOR = 800):
+ * P(A beats B) = 1 / (1 + 10^((eloB - eloA) / 800))
+ * NHL uses a higher parity factor than the standard 400 to dampen the Elo
+ * spread and reflect the high variance of hockey.
+ *
+ * Placement tiers → SimulationProbabilities mapping:
+ * probFirst = Stanley Cup champion (1 per sim)
+ * probSecond = Stanley Cup Final loser (1 per sim)
+ * probThird / probFourth = Conference Final losers (2 per sim — East + West)
+ * probFifth–probEighth = Second Round losers (4 per sim)
+ * First Round losers → all 0 (score 0 points)
+ * Missed playoffs → all 0
+ *
+ * Seeding probability keys per team:
+ * p_div1 = prob of winning own division
+ * p_div2 = prob of finishing 2nd in own division
+ * p_div3 = prob of finishing 3rd in own division
+ * p_wc1 = prob of being conference wildcard 1 (higher-ranked WC)
+ * p_wc2 = prob of being conference wildcard 2 (lower-ranked WC)
+ * Sum of all p_* ≈ team's overall playoff probability.
+ * Teams with no p_* entries always miss the playoffs.
+ *
+ * Elo ratings and seeding probabilities are hardcoded below (March 2026 data).
+ * Source: https://elo.harvitronix.com/nhl/2025-2026 (Elo ratings + playoff% calibration).
+ * Seeding probabilities are hand-derived from current standings as of March 18, 2026.
+ * Update at the start of each season.
+ */
+
+import { database } from "~/database/context";
+import { eq } from "drizzle-orm";
+import * as schema from "~/database/schema";
+import type { Simulator, SimulationResult } from "./types";
+
+// ─── Simulation parameters ────────────────────────────────────────────────────
+
+const NUM_SIMULATIONS = 50_000;
+
+/**
+ * Elo parity factor. NHL uses 800 (double the standard 400) to reflect the
+ * high game-to-game variance in hockey vs other sports.
+ * An 800-point Elo difference → ~90.9% win probability per game.
+ */
+const PARITY_FACTOR = 800;
+
+// ─── Team data (2025-26 season, as of March 18, 2026) ────────────────────────
+//
+// elo: Elo rating from elo.harvitronix.com/nhl/2025-2026.
+// p_div1: Probability of finishing 1st in own division.
+// p_div2: Probability of finishing 2nd in own division.
+// p_div3: Probability of finishing 3rd in own division.
+// p_wc1: Probability of being conference wildcard 1 (higher seed).
+// p_wc2: Probability of being conference wildcard 2 (lower seed).
+//
+// These are weights used in sequential weighted sampling (not strict distributions).
+// Sum of all p_* per team ≈ their overall playoff% from the Harvitronix site.
+//
+// Divisions:
+// Eastern — Atlantic: BOS, BUF, DET, FLA, MTL, OTT, TBL, TOR
+// Eastern — Metropolitan: CAR, CBJ, NJD, NYI, NYR, PHI, PIT, WSH
+// Western — Central: CHI, COL, DAL, MIN, NSH, STL, UTA, WPG
+// Western — Pacific: ANA, CGY, EDM, LAK, SJS, SEA, VAN, VGK
+
+interface NhlTeamData {
+ conference: "Eastern" | "Western";
+ division: "Atlantic" | "Metropolitan" | "Central" | "Pacific";
+ elo: number;
+ p_div1?: number;
+ p_div2?: number;
+ p_div3?: number;
+ p_wc1?: number;
+ p_wc2?: number;
+}
+
+const TEAMS_DATA: Record = {
+ // ── Eastern Conference — Atlantic ──────────────────────────────────────────
+ // BUF 108 pts, TBL 107 pts — neck-and-neck for 1st; both near-certain to make playoffs.
+ // MTL 101 pts (86.7% PO) — almost certainly 3rd in Atlantic or WC.
+ // OTT 96 pts (50.2%), DET 98 pts (63%), BOS 96 pts (51.1%) — WC bubble.
+ // FLA 85 pts (0.5%), TOR 83 pts (0%) — eliminated.
+
+ "Tampa Bay Lightning": {
+ conference: "Eastern", division: "Atlantic", elo: 1587,
+ p_div1: 0.50, p_div2: 0.40, p_div3: 0.06,
+ },
+ "Buffalo Sabres": {
+ conference: "Eastern", division: "Atlantic", elo: 1572,
+ p_div1: 0.45, p_div2: 0.42, p_div3: 0.07,
+ },
+ "Montreal Canadiens": {
+ conference: "Eastern", division: "Atlantic", elo: 1527,
+ p_div1: 0.01, p_div2: 0.05, p_div3: 0.60, p_wc1: 0.12, p_wc2: 0.06,
+ },
+ "Ottawa Senators": {
+ conference: "Eastern", division: "Atlantic", elo: 1542,
+ p_div1: 0.01, p_div2: 0.05, p_div3: 0.08, p_wc1: 0.22, p_wc2: 0.19,
+ },
+ "Detroit Red Wings": {
+ conference: "Eastern", division: "Atlantic", elo: 1506,
+ p_div3: 0.09, p_wc1: 0.27, p_wc2: 0.22,
+ },
+ "Boston Bruins": {
+ conference: "Eastern", division: "Atlantic", elo: 1501,
+ p_div3: 0.08, p_wc1: 0.22, p_wc2: 0.19,
+ },
+ "Florida Panthers": {
+ conference: "Eastern", division: "Atlantic", elo: 1505,
+ p_wc2: 0.005,
+ },
+ "Toronto Maple Leafs": {
+ conference: "Eastern", division: "Atlantic", elo: 1479,
+ // 0% playoff probability — always miss
+ },
+
+ // ── Eastern Conference — Metropolitan ─────────────────────────────────────
+ // CAR 109 pts (99.9%) — clear 1st seed.
+ // CBJ/PIT/NYI all tied at 99 pts — volatile 2nd/3rd/WC race.
+ // WSH 89 pts (4.7%), PHI 90 pts (7.9%) — long shots.
+ // NJD 86 pts (0.5%), NYR 80 pts (0%) — eliminated.
+
+ "Carolina Hurricanes": {
+ conference: "Eastern", division: "Metropolitan", elo: 1574,
+ p_div1: 0.98, p_div2: 0.01,
+ },
+ "Columbus Blue Jackets": {
+ conference: "Eastern", division: "Metropolitan", elo: 1530,
+ p_div2: 0.33, p_div3: 0.33, p_wc1: 0.05, p_wc2: 0.04,
+ },
+ "Pittsburgh Penguins": {
+ conference: "Eastern", division: "Metropolitan", elo: 1518,
+ p_div2: 0.35, p_div3: 0.35, p_wc1: 0.07, p_wc2: 0.07,
+ },
+ "New York Islanders": {
+ conference: "Eastern", division: "Metropolitan", elo: 1513,
+ p_div2: 0.28, p_div3: 0.35, p_wc1: 0.07, p_wc2: 0.07,
+ },
+ "Philadelphia Flyers": {
+ conference: "Eastern", division: "Metropolitan", elo: 1473,
+ p_wc1: 0.02, p_wc2: 0.05,
+ },
+ "Washington Capitals": {
+ conference: "Eastern", division: "Metropolitan", elo: 1506,
+ p_wc1: 0.01, p_wc2: 0.03,
+ },
+ "New Jersey Devils": {
+ conference: "Eastern", division: "Metropolitan", elo: 1488,
+ p_wc2: 0.005,
+ },
+ "New York Rangers": {
+ conference: "Eastern", division: "Metropolitan", elo: 1480,
+ // 0% playoff probability — always miss
+ },
+
+ // ── Western Conference — Central ───────────────────────────────────────────
+ // COL 119 pts, DAL 113 pts, MIN 106 pts — all locked in as top 3.
+ // UTA 93 pts (92.8%) — leading WC candidate from Central.
+ // NSH 85 pts (21.9%), WPG 82 pts (6.6%), STL 80 pts (2.2%) — long shots.
+ // CHI 75 pts (0%) — eliminated.
+
+ "Colorado Avalanche": {
+ conference: "Western", division: "Central", elo: 1594,
+ p_div1: 0.90, p_div2: 0.09, p_div3: 0.01,
+ },
+ "Dallas Stars": {
+ conference: "Western", division: "Central", elo: 1581,
+ p_div1: 0.08, p_div2: 0.80, p_div3: 0.11,
+ },
+ "Minnesota Wild": {
+ conference: "Western", division: "Central", elo: 1548,
+ p_div1: 0.02, p_div2: 0.10, p_div3: 0.86, p_wc1: 0.01,
+ },
+ "Utah Mammoth": {
+ conference: "Western", division: "Central", elo: 1529,
+ p_div3: 0.02, p_wc1: 0.55, p_wc2: 0.33,
+ },
+ "Nashville Predators": {
+ conference: "Western", division: "Central", elo: 1471,
+ p_wc1: 0.04, p_wc2: 0.17,
+ },
+ "Winnipeg Jets": {
+ conference: "Western", division: "Central", elo: 1483,
+ p_wc1: 0.01, p_wc2: 0.05,
+ },
+ "St. Louis Blues": {
+ conference: "Western", division: "Central", elo: 1473,
+ p_wc2: 0.02,
+ },
+ "Chicago Blackhawks": {
+ conference: "Western", division: "Central", elo: 1411,
+ // 0% playoff probability — always miss
+ },
+
+ // ── Western Conference — Pacific ───────────────────────────────────────────
+ // ANA 94 pts, EDM 93 pts, VGK 93 pts — tight 3-way race for all 3 Pacific seeds.
+ // LAK 87 pts (39.1%), SJS 87 pts (38.9%), SEA 86 pts (26.6%) — WC bubble.
+ // CGY 73 pts (0%), VAN 63 pts (0%) — eliminated.
+
+ "Anaheim Ducks": {
+ conference: "Western", division: "Pacific", elo: 1490,
+ p_div1: 0.40, p_div2: 0.33, p_div3: 0.17, p_wc1: 0.02, p_wc2: 0.01,
+ },
+ "Edmonton Oilers": {
+ conference: "Western", division: "Pacific", elo: 1531,
+ p_div1: 0.30, p_div2: 0.32, p_div3: 0.20, p_wc1: 0.04, p_wc2: 0.04,
+ },
+ "Vegas Golden Knights": {
+ conference: "Western", division: "Pacific", elo: 1519,
+ p_div1: 0.25, p_div2: 0.28, p_div3: 0.20, p_wc1: 0.06, p_wc2: 0.06,
+ },
+ "Los Angeles Kings": {
+ conference: "Western", division: "Pacific", elo: 1482,
+ p_div2: 0.02, p_div3: 0.09, p_wc1: 0.14, p_wc2: 0.12,
+ },
+ "San Jose Sharks": {
+ conference: "Western", division: "Pacific", elo: 1455,
+ p_div2: 0.01, p_div3: 0.08, p_wc1: 0.14, p_wc2: 0.12,
+ },
+ "Seattle Kraken": {
+ conference: "Western", division: "Pacific", elo: 1469,
+ p_div3: 0.07, p_wc1: 0.10, p_wc2: 0.10,
+ },
+ "Calgary Flames": {
+ conference: "Western", division: "Pacific", elo: 1436,
+ // 0% playoff probability — always miss
+ },
+ "Vancouver Canucks": {
+ conference: "Western", division: "Pacific", elo: 1403,
+ // 0% playoff probability — always miss
+ },
+};
+
+// ─── Public helpers (exported for unit testing) ───────────────────────────────
+
+/** Normalize a team name for lookup (lowercase, trimmed, collapsed whitespace). */
+export function normalizeTeamName(name: string): string {
+ return name.toLowerCase().trim().replace(/\s+/g, " ");
+}
+
+/** Look up team data by participant name (case-insensitive). */
+export function getTeamData(name: string): NhlTeamData | undefined {
+ const normalized = normalizeTeamName(name);
+ for (const [teamName, data] of Object.entries(TEAMS_DATA)) {
+ if (normalizeTeamName(teamName) === normalized) return data;
+ }
+ return undefined;
+}
+
+/**
+ * Elo win probability for team A over team B.
+ * P(A) = 1 / (1 + 10^((eloB - eloA) / PARITY_FACTOR))
+ * Exported for unit testing.
+ */
+export function eloWinProbability(eloA: number, eloB: number): number {
+ return 1 / (1 + Math.pow(10, (eloB - eloA) / PARITY_FACTOR));
+}
+
+// ─── Internal types ───────────────────────────────────────────────────────────
+
+interface TeamEntry {
+ id: string;
+ name: string;
+ data: NhlTeamData | undefined;
+}
+
+type DivisionSeedings = {
+ first: TeamEntry;
+ second: TeamEntry;
+ third: TeamEntry;
+};
+
+// ─── Simulator ────────────────────────────────────────────────────────────────
+
+export class NHLSimulator implements Simulator {
+ async simulate(sportsSeasonId: string): Promise {
+ const db = database();
+
+ // 1. Load all participants for this sports season.
+ const participantRows = await db
+ .select({ id: schema.participants.id, name: schema.participants.name })
+ .from(schema.participants)
+ .where(eq(schema.participants.sportsSeasonId, sportsSeasonId));
+
+ if (participantRows.length === 0) {
+ throw new Error(
+ `No participants found for sports season ${sportsSeasonId}. ` +
+ `Add NHL teams as participants before running simulation.`
+ );
+ }
+
+ const participantIds = participantRows.map((r) => r.id);
+
+ const teams: TeamEntry[] = participantRows.map((r) => ({
+ id: r.id,
+ name: r.name,
+ data: getTeamData(r.name),
+ }));
+
+ // Warn about participants that don't match any hardcoded team.
+ // These are excluded entirely rather than silently landing in the wildcard pool.
+ const unrecognized = teams.filter((t) => !t.data);
+ if (unrecognized.length > 0) {
+ console.warn(
+ `[NHLSimulator] ${unrecognized.length} participant(s) not found in TEAMS_DATA and will be excluded: ` +
+ unrecognized.map((t) => t.name).join(", ")
+ );
+ }
+
+ // Separate recognized teams by conference + division.
+ const easternAtlantic = teams.filter((t) => t.data?.division === "Atlantic");
+ const easternMetro = teams.filter((t) => t.data?.division === "Metropolitan");
+ const westernCentral = teams.filter((t) => t.data?.division === "Central");
+ const westernPacific = teams.filter((t) => t.data?.division === "Pacific");
+
+ // Only recognized teams enter the conference wildcard pools.
+ const easternTeams = teams.filter((t) => t.data?.conference === "Eastern");
+ const westernTeams = teams.filter((t) => t.data?.conference === "Western");
+
+ if (easternTeams.length < 8 || westernTeams.length < 8) {
+ throw new Error(
+ `Each conference needs at least 8 recognized participants ` +
+ `(got East: ${easternTeams.length}, West: ${westernTeams.length}). ` +
+ `Add all 32 NHL teams before running simulation.`
+ );
+ }
+
+ // ─── Helpers (defined once, outside the hot loop) ─────────────────────────
+
+ /** Get Elo for a team entry. Fallback 1400 for unknown teams. */
+ const elo = (entry: TeamEntry): number => entry.data?.elo ?? 1400;
+
+ /** Simulate a best-of-7 series. Returns winner and loser. */
+ const simSeries = (a: TeamEntry, b: TeamEntry): { winner: TeamEntry; loser: TeamEntry } => {
+ const winProb = eloWinProbability(elo(a), elo(b));
+ let winsA = 0;
+ let winsB = 0;
+ while (winsA < 4 && winsB < 4) {
+ if (Math.random() < winProb) winsA++; else winsB++;
+ }
+ return winsA === 4 ? { winner: a, loser: b } : { winner: b, loser: a };
+ };
+
+ /**
+ * Weighted pick without replacement.
+ * Draws one team from `pool` using the given seeding weight key, excluding `excluded`.
+ * Returns undefined if no eligible team has positive weight — the caller should
+ * treat that as a degenerate draw and skip the iteration.
+ */
+ const weightedPick = (
+ pool: TeamEntry[],
+ weightKey: "p_div1" | "p_div2" | "p_div3" | "p_wc1" | "p_wc2",
+ excluded: Set
+ ): TeamEntry | undefined => {
+ const eligible = pool.filter((t) => !excluded.has(t));
+ if (eligible.length === 0) return undefined;
+
+ const weights = eligible.map((t) => t.data?.[weightKey] ?? 0);
+ const total = weights.reduce((s, w) => s + w, 0);
+ if (total === 0) return undefined; // no team has positive weight for this slot
+
+ let r = Math.random() * total;
+ for (let i = 0; i < eligible.length; i++) {
+ r -= weights[i];
+ if (r <= 0) return eligible[i];
+ }
+ return eligible[eligible.length - 1];
+ };
+
+ /**
+ * Draw the top-3 playoff seeds for a single division.
+ * Returns undefined for each position if no team has weight for that slot
+ * (shouldn't happen with correct data, but handled gracefully).
+ */
+ const drawDivisionSeedings = (divTeams: TeamEntry[]): DivisionSeedings | undefined => {
+ const taken = new Set();
+
+ const first = weightedPick(divTeams, "p_div1", taken);
+ if (!first) return undefined;
+ taken.add(first);
+
+ const second = weightedPick(divTeams, "p_div2", taken);
+ if (!second) return undefined;
+ taken.add(second);
+
+ const third = weightedPick(divTeams, "p_div3", taken);
+ if (!third) return undefined;
+
+ return { first, second, third };
+ };
+
+ /**
+ * Build the 8-team playoff bracket for one conference.
+ * Returns [m0, m1, m2, m3] where each element is [higher-seed, lower-seed].
+ *
+ * Bracket:
+ * m0: topDiv_1st vs WC2 (top division winner plays weaker wildcard)
+ * m1: otherDiv_1st vs WC1 (other division winner plays stronger wildcard)
+ * m2: topDiv_2nd vs topDiv_3rd
+ * m3: otherDiv_2nd vs otherDiv_3rd
+ *
+ * "Top division" = whichever division winner has higher Elo. The actual NHL rule
+ * uses regular season points, but Elo is a reasonable per-simulation proxy since
+ * we don't simulate the regular season — it approximates the same ordering.
+ */
+ const buildConferenceBracket = (
+ divATeams: TeamEntry[],
+ divBTeams: TeamEntry[],
+ allConfTeams: TeamEntry[]
+ ): [[TeamEntry, TeamEntry], [TeamEntry, TeamEntry], [TeamEntry, TeamEntry], [TeamEntry, TeamEntry]] | undefined => {
+ const divA = drawDivisionSeedings(divATeams);
+ const divB = drawDivisionSeedings(divBTeams);
+ if (!divA || !divB) return undefined;
+
+ const divisionWinners = new Set([divA.first, divA.second, divA.third, divB.first, divB.second, divB.third]);
+ const wcPool = allConfTeams.filter((t) => !divisionWinners.has(t));
+ const wcTaken = new Set();
+
+ const wc1 = weightedPick(wcPool, "p_wc1", wcTaken);
+ if (!wc1) return undefined;
+ wcTaken.add(wc1);
+
+ const wc2 = weightedPick(wcPool, "p_wc2", wcTaken);
+ if (!wc2) return undefined;
+
+ // Higher-Elo division winner faces WC2 (the weaker wildcard).
+ const [topDiv, otherDiv] =
+ elo(divA.first) >= elo(divB.first)
+ ? [divA, divB]
+ : [divB, divA];
+
+ return [
+ [topDiv.first, wc2], // m0
+ [otherDiv.first, wc1], // m1
+ [topDiv.second, topDiv.third], // m2
+ [otherDiv.second, otherDiv.third], // m3
+ ];
+ };
+
+ // ─── Placement count maps ──────────────────────────────────────────────────
+
+ const championCounts = new Map(participantIds.map((id) => [id, 0]));
+ const finalistCounts = new Map(participantIds.map((id) => [id, 0]));
+ const confFinalLoserCounts = new Map(participantIds.map((id) => [id, 0]));
+ const r2LoserCounts = new Map(participantIds.map((id) => [id, 0]));
+
+ // ─── Monte Carlo simulation loop ───────────────────────────────────────────
+
+ // Track effective iterations separately: degenerate bracket draws are skipped
+ // and must not count toward the probability denominators.
+ let effectiveN = 0;
+
+ for (let s = 0; s < NUM_SIMULATIONS; s++) {
+ // Build conference brackets.
+ const eastBracket = buildConferenceBracket(easternAtlantic, easternMetro, easternTeams);
+ const westBracket = buildConferenceBracket(westernCentral, westernPacific, westernTeams);
+ if (!eastBracket || !westBracket) continue; // degenerate draw — do not count
+ effectiveN++;
+
+ // ── Eastern Conference ────────────────────────────────────────────────────
+ // Round 1: 4 series (Wild Card round).
+ const eastR1Winners = eastBracket.map(([a, b]) => simSeries(a, b).winner);
+
+ // Round 2 (Division Finals):
+ // m0w (topDiv1st/WC2 winner) vs m2w (topDiv 2nd/3rd winner)
+ // m1w (otherDiv1st/WC1 winner) vs m3w (otherDiv 2nd/3rd winner)
+ const eastR2m1 = simSeries(eastR1Winners[0], eastR1Winners[2]);
+ const eastR2m2 = simSeries(eastR1Winners[1], eastR1Winners[3]);
+
+ // Conference Final.
+ const eastCF = simSeries(eastR2m1.winner, eastR2m2.winner);
+ const eastChamp = eastCF.winner;
+ confFinalLoserCounts.set(eastCF.loser.id, confFinalLoserCounts.get(eastCF.loser.id)! + 1);
+
+ // ── Western Conference ────────────────────────────────────────────────────
+ const westR1Winners = westBracket.map(([a, b]) => simSeries(a, b).winner);
+ const westR2m1 = simSeries(westR1Winners[0], westR1Winners[2]);
+ const westR2m2 = simSeries(westR1Winners[1], westR1Winners[3]);
+ const westCF = simSeries(westR2m1.winner, westR2m2.winner);
+ const westChamp = westCF.winner;
+ confFinalLoserCounts.set(westCF.loser.id, confFinalLoserCounts.get(westCF.loser.id)! + 1);
+
+ // ── Stanley Cup Final ─────────────────────────────────────────────────────
+ const final = simSeries(eastChamp, westChamp);
+ championCounts.set(final.winner.id, championCounts.get(final.winner.id)! + 1);
+ finalistCounts.set(final.loser.id, finalistCounts.get(final.loser.id)! + 1);
+
+ // Round 2 losers (4 per sim). Round 1 losers are not counted (0 points).
+ for (const loser of [eastR2m1.loser, eastR2m2.loser, westR2m1.loser, westR2m2.loser]) {
+ r2LoserCounts.set(loser.id, r2LoserCounts.get(loser.id)! + 1);
+ }
+ }
+
+ if (effectiveN === 0) {
+ throw new Error(
+ "All simulations produced degenerate brackets. " +
+ "Check that each division has teams with positive seeding probabilities."
+ );
+ }
+
+ // ─── Convert counts to probability distributions ───────────────────────────
+ //
+ // probFirst/Second → count / N (1 team per sim)
+ // probThird/Fourth → count / (2 * N) (2 conf final losers per sim)
+ // probFifth–Eighth → count / (4 * N) (4 R2 losers per sim)
+ //
+ const N = effectiveN;
+ const results: SimulationResult[] = participantIds.map((participantId) => {
+ const c = championCounts.get(participantId)!;
+ const f = finalistCounts.get(participantId)!;
+ const cf = confFinalLoserCounts.get(participantId)!;
+ const r2 = r2LoserCounts.get(participantId)!;
+ return {
+ participantId,
+ probabilities: {
+ probFirst: c / N,
+ probSecond: f / N,
+ probThird: cf / (2 * N),
+ probFourth: cf / (2 * N),
+ probFifth: r2 / (4 * N),
+ probSixth: r2 / (4 * N),
+ probSeventh: r2 / (4 * N),
+ probEighth: r2 / (4 * N),
+ },
+ source: "nhl_bracket_monte_carlo",
+ };
+ });
+
+ // ─── Per-position normalization ────────────────────────────────────────────
+ //
+ // Belt-and-suspenders guard against floating-point residuals.
+ // Columns are already near-exactly 1.0 by construction above.
+ //
+ const positionKeys: Array = [
+ "probFirst", "probSecond", "probThird", "probFourth",
+ "probFifth", "probSixth", "probSeventh", "probEighth",
+ ];
+ for (const key of positionKeys) {
+ const colSum = results.reduce((s, r) => s + r.probabilities[key], 0);
+ const residual = 1.0 - colSum;
+ if (residual !== 0) {
+ const maxResult = results.reduce((best, r) =>
+ r.probabilities[key] > best.probabilities[key] ? r : best
+ );
+ maxResult.probabilities[key] += residual;
+ }
+ }
+
+ return results;
+ }
+}
diff --git a/app/services/simulations/registry.ts b/app/services/simulations/registry.ts
index 7b82f04..98eb0b9 100644
--- a/app/services/simulations/registry.ts
+++ b/app/services/simulations/registry.ts
@@ -14,6 +14,7 @@ import { UCLSimulator } from "./ucl-simulator";
import { NCAAMSimulator } from "./ncaam-simulator";
import { NCAAWSimulator } from "./ncaaw-simulator";
import { NBASimulator } from "./nba-simulator";
+import { NHLSimulator } from "./nhl-simulator";
export const SIMULATOR_TYPES = [
"f1_standings",
@@ -24,6 +25,7 @@ export const SIMULATOR_TYPES = [
"ncaam_bracket",
"ncaaw_bracket",
"nba_bracket",
+ "nhl_bracket",
] as const;
export type SimulatorType = typeof SIMULATOR_TYPES[number];
@@ -80,6 +82,10 @@ const REGISTRY: Record Simul
info: { name: "NBA Playoff Monte Carlo", description: "Simulates NBA playoff seedings (via seed probabilities) and full bracket (best-of-7 series) using Elo ratings" },
create: () => new NBASimulator(),
},
+ nhl_bracket: {
+ info: { name: "NHL Playoff Monte Carlo", description: "Simulates NHL playoff seedings (divisional format, via seed probabilities) and full bracket (best-of-7 series) using Elo ratings" },
+ create: () => new NHLSimulator(),
+ },
};
export function getSimulator(simulatorType: SimulatorType): Simulator {
diff --git a/database/schema.ts b/database/schema.ts
index dd2df89..59196d5 100644
--- a/database/schema.ts
+++ b/database/schema.ts
@@ -86,6 +86,7 @@ export const simulatorTypeEnum = pgEnum("simulator_type", [
"ncaam_bracket",
"ncaaw_bracket",
"nba_bracket",
+ "nhl_bracket",
]);
export const playoffMatchGameStatusEnum = pgEnum("playoff_match_game_status", [
diff --git a/drizzle/0050_chief_peter_quill.sql b/drizzle/0050_chief_peter_quill.sql
new file mode 100644
index 0000000..32593a3
--- /dev/null
+++ b/drizzle/0050_chief_peter_quill.sql
@@ -0,0 +1 @@
+ALTER TYPE "public"."simulator_type" ADD VALUE 'nhl_bracket';
diff --git a/drizzle/meta/0050_snapshot.json b/drizzle/meta/0050_snapshot.json
new file mode 100644
index 0000000..89940b8
--- /dev/null
+++ b/drizzle/meta/0050_snapshot.json
@@ -0,0 +1,3545 @@
+{
+ "id": "31dd50f8-e1c7-4e76-9150-0f36507ac4a2",
+ "prevId": "b36f2af2-46ba-48e1-9c59-eb38bcbfdedc",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.autodraft_settings": {
+ "name": "autodraft_settings",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "is_enabled": {
+ "name": "is_enabled",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "mode": {
+ "name": "mode",
+ "type": "autodraft_mode",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'next_pick'"
+ },
+ "queue_only": {
+ "name": "queue_only",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "autodraft_settings_season_id_seasons_id_fk": {
+ "name": "autodraft_settings_season_id_seasons_id_fk",
+ "tableFrom": "autodraft_settings",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "autodraft_settings_team_id_teams_id_fk": {
+ "name": "autodraft_settings_team_id_teams_id_fk",
+ "tableFrom": "autodraft_settings",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.commissioners": {
+ "name": "commissioners",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "league_id": {
+ "name": "league_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "commissioners_league_id_leagues_id_fk": {
+ "name": "commissioners_league_id_leagues_id_fk",
+ "tableFrom": "commissioners",
+ "tableTo": "leagues",
+ "columnsFrom": [
+ "league_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.draft_picks": {
+ "name": "draft_picks",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pick_number": {
+ "name": "pick_number",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "round": {
+ "name": "round",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pick_in_round": {
+ "name": "pick_in_round",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "picked_by_user_id": {
+ "name": "picked_by_user_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "picked_by_type": {
+ "name": "picked_by_type",
+ "type": "picked_by_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_used": {
+ "name": "time_used",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "draft_picks_season_pick_unique": {
+ "name": "draft_picks_season_pick_unique",
+ "columns": [
+ {
+ "expression": "season_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "pick_number",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "draft_picks_season_id_seasons_id_fk": {
+ "name": "draft_picks_season_id_seasons_id_fk",
+ "tableFrom": "draft_picks",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "draft_picks_team_id_teams_id_fk": {
+ "name": "draft_picks_team_id_teams_id_fk",
+ "tableFrom": "draft_picks",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "draft_picks_participant_id_participants_id_fk": {
+ "name": "draft_picks_participant_id_participants_id_fk",
+ "tableFrom": "draft_picks",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.draft_queue": {
+ "name": "draft_queue",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "queue_position": {
+ "name": "queue_position",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "draft_queue_season_id_seasons_id_fk": {
+ "name": "draft_queue_season_id_seasons_id_fk",
+ "tableFrom": "draft_queue",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "draft_queue_team_id_teams_id_fk": {
+ "name": "draft_queue_team_id_teams_id_fk",
+ "tableFrom": "draft_queue",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "draft_queue_participant_id_participants_id_fk": {
+ "name": "draft_queue_participant_id_participants_id_fk",
+ "tableFrom": "draft_queue",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.draft_slots": {
+ "name": "draft_slots",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "draft_order": {
+ "name": "draft_order",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "draft_slots_season_id_seasons_id_fk": {
+ "name": "draft_slots_season_id_seasons_id_fk",
+ "tableFrom": "draft_slots",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "draft_slots_team_id_teams_id_fk": {
+ "name": "draft_slots_team_id_teams_id_fk",
+ "tableFrom": "draft_slots",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.draft_timers": {
+ "name": "draft_timers",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_remaining": {
+ "name": "time_remaining",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "draft_timers_season_id_seasons_id_fk": {
+ "name": "draft_timers_season_id_seasons_id_fk",
+ "tableFrom": "draft_timers",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "draft_timers_team_id_teams_id_fk": {
+ "name": "draft_timers_team_id_teams_id_fk",
+ "tableFrom": "draft_timers",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.event_results": {
+ "name": "event_results",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "scoring_event_id": {
+ "name": "scoring_event_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "placement": {
+ "name": "placement",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "qualifying_points_awarded": {
+ "name": "qualifying_points_awarded",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "eliminated": {
+ "name": "eliminated",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "raw_score": {
+ "name": "raw_score",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "event_results_scoring_event_id_scoring_events_id_fk": {
+ "name": "event_results_scoring_event_id_scoring_events_id_fk",
+ "tableFrom": "event_results",
+ "tableTo": "scoring_events",
+ "columnsFrom": [
+ "scoring_event_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "event_results_participant_id_participants_id_fk": {
+ "name": "event_results_participant_id_participants_id_fk",
+ "tableFrom": "event_results",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.leagues": {
+ "name": "leagues",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_by": {
+ "name": "created_by",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "current_season_id": {
+ "name": "current_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_public_draft_board": {
+ "name": "is_public_draft_board",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "discord_webhook_url": {
+ "name": "discord_webhook_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.participant_ev_snapshots": {
+ "name": "participant_ev_snapshots",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "snapshot_date": {
+ "name": "snapshot_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "prob_first": {
+ "name": "prob_first",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_second": {
+ "name": "prob_second",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_third": {
+ "name": "prob_third",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_fourth": {
+ "name": "prob_fourth",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_fifth": {
+ "name": "prob_fifth",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_sixth": {
+ "name": "prob_sixth",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_seventh": {
+ "name": "prob_seventh",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_eighth": {
+ "name": "prob_eighth",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "calculated_ev": {
+ "name": "calculated_ev",
+ "type": "numeric(10, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "source": {
+ "name": "source",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "participant_ev_snapshots_unique": {
+ "name": "participant_ev_snapshots_unique",
+ "columns": [
+ {
+ "expression": "participant_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "sports_season_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "snapshot_date",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "participant_ev_snapshots_participant_id_participants_id_fk": {
+ "name": "participant_ev_snapshots_participant_id_participants_id_fk",
+ "tableFrom": "participant_ev_snapshots",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "participant_ev_snapshots_sports_season_id_sports_seasons_id_fk": {
+ "name": "participant_ev_snapshots_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "participant_ev_snapshots",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.participant_expected_values": {
+ "name": "participant_expected_values",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "prob_first": {
+ "name": "prob_first",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_second": {
+ "name": "prob_second",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_third": {
+ "name": "prob_third",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_fourth": {
+ "name": "prob_fourth",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_fifth": {
+ "name": "prob_fifth",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_sixth": {
+ "name": "prob_sixth",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_seventh": {
+ "name": "prob_seventh",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "prob_eighth": {
+ "name": "prob_eighth",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "expected_value": {
+ "name": "expected_value",
+ "type": "numeric(10, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "source": {
+ "name": "source",
+ "type": "probability_source",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "'manual'"
+ },
+ "source_odds": {
+ "name": "source_odds",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "calculated_at": {
+ "name": "calculated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "participant_expected_values_participant_id_participants_id_fk": {
+ "name": "participant_expected_values_participant_id_participants_id_fk",
+ "tableFrom": "participant_expected_values",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "participant_expected_values_sports_season_id_sports_seasons_id_fk": {
+ "name": "participant_expected_values_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "participant_expected_values",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.participant_qualifying_totals": {
+ "name": "participant_qualifying_totals",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "total_qualifying_points": {
+ "name": "total_qualifying_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "events_scored": {
+ "name": "events_scored",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "final_ranking": {
+ "name": "final_ranking",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "participant_qualifying_totals_participant_id_participants_id_fk": {
+ "name": "participant_qualifying_totals_participant_id_participants_id_fk",
+ "tableFrom": "participant_qualifying_totals",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "participant_qualifying_totals_sports_season_id_sports_seasons_id_fk": {
+ "name": "participant_qualifying_totals_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "participant_qualifying_totals",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.participant_results": {
+ "name": "participant_results",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "final_position": {
+ "name": "final_position",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_partial_score": {
+ "name": "is_partial_score",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "qualifying_points": {
+ "name": "qualifying_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "participant_results_participant_id_participants_id_fk": {
+ "name": "participant_results_participant_id_participants_id_fk",
+ "tableFrom": "participant_results",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "participant_results_sports_season_id_sports_seasons_id_fk": {
+ "name": "participant_results_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "participant_results",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.participant_season_results": {
+ "name": "participant_season_results",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "current_points": {
+ "name": "current_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "current_position": {
+ "name": "current_position",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "participant_season_results_participant_id_participants_id_fk": {
+ "name": "participant_season_results_participant_id_participants_id_fk",
+ "tableFrom": "participant_season_results",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "participant_season_results_sports_season_id_sports_seasons_id_fk": {
+ "name": "participant_season_results_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "participant_season_results",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.participants": {
+ "name": "participants",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "short_name": {
+ "name": "short_name",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "external_id": {
+ "name": "external_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "expected_value": {
+ "name": "expected_value",
+ "type": "numeric(10, 4)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "participants_sports_season_id_sports_seasons_id_fk": {
+ "name": "participants_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "participants",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.playoff_match_games": {
+ "name": "playoff_match_games",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "playoff_match_id": {
+ "name": "playoff_match_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "game_number": {
+ "name": "game_number",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "scheduled_at": {
+ "name": "scheduled_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "playoff_match_game_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'scheduled'"
+ },
+ "participant1_score": {
+ "name": "participant1_score",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "participant2_score": {
+ "name": "participant2_score",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "winner_id": {
+ "name": "winner_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "playoff_match_games_playoff_match_id_playoff_matches_id_fk": {
+ "name": "playoff_match_games_playoff_match_id_playoff_matches_id_fk",
+ "tableFrom": "playoff_match_games",
+ "tableTo": "playoff_matches",
+ "columnsFrom": [
+ "playoff_match_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "playoff_match_games_winner_id_participants_id_fk": {
+ "name": "playoff_match_games_winner_id_participants_id_fk",
+ "tableFrom": "playoff_match_games",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "winner_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.playoff_match_odds": {
+ "name": "playoff_match_odds",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "playoff_match_id": {
+ "name": "playoff_match_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "moneyline_odds": {
+ "name": "moneyline_odds",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "implied_probability": {
+ "name": "implied_probability",
+ "type": "numeric(6, 4)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "odds_source": {
+ "name": "odds_source",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "recorded_at": {
+ "name": "recorded_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "playoff_match_odds_playoff_match_id_playoff_matches_id_fk": {
+ "name": "playoff_match_odds_playoff_match_id_playoff_matches_id_fk",
+ "tableFrom": "playoff_match_odds",
+ "tableTo": "playoff_matches",
+ "columnsFrom": [
+ "playoff_match_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "playoff_match_odds_participant_id_participants_id_fk": {
+ "name": "playoff_match_odds_participant_id_participants_id_fk",
+ "tableFrom": "playoff_match_odds",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.playoff_matches": {
+ "name": "playoff_matches",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "scoring_event_id": {
+ "name": "scoring_event_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "round": {
+ "name": "round",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "match_number": {
+ "name": "match_number",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "participant1_id": {
+ "name": "participant1_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "participant2_id": {
+ "name": "participant2_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "winner_id": {
+ "name": "winner_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "loser_id": {
+ "name": "loser_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_complete": {
+ "name": "is_complete",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "participant1_score": {
+ "name": "participant1_score",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "participant2_score": {
+ "name": "participant2_score",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_scoring": {
+ "name": "is_scoring",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "template_round": {
+ "name": "template_round",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "seed_info": {
+ "name": "seed_info",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "playoff_matches_scoring_event_id_scoring_events_id_fk": {
+ "name": "playoff_matches_scoring_event_id_scoring_events_id_fk",
+ "tableFrom": "playoff_matches",
+ "tableTo": "scoring_events",
+ "columnsFrom": [
+ "scoring_event_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "playoff_matches_participant1_id_participants_id_fk": {
+ "name": "playoff_matches_participant1_id_participants_id_fk",
+ "tableFrom": "playoff_matches",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant1_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "playoff_matches_participant2_id_participants_id_fk": {
+ "name": "playoff_matches_participant2_id_participants_id_fk",
+ "tableFrom": "playoff_matches",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant2_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "playoff_matches_winner_id_participants_id_fk": {
+ "name": "playoff_matches_winner_id_participants_id_fk",
+ "tableFrom": "playoff_matches",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "winner_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "playoff_matches_loser_id_participants_id_fk": {
+ "name": "playoff_matches_loser_id_participants_id_fk",
+ "tableFrom": "playoff_matches",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "loser_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.qualifying_point_config": {
+ "name": "qualifying_point_config",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "placement": {
+ "name": "placement",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "points": {
+ "name": "points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "qualifying_point_config_sports_season_id_sports_seasons_id_fk": {
+ "name": "qualifying_point_config_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "qualifying_point_config",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.scoring_events": {
+ "name": "scoring_events",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "event_date": {
+ "name": "event_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "event_starts_at": {
+ "name": "event_starts_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "event_type": {
+ "name": "event_type",
+ "type": "event_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "playoff_round": {
+ "name": "playoff_round",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_qualifying_event": {
+ "name": "is_qualifying_event",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "bracket_template_id": {
+ "name": "bracket_template_id",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scoring_starts_at_round": {
+ "name": "scoring_starts_at_round",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "bracket_region_config": {
+ "name": "bracket_region_config",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_complete": {
+ "name": "is_complete",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "completed_at": {
+ "name": "completed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "scoring_events_sports_season_id_sports_seasons_id_fk": {
+ "name": "scoring_events_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "scoring_events",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.season_sports": {
+ "name": "season_sports",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "season_sports_season_id_seasons_id_fk": {
+ "name": "season_sports_season_id_seasons_id_fk",
+ "tableFrom": "season_sports",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "season_sports_sports_season_id_sports_seasons_id_fk": {
+ "name": "season_sports_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "season_sports",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.season_template_sports": {
+ "name": "season_template_sports",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "season_template_sports_template_id_season_templates_id_fk": {
+ "name": "season_template_sports_template_id_season_templates_id_fk",
+ "tableFrom": "season_template_sports",
+ "tableTo": "season_templates",
+ "columnsFrom": [
+ "template_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "season_template_sports_sports_season_id_sports_seasons_id_fk": {
+ "name": "season_template_sports_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "season_template_sports",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.season_templates": {
+ "name": "season_templates",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "year": {
+ "name": "year",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "is_active": {
+ "name": "is_active",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.seasons": {
+ "name": "seasons",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "league_id": {
+ "name": "league_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "year": {
+ "name": "year",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "season_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pre_draft'"
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "draft_rounds": {
+ "name": "draft_rounds",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 20
+ },
+ "flex_spots": {
+ "name": "flex_spots",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "draft_date_time": {
+ "name": "draft_date_time",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "draft_initial_time": {
+ "name": "draft_initial_time",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 120
+ },
+ "draft_increment_time": {
+ "name": "draft_increment_time",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 30
+ },
+ "current_pick_number": {
+ "name": "current_pick_number",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "default": 1
+ },
+ "draft_started_at": {
+ "name": "draft_started_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "draft_paused": {
+ "name": "draft_paused",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "invite_code": {
+ "name": "invite_code",
+ "type": "varchar(20)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "points_for_1st": {
+ "name": "points_for_1st",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 100
+ },
+ "points_for_2nd": {
+ "name": "points_for_2nd",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 70
+ },
+ "points_for_3rd": {
+ "name": "points_for_3rd",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 50
+ },
+ "points_for_4th": {
+ "name": "points_for_4th",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 40
+ },
+ "points_for_5th": {
+ "name": "points_for_5th",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 25
+ },
+ "points_for_6th": {
+ "name": "points_for_6th",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 25
+ },
+ "points_for_7th": {
+ "name": "points_for_7th",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 15
+ },
+ "points_for_8th": {
+ "name": "points_for_8th",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 15
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "seasons_league_id_leagues_id_fk": {
+ "name": "seasons_league_id_leagues_id_fk",
+ "tableFrom": "seasons",
+ "tableTo": "leagues",
+ "columnsFrom": [
+ "league_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "seasons_template_id_season_templates_id_fk": {
+ "name": "seasons_template_id_season_templates_id_fk",
+ "tableFrom": "seasons",
+ "tableTo": "season_templates",
+ "columnsFrom": [
+ "template_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "seasons_invite_code_unique": {
+ "name": "seasons_invite_code_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "invite_code"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.sports": {
+ "name": "sports",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "sport_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "icon_url": {
+ "name": "icon_url",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "simulator_type": {
+ "name": "simulator_type",
+ "type": "simulator_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "sports_slug_unique": {
+ "name": "sports_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.sports_seasons": {
+ "name": "sports_seasons",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "sport_id": {
+ "name": "sport_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "year": {
+ "name": "year",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "start_date": {
+ "name": "start_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "end_date": {
+ "name": "end_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "sports_season_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'upcoming'"
+ },
+ "scoring_type": {
+ "name": "scoring_type",
+ "type": "scoring_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "scoring_pattern": {
+ "name": "scoring_pattern",
+ "type": "scoring_pattern",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "total_majors": {
+ "name": "total_majors",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "majors_completed": {
+ "name": "majors_completed",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "qualifying_points_finalized": {
+ "name": "qualifying_points_finalized",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "elo_calibration_exponent": {
+ "name": "elo_calibration_exponent",
+ "type": "numeric(3, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "elo_min_rating": {
+ "name": "elo_min_rating",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "default": 1250
+ },
+ "elo_max_rating": {
+ "name": "elo_max_rating",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false,
+ "default": 1750
+ },
+ "simulation_status": {
+ "name": "simulation_status",
+ "type": "simulation_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'idle'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "sports_seasons_sport_id_sports_id_fk": {
+ "name": "sports_seasons_sport_id_sports_id_fk",
+ "tableFrom": "sports_seasons",
+ "tableTo": "sports",
+ "columnsFrom": [
+ "sport_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.team_ev_snapshots": {
+ "name": "team_ev_snapshots",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "snapshot_date": {
+ "name": "snapshot_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "projected_points": {
+ "name": "projected_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "actual_points": {
+ "name": "actual_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "team_ev_snapshots_unique": {
+ "name": "team_ev_snapshots_unique",
+ "columns": [
+ {
+ "expression": "team_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "season_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "snapshot_date",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "team_ev_snapshots_team_id_teams_id_fk": {
+ "name": "team_ev_snapshots_team_id_teams_id_fk",
+ "tableFrom": "team_ev_snapshots",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "team_ev_snapshots_season_id_seasons_id_fk": {
+ "name": "team_ev_snapshots_season_id_seasons_id_fk",
+ "tableFrom": "team_ev_snapshots",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.team_sport_scores": {
+ "name": "team_sport_scores",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sports_season_id": {
+ "name": "sports_season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "total_points": {
+ "name": "total_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "participants_completed": {
+ "name": "participants_completed",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "participants_total": {
+ "name": "participants_total",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "calculated_at": {
+ "name": "calculated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "team_sport_scores_team_id_teams_id_fk": {
+ "name": "team_sport_scores_team_id_teams_id_fk",
+ "tableFrom": "team_sport_scores",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "team_sport_scores_sports_season_id_sports_seasons_id_fk": {
+ "name": "team_sport_scores_sports_season_id_sports_seasons_id_fk",
+ "tableFrom": "team_sport_scores",
+ "tableTo": "sports_seasons",
+ "columnsFrom": [
+ "sports_season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.team_standings": {
+ "name": "team_standings",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "total_points": {
+ "name": "total_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "current_rank": {
+ "name": "current_rank",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "previous_rank": {
+ "name": "previous_rank",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "first_place_count": {
+ "name": "first_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "second_place_count": {
+ "name": "second_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "third_place_count": {
+ "name": "third_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "fourth_place_count": {
+ "name": "fourth_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "fifth_place_count": {
+ "name": "fifth_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "sixth_place_count": {
+ "name": "sixth_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "seventh_place_count": {
+ "name": "seventh_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "eighth_place_count": {
+ "name": "eighth_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "participants_remaining": {
+ "name": "participants_remaining",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "actual_points": {
+ "name": "actual_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "projected_points": {
+ "name": "projected_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "participants_finished": {
+ "name": "participants_finished",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "calculated_at": {
+ "name": "calculated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "team_standings_team_id_teams_id_fk": {
+ "name": "team_standings_team_id_teams_id_fk",
+ "tableFrom": "team_standings",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "team_standings_season_id_seasons_id_fk": {
+ "name": "team_standings_season_id_seasons_id_fk",
+ "tableFrom": "team_standings",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.team_standings_snapshots": {
+ "name": "team_standings_snapshots",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "team_id": {
+ "name": "team_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "snapshot_date": {
+ "name": "snapshot_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "total_points": {
+ "name": "total_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'0'"
+ },
+ "rank": {
+ "name": "rank",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "first_place_count": {
+ "name": "first_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "second_place_count": {
+ "name": "second_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "third_place_count": {
+ "name": "third_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "fourth_place_count": {
+ "name": "fourth_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "fifth_place_count": {
+ "name": "fifth_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "sixth_place_count": {
+ "name": "sixth_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "seventh_place_count": {
+ "name": "seventh_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "eighth_place_count": {
+ "name": "eighth_place_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "participants_remaining": {
+ "name": "participants_remaining",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "actual_points": {
+ "name": "actual_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "projected_points": {
+ "name": "projected_points",
+ "type": "numeric(10, 2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "participants_finished": {
+ "name": "participants_finished",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "team_standings_snapshots_team_id_teams_id_fk": {
+ "name": "team_standings_snapshots_team_id_teams_id_fk",
+ "tableFrom": "team_standings_snapshots",
+ "tableTo": "teams",
+ "columnsFrom": [
+ "team_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "team_standings_snapshots_season_id_seasons_id_fk": {
+ "name": "team_standings_snapshots_season_id_seasons_id_fk",
+ "tableFrom": "team_standings_snapshots",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.teams": {
+ "name": "teams",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "season_id": {
+ "name": "season_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "logo_url": {
+ "name": "logo_url",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "owner_id": {
+ "name": "owner_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "teams_season_id_seasons_id_fk": {
+ "name": "teams_season_id_seasons_id_fk",
+ "tableFrom": "teams",
+ "tableTo": "seasons",
+ "columnsFrom": [
+ "season_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.tournament_group_members": {
+ "name": "tournament_group_members",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "tournament_group_id": {
+ "name": "tournament_group_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "participant_id": {
+ "name": "participant_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "eliminated": {
+ "name": "eliminated",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "tournament_group_members_tournament_group_id_tournament_groups_id_fk": {
+ "name": "tournament_group_members_tournament_group_id_tournament_groups_id_fk",
+ "tableFrom": "tournament_group_members",
+ "tableTo": "tournament_groups",
+ "columnsFrom": [
+ "tournament_group_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "tournament_group_members_participant_id_participants_id_fk": {
+ "name": "tournament_group_members_participant_id_participants_id_fk",
+ "tableFrom": "tournament_group_members",
+ "tableTo": "participants",
+ "columnsFrom": [
+ "participant_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.tournament_groups": {
+ "name": "tournament_groups",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "scoring_event_id": {
+ "name": "scoring_event_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "group_name": {
+ "name": "group_name",
+ "type": "varchar(10)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "tournament_groups_scoring_event_id_scoring_events_id_fk": {
+ "name": "tournament_groups_scoring_event_id_scoring_events_id_fk",
+ "tableFrom": "tournament_groups",
+ "tableTo": "scoring_events",
+ "columnsFrom": [
+ "scoring_event_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.users": {
+ "name": "users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "clerk_id": {
+ "name": "clerk_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "username": {
+ "name": "username",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "display_name": {
+ "name": "display_name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "first_name": {
+ "name": "first_name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_name": {
+ "name": "last_name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "image_url": {
+ "name": "image_url",
+ "type": "varchar(512)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "is_admin": {
+ "name": "is_admin",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "users_clerk_id_unique": {
+ "name": "users_clerk_id_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "clerk_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {
+ "public.autodraft_mode": {
+ "name": "autodraft_mode",
+ "schema": "public",
+ "values": [
+ "next_pick",
+ "while_on"
+ ]
+ },
+ "public.event_type": {
+ "name": "event_type",
+ "schema": "public",
+ "values": [
+ "playoff_game",
+ "major_tournament",
+ "final_standings",
+ "schedule_event"
+ ]
+ },
+ "public.picked_by_type": {
+ "name": "picked_by_type",
+ "schema": "public",
+ "values": [
+ "owner",
+ "commissioner",
+ "admin",
+ "auto"
+ ]
+ },
+ "public.playoff_match_game_status": {
+ "name": "playoff_match_game_status",
+ "schema": "public",
+ "values": [
+ "scheduled",
+ "complete",
+ "postponed"
+ ]
+ },
+ "public.probability_source": {
+ "name": "probability_source",
+ "schema": "public",
+ "values": [
+ "manual",
+ "futures_odds",
+ "elo_simulation",
+ "performance_model"
+ ]
+ },
+ "public.scoring_pattern": {
+ "name": "scoring_pattern",
+ "schema": "public",
+ "values": [
+ "playoff_bracket",
+ "season_standings",
+ "qualifying_points"
+ ]
+ },
+ "public.scoring_type": {
+ "name": "scoring_type",
+ "schema": "public",
+ "values": [
+ "playoffs",
+ "regular_season",
+ "majors"
+ ]
+ },
+ "public.season_status": {
+ "name": "season_status",
+ "schema": "public",
+ "values": [
+ "pre_draft",
+ "draft",
+ "active",
+ "completed"
+ ]
+ },
+ "public.simulation_status": {
+ "name": "simulation_status",
+ "schema": "public",
+ "values": [
+ "idle",
+ "running",
+ "failed"
+ ]
+ },
+ "public.simulator_type": {
+ "name": "simulator_type",
+ "schema": "public",
+ "values": [
+ "f1_standings",
+ "indycar_standings",
+ "golf_qualifying_points",
+ "playoff_bracket",
+ "ucl_bracket",
+ "ncaam_bracket",
+ "ncaaw_bracket",
+ "nba_bracket",
+ "nhl_bracket"
+ ]
+ },
+ "public.sport_type": {
+ "name": "sport_type",
+ "schema": "public",
+ "values": [
+ "team",
+ "individual"
+ ]
+ },
+ "public.sports_season_status": {
+ "name": "sports_season_status",
+ "schema": "public",
+ "values": [
+ "upcoming",
+ "active",
+ "completed"
+ ]
+ }
+ },
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json
index 218a718..6213af1 100644
--- a/drizzle/meta/_journal.json
+++ b/drizzle/meta/_journal.json
@@ -351,6 +351,13 @@
"when": 1773800000000,
"tag": "0049_add_admin_picked_by_type",
"breakpoints": true
+ },
+ {
+ "idx": 50,
+ "version": "7",
+ "when": 1773821310661,
+ "tag": "0050_chief_peter_quill",
+ "breakpoints": true
}
]
}
\ No newline at end of file