| import altair as alt |
| import streamlit as st |
| import pandas as pd |
|
|
| import strava |
| from utils import find_default_publish_start_end_date |
|
|
| st.set_page_config( |
| page_title="Streamlit Activities analysis for Strava", |
| page_icon=":safety_pin:", |
| ) |
|
|
| strava_header = strava.header() |
|
|
| st.header(":safety_pin: Streamlit Strava activities analysis") |
|
|
| strava_auth = strava.authenticate(header=strava_header, stop_if_unauthenticated=False) |
|
|
| if strava_auth is None: |
| st.markdown("Click the \"Connect with Strava\" button at the top to login with your Strava account and get started.") |
| st.stop() |
|
|
| |
| st.divider() |
| st.header("Display shoes analysis") |
| if 'athlete' not in st.session_state: |
| athlete = strava.get_athlete_detail(strava_auth) |
| st.session_state.athlete = athlete |
|
|
| if 'dict_shoes' not in st.session_state: |
| shoes = strava.get_shoes(st.session_state.athlete) |
| dict_shoes = {shoe["name"]: shoe["converted_distance"] for shoe in shoes} |
| st.session_state.dict_shoes = dict_shoes |
|
|
| all_shoes_names = st.session_state.dict_shoes.keys() |
|
|
| selected_shoes = st.multiselect( |
| label="Select columns to plot", |
| options=all_shoes_names, |
| ) |
|
|
| distances = [st.session_state.dict_shoes[shoe_name] for shoe_name in selected_shoes] |
| if selected_shoes: |
| chart_data = pd.DataFrame({ |
| 'index':selected_shoes, |
| 'kilometers':distances |
| }) |
| st.bar_chart(chart_data) |
| else: |
| st.info("No column(s) selected") |
|
|
| |
| st.divider() |
| st.header("Display zones on a period") |
|
|
| default_start_date, default_end_date = find_default_publish_start_end_date() |
|
|
| col_start_date, col_end_date = st.columns(2) |
| with col_start_date: |
| st.date_input("Start date", value=default_start_date, key="start_date") |
| with col_end_date: |
| st.date_input("End date", value=default_end_date, key="end_date") |
| if st.session_state.start_date > st.session_state.end_date: |
| st.error("Error: End date must fall after start date.") |
| else: |
| st.session_state.activities = strava.get_activities_on_period(strava_auth, [], st.session_state.start_date, st.session_state.end_date, 1) |
|
|
| if len(st.session_state.activities) == 0: |
| st.error("No activities found on this period") |
| st.stop() |
| else: |
| activities_zones = {} |
| number_activities_with_heartrate = 0 |
| for activity in st.session_state.activities: |
| if not activity["has_heartrate"]: |
| continue |
| try: |
| st.session_state.activity_zones = strava.get_activity_zones(strava_auth, activity["id"])[0]["distribution_buckets"] |
| number_activities_with_heartrate += 1 |
| except Exception as e: |
| st.write(e) |
| if not activities_zones: |
| activities_zones = {idx: zone["time"] // 60 for idx, zone in enumerate(st.session_state.activity_zones)} |
| else: |
| for idx, zone in enumerate(st.session_state.activity_zones): |
| activities_zones[idx] += (zone["time"] // 60) |
|
|
| st.info(f"You got {len(st.session_state.activities)} activities on this period and {number_activities_with_heartrate} have heart rate information.") |
|
|
| zones_label = ["zone 1", "zone 2", "zone 3", "zone 4", "zone 5"] |
| zones_df = pd.DataFrame({ |
| 'zones': zones_label, |
| 'minutes': activities_zones.values() |
| }) |
|
|
| scale = alt.Scale( |
| domain=zones_label, |
| range=["#008000", "#ffcf3e", "#f67200", "#ee1010", "#3f2204"], |
| ) |
| color = alt.Color("zones:N", scale=scale) |
|
|
| bars = ( |
| alt.Chart(zones_df) |
| .mark_bar() |
| .encode( |
| x="zones", |
| y="minutes", |
| color=color, |
| ) |
| ) |
|
|
| st.altair_chart(bars, theme="streamlit", use_container_width=True) |