Skip to content

Commit

Permalink
misc cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
voynow committed Aug 18, 2024
1 parent 8b69fb1 commit 854eb7b
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 98 deletions.
30 changes: 30 additions & 0 deletions src/activities.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from stravalib.client import Client
from stravalib.model import Activity

from src.types.activity_summary import ActivitySummary
from src.types.day_of_week_summary import DayOfWeekSummary
from src.types.week_summary import WeekSummary

Expand Down Expand Up @@ -80,6 +81,7 @@ def get_activities_df(strava_client: Client, num_weeks: int = 8) -> pl.DataFrame
cleansed and processed
:param athlete_id: The Strava athlete ID
:param num_weeks: The number of weeks to fetch activities for
:return: A cleaned and processed DataFrame of the athlete's activities
"""
timedela_x_weeks = datetime.now() - timedelta(weeks=num_weeks)
Expand All @@ -90,6 +92,34 @@ def get_activities_df(strava_client: Client, num_weeks: int = 8) -> pl.DataFrame
return preprocess_activities_df(raw_df)


def get_activity_summaries(strava_client, num_weeks=8) -> List[ActivitySummary]:
"""
Fetches and returns activity summaries for a given athlete ID
:param athlete_id: The Strava athlete ID
:param num_weeks: The number of weeks to fetch activities for
:return: A list of ActivitySummary objects, lighter weight than the full get_activities_df DataFrame
"""
df = get_activities_df(strava_client, num_weeks)
concise_activities_df = df.with_columns(
pl.col("start_date_local")
.apply(lambda x: x.strftime("%A, %B %d, %Y %I:%M %p"), return_dtype=pl.Utf8)
.alias("date_and_time"),
pl.col("distance_in_miles").apply(lambda x: round(x, 2)),
pl.col("elevation_gain_in_feet").apply(lambda x: round(x, 2)),
pl.col("pace_minutes_per_mile").apply(lambda x: round(x, 2)),
).drop(
"id",
"name",
"day_of_week",
"week_of_year",
"year",
"moving_time_in_minutes",
"start_date_local",
)
return [ActivitySummary(**row) for row in concise_activities_df.rows(named=True)]


def get_day_of_week_summaries(activities_df: pl.DataFrame) -> List[DayOfWeekSummary]:
"""
Aggregate activities DataFrame by day of the week and calculate summary statistics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from src.constants import COACH_ROLE
from src.email_manager import send_email, training_week_to_html
from src.supabase_client import upsert_training_week_with_coaching
from src.training_week_generation.training_week import generate_training_week
from src.training_week import generate_training_week


def lambda_handler(event, context):
Expand Down
File renamed without changes.
Empty file.
26 changes: 26 additions & 0 deletions src/training_week_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from src.llm import get_completion_json
from src.types.mid_week_analysis import MidWeekAnalysis
from src.types.training_week import TrainingWeekWithPlanning


def get_updated_training_week(
sysmsg_base: str,
mid_week_analysis: MidWeekAnalysis,
) -> TrainingWeekWithPlanning:
msg = (
sysmsg_base
+ f"""\nThe original plan for this week targeted {mid_week_analysis.miles_target} miles. Your client has run {mid_week_analysis.miles_ran} miles so far (and they have {mid_week_analysis.miles_remaining} miles left to run this week), but the plan for the rest of the week includes {mid_week_analysis.future_miles_planned} miles. Adjust the plan accordingly given the following information:
Here is your client's progress so far this week:
{mid_week_analysis.activities}
Here is the plan for the rest of the week:
{mid_week_analysis.training_week_future}
What changes need to be made so that your client runs {mid_week_analysis.miles_remaining} more miles this week?"""
)

