type ScoreLikeValue = number | string | null | undefined; type ScoreLike = { home?: ScoreLikeValue; away?: ScoreLikeValue; } | null; export interface MatchStatusLike { state?: string | null; status?: string | null; substate?: string | null; statusBoxContent?: string | null; scoreHome?: ScoreLikeValue; scoreAway?: ScoreLikeValue; score?: ScoreLike; } const LIVE_STATUS_TOKENS = [ "live", "livegame", "playing", "half time", "halftime", "1h", "2h", "ht", "1q", "2q", "3q", "4q", ]; const LIVE_STATE_TOKENS = [ "live", "livegame", "firsthalf", "secondhalf", "halftime", "1h", "2h", "ht", "1q", "2q", "3q", "4q", ]; const FINISHED_STATUS_TOKENS = [ "finished", "played", "ft", "aet", "pen", "penalties", "afterpenalties", "ended", "post", "postgame", "posted", ]; const FINISHED_STATE_TOKENS = [ "finished", "post", "postgame", "posted", "ft", "ended", ]; export const LIVE_STATUS_VALUES_FOR_DB = [ "LIVE", "live", "1H", "2H", "HT", "1Q", "2Q", "3Q", "4Q", "Playing", "Half Time", "liveGame", ]; export const LIVE_STATE_VALUES_FOR_DB = [ "live", "liveGame", "firsthalf", "secondhalf", "halfTime", "1H", "2H", "HT", "1Q", "2Q", "3Q", "4Q", ]; export const FINISHED_STATUS_VALUES_FOR_DB = [ "Finished", "Played", "FT", "AET", "PEN", "Ended", "post", "postGame", "posted", "Posted", ]; export const FINISHED_STATE_VALUES_FOR_DB = [ "Finished", "post", "postGame", "postgame", "posted", "FT", "Ended", ]; function normalizeToken(value: unknown): string { return String(value || "") .trim() .toLowerCase(); } function parseScoreValue(value: ScoreLikeValue): number | null { if (value === null || value === undefined || value === "") { return null; } const parsed = Number(value); return Number.isFinite(parsed) ? parsed : null; } export function hasResolvedScore(match: MatchStatusLike): boolean { const homeScore = parseScoreValue(match.score?.home ?? match.scoreHome); const awayScore = parseScoreValue(match.score?.away ?? match.scoreAway); return homeScore !== null && awayScore !== null; } export function isMatchLive(match: MatchStatusLike): boolean { const state = normalizeToken(match.state); const status = normalizeToken(match.status); const substate = normalizeToken(match.substate); return ( LIVE_STATE_TOKENS.includes(state) || LIVE_STATUS_TOKENS.includes(status) || LIVE_STATE_TOKENS.includes(substate) ); } export function isMatchCompleted(match: MatchStatusLike): boolean { if (normalizeToken(match.statusBoxContent) === "ert") { return false; } const state = normalizeToken(match.state); const status = normalizeToken(match.status); const substate = normalizeToken(match.substate); if ( FINISHED_STATE_TOKENS.includes(state) || FINISHED_STATUS_TOKENS.includes(status) || FINISHED_STATE_TOKENS.includes(substate) ) { return true; } return hasResolvedScore(match) && !isMatchLive(match); } export function deriveStoredMatchStatus(match: MatchStatusLike): string { if (normalizeToken(match.statusBoxContent) === "ert") { return "POSTPONED"; } if (isMatchLive(match)) { return "LIVE"; } if (isMatchCompleted(match)) { return "FT"; } return "NS"; } export function getDisplayMatchStatus(match: MatchStatusLike): string { if (isMatchLive(match)) { return "LIVE"; } if (isMatchCompleted(match)) { return "Finished"; } return String(match.status || match.state || "NS"); }