added constructors standings and tidied up the UI for driver standings
Browse files- api_playground.ipynb +201 -0
- app.py +18 -19
- tools.py +22 -1
- utils/constants.py +14 -1
api_playground.ipynb
CHANGED
@@ -385,6 +385,207 @@
|
|
385 |
"driver_standings.head(2)"
|
386 |
]
|
387 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
388 |
{
|
389 |
"cell_type": "code",
|
390 |
"execution_count": 2,
|
|
|
385 |
"driver_standings.head(2)"
|
386 |
]
|
387 |
},
|
388 |
+
{
|
389 |
+
"cell_type": "code",
|
390 |
+
"execution_count": 33,
|
391 |
+
"id": "feeb4592",
|
392 |
+
"metadata": {},
|
393 |
+
"outputs": [
|
394 |
+
{
|
395 |
+
"data": {
|
396 |
+
"text/html": [
|
397 |
+
"<div>\n",
|
398 |
+
"<style scoped>\n",
|
399 |
+
" .dataframe tbody tr th:only-of-type {\n",
|
400 |
+
" vertical-align: middle;\n",
|
401 |
+
" }\n",
|
402 |
+
"\n",
|
403 |
+
" .dataframe tbody tr th {\n",
|
404 |
+
" vertical-align: top;\n",
|
405 |
+
" }\n",
|
406 |
+
"\n",
|
407 |
+
" .dataframe thead th {\n",
|
408 |
+
" text-align: right;\n",
|
409 |
+
" }\n",
|
410 |
+
"</style>\n",
|
411 |
+
"<table border=\"1\" class=\"dataframe\">\n",
|
412 |
+
" <thead>\n",
|
413 |
+
" <tr style=\"text-align: right;\">\n",
|
414 |
+
" <th></th>\n",
|
415 |
+
" <th>position</th>\n",
|
416 |
+
" <th>positionText</th>\n",
|
417 |
+
" <th>points</th>\n",
|
418 |
+
" <th>wins</th>\n",
|
419 |
+
" <th>constructorId</th>\n",
|
420 |
+
" <th>constructorUrl</th>\n",
|
421 |
+
" <th>constructorName</th>\n",
|
422 |
+
" <th>constructorNationality</th>\n",
|
423 |
+
" </tr>\n",
|
424 |
+
" </thead>\n",
|
425 |
+
" <tbody>\n",
|
426 |
+
" <tr>\n",
|
427 |
+
" <th>0</th>\n",
|
428 |
+
" <td>1</td>\n",
|
429 |
+
" <td>1</td>\n",
|
430 |
+
" <td>362.0</td>\n",
|
431 |
+
" <td>7</td>\n",
|
432 |
+
" <td>mclaren</td>\n",
|
433 |
+
" <td>http://en.wikipedia.org/wiki/McLaren</td>\n",
|
434 |
+
" <td>McLaren</td>\n",
|
435 |
+
" <td>British</td>\n",
|
436 |
+
" </tr>\n",
|
437 |
+
" <tr>\n",
|
438 |
+
" <th>1</th>\n",
|
439 |
+
" <td>2</td>\n",
|
440 |
+
" <td>2</td>\n",
|
441 |
+
" <td>165.0</td>\n",
|
442 |
+
" <td>0</td>\n",
|
443 |
+
" <td>ferrari</td>\n",
|
444 |
+
" <td>http://en.wikipedia.org/wiki/Scuderia_Ferrari</td>\n",
|
445 |
+
" <td>Ferrari</td>\n",
|
446 |
+
" <td>Italian</td>\n",
|
447 |
+
" </tr>\n",
|
448 |
+
" <tr>\n",
|
449 |
+
" <th>2</th>\n",
|
450 |
+
" <td>3</td>\n",
|
451 |
+
" <td>3</td>\n",
|
452 |
+
" <td>159.0</td>\n",
|
453 |
+
" <td>0</td>\n",
|
454 |
+
" <td>mercedes</td>\n",
|
455 |
+
" <td>http://en.wikipedia.org/wiki/Mercedes-Benz_in_...</td>\n",
|
456 |
+
" <td>Mercedes</td>\n",
|
457 |
+
" <td>German</td>\n",
|
458 |
+
" </tr>\n",
|
459 |
+
" <tr>\n",
|
460 |
+
" <th>3</th>\n",
|
461 |
+
" <td>4</td>\n",
|
462 |
+
" <td>4</td>\n",
|
463 |
+
" <td>144.0</td>\n",
|
464 |
+
" <td>2</td>\n",
|
465 |
+
" <td>red_bull</td>\n",
|
466 |
+
" <td>http://en.wikipedia.org/wiki/Red_Bull_Racing</td>\n",
|
467 |
+
" <td>Red Bull</td>\n",
|
468 |
+
" <td>Austrian</td>\n",
|
469 |
+
" </tr>\n",
|
470 |
+
" <tr>\n",
|
471 |
+
" <th>4</th>\n",
|
472 |
+
" <td>5</td>\n",
|
473 |
+
" <td>5</td>\n",
|
474 |
+
" <td>54.0</td>\n",
|
475 |
+
" <td>0</td>\n",
|
476 |
+
" <td>williams</td>\n",
|
477 |
+
" <td>http://en.wikipedia.org/wiki/Williams_Grand_Pr...</td>\n",
|
478 |
+
" <td>Williams</td>\n",
|
479 |
+
" <td>British</td>\n",
|
480 |
+
" </tr>\n",
|
481 |
+
" <tr>\n",
|
482 |
+
" <th>5</th>\n",
|
483 |
+
" <td>6</td>\n",
|
484 |
+
" <td>6</td>\n",
|
485 |
+
" <td>28.0</td>\n",
|
486 |
+
" <td>0</td>\n",
|
487 |
+
" <td>rb</td>\n",
|
488 |
+
" <td>http://en.wikipedia.org/wiki/RB_Formula_One_Team</td>\n",
|
489 |
+
" <td>RB F1 Team</td>\n",
|
490 |
+
" <td>Italian</td>\n",
|
491 |
+
" </tr>\n",
|
492 |
+
" <tr>\n",
|
493 |
+
" <th>6</th>\n",
|
494 |
+
" <td>7</td>\n",
|
495 |
+
" <td>7</td>\n",
|
496 |
+
" <td>26.0</td>\n",
|
497 |
+
" <td>0</td>\n",
|
498 |
+
" <td>haas</td>\n",
|
499 |
+
" <td>http://en.wikipedia.org/wiki/Haas_F1_Team</td>\n",
|
500 |
+
" <td>Haas F1 Team</td>\n",
|
501 |
+
" <td>American</td>\n",
|
502 |
+
" </tr>\n",
|
503 |
+
" <tr>\n",
|
504 |
+
" <th>7</th>\n",
|
505 |
+
" <td>8</td>\n",
|
506 |
+
" <td>8</td>\n",
|
507 |
+
" <td>16.0</td>\n",
|
508 |
+
" <td>0</td>\n",
|
509 |
+
" <td>sauber</td>\n",
|
510 |
+
" <td>http://en.wikipedia.org/wiki/Sauber_Motorsport</td>\n",
|
511 |
+
" <td>Sauber</td>\n",
|
512 |
+
" <td>Swiss</td>\n",
|
513 |
+
" </tr>\n",
|
514 |
+
" <tr>\n",
|
515 |
+
" <th>8</th>\n",
|
516 |
+
" <td>9</td>\n",
|
517 |
+
" <td>9</td>\n",
|
518 |
+
" <td>16.0</td>\n",
|
519 |
+
" <td>0</td>\n",
|
520 |
+
" <td>aston_martin</td>\n",
|
521 |
+
" <td>http://en.wikipedia.org/wiki/Aston_Martin_in_F...</td>\n",
|
522 |
+
" <td>Aston Martin</td>\n",
|
523 |
+
" <td>British</td>\n",
|
524 |
+
" </tr>\n",
|
525 |
+
" <tr>\n",
|
526 |
+
" <th>9</th>\n",
|
527 |
+
" <td>10</td>\n",
|
528 |
+
" <td>10</td>\n",
|
529 |
+
" <td>11.0</td>\n",
|
530 |
+
" <td>0</td>\n",
|
531 |
+
" <td>alpine</td>\n",
|
532 |
+
" <td>http://en.wikipedia.org/wiki/Alpine_F1_Team</td>\n",
|
533 |
+
" <td>Alpine F1 Team</td>\n",
|
534 |
+
" <td>French</td>\n",
|
535 |
+
" </tr>\n",
|
536 |
+
" </tbody>\n",
|
537 |
+
"</table>\n",
|
538 |
+
"</div>"
|
539 |
+
],
|
540 |
+
"text/plain": [
|
541 |
+
" position positionText points wins constructorId \\\n",
|
542 |
+
"0 1 1 362.0 7 mclaren \n",
|
543 |
+
"1 2 2 165.0 0 ferrari \n",
|
544 |
+
"2 3 3 159.0 0 mercedes \n",
|
545 |
+
"3 4 4 144.0 2 red_bull \n",
|
546 |
+
"4 5 5 54.0 0 williams \n",
|
547 |
+
"5 6 6 28.0 0 rb \n",
|
548 |
+
"6 7 7 26.0 0 haas \n",
|
549 |
+
"7 8 8 16.0 0 sauber \n",
|
550 |
+
"8 9 9 16.0 0 aston_martin \n",
|
551 |
+
"9 10 10 11.0 0 alpine \n",
|
552 |
+
"\n",
|
553 |
+
" constructorUrl constructorName \\\n",
|
554 |
+
"0 http://en.wikipedia.org/wiki/McLaren McLaren \n",
|
555 |
+
"1 http://en.wikipedia.org/wiki/Scuderia_Ferrari Ferrari \n",
|
556 |
+
"2 http://en.wikipedia.org/wiki/Mercedes-Benz_in_... Mercedes \n",
|
557 |
+
"3 http://en.wikipedia.org/wiki/Red_Bull_Racing Red Bull \n",
|
558 |
+
"4 http://en.wikipedia.org/wiki/Williams_Grand_Pr... Williams \n",
|
559 |
+
"5 http://en.wikipedia.org/wiki/RB_Formula_One_Team RB F1 Team \n",
|
560 |
+
"6 http://en.wikipedia.org/wiki/Haas_F1_Team Haas F1 Team \n",
|
561 |
+
"7 http://en.wikipedia.org/wiki/Sauber_Motorsport Sauber \n",
|
562 |
+
"8 http://en.wikipedia.org/wiki/Aston_Martin_in_F... Aston Martin \n",
|
563 |
+
"9 http://en.wikipedia.org/wiki/Alpine_F1_Team Alpine F1 Team \n",
|
564 |
+
"\n",
|
565 |
+
" constructorNationality \n",
|
566 |
+
"0 British \n",
|
567 |
+
"1 Italian \n",
|
568 |
+
"2 German \n",
|
569 |
+
"3 Austrian \n",
|
570 |
+
"4 British \n",
|
571 |
+
"5 Italian \n",
|
572 |
+
"6 American \n",
|
573 |
+
"7 Swiss \n",
|
574 |
+
"8 British \n",
|
575 |
+
"9 French "
|
576 |
+
]
|
577 |
+
},
|
578 |
+
"execution_count": 33,
|
579 |
+
"metadata": {},
|
580 |
+
"output_type": "execute_result"
|
581 |
+
}
|
582 |
+
],
|
583 |
+
"source": [
|
584 |
+
"ergastandings = fastf1.ergast.Ergast()\n",
|
585 |
+
"constructor_standings = ergastandings.get_constructor_standings(2025).content[0]\n",
|
586 |
+
"constructor_standings.head(10)"
|
587 |
+
]
|
588 |
+
},
|
589 |
{
|
590 |
"cell_type": "code",
|
591 |
"execution_count": 2,
|
app.py
CHANGED
@@ -1,35 +1,33 @@
|
|
1 |
-
import json
|
2 |
-
import random
|
3 |
-
import datetime
|
4 |
import gradio as gr
|
5 |
|
6 |
# Local modules
|
7 |
import tools
|
8 |
from utils.constants import (
|
9 |
-
|
10 |
-
|
|
|
11 |
)
|
12 |
|
13 |
-
# Variables
|
14 |
-
CURRENT_YEAR = datetime.datetime.now().year
|
15 |
-
|
16 |
-
|
17 |
-
# Load in driver names
|
18 |
-
with open("assets/driver_names.json") as f:
|
19 |
-
driver_names = json.load(f)["drivers"]
|
20 |
-
with open("assets/constructor_details.json") as f:
|
21 |
-
constructor_names = [constructor["constructor"] for constructor in json.load(f)["constructors"]]
|
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(
|
29 |
],
|
30 |
outputs="text",
|
31 |
title="Driver Championship Standings",
|
32 |
-
description="Get the championship standings
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
)
|
34 |
|
35 |
iface_event_info = gr.Interface(
|
@@ -60,7 +58,7 @@ iface_track_visualization = gr.Interface(
|
|
60 |
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
61 |
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported)"),
|
62 |
gr.Radio(["speed", "corners", "gear"], label="Visualization type", value="speed"),
|
63 |
-
gr.Dropdown(
|
64 |
],
|
65 |
outputs="image",
|
66 |
title="Track Visualizations",
|
@@ -70,6 +68,7 @@ iface_track_visualization = gr.Interface(
|
|
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
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
|
3 |
# Local modules
|
4 |
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(
|
12 |
fn=tools.driver_championship_standings,
|
13 |
inputs=[
|
14 |
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
15 |
+
gr.Dropdown(label="Driver", choices=DRIVER_NAMES)
|
16 |
],
|
17 |
outputs="text",
|
18 |
title="Driver Championship Standings",
|
19 |
+
description="Get the driver championship standings"
|
20 |
+
)
|
21 |
+
|
22 |
+
iface_constructor_championship_standings = gr.Interface(
|
23 |
+
fn=tools.constructor_championship_standings,
|
24 |
+
inputs=[
|
25 |
+
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
26 |
+
gr.Dropdown(label="Constructor", choices=CONSTRUCTOR_NAMES)
|
27 |
+
],
|
28 |
+
outputs="text",
|
29 |
+
title="Constructor Championship Standings",
|
30 |
+
description="Get the constructor championship standings"
|
31 |
)
|
32 |
|
33 |
iface_event_info = gr.Interface(
|
|
|
58 |
gr.Number(label="Calendar year", value=CURRENT_YEAR, minimum=1950, maximum=CURRENT_YEAR),
|
59 |
gr.Textbox(label="Grand Prix", placeholder="Ex: Monaco", info="The name of the GP/country/location (Fuzzy matching supported)"),
|
60 |
gr.Radio(["speed", "corners", "gear"], label="Visualization type", value="speed"),
|
61 |
+
gr.Dropdown(DRIVER_NAMES)
|
62 |
],
|
63 |
outputs="image",
|
64 |
title="Track Visualizations",
|
|
|
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
|
tools.py
CHANGED
@@ -73,7 +73,28 @@ def driver_championship_standings(year: int, driver_name: str) -> str:
|
|
73 |
|
74 |
|
75 |
def constructor_championship_standings(year: int, constructor_name: str) -> str:
|
76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
|
79 |
|
|
|
73 |
|
74 |
|
75 |
def constructor_championship_standings(year: int, constructor_name: str) -> str:
|
76 |
+
|
77 |
+
team_mapping = {
|
78 |
+
"McLaren": "McLaren",
|
79 |
+
"Ferrari": "Ferrari",
|
80 |
+
"Red Bull Racing": "Red Bull",
|
81 |
+
"Mercedes": "Mercedes",
|
82 |
+
"Aston Martin": "Aston Martin",
|
83 |
+
"Alpine": "Alpine F1 Team",
|
84 |
+
"Haas": "Haas F1 Team",
|
85 |
+
"Racing Bulls": "RB F1 Team",
|
86 |
+
"Williams": "Williams",
|
87 |
+
"Kick Sauber": "Sauber"
|
88 |
+
}
|
89 |
+
|
90 |
+
ergast = fastf1.ergast.Ergast()
|
91 |
+
constructor_standings = ergast.get_constructor_standings(year).content[0]
|
92 |
+
constructor_standing = constructor_standings[["position", "points", "wins", "constructorName"]].reset_index(drop=True)
|
93 |
+
mapped_name = team_mapping[constructor_name]
|
94 |
+
constructor_standing = constructor_standing[constructor_standing["constructorName"] == mapped_name]
|
95 |
+
suffix = "st" if constructor_standing['position'].iloc[0] == 1 else "nd" if constructor_standing['position'].iloc[0] == 2 else "rd" if constructor_standing['position'].iloc[0] == 3 else "th"
|
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 |
|
utils/constants.py
CHANGED
@@ -1,3 +1,5 @@
|
|
|
|
|
|
1 |
|
2 |
AVAILABLE_SESSION_TYPES = [
|
3 |
"fp1", "fp2", "fp3", "q", "s", "ss", "sq", "r",
|
@@ -8,4 +10,15 @@ AVAILABLE_SESSION_TYPES = [
|
|
8 |
DROPDOWN_SESSION_TYPES = [
|
9 |
"practice 1", "practice 2", "practice 3", "sprint",
|
10 |
"sprint shootout", "sprint qualifying", "qualifying", "race"
|
11 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import datetime
|
3 |
|
4 |
AVAILABLE_SESSION_TYPES = [
|
5 |
"fp1", "fp2", "fp3", "q", "s", "ss", "sq", "r",
|
|
|
10 |
DROPDOWN_SESSION_TYPES = [
|
11 |
"practice 1", "practice 2", "practice 3", "sprint",
|
12 |
"sprint shootout", "sprint qualifying", "qualifying", "race"
|
13 |
+
]
|
14 |
+
|
15 |
+
# Load in driver names
|
16 |
+
with open("assets/driver_names.json") as f:
|
17 |
+
DRIVER_NAMES: list[str] = json.load(f)["drivers"]
|
18 |
+
|
19 |
+
# Load in constructor names
|
20 |
+
with open("assets/constructors.json") as f:
|
21 |
+
CONSTRUCTOR_NAMES: list[str] = json.load(f)["constructors"]
|
22 |
+
|
23 |
+
# Variables
|
24 |
+
CURRENT_YEAR = datetime.datetime.now().year
|