session results for race, quali, sprint quali and sprint
Browse files- api_playground.ipynb +84 -190
- app.py +17 -2
- tools.py +25 -6
- utils/constants.py +2 -2
api_playground.ipynb
CHANGED
@@ -34,234 +34,128 @@
|
|
34 |
},
|
35 |
{
|
36 |
"cell_type": "code",
|
37 |
-
"execution_count":
|
38 |
-
"id": "
|
39 |
"metadata": {},
|
40 |
"outputs": [
|
41 |
{
|
42 |
"name": "stderr",
|
43 |
"output_type": "stream",
|
44 |
"text": [
|
45 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
]
|
47 |
},
|
48 |
{
|
49 |
"name": "stdout",
|
50 |
"output_type": "stream",
|
51 |
"text": [
|
52 |
-
"
|
53 |
-
"
|
54 |
-
"
|
55 |
-
"
|
56 |
-
"
|
57 |
-
"
|
58 |
-
" 'get_circuit_info',\n",
|
59 |
-
" 'get_driver',\n",
|
60 |
-
" 'laps',\n",
|
61 |
-
" 'load',\n",
|
62 |
-
" 'name',\n",
|
63 |
-
" 'pos_data',\n",
|
64 |
-
" 'race_control_messages',\n",
|
65 |
-
" 'results',\n",
|
66 |
-
" 'session_info',\n",
|
67 |
-
" 'session_start_time',\n",
|
68 |
-
" 'session_status',\n",
|
69 |
-
" 't0_date',\n",
|
70 |
-
" 'total_laps',\n",
|
71 |
-
" 'track_status',\n",
|
72 |
-
" 'weather_data']\n"
|
73 |
-
]
|
74 |
-
}
|
75 |
-
],
|
76 |
-
"source": [
|
77 |
-
"session = fastf1.get_session(2025, 'Bahrain', 'Race')\n",
|
78 |
-
"attributes = [x for x in dir(session) if not x.startswith(\"_\")]\n",
|
79 |
-
"pprint(attributes)"
|
80 |
-
]
|
81 |
-
},
|
82 |
-
{
|
83 |
-
"cell_type": "code",
|
84 |
-
"execution_count": 21,
|
85 |
-
"id": "1cc4ab17",
|
86 |
-
"metadata": {},
|
87 |
-
"outputs": [
|
88 |
-
{
|
89 |
-
"name": "stdout",
|
90 |
-
"output_type": "stream",
|
91 |
-
"text": [
|
92 |
-
"ATTR: api_path: /static/2025/2025-04-13_Bahrain_Grand_Prix/2025-04-13_Race/\n",
|
93 |
-
"\n",
|
94 |
-
"Failed to get attribute: car_data\n",
|
95 |
-
"ATTR: date: 2025-04-13 15:00:00\n",
|
96 |
-
"\n",
|
97 |
-
"Failed to get attribute: drivers\n",
|
98 |
-
"ATTR: event: RoundNumber 4\n",
|
99 |
-
"Country Bahrain\n",
|
100 |
-
"Location Sakhir\n",
|
101 |
-
"OfficialEventName FORMULA 1 GULF AIR BAHRAIN GRAND PRIX 2025\n",
|
102 |
-
"EventDate 2025-04-13 00:00:00\n",
|
103 |
-
"EventName Bahrain Grand Prix\n",
|
104 |
-
"EventFormat conventional\n",
|
105 |
-
"Session1 Practice 1\n",
|
106 |
-
"Session1Date 2025-04-11 14:30:00+03:00\n",
|
107 |
-
"Session1DateUtc 2025-04-11 11:30:00\n",
|
108 |
-
"Session2 Practice 2\n",
|
109 |
-
"Session2Date 2025-04-11 18:00:00+03:00\n",
|
110 |
-
"Session2DateUtc 2025-04-11 15:00:00\n",
|
111 |
-
"Session3 Practice 3\n",
|
112 |
-
"Session3Date 2025-04-12 15:30:00+03:00\n",
|
113 |
-
"Session3DateUtc 2025-04-12 12:30:00\n",
|
114 |
-
"Session4 Qualifying\n",
|
115 |
-
"Session4Date 2025-04-12 19:00:00+03:00\n",
|
116 |
-
"Session4DateUtc 2025-04-12 16:00:00\n",
|
117 |
-
"Session5 Race\n",
|
118 |
-
"Session5Date 2025-04-13 18:00:00+03:00\n",
|
119 |
-
"Session5DateUtc 2025-04-13 15:00:00\n",
|
120 |
-
"F1ApiSupport True\n",
|
121 |
-
"Name: 4, dtype: object\n",
|
122 |
"\n",
|
123 |
-
"
|
|
|
|
|
|
|
|
|
|
|
124 |
"\n",
|
125 |
-
"
|
|
|
|
|
|
|
|
|
|
|
126 |
"\n",
|
127 |
-
"
|
|
|
|
|
|
|
|
|
|
|
128 |
"\n",
|
129 |
-
"
|
130 |
-
"ATTR: load: <bound method Session.load of 2025 Season Round 4: Bahrain Grand Prix - Race>\n",
|
131 |
-
"\n",
|
132 |
-
"ATTR: name: Race\n",
|
133 |
-
"\n",
|
134 |
-
"Failed to get attribute: pos_data\n",
|
135 |
-
"Failed to get attribute: race_control_messages\n",
|
136 |
-
"Failed to get attribute: results\n",
|
137 |
-
"Failed to get attribute: session_info\n",
|
138 |
-
"Failed to get attribute: session_start_time\n",
|
139 |
-
"Failed to get attribute: session_status\n",
|
140 |
-
"Failed to get attribute: t0_date\n",
|
141 |
-
"Failed to get attribute: total_laps\n",
|
142 |
-
"Failed to get attribute: track_status\n",
|
143 |
-
"Failed to get attribute: weather_data\n"
|
144 |
]
|
145 |
}
|
146 |
],
|
147 |
"source": [
|
148 |
-
"
|
149 |
-
"
|
150 |
-
"
|
151 |
-
"
|
152 |
-
"
|
153 |
]
|
154 |
},
|
155 |
{
|
156 |
"cell_type": "code",
|
157 |
-
"execution_count":
|
158 |
-
"id": "
|
159 |
"metadata": {},
|
160 |
"outputs": [
|
161 |
{
|
162 |
-
"name": "
|
163 |
"output_type": "stream",
|
164 |
"text": [
|
165 |
-
"
|
166 |
-
"
|
167 |
-
"
|
168 |
-
"
|
169 |
-
"
|
170 |
-
"
|
171 |
-
"
|
172 |
-
"
|
173 |
-
"
|
174 |
-
"
|
175 |
-
"
|
176 |
-
"Session2Date 2025-04-11 18:00:00+03:00\n",
|
177 |
-
"Session2DateUtc 2025-04-11 15:00:00\n",
|
178 |
-
"Session3 Practice 3\n",
|
179 |
-
"Session3Date 2025-04-12 15:30:00+03:00\n",
|
180 |
-
"Session3DateUtc 2025-04-12 12:30:00\n",
|
181 |
-
"Session4 Qualifying\n",
|
182 |
-
"Session4Date 2025-04-12 19:00:00+03:00\n",
|
183 |
-
"Session4DateUtc 2025-04-12 16:00:00\n",
|
184 |
-
"Session5 Race\n",
|
185 |
-
"Session5Date 2025-04-13 18:00:00+03:00\n",
|
186 |
-
"Session5DateUtc 2025-04-13 15:00:00\n",
|
187 |
-
"F1ApiSupport True\n",
|
188 |
-
"Name: 4, dtype: object\n",
|
189 |
-
"RoundNumber 4\n",
|
190 |
-
"Country Bahrain\n",
|
191 |
-
"Location Sakhir\n",
|
192 |
-
"OfficialEventName FORMULA 1 GULF AIR BAHRAIN GRAND PRIX 2025\n",
|
193 |
-
"EventDate 2025-04-13 00:00:00\n",
|
194 |
-
"EventName Bahrain Grand Prix\n",
|
195 |
-
"EventFormat conventional\n",
|
196 |
-
"Session1 Practice 1\n",
|
197 |
-
"Session1Date 2025-04-11 14:30:00+03:00\n",
|
198 |
-
"Session1DateUtc 2025-04-11 11:30:00\n",
|
199 |
-
"Session2 Practice 2\n",
|
200 |
-
"Session2Date 2025-04-11 18:00:00+03:00\n",
|
201 |
-
"Session2DateUtc 2025-04-11 15:00:00\n",
|
202 |
-
"Session3 Practice 3\n",
|
203 |
-
"Session3Date 2025-04-12 15:30:00+03:00\n",
|
204 |
-
"Session3DateUtc 2025-04-12 12:30:00\n",
|
205 |
-
"Session4 Qualifying\n",
|
206 |
-
"Session4Date 2025-04-12 19:00:00+03:00\n",
|
207 |
-
"Session4DateUtc 2025-04-12 16:00:00\n",
|
208 |
-
"Session5 Race\n",
|
209 |
-
"Session5Date 2025-04-13 18:00:00+03:00\n",
|
210 |
-
"Session5DateUtc 2025-04-13 15:00:00\n",
|
211 |
-
"F1ApiSupport True\n",
|
212 |
-
"Name: 4, dtype: object\n"
|
213 |
]
|
214 |
-
}
|
215 |
-
],
|
216 |
-
"source": [
|
217 |
-
"event1 = fastf1.get_session(2025, 'Bahrain', \"fp1\").event\n",
|
218 |
-
"print(event1)\n",
|
219 |
-
"event2 = fastf1.get_session(2025, 'Bahrain', \"race\").event\n",
|
220 |
-
"print(event2)"
|
221 |
-
]
|
222 |
-
},
|
223 |
-
{
|
224 |
-
"cell_type": "code",
|
225 |
-
"execution_count": null,
|
226 |
-
"id": "067ab2ac",
|
227 |
-
"metadata": {},
|
228 |
-
"outputs": [
|
229 |
{
|
230 |
"name": "stdout",
|
231 |
"output_type": "stream",
|
232 |
"text": [
|
233 |
-
"
|
234 |
-
"
|
235 |
-
"
|
236 |
-
"
|
237 |
-
"
|
238 |
-
"
|
239 |
-
"
|
240 |
-
"
|
241 |
-
"
|
242 |
-
"
|
243 |
-
"
|
244 |
-
"
|
245 |
-
"
|
246 |
-
"
|
247 |
-
"
|
248 |
-
"
|
249 |
-
"
|
250 |
-
"
|
251 |
-
"
|
252 |
-
"
|
253 |
-
"
|
254 |
-
"Session5Date 2025-04-13 18:00:00+03:00\n",
|
255 |
-
"Session5DateUtc 2025-04-13 15:00:00\n",
|
256 |
-
"F1ApiSupport True\n",
|
257 |
-
"Name: 4, dtype: object\n"
|
258 |
]
|
259 |
}
|
260 |
],
|
261 |
"source": [
|
262 |
-
"
|
263 |
-
"
|
264 |
-
"
|
|
|
265 |
]
|
266 |
},
|
267 |
{
|
|
|
34 |
},
|
35 |
{
|
36 |
"cell_type": "code",
|
37 |
+
"execution_count": 9,
|
38 |
+
"id": "a2ee421b",
|
39 |
"metadata": {},
|
40 |
"outputs": [
|
41 |
{
|
42 |
"name": "stderr",
|
43 |
"output_type": "stream",
|
44 |
"text": [
|
45 |
+
"core INFO \tLoading data for Miami Grand Prix - Sprint Qualifying [v3.5.3]\n",
|
46 |
+
"req INFO \tUsing cached data for session_info\n",
|
47 |
+
"req INFO \tUsing cached data for driver_info\n",
|
48 |
+
"core WARNING \tSprint Qualifying is not supported by Ergast! Limited results are calculated from timing data.\n",
|
49 |
+
"req INFO \tUsing cached data for session_status_data\n",
|
50 |
+
"req INFO \tUsing cached data for track_status_data\n",
|
51 |
+
"req INFO \tUsing cached data for _extended_timing_data\n",
|
52 |
+
"req INFO \tUsing cached data for timing_app_data\n",
|
53 |
+
"core INFO \tProcessing timing data...\n",
|
54 |
+
"req INFO \tUsing cached data for weather_data\n",
|
55 |
+
"req INFO \tUsing cached data for race_control_messages\n",
|
56 |
+
"core INFO \tFinished loading data for 20 drivers: ['12', '81', '4', '1', '63', '16', '44', '23', '6', '14', '27', '31', '10', '30', '55', '18', '7', '22', '5', '87']\n"
|
57 |
]
|
58 |
},
|
59 |
{
|
60 |
"name": "stdout",
|
61 |
"output_type": "stream",
|
62 |
"text": [
|
63 |
+
" DriverNumber BroadcastName Abbreviation DriverId TeamName \\\n",
|
64 |
+
"12 12 K ANTONELLI ANT Mercedes \n",
|
65 |
+
"81 81 O PIASTRI PIA McLaren \n",
|
66 |
+
"4 4 L NORRIS NOR McLaren \n",
|
67 |
+
"1 1 M VERSTAPPEN VER Red Bull Racing \n",
|
68 |
+
"63 63 G RUSSELL RUS Mercedes \n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
"\n",
|
70 |
+
" TeamColor TeamId FirstName LastName FullName ... CountryCode \\\n",
|
71 |
+
"12 27F4D2 Kimi Antonelli Kimi Antonelli ... \n",
|
72 |
+
"81 FF8000 Oscar Piastri Oscar Piastri ... \n",
|
73 |
+
"4 FF8000 Lando Norris Lando Norris ... \n",
|
74 |
+
"1 3671C6 Max Verstappen Max Verstappen ... \n",
|
75 |
+
"63 27F4D2 George Russell George Russell ... \n",
|
76 |
"\n",
|
77 |
+
" Position ClassifiedPosition GridPosition Q1 \\\n",
|
78 |
+
"12 1.0 NaN 0 days 00:01:27.858000 \n",
|
79 |
+
"81 2.0 NaN 0 days 00:01:27.951000 \n",
|
80 |
+
"4 3.0 NaN 0 days 00:01:27.890000 \n",
|
81 |
+
"1 4.0 NaN 0 days 00:01:27.953000 \n",
|
82 |
+
"63 5.0 NaN 0 days 00:01:27.688000 \n",
|
83 |
"\n",
|
84 |
+
" Q2 Q3 Time Status Points \n",
|
85 |
+
"12 0 days 00:01:27.384000 0 days 00:01:26.482000 NaT NaN \n",
|
86 |
+
"81 0 days 00:01:27.354000 0 days 00:01:26.527000 NaT NaN \n",
|
87 |
+
"4 0 days 00:01:27.109000 0 days 00:01:26.582000 NaT NaN \n",
|
88 |
+
"1 0 days 00:01:27.245000 0 days 00:01:26.737000 NaT NaN \n",
|
89 |
+
"63 0 days 00:01:27.666000 0 days 00:01:26.791000 NaT NaN \n",
|
90 |
"\n",
|
91 |
+
"[5 rows x 21 columns]\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
]
|
93 |
}
|
94 |
],
|
95 |
"source": [
|
96 |
+
"session = fastf1.get_session(2025, \"Miami\", \"sprint qualifying\")\n",
|
97 |
+
"session.load(telemetry=False)\n",
|
98 |
+
"results = session.results\n",
|
99 |
+
"print(results.head())\n",
|
100 |
+
"#df = results[[\"DriverNumber\", \"Abbreviation\", \"FullName\", \"Position\", \"ClassifiedPosition\", \"GridPosition\", \"Points\", \"Status\", \"Q1\", \"Q2\", \"Q3\"]]"
|
101 |
]
|
102 |
},
|
103 |
{
|
104 |
"cell_type": "code",
|
105 |
+
"execution_count": null,
|
106 |
+
"id": "352270a0",
|
107 |
"metadata": {},
|
108 |
"outputs": [
|
109 |
{
|
110 |
+
"name": "stderr",
|
111 |
"output_type": "stream",
|
112 |
"text": [
|
113 |
+
"core INFO \tLoading data for Japanese Grand Prix - Practice 1 [v3.5.3]\n",
|
114 |
+
"req INFO \tUsing cached data for session_info\n",
|
115 |
+
"req INFO \tUsing cached data for driver_info\n",
|
116 |
+
"req INFO \tUsing cached data for session_status_data\n",
|
117 |
+
"req INFO \tUsing cached data for track_status_data\n",
|
118 |
+
"req INFO \tUsing cached data for _extended_timing_data\n",
|
119 |
+
"req INFO \tUsing cached data for timing_app_data\n",
|
120 |
+
"core INFO \tProcessing timing data...\n",
|
121 |
+
"req INFO \tUsing cached data for weather_data\n",
|
122 |
+
"req INFO \tUsing cached data for race_control_messages\n",
|
123 |
+
"core INFO \tFinished loading data for 20 drivers: ['1', '4', '5', '6', '10', '12', '14', '16', '18', '22', '23', '27', '30', '31', '44', '55', '62', '63', '81', '87']\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
]
|
125 |
+
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
{
|
127 |
"name": "stdout",
|
128 |
"output_type": "stream",
|
129 |
"text": [
|
130 |
+
"{'Abbreviation': 'VER',\n",
|
131 |
+
" 'BroadcastName': 'M VERSTAPPEN',\n",
|
132 |
+
" 'ClassifiedPosition': '',\n",
|
133 |
+
" 'CountryCode': '',\n",
|
134 |
+
" 'DriverId': 'max_verstappen',\n",
|
135 |
+
" 'DriverNumber': '1',\n",
|
136 |
+
" 'FirstName': 'Max',\n",
|
137 |
+
" 'FullName': 'Max Verstappen',\n",
|
138 |
+
" 'GridPosition': nan,\n",
|
139 |
+
" 'HeadshotUrl': 'https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/M/MAXVER01_Max_Verstappen/maxver01.png.transform/1col/image.png',\n",
|
140 |
+
" 'LastName': 'Verstappen',\n",
|
141 |
+
" 'Points': nan,\n",
|
142 |
+
" 'Position': nan,\n",
|
143 |
+
" 'Q1': NaT,\n",
|
144 |
+
" 'Q2': NaT,\n",
|
145 |
+
" 'Q3': NaT,\n",
|
146 |
+
" 'Status': '',\n",
|
147 |
+
" 'TeamColor': '3671C6',\n",
|
148 |
+
" 'TeamId': 'red_bull',\n",
|
149 |
+
" 'TeamName': 'Red Bull Racing',\n",
|
150 |
+
" 'Time': NaT}\n"
|
|
|
|
|
|
|
|
|
151 |
]
|
152 |
}
|
153 |
],
|
154 |
"source": [
|
155 |
+
"session = fastf1.get_session(2025, 3, \"FP1\")\n",
|
156 |
+
"session.load(telemetry=False)\n",
|
157 |
+
"driver_info = session.get_driver(\"VER\").to_dict()\n",
|
158 |
+
"pprint(driver_info)"
|
159 |
]
|
160 |
},
|
161 |
{
|
app.py
CHANGED
@@ -5,7 +5,9 @@ import tools
|
|
5 |
from utils.constants import (
|
6 |
DRIVER_NAMES,
|
7 |
CONSTRUCTOR_NAMES,
|
8 |
-
CURRENT_YEAR
|
|
|
|
|
9 |
)
|
10 |
|
11 |
iface_driver_championship_standings = gr.Interface(
|
@@ -65,13 +67,26 @@ iface_track_visualization = gr.Interface(
|
|
65 |
description="Get the track visualization for the given Grand Prix"
|
66 |
)
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
|
69 |
named_interfaces = {
|
70 |
"Driver Championship Standings": iface_driver_championship_standings,
|
71 |
"Constructor Championship Standings": iface_constructor_championship_standings,
|
72 |
"Event Info": iface_event_info,
|
73 |
"Season Calendar": iface_season_calendar,
|
74 |
-
"Track Visualizations": iface_track_visualization
|
|
|
75 |
}
|
76 |
|
77 |
# Tab names and interfaces
|
|
|
5 |
from utils.constants import (
|
6 |
DRIVER_NAMES,
|
7 |
CONSTRUCTOR_NAMES,
|
8 |
+
CURRENT_YEAR,
|
9 |
+
AVAILABLE_SESSION_TYPES,
|
10 |
+
DROPDOWN_SESSION_TYPES
|
11 |
)
|
12 |
|
13 |
iface_driver_championship_standings = gr.Interface(
|
|
|
67 |
description="Get the track visualization for the given Grand Prix"
|
68 |
)
|
69 |
|
70 |
+
iface_session_results = gr.Interface(
|
71 |
+
fn=tools.get_session_results,
|
72 |
+
inputs=[
|
73 |
+
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
74 |
+
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported)"),
|
75 |
+
gr.Dropdown([session_type for session_type in DROPDOWN_SESSION_TYPES if "practice" not in session_type], label="Session type", value="race")
|
76 |
+
],
|
77 |
+
outputs=gr.DataFrame(),
|
78 |
+
title="Session Results",
|
79 |
+
description="Get the session results for the given Grand Prix"
|
80 |
+
)
|
81 |
+
|
82 |
|
83 |
named_interfaces = {
|
84 |
"Driver Championship Standings": iface_driver_championship_standings,
|
85 |
"Constructor Championship Standings": iface_constructor_championship_standings,
|
86 |
"Event Info": iface_event_info,
|
87 |
"Season Calendar": iface_season_calendar,
|
88 |
+
"Track Visualizations": iface_track_visualization,
|
89 |
+
"Session Results": iface_session_results
|
90 |
}
|
91 |
|
92 |
# Tab names and interfaces
|
tools.py
CHANGED
@@ -4,15 +4,14 @@ Here we implement the MCP tools
|
|
4 |
Tools to implement
|
5 |
- session result
|
6 |
- driver info
|
7 |
-
- championship standings
|
8 |
-
- driver standings
|
9 |
-
- constructor standings
|
10 |
- compare drivers
|
11 |
|
12 |
"""
|
13 |
|
14 |
import json
|
15 |
import fastf1
|
|
|
|
|
16 |
from PIL import Image
|
17 |
from typing import Union
|
18 |
from fastf1.core import Session
|
@@ -71,7 +70,6 @@ def driver_championship_standings(year: int, driver_name: str) -> str:
|
|
71 |
standings_string = f"{driver_name} is {driver_standing['position'].iloc[0]}{suffix} with {driver_standing['points'].iloc[0]} points and {driver_standing['wins'].iloc[0]} wins"
|
72 |
return standings_string
|
73 |
|
74 |
-
|
75 |
def constructor_championship_standings(year: int, constructor_name: str) -> str:
|
76 |
|
77 |
team_mapping = {
|
@@ -96,8 +94,6 @@ def constructor_championship_standings(year: int, constructor_name: str) -> str:
|
|
96 |
standings_string = f"{constructor_name} are {constructor_standing['position'].iloc[0]}{suffix} with {constructor_standing['points'].iloc[0]} points and {constructor_standing['wins'].iloc[0]} wins"
|
97 |
return standings_string
|
98 |
|
99 |
-
|
100 |
-
|
101 |
def track_visualization(year: int, round: gp, visualization_type: str, driver_name: str) -> Image:
|
102 |
|
103 |
session = get_session(year, round, "race")
|
@@ -110,6 +106,29 @@ def track_visualization(year: int, round: gp, visualization_type: str, driver_na
|
|
110 |
elif visualization_type == "gear":
|
111 |
return track_utils.create_track_gear_visualization(session)
|
112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
|
114 |
if __name__ == "__main__":
|
115 |
session = get_session(2024, 1, "fp1")
|
|
|
4 |
Tools to implement
|
5 |
- session result
|
6 |
- driver info
|
|
|
|
|
|
|
7 |
- compare drivers
|
8 |
|
9 |
"""
|
10 |
|
11 |
import json
|
12 |
import fastf1
|
13 |
+
import gradio as gr
|
14 |
+
import pandas as pd
|
15 |
from PIL import Image
|
16 |
from typing import Union
|
17 |
from fastf1.core import Session
|
|
|
70 |
standings_string = f"{driver_name} is {driver_standing['position'].iloc[0]}{suffix} with {driver_standing['points'].iloc[0]} points and {driver_standing['wins'].iloc[0]} wins"
|
71 |
return standings_string
|
72 |
|
|
|
73 |
def constructor_championship_standings(year: int, constructor_name: str) -> str:
|
74 |
|
75 |
team_mapping = {
|
|
|
94 |
standings_string = f"{constructor_name} are {constructor_standing['position'].iloc[0]}{suffix} with {constructor_standing['points'].iloc[0]} points and {constructor_standing['wins'].iloc[0]} wins"
|
95 |
return standings_string
|
96 |
|
|
|
|
|
97 |
def track_visualization(year: int, round: gp, visualization_type: str, driver_name: str) -> Image:
|
98 |
|
99 |
session = get_session(year, round, "race")
|
|
|
106 |
elif visualization_type == "gear":
|
107 |
return track_utils.create_track_gear_visualization(session)
|
108 |
|
109 |
+
def get_session_results(year: int, round: gp, session_type: session_type) -> pd.DataFrame:
|
110 |
+
|
111 |
+
try:
|
112 |
+
session = get_session(year, round, session_type)
|
113 |
+
session.load(telemetry=False)
|
114 |
+
results = session.results
|
115 |
+
except ValueError as e:
|
116 |
+
raise gr.Error(f"Session type {session_type} is not supported for the specified round. This Grand Prix most likely did not include a sprint race/quali.")
|
117 |
+
|
118 |
+
df = results[["DriverNumber", "Abbreviation", "FullName", "Position", "GridPosition", "Points", "Status", "Q1", "Q2", "Q3"]]
|
119 |
+
df["Name"] = df.apply(lambda row: f"{row['FullName']} ({row['Abbreviation']} • {row['DriverNumber']})", axis=1)
|
120 |
+
df = df.drop(columns=["FullName", "Abbreviation", "DriverNumber"])
|
121 |
+
df = df.rename(columns={"Position": "Pos", "GridPosition": "Grid Pos"})
|
122 |
+
|
123 |
+
# Process results based on session type
|
124 |
+
if session_type in ["race", "sprint"]:
|
125 |
+
df = df[["Pos", "Name", "Points", "Grid Pos", "Status"]]
|
126 |
+
elif "qualifying" in session_type:
|
127 |
+
df[["Q1", "Q2", "Q3"]] = df[["Q1", "Q2", "Q3"]].apply(lambda x: x.dt.total_seconds().apply(lambda y: f"{int(y//60):02d}:{int(y%60):02d}.{int(y%1*1000):03d}" if pd.notna(y) else "-"))
|
128 |
+
df = df[["Pos", "Name", "Q1", "Q2", "Q3"]]
|
129 |
+
return df
|
130 |
+
|
131 |
+
|
132 |
|
133 |
if __name__ == "__main__":
|
134 |
session = get_session(2024, 1, "fp1")
|
utils/constants.py
CHANGED
@@ -4,12 +4,12 @@ import datetime
|
|
4 |
AVAILABLE_SESSION_TYPES = [
|
5 |
"fp1", "fp2", "fp3", "q", "s", "ss", "sq", "r",
|
6 |
"practice 1", "practice 2", "practice 3", "sprint",
|
7 |
-
"sprint
|
8 |
]
|
9 |
|
10 |
DROPDOWN_SESSION_TYPES = [
|
11 |
"practice 1", "practice 2", "practice 3", "sprint",
|
12 |
-
"sprint
|
13 |
]
|
14 |
|
15 |
# Load in driver names
|
|
|
4 |
AVAILABLE_SESSION_TYPES = [
|
5 |
"fp1", "fp2", "fp3", "q", "s", "ss", "sq", "r",
|
6 |
"practice 1", "practice 2", "practice 3", "sprint",
|
7 |
+
"sprint qualifying", "qualifying", "race"
|
8 |
]
|
9 |
|
10 |
DROPDOWN_SESSION_TYPES = [
|
11 |
"practice 1", "practice 2", "practice 3", "sprint",
|
12 |
+
"sprint qualifying", "qualifying", "race"
|
13 |
]
|
14 |
|
15 |
# Load in driver names
|