diff --git a/rowers/forms.py b/rowers/forms.py index 542f7cba..3cafb247 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -991,7 +991,9 @@ class SessionDateShiftForm(forms.Form): class DeltaDaysForm(forms.Form): deltadays = forms.IntegerField(initial=7, required=False, label='') - +class PlanByRscoreForm(forms.Form): + byrscore = forms.BooleanField(initial=False, required=False, label='plan by rScore') + class RegistrationForm(UserCreationForm): """ Form for registering a new user account. diff --git a/rowers/models.py b/rowers/models.py index 4d66ab55..63da2915 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -1715,6 +1715,8 @@ class InstantPlan(models.Model): price = models.IntegerField(default=0, verbose_name="Price in EURO") url = models.CharField(max_length=250, blank=True, verbose_name="Link to page with more information") + private = models.BooleanField(default=False, + verbose_name="Hidden, personal") def __str__(self): # pragma: no cover return self.name @@ -1753,6 +1755,7 @@ class InstantPlanForm(ModelForm): 'hoursperweek', 'sessionsperweek', 'yaml', + 'private' ] @@ -2810,7 +2813,7 @@ class PlannedSession(models.Model): self.sessionvalue = self.approximate_duration elif self.sessionmode == 'distance': # pragma: no cover self.sessionvalue = self.approximate_distance - elif self.sessionmode == 'rscore': # pragma: no cover + elif self.sessionmode == 'rScore': # pragma: no cover self.sessionvalue = self.approximate_rscore super(PlannedSession, self).save(*args, **kwargs) diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index 1b52f280..8b795e05 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -1063,7 +1063,7 @@ def get_workouts_session(r, ps): return ws -def create_sessions_from_json(plansteps, rower, startdate, manager): +def create_sessions_from_json(plansteps, rower, startdate, manager, planbyrscore=False): trainingdays = plansteps['trainingDays'] planstartdate = startdate for day in trainingdays: @@ -1076,6 +1076,10 @@ def create_sessions_from_json(plansteps, rower, startdate, manager): preferreddate = planstartdate+timedelta(days=day['order']) + sessionmode = 'time' + if planbyrscore: + sessionmode = 'rScore' + ps = PlannedSession( startdate=preferreddate - timedelta(days=preferreddate.weekday()), @@ -1086,7 +1090,7 @@ def create_sessions_from_json(plansteps, rower, startdate, manager): name=workout['workoutName'], steps=workout, manager=manager, - sessionmode='time', + sessionmode=sessionmode, comment=workout['description'] ) diff --git a/rowers/templates/instantplan.html b/rowers/templates/instantplan.html index 313d75d8..727bcbcf 100644 --- a/rowers/templates/instantplan.html +++ b/rowers/templates/instantplan.html @@ -58,6 +58,9 @@ {% endif %}
Created by: {{ plan.owner.first_name }} {{ plan.owner.last_name }}
Plan length: {{ plan.duration }} days
{{ plan.description }}
+ {% if plan.private %} +Private
+ {% endif %} {% if plan.target %}What the plan will achieve: {{ plan.target }}
{% endif %} diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 95c8d3aa..f1e5bf85 100644 Binary files a/rowers/tests/testdata/testdata.tcx.gz and b/rowers/tests/testdata/testdata.tcx.gz differ diff --git a/rowers/utils.py b/rowers/utils.py index 72e4b799..a77e3fd8 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -690,7 +690,7 @@ def steps_write_fit(steps): return filename -def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7): +def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7, powerzones=None): seconds = 0 distance = 0 rscore = 0 @@ -721,6 +721,8 @@ def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7): else: velomid = avgspeed + distance = velomid*seconds + veloratio = (velomid/ftv)**(3.0) rscoreperhour = 100.*veloratio rscore = rscoreperhour*seconds/3600. @@ -732,7 +734,9 @@ def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7): if value != 0: if value < 10 and value > 0: # pragma: no cover - targetpower = ftp*0.6 + targetpower = ftp*0.6 # dit is niet correct + if powerzones is not None and value < len(powerzones)-1 and value>1: + targetpower = (powerzones[int(value)-1]+powerzones[int(value)])/(2.) elif value > 10 and value < 1000: # pragma: no cover targetpower = value*ftp/100. elif value > 1000: @@ -742,7 +746,7 @@ def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7): avgpower = targetpower if valuelow != 0 and valuehigh != 0: # pragma: no cover avgpower = (valuelow+valuehigh)/2. - avgspeed = ftv*(avgspeed/ftv)**(1./3.) + avgspeed = ftv*(avgpower/ftp)**(1./3.) distance = avgspeed*seconds rscore = 100.*(avgpower/ftp)*seconds/3600. @@ -758,6 +762,9 @@ def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7): avgspm = (valuelow+valuehigh)/2. avgpower = ftp*avgspm/ftspm + avgspeed = ftv*(avgpower/ftp)**(1./3.) + distance = avgspeed*seconds + rscore = 100*(avgpower/ftp)*seconds/3600. return seconds, distance, rscore @@ -782,6 +789,7 @@ def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7): veloratio = (velomid/ftv)**(3.0) rscoreperhour = 100.*veloratio rscore = rscoreperhour*seconds/3600. + seconds = distance/velomid if targettype == 'Power': # pragma: no cover value = step.get('targetValue', 0) @@ -800,7 +808,7 @@ def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7): avgpower = targetpower if valuelow != 0 and valuehigh != 0: avgpower = (valuelow+valuehigh)/2. - avgspeed = ftv*(avgspeed/ftv)**(1./3.) + avgspeed = ftv*(avgpower/ftp)**(1./3.) seconds = distance/avgspeed rscore = 100.*(avgpower/ftp)*seconds/3600. @@ -817,6 +825,8 @@ def step_to_time_dist(step, avgspeed=3.2, ftp=200, ftspm=25, ftv=3.7): avgpower = ftp*avgspm/ftspm rscore = 100*(avgpower/ftp)*seconds/3600. + avgspeed = ftv*(avgpower/ftp)**(1./3.) + seconds = distance/avgspeed return seconds, distance, rscore elif durationtype in ['PowerLessThan', 'PowerGreaterThan', 'HrLessThan', 'HrGreaterThan']: # pragma: no cover @@ -890,15 +900,17 @@ def ps_dict_order(d, short=False, rower=None, html=True): steps = d['steps'] ftp = 200 + powerzones = None if rower is not None: ftp = rower.ftp + powerzones = [rower.pw_ut2, rower.pw_ut1, rower.pw_at, rower.pw_tr, rower.pw_an] # ftv = rower.ftv # ftspm = rower.ftspm for step in steps: sstring, type, stepID, repeatID, repeatValue = step_to_string( step, short=short) - seconds, meters, rscore = step_to_time_dist(step, ftp=ftp) + seconds, meters, rscore = step_to_time_dist(step, ftp=ftp, powerzones=powerzones) sdict[stepID] = { 'string': sstring, @@ -913,6 +925,7 @@ def ps_dict_order(d, short=False, rower=None, html=True): sdict2 = collections.OrderedDict(reversed(list(sdict.items()))) + for step in steps: sstring, type, stepID, repeatID, repeatValue = step_to_string( step, short=short) diff --git a/rowers/views/paymentviews.py b/rowers/views/paymentviews.py index 07f5efb7..87fe7bac 100644 --- a/rowers/views/paymentviews.py +++ b/rowers/views/paymentviews.py @@ -848,7 +848,12 @@ def rower_register_view(request): weightcategory = form.cleaned_data['weightcategory'] adaptiveclass = form.cleaned_data['adaptiveclass'] nextpage = request.POST['next'] - theuser = User.objects.create_user(username, password=password) + try: + theuser = User.objects.create_user(username, password=password) + except: + messages.error(request, "This user name already exists, choose another one") + url = reverse('rower_register_view') + return HttpResponseRedirect(url) theuser.first_name = first_name theuser.last_name = last_name theuser.email = email diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py index 6244efb7..bb0248a7 100644 --- a/rowers/views/planviews.py +++ b/rowers/views/planviews.py @@ -1417,7 +1417,6 @@ def save_plan_yaml(request, userid=0): elif ps.sessionmode == 'time': ps.interval_string = '{d}min'.format(d=ps.sessionvalue) elif ps.sessionmode == 'rScore': - print('aap') ps.approximate_duration = ps.sessionvalue ps.interval_string = '{d}min'.format(d=ps.sessionvalue) elif ps.sessionmode == 'TRIMP': @@ -2624,6 +2623,8 @@ def rower_view_instantplan(request, id='', userid=0): nextday['week'] = (divmod(i, 7)[0])+1 trainingdays2.append(nextday) + + workouts = nextday['workouts'] try: nextday = trainingdays.pop(0) except IndexError: @@ -2670,6 +2671,14 @@ def rower_view_instantplan(request, id='', userid=0): return HttpResponseRedirect(url) form = InstantPlanSelectForm(request.POST, targets=targets) + byrscoreform = PlanByRscoreForm(request.POST) + if byrscoreform.is_valid(): + try: + byrscore = byrscoreform.cleaned_data['byrscore'] + except KeyError: + byrscore = False + else: + byrscore = False if form.is_valid(): if plan.price > 0: # pragma: no cover @@ -2718,7 +2727,7 @@ def rower_view_instantplan(request, id='', userid=0): p.save() p.rowers.add(r) - create_sessions_from_json(plansteps, r, startdate, r.user) + create_sessions_from_json(plansteps, r, startdate, r.user, planbyrscore=byrscore) messages.info(request, 'Your Sessions have been added') @@ -2739,6 +2748,13 @@ def rower_view_instantplan(request, id='', userid=0): } form = InstantPlanSelectForm( targets=targets, instantplan=plan, initial=initial) + if request.user.is_superuser: + byrscoreform = PlanByRscoreForm() + else: + byrscoreform = None + + + else: # pragma: no cover form = None @@ -2771,6 +2787,7 @@ def rower_view_instantplan(request, id='', userid=0): 'rower': r, 'active': 'nav-plan', 'plan': plan, + 'byrscoreform': byrscoreform, 'trainingdays': trainingdays2, 'breadcrumbs': breadcrumbs, 'form': form, @@ -2849,8 +2866,15 @@ def rower_select_instantplan(request, id=0): r = getrequestrower(request, userid=id) # get and present available plans - ips = InstantPlan.objects.all().order_by( - "name", "sessionsperweek", "hoursperweek", "duration", "id") + ips = InstantPlan.objects.filter(private=False) + + if not request.user.is_anonymous: + + ips2 = InstantPlan.objects.filter(owner=request.user) + + ips = ips | ips2 + + ips = ips.order_by("private", "name", "sessionsperweek", "hoursperweek", "duration", "id") breadcrumbs = [ { @@ -2976,6 +3000,7 @@ def rower_create_trainingplan(request, id=0): initial={'status': False, 'rowers': [therower]}, user=request.user) + breadcrumbs = [ { 'url': reverse(plannedsessions_view, diff --git a/rowers/views/statements.py b/rowers/views/statements.py index 1dc57d34..a1d2acc3 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -113,7 +113,7 @@ from rowers.forms import ( StravaChartForm, FitnessFitForm, PerformanceManagerForm, TrainingPlanBillingForm, InstantPlanSelectForm, TrainingZonesForm, InstrokeForm, InStrokeMultipleCompareForm, - ForceCurveMultipleCompareForm + ForceCurveMultipleCompareForm, PlanByRscoreForm ) from django.urls import reverse, reverse_lazy