From 40a713eb7d00e1e4c9542ee38ec291312be14402 Mon Sep 17 00:00:00 2001 From: appsbytom Date: Tue, 8 Aug 2023 23:38:30 +0100 Subject: [PATCH] add IndyCar and refactor session mapping --- lib/motorsportstats/motorsportstats.ts | 27 +++++++++++++++++--------- lib/motorsportstats/types.ts | 2 +- series/config.ts | 9 +++++++-- series/fetcher-config.ts | 4 +++- series/fetchers/btcc.ts | 13 ++++++------- series/fetchers/extreme-e.ts | 14 ++++++------- series/fetchers/fe.ts | 16 +++++++-------- series/fetchers/indycar.ts | 21 ++++++++++++++++++++ types/session.ts | 2 +- types/week.ts | 3 ++- 10 files changed, 72 insertions(+), 39 deletions(-) create mode 100644 series/fetchers/indycar.ts diff --git a/lib/motorsportstats/motorsportstats.ts b/lib/motorsportstats/motorsportstats.ts index 083da4b..7448700 100644 --- a/lib/motorsportstats/motorsportstats.ts +++ b/lib/motorsportstats/motorsportstats.ts @@ -3,7 +3,15 @@ import Event from '@/types/event' import Session from '@/types/session' import axios from 'axios' import dayjs from 'dayjs' -import { CalendarResponse, EventResponse, ProcessSessions, Season, SeasonsResponse, SessionMap, SessionResponse } from './types' +import { + CalendarResponse, + EventResponse, + GetSessionType, + ProcessSessions, + Season, + SeasonsResponse, + SessionResponse +} from './types' const CLIENT = axios.create({ baseURL: 'https://api.motorsportstats.com/widgets/1.0.0', @@ -13,7 +21,8 @@ const CLIENT = axios.create({ const SERIES_MAP: { [key in MotorsportStatsSeries]: string } = { [Series.FE]: '7415d1ab-c31d-49dd-9143-1e7e33bff889', [Series.BTCC]: 'ee00e922-a28b-4a8e-ae84-597af14ed931', - [Series.ExtremeE]: 'a4373eb9-8102-48fd-a11f-215a2ce662c1' + [Series.ExtremeE]: 'a4373eb9-8102-48fd-a11f-215a2ce662c1', + [Series.IndyCar]: '220b82cb-7fdb-46df-b8f8-d180118aa605' } const getCurrentSeason = async (series: MotorsportStatsSeries): Promise => { @@ -24,19 +33,19 @@ const getCurrentSeason = async (series: MotorsportStatsSeries): Promise const isoFromUnix = (unix: number) => dayjs.unix(unix).toISOString() -const toEvent = (event: EventResponse, series: MotorsportStatsSeries, sessionMap: SessionMap, processSessions: ProcessSessions): Event => { +const toEvent = (event: EventResponse, series: MotorsportStatsSeries, getSessionType: GetSessionType, processSessions: ProcessSessions): Event => { const hasSessions = event.sessions.length > 0 return { id: event.uuid, name: event.name.replace('/', ' '), - sessions: hasSessions ? getSessions(processSessions(event.sessions), sessionMap) : [], + sessions: hasSessions ? getSessions(processSessions(event.sessions), getSessionType) : [], provisional: !hasSessions, series, raceDate: isoFromUnix(event.endTimeUtc) } } -export const getSeriesEvents = async (series: MotorsportStatsSeries, sessionMap: SessionMap, processSessions: ProcessSessions = sessions => sessions, processEvent: (event: EventResponse) => EventResponse | EventResponse[] = event => event): Promise => { +export const getSeriesEvents = async (series: MotorsportStatsSeries, getSessionType: GetSessionType, processSessions: ProcessSessions = sessions => sessions, processEvent: (event: EventResponse) => EventResponse | EventResponse[] = event => event): Promise => { const season = await getCurrentSeason(series) const { data } = await CLIENT.get(`/seasons/${season.uuid}/calendar`) @@ -44,9 +53,9 @@ export const getSeriesEvents = async (series: MotorsportStatsSeries, sessionMap: if (!event.status) { const processed = processEvent(event); if (Array.isArray(processed)) { - acc.push(...processed.map(value => toEvent(value, series, sessionMap, processSessions))) + acc.push(...processed.map(value => toEvent(value, series, getSessionType, processSessions))) } else { - acc.push(toEvent(processed, series, sessionMap, processSessions)) + acc.push(toEvent(processed, series, getSessionType, processSessions)) } } @@ -54,13 +63,13 @@ export const getSeriesEvents = async (series: MotorsportStatsSeries, sessionMap: }, []) } -const getSessions = (sessions: SessionResponse[], sessionMap: SessionMap): Session[] => { +const getSessions = (sessions: SessionResponse[], getSessionType: GetSessionType): Session[] => { return sessions .sort((a, b) => a.startTimeUtc - b.startTimeUtc) .map(session => ({ id: session.uuid, name: session.name, - type: sessionMap[session.shortCode], + type: getSessionType(session.shortCode), unconfirmed: false, startTime: isoFromUnix(session.startTimeUtc), endTime: isoFromUnix(session.endTimeUtc) diff --git a/lib/motorsportstats/types.ts b/lib/motorsportstats/types.ts index e1ff74a..5966fd8 100644 --- a/lib/motorsportstats/types.ts +++ b/lib/motorsportstats/types.ts @@ -27,6 +27,6 @@ export type Season = { status: string } -export type SessionMap = { [key: string]: Type } +export type GetSessionType = (sessionCode: string) => Type | undefined export type ProcessSessions = (sessions: SessionResponse[]) => SessionResponse[] \ No newline at end of file diff --git a/series/config.ts b/series/config.ts index 52dd5cd..71507b9 100644 --- a/series/config.ts +++ b/series/config.ts @@ -4,10 +4,11 @@ export enum Series { F3 = 'f3', FE = 'fe', BTCC = 'btcc', - ExtremeE = 'extreme-e' + ExtremeE = 'extreme-e', + IndyCar = 'indycar' } -export type MotorsportStatsSeries = Series.FE | Series.BTCC | Series.ExtremeE +export type MotorsportStatsSeries = Series.FE | Series.BTCC | Series.ExtremeE | Series.IndyCar export type SeriesMap = { [key in Series]: T } @@ -40,6 +41,10 @@ const SERIES_CONFIG: SeriesMap = { [Series.ExtremeE]: { name: 'Extreme E', colours: 'bg-[#02FD9C]' + }, + [Series.IndyCar]: { + name: 'IndyCar', + colours: 'bg-[#0075C9]' } } diff --git a/series/fetcher-config.ts b/series/fetcher-config.ts index fd0d636..05e3ced 100644 --- a/series/fetcher-config.ts +++ b/series/fetcher-config.ts @@ -6,6 +6,7 @@ import f1 from './fetchers/f1/f1' import f2 from './fetchers/f2f3/f2' import f3 from './fetchers/f2f3/f3' import fe from './fetchers/fe' +import indycar from './fetchers/indycar' const SERIES_FETCHER_CONFIG: SeriesMap<() => Promise> = { [Series.F1]: f1, @@ -13,7 +14,8 @@ const SERIES_FETCHER_CONFIG: SeriesMap<() => Promise> = { [Series.F3]: f3, [Series.FE]: fe, [Series.BTCC]: btcc, - [Series.ExtremeE]: extremeE + [Series.ExtremeE]: extremeE, + [Series.IndyCar]: indycar } export const getAllEvents = async (): Promise => { diff --git a/series/fetchers/btcc.ts b/series/fetchers/btcc.ts index 3d972bc..d402a54 100644 --- a/series/fetchers/btcc.ts +++ b/series/fetchers/btcc.ts @@ -1,14 +1,13 @@ import { getSeriesEvents } from '@/lib/motorsportstats/motorsportstats' +import { GetSessionType } from '@/lib/motorsportstats/types' import { Series } from '@/series/config' import Event from '@/types/event' import { Type } from '@/types/session' -const SESSION_TYPE_MAP = { - P1: Type.Practice, - P2: Type.Practice, - Q1: Type.Qualifying, - Q2: Type.Qualifying, - Race: Type.Race +const getSessionType: GetSessionType = (sessionCode) => { + if (/^P\d*$/.test(sessionCode)) return Type.Practice + if (/^Q\d*$/.test(sessionCode)) return Type.Qualifying + if (sessionCode === 'Race') return Type.Race } -export default async (): Promise => getSeriesEvents(Series.BTCC, SESSION_TYPE_MAP) \ No newline at end of file +export default async (): Promise => getSeriesEvents(Series.BTCC, getSessionType) \ No newline at end of file diff --git a/series/fetchers/extreme-e.ts b/series/fetchers/extreme-e.ts index 0b82b11..10d3db6 100644 --- a/series/fetchers/extreme-e.ts +++ b/series/fetchers/extreme-e.ts @@ -1,17 +1,15 @@ import { getSeriesEvents } from '@/lib/motorsportstats/motorsportstats' +import { GetSessionType } from '@/lib/motorsportstats/types' import { Series } from '@/series/config' import { Type } from '@/types/session' -const SESSION_TYPE_MAP = { - FP1: Type.Practice, - FP2: Type.Practice, - QH1: Type.Qualifying, - QH2: Type.Qualifying, - RR: Type.Race, - Race: Type.Race +const getSessionType: GetSessionType = (sessionCode) => { + if (/^FP\d*$/.test(sessionCode)) return Type.Practice + if (/^QH\d*$/.test(sessionCode)) return Type.Qualifying + if (sessionCode === 'Race' || sessionCode === 'RR') return Type.Race } -export default () => getSeriesEvents(Series.ExtremeE, SESSION_TYPE_MAP, sessions => sessions, (event) => { +export default () => getSeriesEvents(Series.ExtremeE, getSessionType, sessions => sessions, (event) => { const sessions = event.sessions.filter(session => session.name !== 'Race') if (sessions.filter(session => session.shortCode === 'Race').length > 1) { const firstRaceIndex = sessions.findIndex(session => session.shortCode === 'Race') + 1 diff --git a/series/fetchers/fe.ts b/series/fetchers/fe.ts index 5bd57db..834c33d 100644 --- a/series/fetchers/fe.ts +++ b/series/fetchers/fe.ts @@ -1,22 +1,20 @@ import { getSeriesEvents } from '@/lib/motorsportstats/motorsportstats' -import { SessionResponse } from '@/lib/motorsportstats/types' +import { GetSessionType, ProcessSessions } from '@/lib/motorsportstats/types' import { Series } from '@/series/config' import Event from '@/types/event' import { Type } from '@/types/session' import partition from '@/utils/partition' -const SESSION_TYPE_MAP = { - P1: Type.Practice, - P2: Type.Practice, - P3: Type.Practice, - Q: Type.Qualifying, - Race: Type.Race +const getSessionType: GetSessionType = (sessionCode) => { + if (/^P\d*$/.test(sessionCode)) return Type.Practice + if (sessionCode === 'Q') return Type.Qualifying + if (sessionCode === 'Race') return Type.Race } -const groupQualifying = (sessions: SessionResponse[]): SessionResponse[] => { +const groupQualifying: ProcessSessions = (sessions) => { const [{ 0: firstQualifying, length, [length - 1]: lastQualifying }, otherSessions] = partition(sessions, session => session.shortCode.startsWith('Q')) return otherSessions.concat({ uuid: 'q', name: 'Qualifying', shortCode: 'Q', startTimeUtc: firstQualifying.startTimeUtc, endTimeUtc: lastQualifying.endTimeUtc }) } -export default async (): Promise => getSeriesEvents(Series.FE, SESSION_TYPE_MAP, groupQualifying) \ No newline at end of file +export default async (): Promise => getSeriesEvents(Series.FE, getSessionType, groupQualifying) \ No newline at end of file diff --git a/series/fetchers/indycar.ts b/series/fetchers/indycar.ts new file mode 100644 index 0000000..d4de90d --- /dev/null +++ b/series/fetchers/indycar.ts @@ -0,0 +1,21 @@ +import { getSeriesEvents } from '@/lib/motorsportstats/motorsportstats' +import { GetSessionType, ProcessSessions } from '@/lib/motorsportstats/types' +import { Type } from '@/types/session' +import partition from '@/utils/partition' +import { Series } from '../config' + +const getSessionType: GetSessionType = (sessionCode) => { + if (/^P\d*$/.test(sessionCode) || sessionCode === 'FPR' || sessionCode === 'WU') { + return Type.Practice + } + if (sessionCode === 'Q') return Type.Qualifying + if (sessionCode === 'Race') return Type.Race +} + +const groupQualifying: ProcessSessions = (sessions) => { + const [{ 0: firstQualifying, length, [length - 1]: lastQualifying }, otherSessions] = partition(sessions, session => /^Q\d*$/.test(session.shortCode)) + + return otherSessions.concat({ uuid: 'q', name: 'Qualifying', shortCode: 'Q', startTimeUtc: firstQualifying.startTimeUtc, endTimeUtc: lastQualifying.endTimeUtc }) +} + +export default () => getSeriesEvents(Series.IndyCar, getSessionType, groupQualifying) \ No newline at end of file diff --git a/types/session.ts b/types/session.ts index 6f4f61c..a27d25e 100644 --- a/types/session.ts +++ b/types/session.ts @@ -1,7 +1,7 @@ type Session = { id: number | string name: string - type: Type + type?: Type unconfirmed: boolean startTime: string endTime: string diff --git a/types/week.ts b/types/week.ts index 41129f1..11ce8de 100644 --- a/types/week.ts +++ b/types/week.ts @@ -1,6 +1,6 @@ import { Series } from '@/series/config' import Event from './event' -import Session from './session' +import Session, { Type } from './session' type Week = { date: string @@ -16,6 +16,7 @@ type Day = { export type GroupedSession = Session & { series: Series + type: Type eventName: string }