driver live standings
Browse files- api_playground.ipynb +122 -1
- app.py +10 -10
- tools.py +29 -28
api_playground.ipynb
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
-
"execution_count":
|
6 |
"id": "b7d2515e",
|
7 |
"metadata": {},
|
8 |
"outputs": [
|
@@ -264,6 +264,127 @@
|
|
264 |
"print(event2.keys())\n"
|
265 |
]
|
266 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
267 |
{
|
268 |
"cell_type": "code",
|
269 |
"execution_count": 2,
|
|
|
2 |
"cells": [
|
3 |
{
|
4 |
"cell_type": "code",
|
5 |
+
"execution_count": 2,
|
6 |
"id": "b7d2515e",
|
7 |
"metadata": {},
|
8 |
"outputs": [
|
|
|
264 |
"print(event2.keys())\n"
|
265 |
]
|
266 |
},
|
267 |
+
{
|
268 |
+
"cell_type": "code",
|
269 |
+
"execution_count": 24,
|
270 |
+
"id": "e6de8707",
|
271 |
+
"metadata": {},
|
272 |
+
"outputs": [
|
273 |
+
{
|
274 |
+
"data": {
|
275 |
+
"text/html": [
|
276 |
+
"<div>\n",
|
277 |
+
"<style scoped>\n",
|
278 |
+
" .dataframe tbody tr th:only-of-type {\n",
|
279 |
+
" vertical-align: middle;\n",
|
280 |
+
" }\n",
|
281 |
+
"\n",
|
282 |
+
" .dataframe tbody tr th {\n",
|
283 |
+
" vertical-align: top;\n",
|
284 |
+
" }\n",
|
285 |
+
"\n",
|
286 |
+
" .dataframe thead th {\n",
|
287 |
+
" text-align: right;\n",
|
288 |
+
" }\n",
|
289 |
+
"</style>\n",
|
290 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
291 |
+
" <thead>\n",
|
292 |
+
" <tr style=\"text-align: right;\">\n",
|
293 |
+
" <th></th>\n",
|
294 |
+
" <th>position</th>\n",
|
295 |
+
" <th>positionText</th>\n",
|
296 |
+
" <th>points</th>\n",
|
297 |
+
" <th>wins</th>\n",
|
298 |
+
" <th>driverId</th>\n",
|
299 |
+
" <th>driverNumber</th>\n",
|
300 |
+
" <th>driverCode</th>\n",
|
301 |
+
" <th>driverUrl</th>\n",
|
302 |
+
" <th>givenName</th>\n",
|
303 |
+
" <th>familyName</th>\n",
|
304 |
+
" <th>dateOfBirth</th>\n",
|
305 |
+
" <th>driverNationality</th>\n",
|
306 |
+
" <th>constructorIds</th>\n",
|
307 |
+
" <th>constructorUrls</th>\n",
|
308 |
+
" <th>constructorNames</th>\n",
|
309 |
+
" <th>constructorNationalities</th>\n",
|
310 |
+
" </tr>\n",
|
311 |
+
" </thead>\n",
|
312 |
+
" <tbody>\n",
|
313 |
+
" <tr>\n",
|
314 |
+
" <th>0</th>\n",
|
315 |
+
" <td>1</td>\n",
|
316 |
+
" <td>1</td>\n",
|
317 |
+
" <td>575.0</td>\n",
|
318 |
+
" <td>19</td>\n",
|
319 |
+
" <td>max_verstappen</td>\n",
|
320 |
+
" <td>33</td>\n",
|
321 |
+
" <td>VER</td>\n",
|
322 |
+
" <td>http://en.wikipedia.org/wiki/Max_Verstappen</td>\n",
|
323 |
+
" <td>Max</td>\n",
|
324 |
+
" <td>Verstappen</td>\n",
|
325 |
+
" <td>1997-09-30</td>\n",
|
326 |
+
" <td>Dutch</td>\n",
|
327 |
+
" <td>[red_bull]</td>\n",
|
328 |
+
" <td>[http://en.wikipedia.org/wiki/Red_Bull_Racing]</td>\n",
|
329 |
+
" <td>[Red Bull]</td>\n",
|
330 |
+
" <td>[Austrian]</td>\n",
|
331 |
+
" </tr>\n",
|
332 |
+
" <tr>\n",
|
333 |
+
" <th>1</th>\n",
|
334 |
+
" <td>2</td>\n",
|
335 |
+
" <td>2</td>\n",
|
336 |
+
" <td>285.0</td>\n",
|
337 |
+
" <td>2</td>\n",
|
338 |
+
" <td>perez</td>\n",
|
339 |
+
" <td>11</td>\n",
|
340 |
+
" <td>PER</td>\n",
|
341 |
+
" <td>http://en.wikipedia.org/wiki/Sergio_P%C3%A9rez</td>\n",
|
342 |
+
" <td>Sergio</td>\n",
|
343 |
+
" <td>Pérez</td>\n",
|
344 |
+
" <td>1990-01-26</td>\n",
|
345 |
+
" <td>Mexican</td>\n",
|
346 |
+
" <td>[red_bull]</td>\n",
|
347 |
+
" <td>[http://en.wikipedia.org/wiki/Red_Bull_Racing]</td>\n",
|
348 |
+
" <td>[Red Bull]</td>\n",
|
349 |
+
" <td>[Austrian]</td>\n",
|
350 |
+
" </tr>\n",
|
351 |
+
" </tbody>\n",
|
352 |
+
"</table>\n",
|
353 |
+
"</div>"
|
354 |
+
],
|
355 |
+
"text/plain": [
|
356 |
+
" position positionText points wins driverId driverNumber \\\n",
|
357 |
+
"0 1 1 575.0 19 max_verstappen 33 \n",
|
358 |
+
"1 2 2 285.0 2 perez 11 \n",
|
359 |
+
"\n",
|
360 |
+
" driverCode driverUrl givenName \\\n",
|
361 |
+
"0 VER http://en.wikipedia.org/wiki/Max_Verstappen Max \n",
|
362 |
+
"1 PER http://en.wikipedia.org/wiki/Sergio_P%C3%A9rez Sergio \n",
|
363 |
+
"\n",
|
364 |
+
" familyName dateOfBirth driverNationality constructorIds \\\n",
|
365 |
+
"0 Verstappen 1997-09-30 Dutch [red_bull] \n",
|
366 |
+
"1 Pérez 1990-01-26 Mexican [red_bull] \n",
|
367 |
+
"\n",
|
368 |
+
" constructorUrls constructorNames \\\n",
|
369 |
+
"0 [http://en.wikipedia.org/wiki/Red_Bull_Racing] [Red Bull] \n",
|
370 |
+
"1 [http://en.wikipedia.org/wiki/Red_Bull_Racing] [Red Bull] \n",
|
371 |
+
"\n",
|
372 |
+
" constructorNationalities \n",
|
373 |
+
"0 [Austrian] \n",
|
374 |
+
"1 [Austrian] "
|
375 |
+
]
|
376 |
+
},
|
377 |
+
"execution_count": 24,
|
378 |
+
"metadata": {},
|
379 |
+
"output_type": "execute_result"
|
380 |
+
}
|
381 |
+
],
|
382 |
+
"source": [
|
383 |
+
"ergastandings = fastf1.ergast.Ergast()\n",
|
384 |
+
"driver_standings = ergastandings.get_driver_standings(2023).content[0]\n",
|
385 |
+
"driver_standings.head(2)"
|
386 |
+
]
|
387 |
+
},
|
388 |
{
|
389 |
"cell_type": "code",
|
390 |
"execution_count": 2,
|
app.py
CHANGED
@@ -22,7 +22,7 @@ with open("assets/constructor_details.json") as f:
|
|
22 |
|
23 |
|
24 |
iface_driver_championship_standings = gr.Interface(
|
25 |
-
fn=tools.
|
26 |
inputs=[
|
27 |
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
28 |
gr.Dropdown(driver_names)
|
@@ -37,7 +37,7 @@ iface_event_info = gr.Interface(
|
|
37 |
inputs=[
|
38 |
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
39 |
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported)"),
|
40 |
-
gr.Radio(["human", "LLM"], label="
|
41 |
],
|
42 |
outputs="text",
|
43 |
title="Event Info",
|
@@ -63,21 +63,21 @@ iface_track_visualization = gr.Interface(
|
|
63 |
gr.Dropdown(driver_names)
|
64 |
],
|
65 |
outputs="image",
|
66 |
-
title="
|
67 |
description="Get the track visualization for the given Grand Prix"
|
68 |
)
|
69 |
|
70 |
|
71 |
-
# TODO swap to this format
|
72 |
named_interfaces = {
|
73 |
-
"
|
74 |
-
"
|
75 |
-
"
|
76 |
-
"
|
77 |
}
|
78 |
|
79 |
-
|
80 |
-
tab_names =
|
|
|
81 |
|
82 |
|
83 |
# Combine all the interfaces into a single TabbedInterface
|
|
|
22 |
|
23 |
|
24 |
iface_driver_championship_standings = gr.Interface(
|
25 |
+
fn=tools.driver_championship_standings,
|
26 |
inputs=[
|
27 |
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
28 |
gr.Dropdown(driver_names)
|
|
|
37 |
inputs=[
|
38 |
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
39 |
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported)"),
|
40 |
+
gr.Radio(["human", "LLM"], label="Display format", value="human")
|
41 |
],
|
42 |
outputs="text",
|
43 |
title="Event Info",
|
|
|
63 |
gr.Dropdown(driver_names)
|
64 |
],
|
65 |
outputs="image",
|
66 |
+
title="Track Visualizations",
|
67 |
description="Get the track visualization for the given Grand Prix"
|
68 |
)
|
69 |
|
70 |
|
|
|
71 |
named_interfaces = {
|
72 |
+
"Driver Championship Standings": iface_driver_championship_standings,
|
73 |
+
"Event Info": iface_event_info,
|
74 |
+
"Season Calendar": iface_season_calendar,
|
75 |
+
"Track Visualizations": iface_track_visualization
|
76 |
}
|
77 |
|
78 |
+
# Tab names and interfaces
|
79 |
+
tab_names = list(named_interfaces.keys())
|
80 |
+
interface_list = list(named_interfaces.values())
|
81 |
|
82 |
|
83 |
# Combine all the interfaces into a single TabbedInterface
|
tools.py
CHANGED
@@ -6,34 +6,27 @@ Tools to implement
|
|
6 |
- driver info
|
7 |
- championship standings
|
8 |
- driver standings
|
|
|
9 |
- compare drivers
|
10 |
|
11 |
"""
|
12 |
|
13 |
-
|
14 |
-
## Here we implement the MCP tools
|
15 |
import fastf1
|
16 |
-
from
|
17 |
-
|
18 |
-
from fastf1.core import Session
|
19 |
from typing import Union
|
|
|
20 |
|
|
|
21 |
from utils import parser_utils, track_utils
|
22 |
-
from
|
23 |
|
24 |
# Custom types
|
25 |
gp = Union[str, int]
|
26 |
session_type = Union[str, int, None]
|
27 |
|
28 |
-
def get_season_calendar(year: int) -> str:
|
29 |
-
""" Returns the season calendar for the given year """
|
30 |
-
season_calendar = fastf1.get_event_schedule(year)
|
31 |
-
return parser_utils.parse_season_calendar(season_calendar)
|
32 |
-
|
33 |
def get_session(year: int, round: gp, session_type: session_type) -> Session:
|
34 |
-
"""
|
35 |
-
Returns a session specified by year, round and session type
|
36 |
-
"""
|
37 |
|
38 |
# Check if session type is valid
|
39 |
if isinstance(session_type, str):
|
@@ -42,6 +35,11 @@ def get_session(year: int, round: gp, session_type: session_type) -> Session:
|
|
42 |
|
43 |
return fastf1.get_session(year, round, session_type)
|
44 |
|
|
|
|
|
|
|
|
|
|
|
45 |
def get_event_info(year: int, round: gp, format: str) -> str:
|
46 |
""" Returns the event info for the specified session """
|
47 |
|
@@ -57,24 +55,27 @@ def get_event_info(year: int, round: gp, format: str) -> str:
|
|
57 |
def get_constructor_standings(year: int) -> str:
|
58 |
pass
|
59 |
|
60 |
-
def
|
61 |
pass
|
62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
-
def driver_position(driver_name: str) -> str:
|
65 |
-
"""
|
66 |
-
Get the current position of the given driver.
|
67 |
-
|
68 |
-
Args:
|
69 |
-
driver_name (str): The driver's name
|
70 |
-
|
71 |
-
Returns:
|
72 |
-
str: The driver's current position
|
73 |
-
"""
|
74 |
-
return f"Driver {driver_name} is in position {random.randint(1, 20)}"
|
75 |
|
76 |
-
def driver_championship_score(year: int, driver_name: str) -> str:
|
77 |
-
pass
|
78 |
|
79 |
def track_visualization(year: int, round: gp, visualization_type: str, driver_name: str) -> Image:
|
80 |
|
|
|
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
|
19 |
|
20 |
+
# Local modules
|
21 |
from utils import parser_utils, track_utils
|
22 |
+
from utils.constants import AVAILABLE_SESSION_TYPES
|
23 |
|
24 |
# Custom types
|
25 |
gp = Union[str, int]
|
26 |
session_type = Union[str, int, None]
|
27 |
|
|
|
|
|
|
|
|
|
|
|
28 |
def get_session(year: int, round: gp, session_type: session_type) -> Session:
|
29 |
+
""" Returns a session specified by year, round and session type """
|
|
|
|
|
30 |
|
31 |
# Check if session type is valid
|
32 |
if isinstance(session_type, str):
|
|
|
35 |
|
36 |
return fastf1.get_session(year, round, session_type)
|
37 |
|
38 |
+
def get_season_calendar(year: int) -> str:
|
39 |
+
""" Returns the season calendar for the given year """
|
40 |
+
season_calendar = fastf1.get_event_schedule(year)
|
41 |
+
return parser_utils.parse_season_calendar(season_calendar)
|
42 |
+
|
43 |
def get_event_info(year: int, round: gp, format: str) -> str:
|
44 |
""" Returns the event info for the specified session """
|
45 |
|
|
|
55 |
def get_constructor_standings(year: int) -> str:
|
56 |
pass
|
57 |
|
58 |
+
def get_driver_standings(year: int) -> str:
|
59 |
pass
|
60 |
|
61 |
+
def driver_championship_standings(year: int, driver_name: str) -> str:
|
62 |
+
|
63 |
+
with open("assets/driver_abbreviations.json") as f:
|
64 |
+
driver_abbreviations = json.load(f)
|
65 |
+
driver_abbreviation = driver_abbreviations[driver_name]
|
66 |
+
ergast = fastf1.ergast.Ergast()
|
67 |
+
driver_standings = ergast.get_driver_standings(year).content[0]
|
68 |
+
driver_standing = driver_standings[["position", "points", "wins", "driverCode"]].reset_index(drop=True)
|
69 |
+
driver_standing = driver_standing[driver_standing["driverCode"] == driver_abbreviation]
|
70 |
+
suffix = "st" if driver_standing['position'].iloc[0] == 1 else "nd" if driver_standing['position'].iloc[0] == 2 else "rd" if driver_standing['position'].iloc[0] == 3 else "th"
|
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 |
+
pass
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
|
|
|
|
79 |
|
80 |
def track_visualization(year: int, round: gp, visualization_type: str, driver_name: str) -> Image:
|
81 |
|