diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index c4a92124..3cb67bd8 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -6557,3 +6557,200 @@ def interactive_otw_advanced_pace_chart(id=0,promember=0): div = '' return [script,div] + +def get_zones_report(rower,startdate,enddate): + duration = enddate-startdate + + totaldays = duration.total_seconds()/(24*3600) + + dates = [] + dates_sorting = [] + minutes = [] + zones = [] + + workouts = Workout.objects.filter( + user=rower, + startdatetime__gte=startdate, + startdatetime__lte=enddate, + duplicate=False, + ).order_by("-startdatetime") + + ids = [w.id for w in workouts] + + columns = ['workoutid','hr','power','time'] + + df = dataprep.getsmallrowdata_db(columns,ids=ids) + try: + df['deltat'] = df['time'].diff().clip(lower=0) + except KeyError: + pass + + df = dataprep.clean_df_stats(df,workstrokesonly=False, + ignoreadvanced=True,ignorehr=False) + + #totalmeters,totalhours, totalminutes, totalseconds = get_totals(workouts) + + hrzones = rower.hrzones + + for w in workouts: + dd = w.date.strftime('%m/%d') + dd2 = w.date.strftime('%Y/%m/%d') + dd3 = w.date.strftime('%Y/%m') + + qryw = 'workoutid == {workoutid}'.format(workoutid=w.id) + + qry = 'hr < {ut2}'.format(ut2=rower.ut2) + timeinzone = df.query(qry).query(qryw)['deltat'].sum()/(60*1e3) + if totaldays<30: + dates.append(dd) + dates_sorting.append(dd2) + else: # pragma: no cover + dates.append(dd3) + dates_sorting.append(dd3) + minutes.append(timeinzone) + zones.append(' + + + + +

Training Zones

+ +{{ the_script | safe }} + +
    +
  • +
    + {{ the_div|safe }} +
    +
  • +
+ +{% endblock %} + +{% block scripts %} +{% endblock %} + +{% block sidebar %} +{% include 'menu_plan.html' %} +{% endblock %} diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 887f897c..a7bf26c3 100644 Binary files a/rowers/tests/testdata/testdata.tcx.gz and b/rowers/tests/testdata/testdata.tcx.gz differ diff --git a/rowers/urls.py b/rowers/urls.py index 82a7cc1b..61b6ee7e 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -352,6 +352,8 @@ urlpatterns = [ re_path(r'^performancemanager/$',views.performancemanager_view,name='performancemanager_view'), re_path(r'^performancemanager/user/(?P\d+)/$',views.performancemanager_view,name='performancemanager_view'), re_path(r'^performancemanager/user/(?P\d+)/(?P\w+.*)/$',views.performancemanager_view,name='performancemanager_view'), + re_path(r'^trainingzones/$',views.trainingzones_view,name='trainingzones_view'), + re_path(r'^trainingzones/user/(?P\d+)/$',views.trainingzones_view,name='trainingzones_view'), re_path(r'^ote-bests2/user/(?P\d+)/$',views.rankings_view2,name='rankings_view2'), re_path(r'^ote-bests2/$',views.rankings_view2,name='rankings_view2'), re_path(r'^analysisdata/$',views.analysis_view_data,name='analysis_view_data'), diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index 365bf5dd..3641bce5 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -1049,6 +1049,48 @@ def goldmedalscores_view(request,userid=0, 'bestworkouts':bestworkouts, }) +@user_passes_test(ispromember, login_url="/rowers/paidplans", + message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality", + redirect_field_name=None) +@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) +def trainingzones_view(request,userid=0,mode='rower', + startdate=timezone.now()-timezone.timedelta(days=365), + enddate=timezone.now()): + + is_ajax = request_is_ajax(request) + + r = getrequestrower(request,userid=userid) + + startdate,enddate = get_dates_timeperiod(request) + enddate = timezone.now() + startdate = enddate-datetime.timedelta(days=29) + + data = get_zones_report(r,startdate,enddate) + + + script, div = interactive_zoneschart(data,startdate,enddate) + + breadcrumbs = [ + { + 'url':'/rowers/analysis', + 'name':'Analysis' + }, + { + 'url':reverse('trainingzones_view'), + 'name': 'Training Zones' + } + ] + + return render(request,'trainingzones.html', + { + 'active':'nav-analysis', + 'breadcrumbs':breadcrumbs, + 'rower':r, + 'the_script':script, + 'the_div':div, + } + ) + @user_passes_test(ispromember, login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",