diff --git a/.github/workflows/deploy_lambda.yml b/.github/workflows/deploy_lambda.yml index 4505584..344b854 100644 --- a/.github/workflows/deploy_lambda.yml +++ b/.github/workflows/deploy_lambda.yml @@ -2,8 +2,6 @@ name: Deploy to Lambda on: push: - branches: - - main jobs: deploy: diff --git a/scripts/code2clipboard.py b/scripts/code2clipboard.py new file mode 100644 index 0000000..5273350 --- /dev/null +++ b/scripts/code2clipboard.py @@ -0,0 +1,68 @@ +import os +from typing import List + +import pyperclip + + +def get_code_files(directory: str, extensions: List[str]) -> List[str]: + """ + Recursively finds all code files in the given directory with specified extensions, + strictly ignoring any path containing 'node_modules'. + + :param directory: Directory to search for code files. + :param extensions: List of file extensions to include. + :return: List of file paths for code files. + """ + code_files = [] + for root, _, files in os.walk(directory): + if "node_modules" in root or ".next" in root: + continue + + code_files.extend( + os.path.join(root, file) + for file in files + if any(file.endswith(ext) for ext in extensions) + ) + return code_files + + +def read_files(file_paths: List[str], directory: str) -> str: + """ + Reads the content of the given files and returns a combined string. + + :param file_paths: List of file paths to read. + :param directory: Base directory for calculating relative paths. + :return: Combined content of all files as a string. + """ + content = [] + for file_path in file_paths: + with open(file_path, "r") as file: + relative_path = os.path.relpath(file_path, directory) + content.append(f"--- {relative_path} ---\n") + content.append(file.read()) + content.append("\n\n") + return "".join(content) + + +def copy_code_to_clipboard() -> None: + """ + Copies all code files from the current working directory to the clipboard. + """ + extensions = [ + ".py", + ".js", + ".ts", + ".html", + ".css", + ".tsx", + ".jsx", + ] + directory = os.getcwd() + code_files = get_code_files(directory, extensions) + combined_content = read_files(code_files, directory) + pyperclip.copy(combined_content) + + +if __name__ == "__main__": + copy_code_to_clipboard() + print("Code files have been copied to the clipboard.") diff --git a/src/lambda_function.py b/src/lambda_function.py index fd0bd5a..66fb49e 100644 --- a/src/lambda_function.py +++ b/src/lambda_function.py @@ -169,6 +169,7 @@ def lambda_handler(event, context): code=event["code"], ) logging.info(response) + return {"success": True} elif event.get("end_to_end_test"): user = get_user(os.environ["JAMIES_ATHLETE_ID"]) diff --git a/test.ipynb b/test.ipynb index ed82d16..88eb438 100644 --- a/test.ipynb +++ b/test.ipynb @@ -88,67 +88,6 @@ "print(response)" ] }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "athlete_id=98390356 token still valid until 2024-08-30 23:49:42+00:00\n" - ] - } - ], - "source": [ - "from src.activities import get_activity_summaries\n", - "from src.auth_manager import get_strava_client\n", - "from src.constants import COACH_ROLE\n", - "from src.supabase_client import get_training_week_with_coaching\n", - "from src.training_week_update import get_updated_training_week\n", - "from src.types.mid_week_analysis import MidWeekAnalysis\n", - "\n", - "\n", - "user = get_user(os.environ[\"JAMIES_ATHLETE_ID\"])\n", - "\n", - "sysmsg_base = f\"{COACH_ROLE}\\nYour client has included the following preferences: {user.preferences}\\n\"\n", - "strava_client = get_strava_client(user.athlete_id)\n", - "\n", - "training_week_with_coaching = get_training_week_with_coaching(user.athlete_id)\n", - "current_weeks_activity_summaries = get_activity_summaries(\n", - " strava_client, num_weeks=1\n", - ")\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, mid_week_analysis=mid_week_analysis\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "nan" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "mid_week_analysis.activities[0].pace_minutes_per_mile\n", - "# Training week accuracy" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -351,6 +290,116 @@ " print(\".\" * 100)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Manual Training Plan Generation" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "raytrip.curtis@gmail.com\n", + "athlete_id=58608268 token still valid until 2024-09-03 02:57:23+00:00\n", + "TrainingWeekWithCoaching(typical_week_training_review=Your current schedule shows a consistent routine with shorter recovery runs on Monday, and longer efforts on Fridays and Sundays indicating potential long runs. Saturdays, based on your preference, should accommodate your long run for marathon preparation, but current mileage suggests a lighter run. Your speed work on Tuesdays aligns well with your preference, but consider shifting your rest days to Monday or Sunday to ensure recovery after these intensive sessions., weekly_mileage_target=Based on your recent training, you're showing consistent higher mileage with alternating long run distances. For next week, aim for a weekly mileage target of about 65-68 miles to maintain momentum while avoiding burnout. Schedule your long run on Saturday with a distance between 18-20 miles, as you've achieved in Week 32 and 34. Keep focusing on quality workouts on Tuesdays, maintaining a pace relevant to your marathon goals, such as around 6m 40s per mile, to further build speed endurance., planning=Planning(weekly_mileage_target=65-68 miles, long_run_distance=19.0, remaining_weekly_mileage=68 - 19 = 49 miles, remaining_weekly_mileage_planning=Let's distribute 49 miles over the remaining 6 days: Tuesday session is 10 miles (49 - 10 = 39 miles remaining). Two sessions of 9 miles on Wednesday and Thursday (39 - 18 = 21 miles remaining). One session of 8 miles on Friday (21 - 8 = 13 miles remaining). One session of 5 miles on Monday (13 - 5 = 8 miles remaining). Easy runs on Sunday of 8 miles (8 - 8 = 0 miles remaining). Monday and Sunday are rest days.), training_week=[TrainingSession(day=, session_type=, distance=5.0, notes='Easy pace for recovery.'), TrainingSession(day=, session_type=, distance=10.0, notes='Intervals at 6m 40s pace, e.g., 6x1mi @ 6m 40s per mile.'), TrainingSession(day=, session_type=, distance=9.0, notes='Steady pace, around 7m 30s per mile.'), TrainingSession(day=, session_type=, distance=9.0, notes='Keep a steady pace, around 7m 30s per mile.'), TrainingSession(day=, session_type=, distance=8.0, notes='Easy pace for recovery, focus on form.'), TrainingSession(day=, session_type=, distance=19.0, notes='Long run at a comfortable pace, aim for endurance.'), TrainingSession(day=, session_type=, distance=8.0, notes='Easy pace, recover from long run.')])\n" + ] + } + ], + "source": [ + "from freezegun import freeze_time\n", + "from src.activities import get_activities_df, get_day_of_week_summaries, get_weekly_summaries\n", + "from src.auth_manager import get_strava_client\n", + "from src.constants import COACH_ROLE\n", + "from src.new_training_week import generate_training_week_with_coaching\n", + "from src.supabase_client import list_users\n", + "\n", + "@freeze_time(\"2024-09-01\")\n", + "def gen_training_week_wrapper(sysmsg_base, strava_client):\n", + " activities_df = get_activities_df(strava_client)\n", + " day_of_week_summaries = get_day_of_week_summaries(activities_df)\n", + " weekly_summaries = get_weekly_summaries(activities_df)\n", + " return generate_training_week_with_coaching(\n", + " sysmsg_base=sysmsg_base,\n", + " weekly_summaries=weekly_summaries,\n", + " day_of_week_summaries=day_of_week_summaries,\n", + " )\n", + "\n", + "# \"voynow99@gmail.com\", \"jaredpalek8@gmail.com\", \"laurenbrooks01@gmail.com\", \"raytrip.curtis@gmail.com\"\n", + "for user in list_users():\n", + " if user.email == \"raytrip.curtis@gmail.com\":\n", + " print(user.email)\n", + " sysmsg_base = f\"{COACH_ROLE}\\nYour client has included the following preferences: {user.preferences}\\n\"\n", + " strava_client = get_strava_client(user.athlete_id)\n", + " response = gen_training_week_wrapper(sysmsg_base, strava_client)\n", + " print(response)\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "68.0\n", + "Based on your recent training, you're showing consistent higher mileage with alternating long run distances. For next week, aim for a weekly mileage target of about 65-68 miles to maintain momentum while avoiding burnout. Schedule your long run on Saturday with a distance between 18-20 miles, as you've achieved in Week 32 and 34. Keep focusing on quality workouts on Tuesdays, maintaining a pace relevant to your marathon goals, such as around 6m 40s per mile, to further build speed endurance.\n" + ] + }, + { + "data": { + "text/plain": [ + "[TrainingSession(day=, session_type=, distance=5.0, notes='Easy pace for recovery.'),\n", + " TrainingSession(day=, session_type=, distance=10.0, notes='Intervals at 6m 40s pace, e.g., 6x1mi @ 6m 40s per mile.'),\n", + " TrainingSession(day=, session_type=, distance=9.0, notes='Steady pace, around 7m 30s per mile.'),\n", + " TrainingSession(day=, session_type=, distance=9.0, notes='Keep a steady pace, around 7m 30s per mile.'),\n", + " TrainingSession(day=, session_type=, distance=8.0, notes='Easy pace for recovery, focus on form.'),\n", + " TrainingSession(day=, session_type=, distance=19.0, notes='Long run at a comfortable pace, aim for endurance.'),\n", + " TrainingSession(day=, session_type=, distance=8.0, notes='Easy pace, recover from long run.')]" + ] + }, + "execution_count": 68, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(response.total_weekly_mileage)\n", + "print(response.weekly_mileage_target)\n", + "response.training_week" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "APIResponse(data=[{'id': 69, 'athlete_id': 60813108, 'training_week': '[{\"day\": \"mon\", \"session_type\": \"rest day\", \"distance\": 0.0, \"notes\": \"Rest and recovery\"}, {\"day\": \"tues\", \"session_type\": \"easy run\", \"distance\": 6.0, \"notes\": \"Easy pace\"}, {\"day\": \"wed\", \"session_type\": \"speed workout\", \"distance\": 8.0, \"notes\": \"3x1 mile @ 7m 30s with 2 minutes rest\"}, {\"day\": \"thurs\", \"session_type\": \"easy run\", \"distance\": 5.0, \"notes\": \"Easy pace\"}, {\"day\": \"fri\", \"session_type\": \"rest day\", \"distance\": 0.0, \"notes\": \"Rest and recovery\"}, {\"day\": \"sat\", \"session_type\": \"long run\", \"distance\": 14.0, \"notes\": \"Steady pace\"}, {\"day\": \"sun\", \"session_type\": \"easy run\", \"distance\": 5.0, \"notes\": \"Easy pace, recovery run\"}]', 'typical_week_training_review': 'Your training schedule aligns well with your marathon goals, with Wednesdays being optimal for workouts as you consistently cover decent mileage at a relatively brisk 8 minutes and 57 seconds per mile pace. Saturdays are effectively utilized for long runs, averaging 12.7 miles at a steady pace. It appears that you take rest days mostly on Mondays and Fridays, providing recovery between your more intense and longer sessions. Consider incorporating speed work on your lower mileage days if possible to boost overall speed.', 'weekly_mileage_target': \"Based on your recent training data, you've had a couple of fluctuations in mileage, with a peak at 46.98 miles followed by a drop. To balance building endurance while remaining conservative, aim for 36-38 miles next week. For the long run, target 13-14 miles to maintain endurance without pushing too hard beyond your recent averages. This setup should allow for a steady build-up as you prepare for your marathon in October.\", 'created_at': '2024-09-02T20:57:06.260306+00:00', 'planning': 'Planning(weekly_mileage_target=36-38 miles, long_run_distance=14.0, remaining_weekly_mileage=38 miles - 14 miles (long run) = 24 miles remaining, remaining_weekly_mileage_planning=For the remaining 24 miles, we will distribute them across 5 days (Tuesday, Wednesday, Thursday, Sunday) as follows: Tuesday: 6 miles, Wednesday: 8 miles speed workout, Thursday: 5 miles easy, Sunday: 5 miles easy. Monday and Friday will be rest days. Total: 6 + 8 + 5 + 5 = 24 miles.)'}], count=None)" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from src.supabase_client import upsert_training_week_with_coaching\n", + "\n", + "upsert_training_week_with_coaching(user.athlete_id, response)" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/web/public/next.svg b/web/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/web/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/web/public/powered_by_strava.png b/web/public/powered_by_strava.png new file mode 100644 index 0000000..39a4da6 Binary files /dev/null and b/web/public/powered_by_strava.png differ diff --git a/landing.png b/web/public/preview.png similarity index 100% rename from landing.png rename to web/public/preview.png diff --git a/web/public/strava-icon.png b/web/public/strava-icon.png new file mode 100644 index 0000000..af88271 Binary files /dev/null and b/web/public/strava-icon.png differ diff --git a/web/public/vercel.svg b/web/public/vercel.svg deleted file mode 100644 index d2f8422..0000000 --- a/web/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/web/src/app/components/Footer.tsx b/web/src/app/components/Footer.tsx new file mode 100644 index 0000000..d89a457 --- /dev/null +++ b/web/src/app/components/Footer.tsx @@ -0,0 +1,22 @@ +import Image from 'next/image'; + +const Footer = (): JSX.Element => { + return ( +
+
+ Powered by Strava +

+ © 2024 TrackFlow. All rights reserved. +

+
+
+ ); +}; + +export default Footer; diff --git a/web/src/app/components/Navbar.tsx b/web/src/app/components/Navbar.tsx new file mode 100644 index 0000000..ac51533 --- /dev/null +++ b/web/src/app/components/Navbar.tsx @@ -0,0 +1,40 @@ +import Image from 'next/image'; +import Link from 'next/link'; +import { useState } from 'react'; +import SignUp from './SignUp'; + +export default function Navbar(): JSX.Element { + const [showSignup, setShowSignup] = useState(false); + + return ( + <> + + {showSignup && setShowSignup(false)} />} + + ); +} \ No newline at end of file diff --git a/web/src/app/components/SignUp.tsx b/web/src/app/components/SignUp.tsx new file mode 100644 index 0000000..4e15205 --- /dev/null +++ b/web/src/app/components/SignUp.tsx @@ -0,0 +1,57 @@ +import Image from 'next/image'; +import { useState } from 'react'; + + +interface SignUpProps { + onClose: () => void; +} + +export default function SignUp({ onClose }: SignUpProps): JSX.Element { + const [email, setEmail] = useState(''); + const [preferences, setPreferences] = useState(''); + + const handleSignUp = (event: React.FormEvent): void => { + event.preventDefault(); + localStorage.setItem('email', email); + localStorage.setItem('preferences', preferences); + const redirectUri = 'http://localhost:3000/'; + const stravaAuthUrl = `https://www.strava.com/oauth/authorize?client_id=95101&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&approval_prompt=auto&scope=read_all,profile:read_all,activity:read_all`; + window.location.href = stravaAuthUrl; + }; + + + return ( +
+
+

+ Sign Up + +

+
+ setEmail(e.target.value)} + placeholder="Email" + required + className="w-full px-3 py-2 border rounded-md" + /> +