# -*- coding: utf-8 -*-
"""AUS Grand Prix.ipynb

Automatically generated by Colab.

Original file is located at
    https://colab.research.google.com/drive/1gWbKlaYRze6-MRRD3zQLRoxJIdWGQ83-
"""

pip install fastf1

#imports required
import os
import fastf1
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.metrics import mean_absolute_error

# Define cache directory
cache_dir = "/content/f1_cache"

# Create the directory
if not os.path.exists(cache_dir):
    os.makedirs(cache_dir)

# Enable FastF1 caching
import fastf1
fastf1.Cache.enable_cache(cache_dir)

print("Cache enabled at:", cache_dir)

#Load Fast F1 2024 AUS GP race session
session_2024 = fastf1.get_session(2024, 3, 'R')
session_2024.load()

#Extract lap times
laps_2024 = session_2024.laps[["Driver","LapTime"]].copy()
laps_2024.dropna(subset=["LapTime"], inplace=True)
laps_2024["LapTime (s)"] = laps_2024["LapTime"].dt.total_seconds()
laps_2024.head()

# 2025 Qualifying data
qualifying_2025 = pd.DataFrame({
    "Driver":[
        "Lando Norris", "Oscar Piastri", "Max Verstappen", "George Russel",
        "Yuki Tsunado", "Alexander Albon", "Charles Leclerc", "Lewis Hamilton",
        "Pierre Gasly", "Carlos Sainz", "Lance Stroll", "Fernando Alonso"],
    "QualifyingTime (s)":[
        75.096, 75.103 ,75.481, 75.546, 75.670,
        75.737, 75.753 ,75.973, 75.980, 76.662,76.4, 76.51
    ]
})
qualifying_2025.head(12)

# map full names to fastF1 3-letter code
drive_mapping = {
    "Lando Norris": "NOR", "Oscar Piastri":"PIA", "Max Verstappen":"VER", "George Russel":"RUS",
    "Yuki Tsunado":"TSU", "Alexander Albon":"ALB", "Charles Leclerc":"LEC", "Lewis Hamilton":"HAM",
    "Pierre Gasly":"GAS", "Carlos Sainz":"SAI", "Lance Stroll":"STR", "Fernando Alonso":"ALO"
}

qualifying_2025["DriverCode"] = qualifying_2025["Driver"].map(drive_mapping)

#merge 2025 qualifying data with 2024 race data
merged_data = qualifying_2025.merge(laps_2024, left_on="DriverCode", right_on="Driver", how="left")
merged_data.dropna(inplace=True)
merged_data["LapTime"] = merged_data["LapTime"].dt.total_seconds()
merged_data.head()

#use only QualifyingTime (s) as a feature
x = merged_data[["QualifyingTime (s)"]]
y = merged_data["LapTime"]

if x.shape[0] == 0:
  raise ValueError("No data available for training.")

print(y.head())  # Should show reasonable values (e.g., 80-100 seconds)

print(merged_data.dtypes)

#Train Gradient Boosting model
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=39)
model = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1, random_state=39)
model.fit(x_train, y_train)

#dataset split
print(x_train.shape, y_train.shape, x_test.shape, y_test.shape)

#Predict using 2025 qualifying times
predicted_lap_times = model.predict(qualifying_2025[["QualifyingTime (s)"]])
qualifying_2025["PredictedRaceTime"] = predicted_lap_times
qualifying_2025.head()

#rank drivers by predicted race times
qualifying_2025 = qualifying_2025.sort_values(by="PredictedRaceTime")
qualifying_2025["Position"] = range(1, len(qualifying_2025) + 1)
qualifying_2025.head()

#print final prediction
print("\n Predicted 2025 Australian GP Winner \n")
print(qualifying_2025[["Driver","PredictedRaceTime"]])

#evaluate model
y_pred = model.predict(x_test)
print(f"\n Model Error(MAE):{mean_absolute_error(y_test, y_pred):.2f} seconds")