brackt/app/services/standings-sync/afl.ts

68 lines
2.4 KiB
TypeScript
Raw Normal View History

import type { FetchedStandingsRecord, StandingsSyncAdapter } from "./types";
const AFL_STANDINGS_URL = "https://api.squiggle.com.au/?q=standings;year=2026;format=json";
/**
* Squiggle API response shape for a single team's ladder entry.
* Docs: https://api.squiggle.com.au/
*/
interface SquiggleStandingsEntry {
id: number; // Squiggle team ID (118)
name: string; // Full team name, e.g. "Western Bulldogs"
wins: number;
losses: number;
draws: number;
played: number; // Games played
for: number; // Points scored for
against: number; // Points scored against
percentage: number;// (for / (for + against)) * 100
pts: number; // Ladder points (4=win, 2=draw, 0=loss)
rank: number; // Current ladder position (1-based)
}
interface SquiggleStandingsResponse {
standings: SquiggleStandingsEntry[];
}
export class AflStandingsAdapter implements StandingsSyncAdapter {
async fetchStandings(): Promise<FetchedStandingsRecord[]> {
const response = await fetch(AFL_STANDINGS_URL, {
headers: {
// Squiggle asks all clients to identify themselves for rate-limit contact.
// Set SQUIGGLE_CONTACT_EMAIL in your environment to identify this client.
"User-Agent": `Brackt.com AFL standings sync - ${process.env.SQUIGGLE_CONTACT_EMAIL ?? "admin@brackt.com"}`,
},
});
if (!response.ok) {
throw new Error(
`AFL Squiggle standings API returned ${response.status}: ${response.statusText}`
);
}
const json = (await response.json()) as SquiggleStandingsResponse;
const entries = json.standings;
if (!entries || entries.length === 0) {
throw new Error(
"AFL Squiggle standings API returned no entries — response shape may have changed"
);
}
// Squiggle already includes `rank` (ladder position), sorted by ladder position.
// Sort ascending by rank so leagueRank matches the AFL ladder order.
2026-03-22 20:41:44 -07:00
const sorted = entries.toSorted((a, b) => a.rank - b.rank);
return sorted.map((entry): FetchedStandingsRecord => ({
teamName: entry.name,
externalTeamId: String(entry.id),
wins: entry.wins,
losses: entry.losses,
ties: entry.draws, // AFL draws are stored in the `ties` column
winPct: entry.percentage / 100, // Squiggle returns e.g. 62.5; store as 0.625
gamesPlayed: entry.played,
leagueRank: entry.rank,
}));
}
}