diff --git a/rowers/forms.py b/rowers/forms.py index 8ebd1804..f54c97b0 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -316,6 +316,9 @@ class MetricsForm(forms.Form): class CNsummaryForm(forms.Form): file = forms.FileField(required=True, validators=[must_be_csv]) +class NextWeekJsonForm(forms.Form): + file = forms.FileField(required=True) + # The little window to type '4x2000m/500m' to update the workout summary diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index 7df99eda..28da7b70 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -18,7 +18,7 @@ import rowers.dataprep as dataprep import numpy as np import rowers.metrics as metrics import rowers.mytypes as mytypes -from rowers.utils import to_pace +from rowers.utils import to_pace, intensitymap from rowers.opaque import encoder from rowingdata import rower as rrower from rowingdata import rowingdata as rrdata @@ -1067,6 +1067,63 @@ def get_workouts_session(r, ps): return ws +def correct_intensity(workout): + # reads the steps and if the intensity is an integer, converts it to a string + steps = workout['steps'] + for step in steps: + if 'intensity' in step: + if isinstance(step['intensity'], int): + step['intensity'] = intensitymap[step['intensity']] + + return workout + + +def create_next_week_from_json(plansteps, rower, planbyrscore=False, plan=None,): + trainingdays = plansteps['cycles'] + # start date is the first day of the following week + today = timezone.now() + startdate = today - timezone.timedelta(days=today.weekday())+timezone.timedelta(days=7) + ndays = 0 + for day in trainingdays: + try: + workouts = day[0][1:] + except IndexError: + workouts =[] + for workout in workouts: + sessionsport = 'water' + try: + sessionsport = mytypes.fitmappinginv[workout['sport'].lower()] + except KeyError: + pass + + preferreddate = startdate+timedelta(days=ndays) + sessionmode = 'time' + if planbyrscore: + sessionmode = 'rScore' + + ps = PlannedSession( + startdate=preferreddate - timedelta(days=preferreddate.weekday()), + enddate=preferreddate + timedelta(days=-preferreddate.weekday()-1, weeks=1), + preferreddate=preferreddate, + sessionsport=sessionsport, # change this + name=workout['workoutName'], + steps=correct_intensity(workout), + manager=rower.user, + sessionmode=sessionmode, + comment=workout['description'], + from_plan=plan, + ) + ps.save() + add_rower_session(rower, ps) + if ps.fitfile: + ps.steps = {} + ps.save() + ndays += 1 + + return + + + def create_sessions_from_json(plansteps, rower, startdate, manager, planbyrscore=False, plan=None, plan_past_days=False, asynchronous=True, queue=queue): @@ -1094,7 +1151,7 @@ def create_sessions_from_json(plansteps, rower, startdate, manager, planbyrscore preferreddate=preferreddate, sessionsport=sessionsport, # change this name=workout['workoutName'], - steps=workout, + steps=correct_intensity(workout), manager=manager, sessionmode=sessionmode, comment=workout['description'], diff --git a/rowers/templates/loadnextweek.html b/rowers/templates/loadnextweek.html new file mode 100644 index 00000000..b7eb16bb --- /dev/null +++ b/rowers/templates/loadnextweek.html @@ -0,0 +1,24 @@ +{% extends "newbase.html" %} +{% load static %} +{% load rowerfilters %} + +{% block title %}Planned Sessions{% endblock %} + +{% block main %} + +

Load next week

+ +
+ + {{ form.as_table }} +
+ {% csrf_token %} + +
+ +{% endblock %} + + +{% block sidebar %} +{% include 'menu_plan.html' %} +{% endblock %} diff --git a/rowers/urls.py b/rowers/urls.py index d8d3451d..05d38608 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -1109,5 +1109,7 @@ urlpatterns = [ name="history_view_data"), re_path(r'^braintree/$', views.braintree_webhook_view, name="braintree_webhook_view"), + re_path(r'^nextweekplan/$', views.nextweekplan_view, + name='nextweekplan_view'), ] diff --git a/rowers/utils.py b/rowers/utils.py index 070f1a45..5b8a0500 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -34,6 +34,17 @@ from django.conf import settings lbstoN = 4.44822 +intensitymap = { + 0: "Active", + 1: "Rest", + 2: "Warmup", + 3: "Cooldown", + 4: "Recovery", + 5: "Interval", + 6: "Other", +} + + landingpages = ( ('workout_view', 'Workout View'), ('workout_edit_view', 'Edit View'), @@ -1363,6 +1374,10 @@ def step_to_string(step, short=False): unit=unit, ) + if isinstance(intensity, int): + intensity = intensitymap[intensity] + + if short and intensity.lower() in ['warmup', 'cooldown', 'rest']: s = '{intensity} {duration} {unit} {target} {repeat}'.format( intensity=intensity, diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py index f1578746..f7fae740 100644 --- a/rowers/views/planviews.py +++ b/rowers/views/planviews.py @@ -4210,3 +4210,46 @@ def planmacrocyclebymonth(request, id=0, userid=0): # pragma: no cover 'thismesoid': str(mesos[0].id)}) return HttpResponseRedirect(url) + +@user_passes_test(can_plan, login_url="/rowers/paidplans", + message="This functionality requires a Pro plan", + redirect_field_name=None) +def nextweekplan_view(request): + r = getrower(request.user) + + form = NextWeekJsonForm() + + if request.method == "POST": + form = NextWeekJsonForm(request.POST, request.FILES) + if form.is_valid(): + f = form.cleaned_data['file'] + if f is not None: + filename, path_and_filename = handle_uploaded_file(f) + try: + with open(path_and_filename,'r') as ff: + data = json.load(ff) + except: + messages.error(request,"Hmm, invalid file") + + create_next_week_from_json(data, r) + messages.info(request,"Your planned sessions were created") + + active = 'nav-plan' + + breadcrumbs = [ + { + 'url': reverse('plannedsessions_view'), + 'name': 'Sessions' + }, + { + 'url': reverse('nextweekplan_view'), + 'name': "Next week" + }, + ] + + return render(request, + 'loadnextweek.html', + {'rower': r, + 'form': form, + 'active': active, + 'breadcrumbs': breadcrumbs}) diff --git a/rowers/views/statements.py b/rowers/views/statements.py index ea7e84e6..0b9e0aa9 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -120,7 +120,7 @@ from rowers.forms import ( TrainingPlanBillingForm, InstantPlanSelectForm, TrainingZonesForm, InstrokeForm, InStrokeMultipleCompareForm, ForceCurveMultipleCompareForm, PlanByRscoreForm, - AssignChoices, + AssignChoices, NextWeekJsonForm, ) from django.urls import reverse, reverse_lazy