forked from bordanattila/OpenF1_tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
153 lines (128 loc) Β· 5.78 KB
/
Copy pathmain.py
File metadata and controls
153 lines (128 loc) Β· 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import streamlit as st
from app.data_loader import (
fetch_data,
fetch_sessions,
fetch_sector_data,
fetch_laps,
fetch_stints,
fetch_pit_stop,
fetch_drivers
)
from app.data_processor import (
process_sector_times,
process_lap_data,
process_stints,
process_pit_stops,
build_driver_color_map
)
from app.visualizer import (
plot_sector_times,
plot_lap_times,
plot_tire_strategy,
plot_pit_stop
)
st.set_page_config(page_title="F1 Strategy Dashboard", layout="wide")
st.title("ποΈ Formula 1 Strategy Dashboard")
st.markdown("_Powered by OpenF1.org β’ Built by Attila Bordan β’ Improvements by Jilliana Alvarez_")
col1, col2 = st.columns(2)
with col1:
# Step 1: Select Year and Country dynamically
available_years = [2023, 2024, 2025]
selected_year = st.selectbox("Select Year", available_years, index=len(available_years) - 1)
# Fetch all meetings for selected year
all_meetings = fetch_data("meetings", {"year": selected_year})
if all_meetings.empty:
st.error("No meetings found for this year.")
st.stop()
available_countries = sorted(all_meetings["country_name"].dropna().unique())
selected_country = st.selectbox("Select Country", available_countries)
# Filter meetings for selected year and country
filtered_meetings = all_meetings[all_meetings["country_name"] == selected_country].copy()
filtered_meetings["label"] = filtered_meetings["meeting_name"] + " - " + filtered_meetings["location"]
filtered_meetings = filtered_meetings.sort_values(by="meeting_key", ascending=False)
with col2:
selected_meeting = st.selectbox("Select Grand Prix", filtered_meetings["label"], disabled=True)
selected_meeting_key = filtered_meetings.loc[
filtered_meetings["label"] == selected_meeting, "meeting_key"
].values[0]
sessions = fetch_sessions(selected_meeting_key)
selected_session = st.selectbox("Select Session", sessions["label"])
sessions["session_type"] = sessions["label"].str.extract(r"^(.*?)\s\(")
selected_session_type = sessions.loc[sessions["label"] == selected_session, "session_type"].values[0]
selected_session_key = sessions.loc[sessions["label"] == selected_session, "session_key"].values[0]
st.markdown(f"### π Session Overview: `{selected_session}`")
with st.expander("π Session Details", expanded=False):
st.write(f"**Meeting Key:** {selected_meeting_key}")
st.write(f"**Session Key:** {selected_session_key}")
# Fetch and preprocess driver info
driver_df = fetch_drivers(selected_session_key)
driver_df["driver_number"] = driver_df["driver_number"].astype(str)
driver_color_map = build_driver_color_map(driver_df)
driver_info = driver_df[["driver_number", "name_acronym"]]
# Sector times
sector_df = fetch_sector_data(selected_session_key)
sector_df["driver_number"] = sector_df["driver_number"].astype(str)
# Let user select driver and lap.
driver_options = {
f"{row['driver_number']} - {row['name_acronym']}": row['driver_number']
for _, row in driver_df.iterrows()
}
selected_driver_label = st.selectbox("Select Driver", list(driver_options.keys()))
selected_driver = driver_options[selected_driver_label]
available_laps = sector_df[sector_df["driver_number"] == selected_driver]["lap_number"].unique()
if len(available_laps) == 0:
st.warning("No laps available for the selected driver.")
st.stop()
selected_lap = st.selectbox("Select Lap", available_laps)
driver_name_row = driver_df[driver_df["driver_number"] == selected_driver ]
if not driver_name_row.empty:
driver_name = driver_name_row["name_acronym"].values[0]
else:
driver_name = selected_driver
filtered = sector_df[
(sector_df["driver_number"] == selected_driver)&
(sector_df["lap_number"] == selected_lap)
]
fig = plot_sector_times(sector_df, selected_driver, selected_lap, driver_name)
if fig:
st.plotly_chart(fig)
else:
st.warning("No sector data for selected driver/lap.")
# Lap Times
with st.expander(f"π Lap Time Chart for {selected_session_type} at {selected_country} {selected_year}",
expanded=True):
lap_df = fetch_laps(selected_session_key)
processed_df = process_lap_data(lap_df)
# Merge name_acronym into the lap data
processed_df["driver_number"] = processed_df["driver_number"].astype(str)
processed_df = processed_df.merge(driver_info, on="driver_number", how="left")
if processed_df.empty:
st.warning("No lap time data found.")
else:
fig = plot_lap_times(processed_df, driver_color_map)
st.plotly_chart(fig, use_container_width=True)
# Tire Strategy
with st.expander(f"π Tire strategy for {selected_session_type} at {selected_country} {selected_year}", expanded=True):
stints = fetch_stints(selected_session_key)
stints_df = process_stints(stints)
stints_df["driver_number"] = stints_df["driver_number"].astype(str)
stints_df = stints_df.merge(driver_info, on="driver_number", how="left")
if stints_df.empty:
st.warning("No tire strategy data found.")
else:
fig = plot_tire_strategy(stints_df, driver_color_map)
st.plotly_chart(fig, use_container_width=True)
# Pit Stops
with st.expander(f"β± Pit stop durations for {selected_session_type} at {selected_country} {selected_year}",
expanded=True):
pit_stop = fetch_pit_stop(selected_session_key)
pit_stop_df = process_pit_stops(pit_stop)
pit_stop_df["driver_number"] = pit_stop_df["driver_number"].astype(str)
pit_stop_df = pit_stop_df.merge(driver_info, on="driver_number", how="left")
if pit_stop_df.empty:
st.warning("No pit stop data found.")
else:
fig = plot_pit_stop(pit_stop_df, driver_color_map)
st.plotly_chart(fig, use_container_width=True)
if processed_df.empty:
st.info("Lap data is not available for this session.")