Spaces:
Sleeping
Sleeping
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
|