Files
f1-circuits/grand-prix.py
T

338 lines
15 KiB
Python

import requests
import json
import time
import os
# Please convert this list into a dictionary of country -> locality/city -> Circuit name -> layouts (some circuits have multiple layouts)
# it should be available_circuits = { "Argentina": { "Buenos Aires": { "Autódromo Juan y Oscar Gálvez": {1953: "Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1953-1960.geo.json", 1954: "Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1953-1960.geo.json", ...} } } }
available_circuits = [
"Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1953-1960.geo.json",
"France - Rouen - Circuit de Rouen-Les-Essarts - 1957-1968.geo.json",
"Singapore - Singapore - Marina Bay Street Circuit - 2008-.geo.json",
"Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1971-1973.geo.json",
"Germany - Berlin - AVUS - 1921-1959.geo.json",
"South Africa - East London - Prince George Circuit - 1934-1967.geo.json",
"Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1974-1981.geo.json",
"Germany - Hockenheim - Hockenheimring - 1932-.geo.json",
"South Africa - Kyalami - Kyalami Grand Prix Circuit - 1961-1985.geo.json",
"Argentina - Buenos Aires - Autódromo Juan y Oscar Gálvez - 1995-1998.geo.json",
"Germany - Nürburg - Nürburgring - 1927-.geo.json",
"South Africa - Kyalami - Kyalami Grand Prix Circuit - 1992-1993.geo.json",
"Australia - Adelaide - Adelaide Street Circuit - 1985-1995.geo.json",
"Great Britain - Aintree - Aintree Circuit - 1954-1962.geo.json",
"Spain - Barcelona - Circuit de Barcelona-Catalunya - 1991-.geo.json",
"Australia - Melbourne - Albert Park Circuit - 1953-.geo.json",
"Great Britain - Brands Hatch - Brands Hatch Circuit - 1964-1974.geo.json",
"Spain - Jarama - Circuito del Jarama - 1967-1981.geo.json",
"Austria - Spielberg - A1 Ring - 1997-2003.geo.json",
"Great Britain - Brands Hatch - Brands Hatch Circuit - 1976-1987.geo.json",
"Spain - Jerez - Circuito de Jerez - 1985-1991.geo.json",
"Austria - Spielberg - Österreichring - 1969-1976.geo.json",
"Great Britain - Silverstone - Silverstone Circuit - 1948-.geo.json",
"Spain - Jerez - Circuito de Jerez - 1994-.geo.json",
"Austria - Spielberg - Österreichring - 1977-1987.geo.json",
"Hungary - Budapest - Hungaroring - 1986-.geo.json",
"Spain - Montjuïc - Montjuïc Circuit - 1969-1975.geo.json",
"Austria - Spielberg - Red Bull Ring - 2014-.geo.json",
"Italy - Imola - Autodromo Enzo e Dino Ferrari - 1953-.geo.json",
"Spain - Pedralbes - Pedralbes Circuit - 1946-1954.geo.json",
"Austria - Zeltweg - Österreichring - 1963-1968.geo.json",
"Italy - Monza - Autodromo Nazionale Monza - 1922-.geo.json",
"Spain - Valencia - Valencia Street Circuit - 2008-2012.geo.json",
"Azerbaijan - Baku - Baku City Circuit - 2016-.geo.json",
"Italy - Pescara - Pescara Circuit - 1924-1957.geo.json",
"Sweden - Anderstorp - Scandinavian Raceway - 1968-1977.geo.json",
"Bahrain - Sakhir - Bahrain International Circuit - 2002-.geo.json",
"Italy - Scarperia e San Piero - Autodromo Internazionale del Mugello - 1914-.geo.json",
"Sweden - Anderstorp - Scandinavian Raceway - 1978-1997.geo.json",
"Bahrain - Sakhir - Bahrain International Circuit - 2010.geo.json",
"Japan - Aida - TI Circuit Aida - 1990-1997.geo.json",
"Switzerland - Bern - Circuit Bremgarten - 1934-1954.geo.json",
"Belgium - Nivelles - Circuit Nivelles-Baulers - 1971-1974.geo.json",
"Japan - Fuji - Fuji Speedway - 1976-1977.geo.json",
"Turkey - Istanbul - Intercity Istanbul Park - 2005-.geo.json",
"Belgium - Spa Francorchamps - Circuit de Spa-Francorchamps - 1950-1978.geo.json",
"Japan - Fuji - Fuji Speedway - 2007-.geo.json",
"United Arab Emirates - Yas Marina - Yas Marina Circuit - 2009-.geo.json",
"Belgium - Spa Francorchamps - Circuit de Spa-Francorchamps - 1983-.geo.json",
"Japan - Suzuka - Suzuka International Racing Course - 1962-.geo.json",
"USA - Austin - Circuit of the Americas - 2012-.geo.json",
"Belgium - Zolder - Circuit Zolder - 1963-.geo.json",
"Malaysia - Sepang - Sepang International Circuit - 1999-.geo.json",
"USA - Dallas - Fair Park - 1984.geo.json",
"Brazil - Jacarepaguá - Autódromo Internacional Nelson Piquet - 1977-.geo.json",
"Mexico - Magdalena Mixhuca - Autódromo Magdalena Mixhuca - 1959-1970.geo.json",
"USA - Detroit - Detroit Street Circuit - 1982-1988.geo.json",
"Brazil - Sao Paulo - Autódromo José Carlos Pace - Interlagos - 1940-.geo.json",
"Mexico - Mexico City - Autódromo Hermanos Rodríguez - 1962-.geo.json",
"USA - Indianapolis - Indianapolis Motor Speedway - 1909-.geo.json",
"Canada - Montreal - Circuit Gilles-Villeneuve - 1978-.geo.json",
"Monaco - Monaco - Circuit de Monaco - 1929-.geo.json",
"USA - Las Vegas - Las Vegas Street Circuit - 2023-.geo.json",
"Canada - Mont-Tremblant - Circuit Mont-Tremblant - 1964-1970.geo.json",
"Morocco - Casablanca - Ain-Diab Circuit - 1957-1958.geo.json",
"USA - Long Beach - Long Beach Grand Prix Circuit - 1976-1981.geo.json",
"Canada - Mosport - Mosport Park - 1961-1977.geo.json",
"Netherlands - Zandvoort - Circuit Zandvoort - 1948-1971.geo.json",
"USA - Long Beach - Long Beach Grand Prix Circuit - 1982.geo.json",
"China - Shanghai - Shanghai International Circuit - 2004-.geo.json",
"Netherlands - Zandvoort - Circuit Zandvoort - 1972-1985.geo.json",
"USA - Long Beach - Long Beach Grand Prix Circuit - 1983.geo.json",
"France - Clermont-Ferrand - Circuit de Charade - 1958-1988.geo.json",
"Netherlands - Zandvoort - Circuit Zandvoort - 2021-.geo.json",
"USA - Miami - Miami International Autodrome - 2022-.geo.json",
"France - Dijon-Prenois - Circuit de Dijon-Prenois - 1972-1984.geo.json",
"Portugal - Estoril - Autódromo do Estoril - 1972-.geo.json",
"USA - Phoenix - Phoenix Street Circuit - 1989-1990.geo.json",
"France - Le Castellet - Circuit Paul Ricard - 1969-.geo.json",
"Portugal - Monsanto - Monsanto Park Circuit - 1954-1959.geo.json",
"USA - Phoenix - Phoenix Street Circuit - 1991.geo.json",
"France - Le Mans - Circuit de la Sarthe - 1923-1966.geo.json",
"Portugal - Oporto - Circuito da Boavista - 1958-1960.geo.json",
"USA - Riverside - Riverside International Raceway - 1960.geo.json",
"France - Magny-Cours - Circuit de Nevers Magny-Cours - 1960-.geo.json",
"Portugal - Portimão - Autódromo Internacional do Algarve - 2008-.geo.json",
"USA - Sebring - Sebring International Raceway - 1959.geo.json",
"France - Reims - Circuit de Reims-Gueux - 1926-1951.geo.json",
"Qatar - Lusail - Losail International Circuit - 2004-.geo.json",
"USA - Watkins Glen - Watkins Glen International - 1948-1980.geo.json",
"France - Reims - Circuit de Reims-Gueux - 1952-.geo.json",
"Russia - Sochi - Sochi Autodrom - 2014-.geo.json",
"France - Rouen - Circuit de Rouen-Les-Essarts - 1952.geo.json",
"Saudi Arabia - Jeddah - Jeddah Corniche Circuit - 2021-.geo.json"
]
def fetch_all_grand_prix_data():
"""
Fetches all Formula 1 Grand Prix data from the Ergast API across multiple pages
and returns the races.
"""
base_url = "https://ergast.com/api/f1.json"
limit = 100 # Maximum number of results per page
offset = 0
all_races = []
total_races = None
print("Fetching Grand Prix data from Ergast API...")
while True:
# Construct URL with pagination parameters
url = f"{base_url}?limit={limit}&offset={offset}"
print(f"Fetching data from offset {offset}...")
# Add a small delay to avoid hitting rate limits
time.sleep(0.5)
# Make the request
response = requests.get(url)
# Check if request was successful
if response.status_code != 200:
print(f"Error fetching data: HTTP {response.status_code}")
print(response.text)
break
# Parse the JSON response
data = response.json()
# Get total number of races if not already set
if total_races is None:
total_races = int(data['MRData']['total'])
print(f"Total races to fetch: {total_races}")
# Extract the races from this page
races = data['MRData']['RaceTable'].get('Races', [])
all_races.extend(races)
# Update the offset for the next page
offset += limit
# Check if we've fetched all data
if offset >= total_races:
break
print(f"Successfully fetched {len(all_races)} races.")
return all_races
def get_circuit_file_mapping():
"""
Creates a mapping of circuit information to corresponding circuit GeoJSON files.
"""
circuit_mapping = {}
# Get circuit files from the circuits directory
circuits_dir = "circuits"
if os.path.exists(circuits_dir):
circuit_files = [f for f in os.listdir(circuits_dir) if f.endswith('.geo.json')]
for file_name in circuit_files:
file_path = os.path.join(circuits_dir, file_name)
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
if 'features' in data and len(data['features']) > 0:
feature = data['features'][0]
if 'properties' in feature:
props = feature['properties']
if 'id' in props and 'Name' in props and 'Location' in props and 'seasons' in props:
circuit_id = props['id']
circuit_name = props['Name']
location = props['Location']
seasons = props['seasons']
# Create a key for each season this circuit was used
for season in seasons:
key = (circuit_name, location, season)
circuit_mapping[key] = file_name
except Exception as e:
print(f"Error processing circuit file {file_name}: {e}")
return circuit_mapping
def create_grand_prix_data(races, circuit_mapping):
"""
Create a dictionary of grand prix organized by name and season.
Format:
{
"Belgian Grand Prix": {
"1953": {
"circuit": "belgium-circuit.geo.json",
"date": "1953-06-22"
}
}
}
"""
grand_prix_data = {}
for race in races:
race_name = race.get('raceName', 'Unknown Grand Prix')
season = race.get('season', 'Unknown')
# Create the GP entry if it doesn't exist
if race_name not in grand_prix_data:
grand_prix_data[race_name] = {}
# Extract circuit info
circuit = race.get('Circuit', {})
circuit_name = circuit.get('circuitName', 'Unknown Circuit')
location = circuit.get('Location', {})
locality = location.get('locality', 'Unknown')
# Create season entry
season_entry = {
"date": race.get('date', ''),
"circuit_name": circuit_name,
"location": locality,
"country": location.get('country', 'Unknown'),
"round": race.get('round', '')
}
# Try to match with a circuit file
circuit_key = (circuit_name, locality, int(season))
if circuit_key in circuit_mapping:
season_entry["circuit"] = circuit_mapping[circuit_key]
else:
# Try to find a close match
for (name, loc, year), file_name in circuit_mapping.items():
if name == circuit_name and loc == locality:
season_entry["circuit"] = file_name
break
# Add to the grand prix data
grand_prix_data[race_name][season] = season_entry
return grand_prix_data
def create_seasons_data(races):
"""
Create a dictionary of races organized by season and round.
Format:
{
"1950": {
"1": {
"name": "British Grand Prix",
"date": "1950-05-13",
"circuit": {...}
}
}
}
"""
seasons_data = {}
for race in races:
season = race.get('season', 'Unknown')
round_num = race.get('round', 'Unknown')
# Create the season entry if it doesn't exist
if season not in seasons_data:
seasons_data[season] = {}
# Extract essential race information
race_name = race.get('raceName', 'Unknown Grand Prix')
circuit = race.get('Circuit', {})
location = circuit.get('Location', {})
# Create race entry
race_entry = {
"name": race_name,
"date": race.get('date', ''),
"time": race.get('time', ''),
"url": race.get('url', ''),
"circuit": {
"name": circuit.get('circuitName', 'Unknown Circuit'),
"url": circuit.get('url', ''),
"location": {
"lat": location.get('lat', ''),
"long": location.get('long', ''),
"locality": location.get('locality', ''),
"country": location.get('country', '')
}
}
}
# Add race results and other data if available
if 'Results' in race:
race_entry['results'] = race['Results']
if 'Qualifying' in race:
race_entry['qualifying'] = race['Qualifying']
if 'Sprint' in race:
race_entry['sprint'] = race['Sprint']
# Add to the seasons data
seasons_data[season][round_num] = race_entry
return seasons_data
def main():
# Fetch all race data
all_races = fetch_all_grand_prix_data()
# Get circuit file mapping
circuit_mapping = get_circuit_file_mapping()
print(f"Found {len(circuit_mapping)} circuit mappings")
# Create grand prix data
grand_prix_data = create_grand_prix_data(all_races, circuit_mapping)
print(f"Created grand prix data with {len(grand_prix_data)} entries")
# Create seasons data
seasons_data = create_seasons_data(all_races)
print(f"Created seasons data with {len(seasons_data)} seasons")
# Save to files
with open('grand_prix.json', 'w', encoding='utf-8') as f:
json.dump(grand_prix_data, f, indent=2, ensure_ascii=False)
print("Saved grand_prix.json")
with open('seasons.json', 'w', encoding='utf-8') as f:
json.dump(seasons_data, f, indent=2, ensure_ascii=False)
print("Saved seasons.json")
if __name__ == "__main__":
main()