This commit is contained in:
2026-04-19 13:23:00 +03:00
parent e4c74025e5
commit 1346924387
25 changed files with 1639 additions and 1076 deletions
+203
View File
@@ -0,0 +1,203 @@
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");
}