sba-website/src/services/standingsService.ts

142 lines
4.6 KiB
TypeScript

import type { Team } from './apiResponseTypes'
import { API_URL } from './utilities'
interface TeamStandingRaw {
away_losses: number
away_wins: number
div1_losses: number
div1_wins: number
div2_losses: number
div2_wins: number
div3_losses: number
div3_wins: number
div4_losses: number
div4_wins: number
div_e_num: number
div_gb: number
home_losses: number
home_wins: number
id: number
last8_losses: number
last8_wins: number
losses: number
one_run_losses: number
one_run_wins: number
pythag_losses: number
pythag_wins: number
run_diff: number
streak_num: number
streak_wl: 'w' | 'l'
team: Team
wc_e_num: number | null
wc_gb: number
wins: number
}
export interface TeamStanding {
season: number
teamName: string
teamAbbreviation: string
divisionName: string
divisionAbbreviation: string
leagueAbbreviation: string
wins: number
losses: number
winPercentage: string,
last8Record: string,
pythagRecord: string,
oneRunRecord: string,
homeRecord: string,
awayRecord: string,
division1Record: string,
division2Record: string,
division3Record: string,
division4Record: string,
streak: string
divisionGamesBack: string
divisionEliminationNumber: string
wildcardGamesBack: string
wildcardEliminationNumber: string
runDifferential: string
isWildcardTeam: boolean
}
export async function fetchStandings(seasonNumber: number): Promise<TeamStanding[]> {
const response = await fetch(`${API_URL}/standings?season=${seasonNumber}`)
const standingsResponse: {
count: number
standings: TeamStandingRaw[]
} = await response.json()
const standings: TeamStandingRaw[] = standingsResponse.standings
return standings.map(normalizeStanding)
}
export async function fetchStandingByTeam(team: Team): Promise<TeamStanding | undefined> {
const response = await fetch(`${API_URL}/standings?season=${team.season}`)
const standingsResponse: {
count: number
standings: TeamStandingRaw[]
} = await response.json()
const standings: TeamStandingRaw[] = standingsResponse.standings
const teamStanding: TeamStandingRaw | undefined = standings.find(ts => ts.team.sname === team.sname)
if (!teamStanding) {
// throw new Error('standingsService.fetchStandingByTeam - Expected one team standing, found none')
console.warn('standingsService.fetchStandingByTeam - Expected one team standing, found none')
return undefined
}
return normalizeStanding(teamStanding)
}
function normalizeStanding(standing: TeamStandingRaw): TeamStanding {
const totalGamesPlayed = standing.wins + standing.losses
// round win percentage to 3 decimal places
const winPercentage: string = totalGamesPlayed ? `${(standing.wins / totalGamesPlayed).toFixed(3)}` : '-'
const formattedRunDiff = `${standing.run_diff > 0 ? '+' : ''}${standing.run_diff}`
const isWildcardTeam = standing.wc_gb !== null || standing.wc_e_num !== null
return {
season: standing.team.season,
teamName: standing.team.sname,
teamAbbreviation: standing.team.abbrev,
divisionName: standing.team.division.division_name,
divisionAbbreviation: standing.team.division.division_abbrev,
leagueAbbreviation: standing.team.division.league_abbrev,
wins: standing.wins,
losses: standing.losses,
winPercentage,
last8Record: `${standing.last8_wins}-${standing.last8_losses}`,
pythagRecord: `${standing.pythag_wins}-${standing.pythag_losses}`,
oneRunRecord: `${standing.one_run_wins}-${standing.one_run_losses}`,
homeRecord: `${standing.home_wins}-${standing.home_losses}`,
awayRecord: `${standing.away_wins}-${standing.away_losses}`,
division1Record: `${standing.div1_wins}-${standing.div1_losses}`,
division2Record: `${standing.div2_wins}-${standing.div2_losses}`,
division3Record: `${standing.div3_wins}-${standing.div3_losses}`,
division4Record: `${standing.div4_wins}-${standing.div4_losses}`,
streak: `${standing.streak_wl.toUpperCase()}${standing.streak_num}`,
divisionGamesBack: parseGamesBack(standing.div_gb),
divisionEliminationNumber: parseEliminationNumber(standing.div_e_num),
wildcardGamesBack: parseGamesBack(standing.wc_gb),
wildcardEliminationNumber: parseEliminationNumber(standing.wc_e_num),
runDifferential: formattedRunDiff,
isWildcardTeam
}
}
function parseGamesBack(gamesBack: number | null): string {
if (gamesBack == null) return '-'
return `${gamesBack < 0 ? '+' : ''}${Math.abs(gamesBack).toFixed(1)}`
}
function parseEliminationNumber(eliminationNumber: number | null): string {
if (eliminationNumber == null) return '-'
return eliminationNumber <= 0 ? 'E' : `${eliminationNumber}`
}