return get_completion_json(
message=msg,
response_model=TrainingWeekWithPlanning,
)
146 changes: 49 additions & 97 deletions test.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,25 @@
"\n",
"from src.activities import (\n",
" get_activities_df,\n",
" get_activity_summaries,\n",
" get_day_of_week_summaries,\n",
" get_weekly_summaries,\n",
")\n",
"from src.constants import COACH_ROLE\n",
"from src.auth_manager import get_strava_client\n",
"from src.email_manager import send_email, training_week_to_html\n",
"from src.constants import COACH_ROLE\n",
"from src.email_manager import (\n",
" send_email,\n",
" training_week_to_html,\n",
" training_week_update_to_html,\n",
")\n",
"from src.supabase_client import (\n",
" upsert_training_week_with_coaching,\n",
" get_training_week_with_coaching,\n",
" upsert_training_week_update,\n",
" upsert_training_week_with_coaching,\n",
")\n",
"from src.training_week_generation.training_week import generate_training_week"
"from src.training_week import generate_training_week\n",
"from src.training_week_update import get_updated_training_week\n",
"from src.types.mid_week_analysis import MidWeekAnalysis\n"
]
},
{
Expand All @@ -46,23 +53,24 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"athlete_id='98390356' token still valid until 2024-08-18 19:38:07+00:00\n"
"athlete_id='98390356' token still valid until 2024-08-19 02:00:31+00:00\n"
]
},
{
"data": {
"text/plain": [
"APIResponse(data=[{'id': 20, 'athlete_id': 98390356, 'training_week': '[{\"day\": \"mon\", \"session_type\": \"easy run\", \"distance\": 4.5, \"notes\": \"Easy pace\"}, {\"day\": \"tues\", \"session_type\": \"easy run\", \"distance\": 5.0, \"notes\": \"Easy pace\"}, {\"day\": \"wed\", \"session_type\": \"speed workout\", \"distance\": 7.0, \"notes\": \"Included intervals e.g. 4x1 mile at 10k pace with rest intervals\"}, {\"day\": \"thurs\", \"session_type\": \"easy run\", \"distance\": 4.5, \"notes\": \"Recovery pace after speed workout\"}, {\"day\": \"fri\", \"session_type\": \"easy run\", \"distance\": 5.0, \"notes\": \"Easy pace\"}, {\"day\": \"sat\", \"session_type\": \"long run\", \"distance\": 16.0, \"notes\": \"Long run at a steady pace of 9m 43s per mile\"}, {\"day\": \"sun\", \"session_type\": \"rest day\", \"distance\": 0.0, \"notes\": \"Recovery day, complete rest\"}]', 'typical_week_training_review': \"Your training week reflects a balanced schedule with room for adjustments to optimize marathon preparation. You consistently run on Wednesdays and Saturdays, aligning with your training preferences, with Saturdays being your long run day at a solid pace of 9 minutes 43 seconds per mile. You rest mainly on Sundays, but there's a single longer run, and your Wednesdays are best suited for speed work, given the frequent yet shorter runs at a consistent pace. Adjusting to include dedicated rest and more structured speed sessions could enhance your performance.\", 'weekly_mileage_target': \"For Week 33, aim for a total weekly mileage of 42–44 miles to continue building endurance, as you've been steadily increasing your mileage over the past weeks. Plan your long run to be in the range of 16–17 miles, pushing slightly beyond your previous longest run of 15.03 miles while avoiding excessive jumps to minimize injury risk. Remember to include sufficient recovery and easy-paced runs throughout the week.\", 'created_at': '2024-08-18T14:27:41.403615+00:00', 'training_week_planning': \"To create a training plan for the week with a total mileage target of 42-44 miles and a long run of 16-17 miles, I'll start by allocating the long run on Saturday as requested, targeting a 16-mile run. We'll keep Sunday as a rest day. The speed workout will be on Wednesday to align with the client's preferences and will be approximately 7 miles, including warm-up and cool-down. The rest of the week will be filled with easy runs to meet the remaining mileage target. I will calculate the mileage each day, adjusting daily miles to stay within the target while also providing adequate rest.\\\\n\\\\n1. Saturday (Long Run): 16 miles.\\\\n2. Wednesday (Speed Workout): 7 miles.\\\\n3. Total so far: 23 miles.\\\\n4. Remaining mileage to achieve the target (42-44): 42-23 = 19 miles minimum.\\\\n5. Distributing 19 miles over 4 days with Monday, Tuesday, Thursday, and Friday with slightly variable distances around 4-5 miles each.\\\\n6. One rest day: Sunday.\\\\n7. Monday, Tuesday, Thursday, Friday - plan easy runs with cumulative mileage around 19 miles.\\\\n\\\\nMonday: Easy run 4.5 miles\\\\nTuesday: Easy run 5 miles\\\\nThursday: Easy run 4.5 miles\\\\nFriday: Easy run 5 miles\\\\n8. Check total mileage for the week: 4.5 + 5 + 4.5 + 5 + 16 + 7 = 42 miles (meets the target)\"}], count=None)"
"{'message_id': '<202408182107.75708478271@smtp-relay.mailin.fr>',\n",
" 'message_ids': None}"
]
},
"execution_count": 3,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
Expand Down Expand Up @@ -92,27 +100,7 @@
"# save data to db and trigger email\n",
"upsert_training_week_with_coaching(\n",
" athlete_id=athlete_id, training_week_with_coaching=training_week_with_coaching\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'message_id': '<202408181427.29686375653@smtp-relay.mailin.fr>',\n",
" 'message_ids': None}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
")\n",
"send_email(\n",
" subject=\"Training Schedule Just Dropped 🏃\",\n",
" html_content=training_week_to_html(training_week_with_coaching),\n",
Expand All @@ -135,13 +123,29 @@
"name": "stdout",
"output_type": "stream",
"text": [
"athlete_id='98390356' token still valid until 2024-08-18 19:38:07+00:00\n"
"athlete_id='98390356' token still valid until 2024-08-19 02:00:31+00:00\n",
"shape: (2, 10)\n",
"┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬───────────┬──────────┐\n",
"│ id ┆ name ┆ start_dat ┆ day_of_we ┆ … ┆ distance_ ┆ elevation ┆ moving_ti ┆ pace_min │\n",
"│ --- ┆ --- ┆ e_local ┆ ek ┆ ┆ in_miles ┆ _gain_in_ ┆ me_in_min ┆ utes_per │\n",
"│ u64 ┆ str ┆ --- ┆ --- ┆ ┆ --- ┆ feet ┆ utes ┆ _mile │\n",
"│ ┆ ┆ datetime[ ┆ str ┆ ┆ f64 ┆ --- ┆ --- ┆ --- │\n",
"│ ┆ ┆ μs] ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ f64 │\n",
"╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪══════════╡\n",
"│ 121272320 ┆ Yeehaw🤠 ┆ 2024-08-1 ┆ mon ┆ … ┆ 8.014466 ┆ 183.72704 ┆ 75.566667 ┆ 9.428784 │\n",
"│ 53 ┆ ┆ 2 ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ ┆ ┆ 06:06:14 ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"│ 121355978 ┆ Morning ┆ 2024-08-1 ┆ tue ┆ … ┆ 4.009967 ┆ 52.49344 ┆ 42.666667 ┆ 10.64015 │\n",
"│ 82 ┆ Run ┆ 3 ┆ ┆ ┆ ┆ ┆ ┆ 5 │\n",
"│ ┆ ┆ 06:15:48 ┆ ┆ ┆ ┆ ┆ ┆ │\n",
"└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘\n"
]
},
{
"data": {
"text/plain": [
"APIResponse(data=[{'id': 7, 'athlete_id': 98390356, 'activities': '[{\"date_and_time\": \"Monday, August 12, 2024 06:06 AM\", \"distance_in_miles\": 8.01, \"elevation_gain_in_feet\": 183.73, \"pace_minutes_per_mile\": 9.43}, {\"date_and_time\": \"Tuesday, August 13, 2024 06:15 AM\", \"distance_in_miles\": 4.01, \"elevation_gain_in_feet\": 52.49, \"pace_minutes_per_mile\": 10.64}]', 'training_week': '[{\"day\": \"mon\", \"session_type\": \"easy run\", \"distance\": 4.5, \"notes\": \"Easy pace\"}, {\"day\": \"tues\", \"session_type\": \"easy run\", \"distance\": 5.0, \"notes\": \"Easy pace\"}, {\"day\": \"wed\", \"session_type\": \"speed workout\", \"distance\": 7.0, \"notes\": \"Included intervals e.g. 4x1 mile at 10k pace with rest intervals\"}, {\"day\": \"thurs\", \"session_type\": \"easy run\", \"distance\": 4.5, \"notes\": \"Recovery pace after speed workout\"}, {\"day\": \"fri\", \"session_type\": \"easy run\", \"distance\": 5.0, \"notes\": \"Easy pace\"}, {\"day\": \"sat\", \"session_type\": \"long run\", \"distance\": 16.0, \"notes\": \"Long run at a steady pace of 9m 43s per mile\"}, {\"day\": \"sun\", \"session_type\": \"rest day\", \"distance\": 0.0, \"notes\": \"Recovery day, complete rest\"}]', 'planning': \"The client's target mileage for the week is 42.0 miles. They have already run 12.02 miles, leaving them with 29.98 miles to go. The remaining plan includes a total of 32.5 miles, which exceeds the target by 2.52 miles. To adjust the plan: 1. Keep the Wednesday speed workout at 7.0 miles. 2. The Thursday easy run is planned for 4.5 miles. 3. Friday's easy run is planned for 5.0 miles. 4. The Saturday long run is planned for 16.0 miles. Since the client prefers long runs on Saturdays and given its importance, we will adjust the Friday easy run by reducing it by 2.52 miles to meet the target.\", 'training_week_update': '[{\"day\": \"wed\", \"session_type\": \"speed workout\", \"distance\": 7.0, \"notes\": \"Included intervals e.g. 4x1 mile at 10k pace with rest intervals\"}, {\"day\": \"thurs\", \"session_type\": \"easy run\", \"distance\": 4.5, \"notes\": \"Recovery pace after speed workout\"}, {\"day\": \"fri\", \"session_type\": \"easy run\", \"distance\": 2.48, \"notes\": \"Easy pace adjusted to reduce total weekly mileage\"}, {\"day\": \"sat\", \"session_type\": \"long run\", \"distance\": 16.0, \"notes\": \"Long run at a steady pace of 9m 43s per mile\"}, {\"day\": \"sun\", \"session_type\": \"rest day\", \"distance\": 0.0, \"notes\": \"Recovery day, complete rest\"}]', 'created_at': '2024-08-18T14:27:47.94352+00:00'}], count=None)"
"{'message_id': '<202408182112.52938248021@smtp-relay.mailin.fr>',\n",
" 'message_ids': None}"
]
},
"execution_count": 5,
Expand All @@ -150,85 +154,33 @@
}
],
"source": [
"from src.types.activity_summary import ActivitySummary\n",
"from src.types.mid_week_analysis import MidWeekAnalysis\n",
"from src.llm import get_completion_json\n",
"from src.types.training_week import TrainingWeekWithPlanning\n",
"\n",
"\n",
"@freeze_time(\"2024-08-13 20:00:00\")\n",
"def get_updated_training_week(\n",
" mid_week_analysis: MidWeekAnalysis,\n",
") -> TrainingWeekWithPlanning:\n",
" client_preferences = \"A) Training for a marathon B) This will be my second marathon C) Prefer workouts on Wednesdays and long runs on Saturdays\"\n",
" sysmsg_base = f\"{COACH_ROLE}\\nYour client has included the following preferences: {client_preferences}\\n\"\n",
"def mock_get_activity_summaries(strava_client, num_weeks=8):\n",
" return get_activity_summaries(strava_client, num_weeks)\n",
"\n",
" msg = sysmsg_base + f\"\"\"\\nThe original plan for this week targeted {mid_week_analysis.miles_target} miles. Your client has run {mid_week_analysis.miles_ran} miles so far (and they have {mid_week_analysis.miles_remaining} miles left to run this week), but the plan for the rest of the week includes {mid_week_analysis.future_miles_planned} miles. Adjust the plan accordingly given the following information:\n",
"\n",
" Here is your client's progress so far this week:\n",
" {mid_week_analysis.activities}\n",
"\n",
" Here is the plan for the rest of the week:\n",
" {mid_week_analysis.training_week_future}\n",
"\n",
" What changes need to be made so that your client runs {mid_week_analysis.miles_remaining} more miles this week?\"\"\"\n",
"\n",
" return get_completion_json(\n",
" message=msg,\n",
" response_model=TrainingWeekWithPlanning,\n",
" )\n",
"\n",
"\n",
"@freeze_time(\"2024-08-13 20:00:00\")\n",
"def mock_get_activities_df(strava_client, num_weeks=8):\n",
" return get_activities_df(strava_client, num_weeks)\n",
"client_preferences = \"A) Training for a marathon B) This will be my second marathon C) Prefer workouts on Wednesdays and long runs on Saturdays\"\n",
"sysmsg_base = f\"{COACH_ROLE}\\nYour client has included the following preferences: {client_preferences}\\n\"\n",
"\n",
"def get_activity_summaries(strava_client, num_weeks=8) -> pl.DataFrame:\n",
" df = mock_get_activities_df(strava_client, num_weeks)\n",
" concise_activities_df = df.with_columns(\n",
" pl.col('start_date_local').apply(lambda x: x.strftime(\"%A, %B %d, %Y %I:%M %p\")).alias('date_and_time'),\n",
" pl.col('distance_in_miles').apply(lambda x: round(x, 2)),\n",
" pl.col('elevation_gain_in_feet').apply(lambda x: round(x, 2)),\n",
" pl.col('pace_minutes_per_mile').apply(lambda x: round(x, 2)),\n",
" ).drop('id', 'name', 'day_of_week', 'week_of_year', 'year', 'moving_time_in_minutes', 'start_date_local') \n",
" return [ActivitySummary(**row) for row in concise_activities_df.rows(named=True)]\n",
"\n",
"athlete_id = os.environ[\"JAMIES_ATHLETE_ID\"]\n",
"strava_client = get_strava_client(athlete_id)\n",
"\n",
"training_week_with_coaching = get_training_week_with_coaching(athlete_id)\n",
"current_weeks_activity_summaries = get_activity_summaries(strava_client, num_weeks=1)\n",
"mid_week_analysis = MidWeekAnalysis(activities=current_weeks_activity_summaries, training_week=training_week_with_coaching.training_week)\n",
"\n",
"training_week_update_with_planning = get_updated_training_week(mid_week_analysis)\n",
"current_weeks_activity_summaries = mock_get_activity_summaries(strava_client, num_weeks=1)\n",
"mid_week_analysis = MidWeekAnalysis(\n",
" activities=current_weeks_activity_summaries,\n",
" training_week=training_week_with_coaching.training_week,\n",
")\n",
"training_week_update_with_planning = get_updated_training_week(\n",
" sysmsg_base=sysmsg_base, \n",
" mid_week_analysis=mid_week_analysis\n",
")\n",
"\n",
"upsert_training_week_update(\n",
" athlete_id=athlete_id,\n",
" mid_week_analysis=mid_week_analysis,\n",
" training_week_update_with_planning=training_week_update_with_planning,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'message_id': '<202408181427.65417576067@smtp-relay.mailin.fr>',\n",
" 'message_ids': None}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from src.email_manager import training_week_update_to_html\n",
"\n",
")\n",
"send_email(\n",
" subject=\"Training Schedule Update 🏃\",\n",
" html_content=training_week_update_to_html(\n",
Expand Down

0 comments on commit 854eb7b

Please sign in to comment.