import datetime import os import fastf1 import pandas as pd from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse, HTMLResponse from pydantic import BaseModel import available_data app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/", response_model=None) async def root(): return HTMLResponse( content="""""", status_code=200) @app.get("/years", response_model=None) def years_available() -> any: # make a list from 2018 to current year current_year = datetime.datetime.now().year years = list(range(2018, current_year+1)) # reverse the list to get the latest year first years.reverse() years = [{"label": str(year), "value": year} for year in years] return {"years": years} # format for events {"events":[{"label":"Saudi Arabian Grand Prix","value":2},{"label":"Bahrain Grand Prix","value":1},{"label":"Pre-Season Testing","value":"t1"}]} @app.get("/{year}", response_model=None) def events_available(year: int) -> any: # get events available for a given year data = available_data.LatestData(year) events = data.get_events() events = [{"label": event, "value": event} for i, event in enumerate(events)] events.reverse() return {"events": events} # format for sessions {"sessions":[{"label":"FP1","value":"FP1"},{"label":"FP2","value":"FP2"},{"label":"FP3","value":"FP3"},{"label":"Qualifying","value":"Q"},{"label":"Race","value":"R"}]} @app.get("/{year}/{event}", response_model=None) def sessions_available(year: int, event: str | int) -> any: # get sessions available for a given year and event data = available_data.LatestData(year) sessions = data.get_sessions(event) sessions = [{"label": session, "value": session} for session in sessions] return {"sessions": sessions} # format for drivers {"drivers":[{"color":"#fff500","label":"RIC","value":"RIC"},{"color":"#ff8700","label":"NOR","value":"NOR"},{"color":"#c00000","label":"VET","value":"VET"},{"color":"#0082fa","label":"LAT","value":"LAT"},{"color":"#787878","label":"GRO","value":"GRO"},{"color":"#ffffff","label":"GAS","value":"GAS"},{"color":"#f596c8","label":"STR","value":"STR"},{"color":"#787878","label":"MAG","value":"MAG"},{"color":"#0600ef","label":"ALB","value":"ALB"},{"color":"#ffffff","label":"KVY","value":"KVY"},{"color":"#fff500","label":"OCO","value":"OCO"},{"color":"#0600ef","label":"VER","value":"VER"},{"color":"#00d2be","label":"HAM","value":"HAM"},{"color":"#ff8700","label":"SAI","value":"SAI"},{"color":"#00d2be","label":"BOT","value":"BOT"},{"color":"#960000","label":"GIO","value":"GIO"}]} @app.get("/{year}/{event}/{session}", response_model=None) def session_drivers(year: int, event: str | int, session: str) -> any: # get drivers available for a given year, event and session f1session = fastf1.get_session(year, event, session) f1session.load(telemetry=False, weather=False, messages=False) laps = f1session.laps team_colors = available_data.team_colors(year) # add team_colors dict to laps on Team column drivers = laps.Driver.unique() # for each driver in drivers, get the Team column from laps and get the color from team_colors dict drivers = [{"color": team_colors[laps[laps.Driver == driver].Team.iloc[0]], "label": driver, "value": driver} for driver in drivers] return {"drivers": drivers} # format for chartData {"chartData":[{"lapnumber":1},{ # "VER":91.564, # "VER_compound":"SOFT", # "VER_compound_color":"#FF5733", # "lapnumber":2 # },{"lapnumber":3},{"VER":90.494,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":4},{"lapnumber":5},{"VER":90.062,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":6},{"lapnumber":7},{"VER":89.815,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":8},{"VER":105.248,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":9},{"lapnumber":10},{"VER":89.79,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":11},{"VER":145.101,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":12},{"lapnumber":13},{"VER":89.662,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":14},{"lapnumber":15},{"VER":89.617,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":16},{"lapnumber":17},{"VER":140.717,"VER_compound":"SOFT","VER_compound_color":"#FF5733","lapnumber":18}]} @app.get("/{year}/{event}/{session}/{driver}", response_model=None) def laps_data(year: int, event: str | int, session: str, driver: str) -> any: # get drivers available for a given year, event and session f1session = fastf1.get_session(year, event, session) f1session.load(telemetry=False, weather=False, messages=False) laps = f1session.laps team_colors = available_data.team_colors(year) # add team_colors dict to laps on Team column drivers = laps.Driver.unique() # for each driver in drivers, get the Team column from laps and get the color from team_colors dict drivers = [{"color": team_colors[laps[laps.Driver == driver].Team.iloc[0]], "label": driver, "value": driver} for driver in drivers] driver_laps = laps.pick_driver(driver) driver_laps['LapTime'] = driver_laps['LapTime'].dt.total_seconds() compound_colors = { "SOFT": "#FF0000", "MEDIUM": "#FFFF00", "HARD": "#FFFFFF", "INTERMEDIATE": "#00FF00", "WET": "#088cd0", } driver_laps_data = [] for _, row in driver_laps.iterrows(): if row['LapTime'] > 0: lap = {f"{driver}": row['LapTime'], f"{driver}_compound": row['Compound'], f"{driver}_compound_color": compound_colors[row['Compound']], "lapnumber": row['LapNumber']} else: lap = {"lapnumber": row['LapNumber']} driver_laps_data.append(lap) return {"chartData": driver_laps_data} @app.get("/{year}/{event}/{session}/{driver}/{lap_number}", response_model=None) def telemetry_data(year: int, event: str | int, session: str, driver: str, lap_number: int) -> any: f1session = fastf1.get_session(year, event, session) f1session.load(telemetry=True, weather=False, messages=False) laps = f1session.laps driver_laps = laps.pick_driver(driver) driver_laps['LapTime'] = driver_laps['LapTime'].dt.total_seconds() # get the telemetry for lap_number selected_lap = driver_laps[driver_laps.LapNumber == lap_number] telemetry = selected_lap.get_telemetry() telemetry['Time'] = telemetry['Time'].dt.total_seconds() laptime = selected_lap.LapTime.values[0] data_key = f"{driver} - Lap {int(lap_number)} - {year} {session} [{int(laptime//60)}:{laptime%60}]" brake_tel = [] drs_tel = [] gear_tel = [] rpm_tel = [] speed_tel = [] throttle_tel = [] time_tel = [] track_map = [] for _, row in telemetry.iterrows(): brake = {"x": row['Distance'], "y": row['Brake'], } brake_tel.append(brake) drs = {"x": row['Distance'], "y": row['DRS'], } drs_tel.append(drs) gear = {"x": row['Distance'], "y": row['nGear'], } gear_tel.append(gear) rpm = {"x": row['Distance'], "y": row['RPM'], } rpm_tel.append(rpm) speed = {"x": row['Distance'], "y": row['Speed'], } speed_tel.append(speed) throttle = {"x": row['Distance'], "y": row['Throttle'], } throttle_tel.append(throttle) time = {"x": row['Distance'], "y": row['Time'], } time_tel.append(time) track = {"x": row['X'], "y": row['Y'], } track_map.append(track) telemetry_data = { "telemetryData":{ "brake": brake_tel, "dataKey": data_key, "drs": drs_tel, "gear": gear_tel, "rpm": rpm_tel, "speed": speed_tel, "throttle": throttle_tel, "time": time_tel, "trackMap": track_map, } } return telemetry_data