|
- 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()
|