from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals from __future__ import unicode_literals, absolute_import from rowers.views.statements import * # Histogram for a date/time range @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def histo(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=365), enddate=timezone.now(), deltadays=-1, enddatestring=timezone.now().strftime("%Y-%m-%d"), startdatestring=(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), options={ 'includereststrokes':False, 'workouttypes':[i[0] for i in mytypes.workouttypes], 'waterboattype':mytypes.waterboattype, 'rankingonly': False, }): r = getrequestrower(request,userid=theuser) theuser = r.user if 'waterboattype' in request.session: waterboattype = request.session['waterboattype'] else: waterboattype = mytypes.waterboattype if 'rankingonly' in request.session: rankingonly = request.session['rankingonly'] else: rankingonly = False if 'modalities' in request.session: modalities = request.session['modalities'] if len(modalities) > 1: modality = 'all' else: modality = modalities[0] else: modalities = [m[0] for m in mytypes.workouttypes] modality = 'all' try: rankingonly = options['rankingonly'] except KeyError: rankingonly = False try: includereststrokes = options['includereststrokes'] except KeyError: includereststrokes = False workstrokesonly = not includereststrokes waterboattype = mytypes.waterboattype if startdatestring != "": startdate = iso8601.parse_date(startdatestring) if enddatestring != "": enddate = iso8601.parse_date(enddatestring) if enddate < startdate: s = enddate enddate = startdate startdate = s # get all indoor rows of in date range # process form if request.method == 'POST': form = DateRangeForm(request.POST) modalityform = TrendFlexModalForm(request.POST) if form.is_valid(): startdate = form.cleaned_data['startdate'] enddate = form.cleaned_data['enddate'] if startdate > enddate: s = enddate enddate = startdate startdate = s startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') if modalityform.is_valid(): modality = modalityform.cleaned_data['modality'] waterboattype = modalityform.cleaned_data['waterboattype'] rankingonly = modalityform.cleaned_data['rankingonly'] if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: modalities = [modality] if modality != 'water': waterboattype = [b[0] for b in mytypes.boattypes] request.session['modalities'] = modalities request.session['waterboattype'] = waterboattype request.session['rankingonly'] = rankingonly form = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) else: form = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) includereststrokes = False workstrokesonly = not includereststrokes modalityform = TrendFlexModalForm( initial={ 'modality':modality, 'waterboattype':waterboattype, 'rankingonly':rankingonly, } ) negtypes = [] for b in mytypes.boattypes: if b[0] not in waterboattype: negtypes.append(b[0]) script = '' div = get_call() js_resources = '' css_resources = '' options = { 'modality': modality, 'theuser': theuser.id, 'waterboattype':waterboattype, 'startdatestring':startdatestring, 'enddatestring':enddatestring, 'rankingonly':rankingonly, 'includereststrokes':includereststrokes, } request.session['options'] = options promember=0 mayedit=0 if not request.user.is_anonymous(): result = request.user.is_authenticated() and ispromember(request.user) if result: promember = 1 request.session['options'] = options return render(request, 'histo.html', {'interactiveplot':script, 'the_div':div, 'id':theuser, 'active':'nav-analysis', 'theuser':theuser, 'rower':r, 'startdate':startdate, 'enddate':enddate, 'form':form, 'optionsform':modalityform, 'teams':get_my_teams(request.user), }) # The Flex plot for a large selection of workouts @login_required() def cum_flex_data( request, options={ 'includereststrokes':False, 'rankingonly':False, 'modality':'all', 'waterboattype':mytypes.waterboattype, 'theuser':0, 'xparam':'spm', 'yparam1':'power', 'yparam2':'None', 'enddatestring':timezone.now().strftime("%Y-%m-%d"), 'startdatestring':(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), 'deltadays':-1, }): def_options = options if 'options' in request.session: options = request.session['options'] modality = keyvalue_get_default('modality',options,def_options) rankingonly = keyvalue_get_default('rankingonly',options,def_options) includereststrokes = keyvalue_get_default('includereststrokes',options,def_options) waterboattype = keyvalue_get_default('waterboattype',options,def_options) workstrokesonly = not includereststrokes theuser = keyvalue_get_default('theuser',options,def_options) xparam = keyvalue_get_default('xparam',options,def_options) yparam1 = keyvalue_get_default('yparam1',options,def_options) yparam2 = keyvalue_get_default('yparam2',options,def_options) startdatestring = keyvalue_get_default('startdatestring',options,def_options) enddatestring = keyvalue_get_default('enddatestring',options,def_options) if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: modalities = [modality] try: startdate = iso8601.parse_date(startdatestring) except ParseError: startdate = timezone.now()-datetime.timedelta(days=7) try: enddate = iso8601.parse_date(enddatestring) except ParseError: enddate = timezone.now() if enddate < startdate: s = enddate enddate = startdate startdate = s promember=0 if theuser == 0: theuser = request.user.id if not request.user.is_anonymous(): r = getrower(request.user) result = request.user.is_authenticated() and ispromember(request.user) if result: promember=1 r2 = getrower(theuser) if rankingonly: rankingpiece = [True,] else: rankingpiece = [True,False] allworkouts = Workout.objects.filter(user=r2, workouttype__in=modalities, boattype__in=waterboattype, startdatetime__gte=startdate, startdatetime__lte=enddate, rankingpiece__in=rankingpiece) if allworkouts: res = interactive_cum_flex_chart2(allworkouts,xparam=xparam, yparam1=yparam1, yparam2=yparam2, promember=promember, workstrokesonly=workstrokesonly, ) script = res[0] div = res[1] else: script = '' div = '

No pieces uploaded for this date range.

' scripta = script.split('\n')[2:-1] script = ''.join(scripta) data = { "script":script, "div":div, } return JSONResponse(data) # The Flex plot for a large selection of workouts @login_required() def histo_data( request, options={ 'includereststrokes':False, 'rankingonly':False, 'modality':'all', 'waterboattype':mytypes.waterboattype, 'theuser':0, 'enddatestring':timezone.now().strftime("%Y-%m-%d"), 'startdatestring':(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), 'deltadays':-1, }): def_options = options if 'options' in request.session: options = request.session['options'] modality = keyvalue_get_default('modality',options,def_options) rankingonly = keyvalue_get_default('rankingonly',options,def_options) includereststrokes = keyvalue_get_default('includereststrokes',options,def_options) waterboattype = keyvalue_get_default('waterboattype',options,def_options) workstrokesonly = not includereststrokes theuser = keyvalue_get_default('theuser',options,def_options) startdatestring = keyvalue_get_default('startdatestring',options,def_options) enddatestring = keyvalue_get_default('enddatestring',options,def_options) if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: modalities = [modality] try: startdate = iso8601.parse_date(startdatestring) except ParseError: startdate = timezone.now()-datetime.timedelta(days=7) try: enddate = iso8601.parse_date(enddatestring) except ParseError: enddate = timezone.now() if enddate < startdate: s = enddate enddate = startdate startdate = s promember=0 if theuser == 0: theuser = request.user.id if not request.user.is_anonymous(): r = getrower(request.user) result = request.user.is_authenticated() and ispromember(request.user) if result: promember=1 r2 = getrower(theuser) if rankingonly: rankingpiece = [True,] else: rankingpiece = [True,False] allworkouts = Workout.objects.filter(user=r2, workouttype__in=modalities, boattype__in=waterboattype, startdatetime__gte=startdate, startdatetime__lte=enddate, rankingpiece__in=rankingpiece) if allworkouts: res = interactive_histoall(allworkouts) script = res[0] div = res[1] else: script = '' div = '

No pieces uploaded for this date range.

' scripta = script.split('\n')[2:-1] script = ''.join(scripta) data = { "script":script, "div":div, } return JSONResponse(data) @login_required() def cum_flex(request,theuser=0, xparam='spm', yparam1='power', yparam2='None', startdate=timezone.now()-datetime.timedelta(days=10), enddate=timezone.now(), deltadays=-1, enddatestring=timezone.now().strftime("%Y-%m-%d"), startdatestring=(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), options={ 'includereststrokes':False, 'workouttypes':[i[0] for i in mytypes.workouttypes], 'waterboattype':mytypes.waterboattype, 'rankingonly':False, }): r = getrequestrower(request,userid=theuser) theuser = r.user if 'waterboattype' in request.session: waterboattype = request.session['waterboattype'] else: waterboattype = mytypes.waterboattype if 'rankingonly' in request.session: rankingonly = request.session['rankingonly'] else: rankingonly = False if 'modalities' in request.session: modalities = request.session['modalities'] if len(modalities) > 1: modality = 'all' else: modality = modalities[0] else: modalities = [m[0] for m in mytypes.workouttypes] modality = 'all' try: rankingonly = options['rankingonly'] except KeyError: rankingonly = False try: includereststrokes = options['includereststrokes'] except KeyError: includereststrokes = False workstrokesonly = not includereststrokes waterboattype = mytypes.waterboattype if startdatestring != "": startdate = iso8601.parse_date(startdatestring) if enddatestring != "": enddate = iso8601.parse_date(enddatestring) if enddate < startdate: s = enddate enddate = startdate startdate = s # get all indoor rows of in date range # process form if request.method == 'POST': form = DateRangeForm(request.POST) modalityform = TrendFlexModalForm(request.POST) flexaxesform = FlexAxesForm(request,request.POST) if form.is_valid(): startdate = form.cleaned_data['startdate'] enddate = form.cleaned_data['enddate'] if startdate > enddate: s = enddate enddate = startdate startdate = s startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') if modalityform.is_valid(): modality = modalityform.cleaned_data['modality'] waterboattype = modalityform.cleaned_data['waterboattype'] rankingonly = modalityform.cleaned_data['rankingonly'] if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: modalities = [modality] if modality != 'water': waterboattype = [b[0] for b in mytypes.boattypes] request.session['modalities'] = modalities request.session['waterboattype'] = waterboattype request.session['rankingonly'] = rankingonly form = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) if flexaxesform.is_valid(): xparam = flexaxesform.cleaned_data['xaxis'] yparam1 = flexaxesform.cleaned_data['yaxis1'] yparam2 = flexaxesform.cleaned_data['yaxis2'] else: form = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) includereststrokes = False workstrokesonly = not includereststrokes modalityform = TrendFlexModalForm( initial={ 'modality':modality, 'waterboattype':waterboattype, 'rankingonly':rankingonly, } ) initial = { 'xaxis':xparam, 'yaxis1':yparam1, 'yaxis2':yparam2 } flexaxesform = FlexAxesForm(request,initial=initial) negtypes = [] for b in mytypes.boattypes: if b[0] not in waterboattype: negtypes.append(b[0]) script = '' div = get_call() js_resources = '' css_resources = '' options = { 'xparam': xparam, 'yparam1': yparam1, 'yparam2': yparam2, 'modality': modality, 'theuser': theuser.id, 'waterboattype':waterboattype, 'startdatestring':startdatestring, 'enddatestring':enddatestring, 'rankingonly':rankingonly, 'includereststrokes':includereststrokes, } request.session['options'] = options promember=0 mayedit=0 if not request.user.is_anonymous(): result = request.user.is_authenticated() and ispromember(request.user) if result: promember = 1 request.session['options'] = options return render(request, 'cum_flex.html', {'interactiveplot':script, 'the_div':div, 'js_res': js_resources, 'css_res':css_resources, 'id':theuser, 'rower':r, 'active':'nav-analysis', 'theuser':theuser, 'startdate':startdate, 'enddate':enddate, 'form':form, 'optionsform':modalityform, 'xparam':xparam, 'yparam1':yparam1, 'yparam2':yparam2, 'promember':promember, 'teams':get_my_teams(request.user), 'flexaxesform':flexaxesform, }) def planrequired_view(request): messages.info(request,"This functionality requires Coach or Self-Coach membership") return HttpResponseRedirect(reverse('paidplans')) @user_passes_test(hasplannedsessions,login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", redirect_field_name=None) def fitnessmetric_view(request,id=0,mode='rower', startdate=timezone.now()-timezone.timedelta(days=365), enddate=timezone.now()): therower = getrequestrower(request,userid=id) theuser = therower.user if request.method == 'POST': form = FitnessMetricForm(request.POST) if form.is_valid(): startdate = form.cleaned_data['startdate'] enddate = form.cleaned_data['enddate'] mode = form.cleaned_data['mode'] else: form = FitnessMetricForm() fitnessmetrics = PowerTimeFitnessMetric.objects.filter( user=theuser, date__gte=startdate, date__lte=enddate) script,thediv = fitnessmetric_chart( fitnessmetrics,theuser, workoutmode=mode ) return render(request,'fitnessmetric.html', { 'rower':therower, 'active':'nav-analysis', 'chartscript':script, 'the_div':thediv, 'mode':mode, 'form':form, }) # Show ranking distances including predicted paces @login_required() def rankings_view(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=365), enddate=timezone.now(), deltadays=-1, startdatestring="", enddatestring=""): if deltadays>0: startdate = enddate-datetime.timedelta(days=int(deltadays)) if startdatestring != "": startdate = iso8601.parse_date(startdatestring) if enddatestring != "": enddate = iso8601.parse_date(enddatestring) if enddate < startdate: s = enddate enddate = startdate startdate = s if theuser == 0: theuser = request.user.id promember=0 if not request.user.is_anonymous(): r = getrower(request.user) if r.birthdate: age = calculate_age(r.birthdate) worldclasspower = int(metrics.getagegrouprecord( age, sex=r.sex, weightcategory=r.weightcategory, )) else: worldclasspower = None result = request.user.is_authenticated() and ispromember(request.user) if result: promember=1 # get all indoor rows in date range # process form if request.method == 'POST' and "daterange" in request.POST: dateform = DateRangeForm(request.POST) deltaform = DeltaDaysForm(request.POST) if dateform.is_valid(): startdate = dateform.cleaned_data['startdate'] enddate = dateform.cleaned_data['enddate'] if startdate > enddate: s = enddate enddate = startdate startdate = s elif request.method == 'POST' and "datedelta" in request.POST: deltaform = DeltaDaysForm(request.POST) if deltaform.is_valid(): deltadays = deltaform.cleaned_data['deltadays'] if deltadays: enddate = timezone.now() startdate = enddate-datetime.timedelta(days=deltadays) if startdate > enddate: s = enddate enddate = startdate startdate = s dateform = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) else: dateform = DateRangeForm() deltaform = DeltaDaysForm() else: dateform = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) deltaform = DeltaDaysForm() # get all 2k (if any) - this rower, in date range try: r = getrower(theuser) except Rower.DoesNotExist: allergworkouts = [] r=0 try: uu = User.objects.get(id=theuser) except User.DoesNotExist: uu = '' # test to fix bug startdate = datetime.datetime.combine(startdate,datetime.time()) enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) #enddate = enddate+datetime.timedelta(days=1) thedistances = [] theworkouts = [] thesecs = [] rankingdistances.sort() rankingdurations.sort() for rankingdistance in rankingdistances: workouts = Workout.objects.filter( user=r,distance=rankingdistance, workouttype__in=['rower','dynamic','slides'], rankingpiece=True, startdatetime__gte=startdate, startdatetime__lte=enddate ).order_by('duration') if workouts: thedistances.append(rankingdistance) theworkouts.append(workouts[0]) timesecs = 3600*workouts[0].duration.hour timesecs += 60*workouts[0].duration.minute timesecs += workouts[0].duration.second timesecs += 1.e-6*workouts[0].duration.microsecond thesecs.append(timesecs) for rankingduration in rankingdurations: workouts = Workout.objects.filter( user=r,duration=rankingduration, workouttype='rower', rankingpiece=True, startdatetime__gte=startdate, startdatetime__lte=enddate ).order_by('-distance') if workouts: thedistances.append(workouts[0].distance) theworkouts.append(workouts[0]) timesecs = 3600*workouts[0].duration.hour timesecs += 60*workouts[0].duration.minute timesecs += workouts[0].duration.second timesecs += 1.e-5*workouts[0].duration.microsecond thesecs.append(timesecs) thedistances = np.array(thedistances) thesecs = np.array(thesecs) thevelos = thedistances/thesecs theavpower = 2.8*(thevelos**3) # create interactive plot if len(thedistances) !=0 : res = interactive_cpchart( r,thedistances,thesecs,theavpower, theworkouts,promember=promember ) script = res[0] div = res[1] paulslope = res[2] paulintercept = res[3] p1 = res[4] message = res[5] else: script = '' div = '

No ranking pieces found.

' paulslope = 1 paulintercept = 1 p1 = [1,1,1,1] message = "" if request.method == 'POST' and "piece" in request.POST: form = PredictedPieceForm(request.POST) if form.is_valid(): value = form.cleaned_data['value'] hourvalue,value = divmod(value,60) if hourvalue >= 24: hourvalue = 23 pieceunit = form.cleaned_data['pieceunit'] if pieceunit == 'd': rankingdistances.append(value) else: rankingdurations.append(datetime.time(minute=int(value),hour=int(hourvalue))) else: form = PredictedPieceForm() rankingdistances.sort() rankingdurations.sort() predictions = [] cpredictions = [] for rankingdistance in rankingdistances: # Paul's model p = paulslope*np.log10(rankingdistance)+paulintercept velo = 500./p t = rankingdistance/velo pwr = 2.8*(velo**3) a = {'distance':rankingdistance, 'duration':timedeltaconv(t), 'pace':timedeltaconv(p), 'power':int(pwr)} predictions.append(a) # CP model - pwr2 = p1[0]/(1+t/p1[2]) pwr2 += p1[1]/(1+t/p1[3]) if pwr2 <= 0: pwr2 = 50. velo2 = (pwr2/2.8)**(1./3.) if np.isnan(velo2) or velo2 <= 0: velo2 = 1.0 t2 = rankingdistance/velo2 pwr3 = p1[0]/(1+t2/p1[2]) pwr3 += p1[1]/(1+t2/p1[3]) if pwr3 <= 0: pwr3 = 50. velo3 = (pwr3/2.8)**(1./3.) if np.isnan(velo3) or velo3 <= 0: velo3 = 1.0 t3 = rankingdistance/velo3 p3 = 500./velo3 a = {'distance':rankingdistance, 'duration':timedeltaconv(t3), 'pace':timedeltaconv(p3), 'power':int(pwr3)} cpredictions.append(a) for rankingduration in rankingdurations: t = 3600.*rankingduration.hour t += 60.*rankingduration.minute t += rankingduration.second t += rankingduration.microsecond/1.e6 # Paul's model ratio = paulintercept/paulslope u = ((2**(2+ratio))*(5.**(3+ratio))*t*np.log(10))/paulslope d = 500*t*np.log(10.) d = d/(paulslope*lambertw(u)) d = d.real velo = d/t p = 500./velo pwr = 2.8*(velo**3) a = {'distance':int(d), 'duration':timedeltaconv(t), 'pace':timedeltaconv(p), 'power':int(pwr)} predictions.append(a) # CP model pwr = p1[0]/(1+t/p1[2]) pwr += p1[1]/(1+t/p1[3]) if pwr <= 0: pwr = 50. velo = (pwr/2.8)**(1./3.) if np.isnan(velo) or velo <=0: velo = 1.0 d = t*velo p = 500./velo a = {'distance':int(d), 'duration':timedeltaconv(t), 'pace':timedeltaconv(p), 'power':int(pwr)} cpredictions.append(a) messages.error(request,message) return render(request, 'rankings.html', {'rankingworkouts':theworkouts, 'interactiveplot':script, 'the_div':div, 'predictions':predictions, 'cpredictions':cpredictions, 'nrdata':len(thedistances), 'form':form, 'rower':r, 'active':'nav-analysis', 'dateform':dateform, 'deltaform':deltaform, 'worldclasspower':worldclasspower, 'id': theuser, 'theuser':uu, 'startdate':startdate, 'enddate':enddate, 'teams':get_my_teams(request.user), }) @login_required() def ajax_agegrouprecords(request, age=25, sex='female', weightcategory='hwt', userid=0): wcdurations = [] wcpower = [] durations = [1,4,30,60] distances = [100,500,1000,2000,5000,6000,10000,21097,42195] df = pd.DataFrame( list( C2WorldClassAgePerformance.objects.filter( sex=sex, weightcategory=weightcategory ).values() ) ) jsondf = df.to_json() job = myqueue(queue, handle_getagegrouprecords, jsondf,distances,durations,age,sex,weightcategory, ) return JSONResponse( { 'job':job.id } ) # Show ranking distances including predicted paces @login_required() def rankings_view2(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=365), enddate=timezone.now(), deltadays=-1, startdatestring="", enddatestring=""): if deltadays>0: startdate = enddate-datetime.timedelta(days=int(deltadays)) if startdatestring != "": startdate = iso8601.parse_date(startdatestring) if enddatestring != "": enddate = iso8601.parse_date(enddatestring) if enddate < startdate: s = enddate enddate = startdate startdate = s if theuser == 0: theuser = request.user.id else: lastupdated = "01-01-1900" promember=0 if not request.user.is_anonymous(): r = getrower(request.user) wcdurations = [] wcpower = [] lastupdated = "01-01-1900" userid = 0 if 'options' in request.session: options = request.session['options'] try: wcdurations = options['wcdurations'] wcpower = options['wcpower'] lastupdated = options['lastupdated'] except KeyError: pass try: userid = options['userid'] except KeyError: userid = 0 else: options = {} lastupdatedtime = arrow.get(lastupdated).timestamp current_time = arrow.utcnow().timestamp deltatime_seconds = current_time - lastupdatedtime recalc = False if str(userid) != str(theuser) or deltatime_seconds > 3600: recalc = True options['lastupdated'] = arrow.utcnow().isoformat() else: recalc = False options['userid'] = theuser if r.birthdate: age = calculate_age(r.birthdate) else: worldclasspower = None age = 0 agerecords = CalcAgePerformance.objects.filter( age = age, sex = r.sex, weightcategory = r.weightcategory) if len(agerecords) == 0: recalc = True wcpower = [] wcduration = [] else: wcdurations = [] wcpower = [] for record in agerecords: wcdurations.append(record.duration) wcpower.append(record.power) options['wcpower'] = wcpower options['wcdurations'] = wcdurations if theuser: options['userid'] = theuser request.session['options'] = options result = request.user.is_authenticated() and ispromember(request.user) if result: promember=1 # get all indoor rows in date range # process form if request.method == 'POST' and "daterange" in request.POST: dateform = DateRangeForm(request.POST) deltaform = DeltaDaysForm(request.POST) if dateform.is_valid(): startdate = dateform.cleaned_data['startdate'] enddate = dateform.cleaned_data['enddate'] if startdate > enddate: s = enddate enddate = startdate startdate = s elif request.method == 'POST' and "datedelta" in request.POST: deltaform = DeltaDaysForm(request.POST) if deltaform.is_valid(): deltadays = deltaform.cleaned_data['deltadays'] if deltadays: enddate = timezone.now() startdate = enddate-datetime.timedelta(days=deltadays) if startdate > enddate: s = enddate enddate = startdate startdate = s dateform = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) else: dateform = DateRangeForm() deltaform = DeltaDaysForm() else: dateform = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) deltaform = DeltaDaysForm() # get all 2k (if any) - this rower, in date range try: r = getrower(theuser) except Rower.DoesNotExist: allergworkouts = [] r=0 try: uu = User.objects.get(id=theuser) except User.DoesNotExist: uu = '' # test to fix bug startdate = datetime.datetime.combine(startdate,datetime.time()) enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) #enddate = enddate+datetime.timedelta(days=1) thedistances = [] theworkouts = [] thesecs = [] rankingdistances.sort() rankingdurations.sort() for rankingdistance in rankingdistances: workouts = Workout.objects.filter( user=r,distance=rankingdistance, workouttype__in=['rower','dynamic','slides'], rankingpiece=True, startdatetime__gte=startdate, startdatetime__lte=enddate).order_by('duration') if workouts: thedistances.append(rankingdistance) theworkouts.append(workouts[0]) timesecs = 3600*workouts[0].duration.hour timesecs += 60*workouts[0].duration.minute timesecs += workouts[0].duration.second timesecs += 1.e-6*workouts[0].duration.microsecond thesecs.append(timesecs) for rankingduration in rankingdurations: workouts = Workout.objects.filter( user=r,duration=rankingduration, workouttype='rower', rankingpiece=True, startdatetime__gte=startdate, startdatetime__lte=enddate).order_by('-distance') if workouts: thedistances.append(workouts[0].distance) theworkouts.append(workouts[0]) timesecs = 3600*workouts[0].duration.hour timesecs += 60*workouts[0].duration.minute timesecs += workouts[0].duration.second timesecs += 1.e-5*workouts[0].duration.microsecond thesecs.append(timesecs) thedistances = np.array(thedistances) thesecs = np.array(thesecs) thevelos = thedistances/thesecs theavpower = 2.8*(thevelos**3) # create interactive plot if len(thedistances) !=0 : res = interactive_cpchart( r,thedistances,thesecs,theavpower, theworkouts,promember=promember, wcdurations=wcdurations,wcpower=wcpower ) script = res[0] div = res[1] paulslope = res[2] paulintercept = res[3] p1 = res[4] message = res[5] try: testcalc = pd.Series(res[6])*3 except TypeError: age = 0 else: script = '' div = '

No ranking pieces found.

' paulslope = 1 paulintercept = 1 p1 = [1,1,1,1] message = "" if request.method == 'POST' and "piece" in request.POST: form = PredictedPieceForm(request.POST) if form.is_valid(): value = form.cleaned_data['value'] hourvalue,value = divmod(value,60) if hourvalue >= 24: hourvalue = 23 pieceunit = form.cleaned_data['pieceunit'] if pieceunit == 'd': rankingdistances.append(value) else: rankingdurations.append(datetime.time(minute=int(value),hour=int(hourvalue))) else: form = PredictedPieceForm() rankingdistances.sort() rankingdurations.sort() predictions = [] cpredictions = [] for rankingdistance in rankingdistances: # Paul's model p = paulslope*np.log10(rankingdistance)+paulintercept velo = 500./p t = rankingdistance/velo pwr = 2.8*(velo**3) a = {'distance':rankingdistance, 'duration':timedeltaconv(t), 'pace':timedeltaconv(p), 'power':int(pwr)} predictions.append(a) # CP model - pwr2 = p1[0]/(1+t/p1[2]) pwr2 += p1[1]/(1+t/p1[3]) if pwr2 <= 0: pwr2 = 50. velo2 = (pwr2/2.8)**(1./3.) if np.isnan(velo2) or velo2 <= 0: velo2 = 1.0 t2 = rankingdistance/velo2 pwr3 = p1[0]/(1+t2/p1[2]) pwr3 += p1[1]/(1+t2/p1[3]) if pwr3 <= 0: pwr3 = 50. velo3 = (pwr3/2.8)**(1./3.) if np.isnan(velo3) or velo3 <= 0: velo3 = 1.0 t3 = rankingdistance/velo3 p3 = 500./velo3 a = {'distance':rankingdistance, 'duration':timedeltaconv(t3), 'pace':timedeltaconv(p3), 'power':int(pwr3)} cpredictions.append(a) for rankingduration in rankingdurations: t = 3600.*rankingduration.hour t += 60.*rankingduration.minute t += rankingduration.second t += rankingduration.microsecond/1.e6 # Paul's model ratio = paulintercept/paulslope u = ((2**(2+ratio))*(5.**(3+ratio))*t*np.log(10))/paulslope d = 500*t*np.log(10.) d = d/(paulslope*lambertw(u)) d = d.real velo = d/t p = 500./velo pwr = 2.8*(velo**3) try: a = {'distance':int(d), 'duration':timedeltaconv(t), 'pace':timedeltaconv(p), 'power':int(pwr)} predictions.append(a) except: pass # CP model pwr = p1[0]/(1+t/p1[2]) pwr += p1[1]/(1+t/p1[3]) if pwr <= 0: pwr = 50. velo = (pwr/2.8)**(1./3.) if np.isnan(velo) or velo <=0: velo = 1.0 d = t*velo p = 500./velo a = {'distance':int(d), 'duration':timedeltaconv(t), 'pace':timedeltaconv(p), 'power':int(pwr)} cpredictions.append(a) if recalc: wcdurations = [] wcpower = [] durations = [1,4,30,60] distances = [100,500,1000,2000,5000,6000,10000,21097,42195] df = pd.DataFrame( list( C2WorldClassAgePerformance.objects.filter( sex=r.sex, weightcategory=r.weightcategory ).values() ) ) jsondf = df.to_json() job = myqueue(queue, handle_getagegrouprecords, jsondf,distances,durations,age,r.sex,r.weightcategory) try: request.session['async_tasks'] += [(job.id,'agegrouprecords')] except KeyError: request.session['async_tasks'] = [(job.id,'agegrouprecords')] messages.error(request,message) return render(request, 'rankings.html', {'rankingworkouts':theworkouts, 'interactiveplot':script, 'the_div':div, 'predictions':predictions, 'cpredictions':cpredictions, 'nrdata':len(thedistances), 'form':form, 'dateform':dateform, 'deltaform':deltaform, 'id': theuser, 'theuser':uu, 'rower':r, 'active':'nav-analysis', 'age':age, 'sex':r.sex, 'recalc':recalc, 'weightcategory':r.weightcategory, 'startdate':startdate, 'enddate':enddate, 'teams':get_my_teams(request.user), }) # Show ranking distances including predicted paces @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def otwrankings_view(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=365), enddate=timezone.now(), startdatestring="", enddatestring=""): if startdatestring != "": try: startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring != "": try: enddate = iso8601.parse_date(enddatestring) except ParseError: pass if enddate < startdate: s = enddate enddate = startdate startdate = s if theuser == 0: if 'rowerid' in request.session: try: r = Rower.objects.get(id=request.session['rowerid']) theuser = r.user.id except Rower.DoesNotExist: theuser = request.user.id else: theuser = request.user.id promember=0 if not request.user.is_anonymous(): r = Rower.objects.get(user=request.user) result = request.user.is_authenticated() and ispromember(request.user) if result: promember=1 # get all OTW rows in date range # process form if request.method == 'POST': dateform = DateRangeForm(request.POST) if dateform.is_valid(): startdate = dateform.cleaned_data['startdate'] enddate = dateform.cleaned_data['enddate'] if startdate > enddate: s = enddate enddate = startdate startdate = s form = PredictedPieceFormNoDistance(request.POST) if form.is_valid(): value = form.cleaned_data['value'] else: value = None trankingdurations = form.cleaned_data['trankingdurations'] trankingdurations = [ datetime.datetime.strptime(d,"%H:%M:%S").time() for d in trankingdurations ] if value: hourvalue,tvalue = divmod(value,60) hourvalue = int(hourvalue) minutevalue = int(tvalue) tvalue = int(60*(tvalue-minutevalue)) if hourvalue >= 24: hourvalue = 23 trankingdurations.append(datetime.time( minute=minutevalue, hour=hourvalue, second=tvalue )) else: form = PredictedPieceFormNoDistance() dateform = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) workouttypes = ['rower','slides','dynamic'] trankingdurations = rankingdurations # get all 2k (if any) - this rower, in date range try: r = Rower.objects.get(user=theuser) request.session['rowerid'] = r.id except Rower.DoesNotExist: raise Http404("Rower doesn't exist") try: uu = User.objects.get(id=theuser) except User.DoesNotExist: uu = '' # test to fix bug startdate = datetime.datetime.combine(startdate,datetime.time()) enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) #enddate = enddate+datetime.timedelta(days=1) thedistances = [] theworkouts = [] thesecs = [] theworkouts = Workout.objects.filter( user=r,rankingpiece=True, workouttype='water', startdatetime__gte=startdate, startdatetime__lte=enddate ).order_by( "-startdatetime" ) delta,cpvalue,avgpower = dataprep.fetchcp(r,theworkouts) runningjob = 0 taskstatus = get_stored_tasks_status(request) for task in taskstatus: if task['func_name'] == 'updatecpwater': if 'success' in task['status'].lower() or 'finished' in task['status'].lower(): runningjob = 1 messages.info(request,'CP chart data have been updated') remove_asynctask(request,task['id']) elif 'fail' in task['status'].lower(): runningjob = 0 try: remove_asynctask(request,task[id]) messages.error(request,'Oh, your task failed') except KeyError: pass elif 'started' in task['status'].lower(): messages.info(request,'Busy updating CP chart data') runningjob = 1 elif 'queued' in task['status'].lower() or 'pending' in task['status'].lower(): messages.info(request,'Getting ready to update CP chart data') runningjob = 1 if not runningjob: job = dataprep.runcpupdate( r,type='water', startdate=startdate, enddate=enddate ) request.session['job_id'] = job.id try: request.session['async_tasks'] += [(job.id,'updatecpwater')] except KeyError: request.session['async_tasks'] = [(job.id,'updatecpwater')] messages.info(request,'New calculation queued. Page will reload automatically. You can check the status of your calculations here') powerdf = pd.DataFrame({ 'Delta':delta, 'CP':cpvalue, }) if powerdf.empty: messages.info(request,'Your calculations are running in the background. Page will reload automatically. You can check the status of your calculations here') powerdf = powerdf[powerdf['CP']>0] powerdf.dropna(axis=0,inplace=True) powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True) powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True) rowername = r.user.first_name+" "+r.user.last_name # create interactive plot if len(powerdf) !=0 : res = interactive_otwcpchart(powerdf,promember=promember,rowername=rowername) script = res[0] div = res[1] p1 = res[2] ratio = res[3] r.p0 = p1[0] r.p1 = p1[1] r.p2 = p1[2] r.p3 = p1[3] r.cpratio = ratio r.save() paulslope = 1 paulintercept = 1 message = res[4] else: script = '' div = '

No ranking pieces found.

' paulslope = 1 paulintercept = 1 p1 = [1,1,1,1] message = "" cpredictions = [] for rankingduration in trankingdurations: t = 3600.*rankingduration.hour t += 60.*rankingduration.minute t += rankingduration.second t += rankingduration.microsecond/1.e6 # CP model pwr = p1[0]/(1+t/p1[2]) pwr += p1[1]/(1+t/p1[3]) if pwr <= 0: pwr = 50. if not np.isnan(pwr): try: pwr2 = pwr*ratio except: pwr2 = pwr a = { 'duration':timedeltaconv(t), 'power':int(pwr), 'upper':int(pwr2)} cpredictions.append(a) startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') request.session['startdate'] = startdatestring request.session['enddate'] = enddatestring messages.error(request,message) return render(request, 'otwrankings.html', {'rankingworkouts':theworkouts, 'interactiveplot':script, 'the_div':div, 'cpredictions':cpredictions, 'rower':r, 'active':'nav-analysis', 'avgpower':avgpower, 'form':form, 'dateform':dateform, 'id': theuser, 'theuser':uu, 'startdate':startdate, 'enddate':enddate, 'teams':get_my_teams(request.user), 'workouttype':'water', }) @login_required() def otecp_toadmin_view(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=365), enddate=timezone.now(), startdatestring="", enddatestring="", ): if startdatestring != "": try: startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring != "": try: enddate = iso8601.parse_date(enddatestring) except ParseError: pass if theuser == 0: theuser = request.user.id u = User.objects.get(id=theuser) r = Rower.objects.get(user=u) startdate = datetime.datetime.combine(startdate,datetime.time()) enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) theworkouts = Workout.objects.filter( user=r,rankingpiece=True, workouttype__in=[ 'rower', 'dynamic', 'slides' ], startdatetime__gte=startdate, startdatetime__lte=enddate ).order_by("-startdatetime") delta,cpvalue,avgpower = dataprep.fetchcp( r,theworkouts,table='cpergdata' ) powerdf = pd.DataFrame({ 'Delta':delta, 'CP':cpvalue, }) csvfilename = 'CP_data_user_{id}.csv'.format( id = theuser ) powerdf = powerdf[powerdf['CP']>0] powerdf.dropna(axis=0,inplace=True) powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True) powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True) powerdf.to_csv(csvfilename) res = myqueue(queuehigh, handle_sendemailfile, 'Sander', 'Roosendaal', 'roosendaalsander@gmail.com', csvfilename, delete=True) successmessage = "The CSV file was sent to the site admin per email" messages.info(request,successmessage) response = HttpResponseRedirect('/rowers/list-workouts/') return response @login_required() def otwcp_toadmin_view(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=365), enddate=timezone.now(), startdatestring="", enddatestring="", ): if startdatestring != "": try: startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring != "": try: enddate = iso8601.parse_date(enddatestring) except ParseError: pass if theuser == 0: theuser = request.user.id u = User.objects.get(id=theuser) r = Rower.objects.get(user=u) startdate = datetime.datetime.combine(startdate,datetime.time()) enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) theworkouts = Workout.objects.filter( user=r,rankingpiece=True, workouttype='water', startdatetime__gte=startdate, startdatetime__lte=enddate ).order_by("-startdatetime") delta,cpvalue,avgpower = dataprep.fetchcp( r,theworkouts,table='cpdata' ) powerdf = pd.DataFrame({ 'Delta':delta, 'CP':cpvalue, }) csvfilename = 'CP_data_user_{id}.csv'.format( id = theuser ) powerdf = powerdf[powerdf['CP']>0] powerdf.dropna(axis=0,inplace=True) powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True) powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True) powerdf.to_csv(csvfilename) res = myqueue(queuehigh, handle_sendemailfile, 'Sander', 'Roosendaal', 'roosendaalsander@gmail.com', csvfilename, delete=True) successmessage = "The CSV file was sent to the site admin per email" messages.info(request,successmessage) response = HttpResponseRedirect('/rowers/list-workouts/') return response # Show ranking distances including predicted paces @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def oterankings_view(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=365), enddate=timezone.now(), startdatestring="", enddatestring=""): if startdatestring != "": try: startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring != "": try: enddate = iso8601.parse_date(enddatestring) except ParseError: pass if enddate < startdate: s = enddate enddate = startdate startdate = s if theuser == 0: if 'rowerid' in request.session: try: r = Rower.objects.get(id=request.session['rowerid']) theuser = r.user.id except Rower.DoesNotExist: theuser = request.user.id else: theuser = request.user.id promember=0 if not request.user.is_anonymous(): r = Rower.objects.get(user=request.user) result = request.user.is_authenticated() and ispromember(request.user) if result: promember=1 # get all OTW rows in date range # process form if request.method == 'POST': dateform = DateRangeForm(request.POST) if dateform.is_valid(): startdate = dateform.cleaned_data['startdate'] enddate = dateform.cleaned_data['enddate'] if startdate > enddate: s = enddate enddate = startdate startdate = s workouttypeform = OteWorkoutTypeForm(request.POST) if workouttypeform.is_valid(): workouttypes = workouttypeform.cleaned_data['workouttypes'] form = PredictedPieceForm(request.POST) if form.is_valid(): value = form.cleaned_data['value'] pieceunit = form.cleaned_data['pieceunit'] else: value = None try: trankingdistances = form.cleaned_data['trankingdistances'] except KeyError: trankingdistances = [] trankingdistances = [int(d) for d in trankingdistances] try: trankingdurations = form.cleaned_data['trankingdurations'] except KeyError: trankingdurations = [] trankingdurations = [ datetime.datetime.strptime(d,"%H:%M:%S").time() for d in trankingdurations ] if value: hourvalue,tvalue = divmod(value,60) hourvalue = int(hourvalue) minutevalue = int(tvalue) tvalue = int(60*(tvalue-minutevalue)) if hourvalue >= 24: hourvalue = 23 if pieceunit == 'd': trankingdistances.append(value) else: trankingdurations.append(datetime.time( minute=minutevalue, hour=hourvalue, second=tvalue )) else: form = PredictedPieceForm() dateform = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) workouttypeform = OteWorkoutTypeForm() workouttypes = ['rower','slides','dynamic'] trankingdistances = rankingdistances trankingdurations = rankingdurations # get all 2k (if any) - this rower, in date range try: r = Rower.objects.get(user=theuser) request.session['rowerid'] = r.id except Rower.DoesNotExist: allergworkouts = [] raise Http404("Rower doesn't exist") try: uu = User.objects.get(id=theuser) except User.DoesNotExist: uu = '' # test to fix bug startdate = datetime.datetime.combine(startdate,datetime.time()) enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) thedistances = [] theworkouts = [] thesecs = [] theworkouts = Workout.objects.filter( user=r,rankingpiece=True, workouttype__in=workouttypes, startdatetime__gte=startdate, startdatetime__lte=enddate ).order_by("-startdatetime") delta,cpvalue,avgpower = dataprep.fetchcp( r,theworkouts,table='cpergdata' ) runningjob = 0 taskstatus = get_stored_tasks_status(request) for task in taskstatus: if task['func_name'] == 'updatecp': if 'success' in task['status'].lower() or 'finished' in task['status'].lower(): runningjob = 1 messages.info(request,'CP chart data have been updated') remove_asynctask(request,task['id']) elif 'fail' in task['status'].lower(): runningjob = 0 try: remove_asynctask(request,task[id]) messages.error(request,'Oh, your task failed') except KeyError: pass elif 'started' in task['status'].lower(): messages.info(request,'Busy updating CP chart data') runningjob = 1 elif 'queued' in task['status'].lower(): messages.info(request,'Getting ready to update CP chart data') runningjob = 1 if not runningjob: job = dataprep.runcpupdate( r,type='rower', startdate=startdate, enddate=enddate ) request.session['job_id'] = job.id try: request.session['async_tasks'] += [(job.id,'updatecp')] except KeyError: request.session['async_tasks'] = [(job.id,'updatecp')] messages.info(request,'New calculation queued. Page will reload automatically. You can check the status of your calculations here') powerdf = pd.DataFrame({ 'Delta':delta, 'CP':cpvalue, }) if powerdf.empty: messages.info(request,'Your calculations are running in the background. Page will reload automatically. You can check the status of your calculations here') powerdf = powerdf[powerdf['CP']>0] powerdf.dropna(axis=0,inplace=True) powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True) powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True) rowername = r.user.first_name+" "+r.user.last_name # create interactive plot if len(powerdf) !=0 : res = interactive_otwcpchart(powerdf,promember=promember,rowername=rowername) script = res[0] div = res[1] p1 = res[2] ratio = res[3] r.ep0 = p1[0] r.ep1 = p1[1] r.ep2 = p1[2] r.ep3 = p1[3] r.ecpratio = ratio r.save() paulslope = 1 paulintercept = 1 message = res[4] else: ratio = 1 script = '' div = '

No ranking pieces found.

' paulslope = 1 paulintercept = 1 p1 = [1,1,1,1] message = "" cpredictions = [] for rankingduration in trankingdurations: t = 3600.*rankingduration.hour t += 60.*rankingduration.minute t += rankingduration.second t += rankingduration.microsecond/1.e6 # CP model pwr = p1[0]/(1+t/p1[2]) pwr += p1[1]/(1+t/p1[3]) velo = (pwr/2.8)**(1./3.) p = 500./velo d = t*velo if pwr <= 0: pwr = 50. if not np.isnan(pwr): try: pwr2 = pwr*ratio except: pwr2 = pwr a = { 'distance':int(d), 'duration':timedeltaconv(t), 'power':int(pwr), 'upper':int(pwr2), 'pace':timedeltaconv(p)} cpredictions.append(a) # initiation - get 10 min power, then use Paul's law t_10 = 600. power_10 = p1[0]/(1+t_10/p1[2]) power_10 += p1[1]/(1+t_10/p1[3]) velo_10 = (power_10/2.8)**(1./3.) pace_10 = 500./velo_10 distance_10 = t_10*velo_10 paulslope = 5. for rankingdistance in trankingdistances: delta = paulslope * np.log(rankingdistance/distance_10)/np.log(2) p = pace_10+delta velo = 500./p t = rankingdistance/velo pwr2 = p1[0]/(1+t/p1[2]) pwr2 += p1[1]/(1+t/p1[3]) try: pwr2 *= ratio except UnboundLocalError: pass if pwr2 <= 0: pwr2 = 50. velo2 = (pwr2/2.8)**(1./3.) if np.isnan(velo2) or velo2 <= 0: velo2 = 1.0 t2 = rankingdistance/velo2 pwr3 = p1[0]/(1+t2/p1[2]) pwr3 += p1[1]/(1+t2/p1[3]) pwr3 *= ratio if pwr3 <= 0: pwr3 = 50. velo3 = (pwr3/2.8)**(1./3.) if np.isnan(velo3) or velo3 <= 0: velo3 = 1.0 t3 = rankingdistance/velo3 p3 = 500./velo3 a = { 'distance':rankingdistance, 'duration':timedeltaconv(t3), 'power':'--', 'upper':int(pwr3), 'pace':timedeltaconv(p3)} cpredictions.append(a) # del form.fields["pieceunit"] messages.error(request,message) return render(request, 'oterankings.html', {'rankingworkouts':theworkouts, 'interactiveplot':script, 'the_div':div, 'rower':r, 'active':'nav-analysis', 'cpredictions':cpredictions, 'avgpower':avgpower, 'form':form, 'dateform':dateform, 'workouttypeform':workouttypeform, 'id': theuser, 'theuser':uu, 'startdate':startdate, 'enddate':enddate, 'teams':get_my_teams(request.user), 'workouttype':'rower', }) # Multi Flex Chart with Grouping @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def user_multiflex_select(request, startdatestring="", enddatestring="", message='', successmessage='', startdate=timezone.now()-datetime.timedelta(days=30), enddate=timezone.now(), userid=0): r = getrequestrower(request,userid=userid) user = r.user if 'options' in request.session: options = request.session['options'] else: options = {} try: palette = request.session['palette'] except KeyError: palette = 'monochrome_blue' try: includereststrokes = request.session['includereststrokes'] except KeyError: includereststrokes = False try: ploterrorbars = request.session['ploterrorbars'] except: ploterrorbars = False if 'startdate' in request.session: startdate = iso8601.parse_date(request.session['startdate']) if 'enddate' in request.session: enddate = iso8601.parse_date(request.session['enddate']) try: waterboattype = request.session['waterboattype'] except KeyError: waterboattype = mytypes.waterboattype else: waterboattype = mytypes.waterboattype if 'rankingonly' in request.session: rankingonly = request.session['rankingonly'] else: rankingonly = False if 'modalities' in request.session: modalities = request.session['modalities'] if len(modalities) > 1: modality = 'all' else: modality = modalities[0] else: modalities = [m[0] for m in mytypes.workouttypes] modality = 'all' if request.method == 'POST': dateform = DateRangeForm(request.POST) if dateform.is_valid(): startdate = dateform.cleaned_data['startdate'] enddate = dateform.cleaned_data['enddate'] startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') request.session['startdate'] = startdatestring request.session['enddate'] = enddatestring modalityform = TrendFlexModalForm(request.POST) if modalityform.is_valid(): modality = modalityform.cleaned_data['modality'] waterboattype = modalityform.cleaned_data['waterboattype'] rankingonly = modalityform.cleaned_data['rankingonly'] if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: modalities = [modality] if modality != 'water': waterboattype = [b[0] for b in mytypes.boattypes] request.session['modalities'] = modalities request.session['waterboattype'] = waterboattype request.session['rankingonly'] = rankingonly else: dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) startdate = datetime.datetime.combine(startdate,datetime.time()) enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) #enddate = enddate+datetime.timedelta(days=1) if startdatestring: startdate = iso8601.parse_date(startdatestring) if enddatestring: enddate = iso8601.parse_date(enddatestring) if enddate < startdate: s = enddate enddate = startdate startdate = s negtypes = [] for b in mytypes.boattypes: if b[0] not in waterboattype: negtypes.append(b[0]) if rankingonly: rankingpiece = [True] else: rankingpiece = [True,False] workouts = Workout.objects.filter( user=r, startdatetime__gte=startdate, startdatetime__lte=enddate, workouttype__in=modalities, rankingpiece__in=rankingpiece ).order_by( "-date", "-starttime" ).exclude( boattype__in=negtypes ) query = request.GET.get('q') if query: query_list = query.split() workouts = workouts.filter( reduce(operator.and_, (Q(name__icontains=q) for q in query_list)) | reduce(operator.and_, (Q(notes__icontains=q) for q in query_list)) ) searchform = SearchForm(initial={'q':query}) else: searchform = SearchForm() form = WorkoutMultipleCompareForm() form.fields["workouts"].queryset = workouts chartform = MultiFlexChoiceForm(initial={ 'palette':palette, 'ploterrorbars':ploterrorbars, 'includereststrokes':includereststrokes, }) modalityform = TrendFlexModalForm(initial={ 'modality':modality, 'waterboattype':waterboattype, 'rankingonly':rankingonly, }) messages.info(request,successmessage) messages.error(request,message) startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') request.session['startdate'] = startdatestring request.session['enddate'] = enddatestring request.session['waterboattype'] = waterboattype request.session['rankingonly'] = rankingonly request.session['modalities'] = modalities breadcrumbs = [ { 'url':'/rowers/analysis', 'name':'Analysis' }, { 'url':reverse(user_multiflex_select,kwargs={'userid':userid}), 'name': 'Compare Select' }, { 'url':reverse('multi_compare_view'), 'name': 'Comparison Chart' } ] return render(request, 'user_multiflex_select.html', {'workouts': workouts, 'dateform':dateform, 'breadcrumbs':breadcrumbs, 'startdate':startdate, 'enddate':enddate, 'theuser':user, 'rower':r, 'form':form, 'chartform':chartform, 'searchform':searchform, 'modalityform':modalityform, 'teams':get_my_teams(request.user), }) @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def multiflex_data(request,userid=0, options={ 'includereststrokes':False, 'ploterrorbars':False, 'userid':0, 'palette': 'monochrome_blue', 'groupby': 'spm', 'binsize': 1, 'xparam': 'hr', 'yparam': 'pace', 'spmmin': 15, 'spmmax': 55, 'workmin': 400, 'workmax': 1500, 'ids': [], 'ploterrorbars':False, }): if 'options' in request.session: options = request.session['options'] try: includereststrokes = options['includereststrokes'] except KeyError: includereststrokes = False try: ploterrorbars = options['ploterrorbars'] except KeyError: ploterrorbars = False try: palette = request.session['palette'] except KeyError: palette = 'monochrome_blue' workstrokesonly = not includereststrokes if userid==0: userid = request.user.id palette = options['palette'] groupby = options['groupby'] binsize = options['binsize'] xparam = options['xparam'] yparam = options['yparam'] spmmin = options['spmmin'] spmmax = options['spmmax'] workmin = options['workmin'] workmax = options['workmax'] ids = options['ids'] workouts = [] for id in ids: try: workouts.append(Workout.objects.get(id=id)) except Workout.DoesNotExist: pass labeldict = { int(w.id): w.__str__() for w in workouts } fieldlist,fielddict = dataprep.getstatsfields() fieldlist = [xparam,yparam,groupby, 'workoutid','spm','driveenergy', 'workoutstate'] # prepare data frame datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist) if xparam == groupby: datadf['groupby'] = datadf[xparam] groupy = 'groupby' datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) datadf = dataprep.filter_df(datadf,'spm',spmmin, largerthan=True) datadf = dataprep.filter_df(datadf,'spm',spmmax, largerthan=False) datadf = dataprep.filter_df(datadf,'driveenergy',workmin, largerthan=True) datadf = dataprep.filter_df(datadf,'driveneergy',workmax, largerthan=False) datadf.dropna(axis=0,how='any',inplace=True) datemapping = { w.id:w.date for w in workouts } datadf['date'] = datadf['workoutid'] datadf['date'].replace(datemapping,inplace=True) today = datetime.date.today() datadf['days ago'] = map(lambda x : x.days, datadf.date - today) if groupby != 'date': try: bins = np.arange(datadf[groupby].min()-binsize, datadf[groupby].max()+binsize, binsize) groups = datadf.groupby(pd.cut(datadf[groupby],bins,labels=False)) except ValueError: messages.error( request, "Unable to compete. Probably not enough data selected" ) url = reverse(user_multiflex_select) return HttpResponseRedirect(url) else: bins = np.arange(datadf['days ago'].min()-binsize, datadf['days ago'].max()+binsize, binsize, ) groups = datadf.groupby(pd.cut(datadf['days ago'], bins, labels=False)) xvalues = groups.mean()[xparam] yvalues = groups.mean()[yparam] xerror = groups.std()[xparam] yerror = groups.std()[yparam] groupsize = groups.count()[xparam] mask = groupsize <= min([0.01*groupsize.sum(),0.2*groupsize.mean()]) xvalues.loc[mask] = np.nan yvalues.loc[mask] = np.nan xerror.loc[mask] = np.nan yerror.loc[mask] = np.nan groupsize.loc[mask] = np.nan xvalues.dropna(inplace=True) yvalues.dropna(inplace=True) xerror.dropna(inplace=True) yerror.dropna(inplace=True) groupsize.dropna(inplace=True) if len(groupsize) == 0: messages.error(request,'No data in selection') url = reverse(user_multiflex_select) return HttpResponseRedirect(url) else: groupsize = 30.*np.sqrt(groupsize/float(groupsize.max())) df = pd.DataFrame({ xparam:xvalues, yparam:yvalues, 'x':xvalues, 'y':yvalues, 'xerror':xerror, 'yerror':yerror, 'groupsize':groupsize, }) if yparam == 'pace': df['y'] = dataprep.paceformatsecs(df['y']/1.0e3) aantal = len(df) if groupby != 'date': try: df['groupval'] = groups.mean()[groupby] df['groupval'].loc[mask] = np.nan groupcols = df['groupval'] except ValueError: df['groupval'] = groups.mean()[groupby].fillna(value=0) df['groupval'].loc[mask] = np.nan groupcols = df['groupval'] except KeyError: messages.error(request,'Data selection error') url = reverse(user_multiflex_select) return HttpResponseRedirect(url) else: try: dates = groups.min()[groupby] dates.loc[mask] = np.nan dates.dropna(inplace=True) df['groupval'] = [x.strftime("%Y-%m-%d") for x in dates] df['groupval'].loc[mask] = np.nan groupcols = 100.*np.arange(aantal)/float(aantal) except AttributeError: df['groupval'] = groups.mean()['days ago'].fillna(value=0) groupcols = 100.*np.arange(aantal)/float(aantal) groupcols = (groupcols-groupcols.min())/(groupcols.max()-groupcols.min()) if aantal == 1: groupcols = np.array([1.]) colors = range_to_color_hex(groupcols,palette=palette) df['color'] = colors clegendx = np.arange(0,1.2,.2) legcolors = range_to_color_hex(clegendx,palette=palette) if groupby != 'date': clegendy = df['groupval'].min()+clegendx*(df['groupval'].max()-df['groupval'].min()) else: clegendy = df.index.min()+clegendx*(df.index.max()-df.index.min()) colorlegend = zip(range(6),clegendy,legcolors) if userid == 0: extratitle = '' else: u = User.objects.get(id=userid) extratitle = ' '+u.first_name+' '+u.last_name script,div = interactive_multiflex(df,xparam,yparam, groupby, extratitle=extratitle, ploterrorbars=ploterrorbars, binsize=binsize, colorlegend=colorlegend) scripta= script.split('\n')[2:-1] script = ''.join(scripta) return JSONResponse({ "script":script, "div":div, }) @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def multiflex_view(request,userid=0, options={ 'includereststrokes':False, 'ploterrorbars':False, }): if 'options' in request.session: options = request.session['options'] try: includereststrokes = options['includereststrokes'] except KeyError: includereststrokes = False try: ploterrorbars = options['ploterrorbars'] except KeyError: ploterrorbars = False try: palette = request.session['palette'] except KeyError: palette = 'monochrome_blue' if 'startdate' in request.session: startdate = iso8601.parse_date(request.session['startdate']) if 'enddate' in request.session: enddate = iso8601.parse_date(request.session['enddate']) workstrokesonly = not includereststrokes if userid==0: userid = request.user.id if request.method == 'POST' and 'workouts' in request.POST: form = WorkoutMultipleCompareForm(request.POST) chartform = MultiFlexChoiceForm(request.POST) if form.is_valid() and chartform.is_valid(): cd = form.cleaned_data workouts = cd['workouts'] xparam = chartform.cleaned_data['xparam'] yparam = chartform.cleaned_data['yparam'] includereststrokes = chartform.cleaned_data['includereststrokes'] ploterrorbars = chartform.cleaned_data['ploterrorbars'] workstrokesonly = not includereststrokes palette = chartform.cleaned_data['palette'] groupby = chartform.cleaned_data['groupby'] binsize = chartform.cleaned_data['binsize'] if binsize <= 0: binsize = 1 if groupby == 'pace': binsize *= 1000 spmmin = chartform.cleaned_data['spmmin'] spmmax = chartform.cleaned_data['spmmax'] workmin = chartform.cleaned_data['workmin'] workmax = chartform.cleaned_data['workmax'] ids = [int(w.id) for w in workouts] request.session['ids'] = ids else: return HttpResponse("Form is not valid") elif request.method == 'POST' and 'ids' in request.session: chartform = MultiFlexChoiceForm(request.POST) if chartform.is_valid(): xparam = chartform.cleaned_data['xparam'] yparam = chartform.cleaned_data['yparam'] includereststrokes = chartform.cleaned_data['includereststrokes'] ploterrorbars = chartform.cleaned_data['ploterrorbars'] request.session['ploterrorbars'] = ploterrorbars request.session['includereststrokes'] = includereststrokes workstrokesonly = not includereststrokes palette = chartform.cleaned_data['palette'] groupby = chartform.cleaned_data['groupby'] binsize = chartform.cleaned_data['binsize'] if binsize <= 0: binsize = 1 if groupby == 'pace': binsize *= 1000. spmmin = chartform.cleaned_data['spmmin'] spmmax = chartform.cleaned_data['spmmax'] workmin = chartform.cleaned_data['workmin'] workmax = chartform.cleaned_data['workmax'] ids = request.session['ids'] request.session['ids'] = ids workouts = dataprep.get_workouts(ids,userid) if not workouts: message = 'Error: Workouts in session storage do not belong to this user.' messages.error(request,message) url = reverse(user_multiflex_select, kwargs={ 'userid':userid, } ) return HttpResponseRedirect(url) # workouts = [Workout.objects.get(id=id) for id in ids] else: return HttpResponse("invalid form") else: url = reverse(user_multiflex_select) return HttpResponseRedirect(url) div = get_call() options['includereststrokes'] = includereststrokes options['ploterrorbars'] = ploterrorbars options['userid'] = userid options['palette'] = palette options['groupby'] = groupby options['binsize'] = binsize options['xparam'] = xparam options['yparam'] = yparam options['spmmin'] = spmmin options['spmmax'] = spmmax options['workmin'] = workmin options['workmax'] = workmax options['ids'] = ids request.session['options'] = options r = getrequestrower(request,userid=userid) breadcrumbs = [ { 'url':'/rowers/analysis', 'name':'Analysis' }, { 'url':reverse(user_multiflex_select,kwargs={'userid':userid}), 'name': 'Trend Flex Select' }, { 'url':reverse(multiflex_view), 'name': 'Trend Flex Chart' } ] return render(request,'multiflex.html', {'interactiveplot':'', 'active':'nav-analysis', 'rower':r, 'breadcrumbs':breadcrumbs, 'the_div':div, 'active':'nav-analysis', 'chartform':chartform, 'userid':userid, 'teams':get_my_teams(request.user), }) # Box plots @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def user_boxplot_select(request, startdatestring="", enddatestring="", message='', successmessage='', startdate=timezone.now()-datetime.timedelta(days=30), enddate=timezone.now(), options={ 'includereststrokes':False, 'workouttypes':['rower','dynamic','slides'], 'waterboattype':mytypes.waterboattype, 'rankingonly':False, }, userid=0): r = getrequestrower(request,userid=userid) user = r.user userid = user.id if 'options' in request.session: options = request.session['options'] try: workouttypes = options['workouttypes'] except KeyError: workouttypes = ['rower','dynamic','slides'] try: rankingonly = options['rankingonly'] except KeyError: rankingonly = False try: includereststrokes = options['includereststrokes'] except KeyError: includereststrokes = False if 'startdate' in request.session: startdate = iso8601.parse_date(request.session['startdate']) if 'enddate' in request.session: enddate = iso8601.parse_date(request.session['enddate']) workstrokesonly = not includereststrokes waterboattype = mytypes.waterboattype if startdatestring != "": startdate = iso8601.parse_date(startdatestring) if enddatestring != "": enddate = iso8601.parse_date(enddatestring) if enddate < startdate: s = enddate enddate = startdate startdate = s if request.method == 'POST': dateform = DateRangeForm(request.POST) if dateform.is_valid(): startdate = dateform.cleaned_data['startdate'] enddate = dateform.cleaned_data['enddate'] startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') request.session['startdate'] = startdatestring request.session['enddate'] = enddatestring optionsform = TrendFlexModalForm(request.POST) if optionsform.is_valid(): modality = optionsform.cleaned_data['modality'] waterboattype = optionsform.cleaned_data['waterboattype'] if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: modalities = [modality] if modality != 'water': waterboattype = [b[0] for b in mytypes.boattypes] if 'rankingonly' in optionsform.cleaned_data: rankingonly = optionsform.cleaned_data['rankingonly'] else: rankingonly = False request.session['modalities'] = modalities request.session['waterboattype'] = waterboattype else: dateform = DateRangeForm(initial={ 'startdate':startdate, 'enddate':enddate, }) if 'modalities' in request.session: modalities = request.session['modalities'] if len(modalities) > 1: modality = 'all' else: modality = modalities[0] else: modalities = [m[0] for m in mytypes.workouttypes] modality = 'all' negtypes = [] for b in mytypes.boattypes: if b[0] not in waterboattype: negtypes.append(b[0]) startdate = datetime.datetime.combine(startdate,datetime.time()) enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) #enddate = enddate+datetime.timedelta(days=1) if startdatestring: startdate = iso8601.parse_date(startdatestring) if enddatestring: enddate = iso8601.parse_date(enddatestring) if enddate < startdate: s = enddate enddate = startdate startdate = s negtypes = [] for b in mytypes.boattypes: if b[0] not in waterboattype: negtypes.append(b[0]) workouts = Workout.objects.filter(user=r, startdatetime__gte=startdate, startdatetime__lte=enddate, workouttype__in=modalities, ).order_by( "-date", "-starttime" ).exclude(boattype__in=negtypes) # workouttypes = [w for w in workouttypes if w not in mytypes.otwtypes] if rankingonly: workouts = workouts.exclude(rankingpiece=False) query = request.GET.get('q') if query: query_list = query.split() workouts = workouts.filter( reduce(operator.and_, (Q(name__icontains=q) for q in query_list)) | reduce(operator.and_, (Q(notes__icontains=q) for q in query_list)) ) searchform = SearchForm(initial={'q':query}) else: searchform = SearchForm() form = WorkoutMultipleCompareForm() form.fields["workouts"].queryset = workouts chartform = BoxPlotChoiceForm() optionsform = TrendFlexModalForm(initial={ 'modality':modality, 'waterboattype':waterboattype, 'rankingonly':rankingonly, }) messages.info(request,successmessage) messages.error(request,message) startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') request.session['startdate'] = startdatestring request.session['enddate'] = enddatestring breadcrumbs = [ { 'url':'/rowers/analysis', 'name':'Analysis' }, { 'url':reverse(user_boxplot_select,kwargs={'userid':userid}), 'name': 'BoxPlot Select' }, ] return render(request, 'user_boxplot_select.html', {'workouts': workouts, 'dateform':dateform, 'startdate':startdate, 'enddate':enddate, 'rower':r, 'breadcrumbs':breadcrumbs, 'theuser':user, 'form':form, 'active':'nav-analysis', 'chartform':chartform, 'searchform':searchform, 'optionsform':optionsform, 'teams':get_my_teams(request.user), }) @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def boxplot_view_data(request,userid=0, options={ 'includereststrokes':False, 'spmmin':15, 'spmmax':55, 'workmin':0, 'workmax':1500, 'ids':[], 'userid':0, 'plotfield':'spm', }): if 'options' in request.session: options = request.session['options'] try: includereststrokes = options['includereststrokes'] spmmin = options['spmmin'] spmmax = options['spmmax'] workmin = options['workmin'] workmax = options['workmax'] ids = options['ids'] userid = options['userid'] plotfield = options['plotfield'] except KeyError: includereststrokes = False spmmin = 15 spmmax = 55 workmin = 0 workmax = 55 ids = [] userid = 0 plotfield = 'spm' workstrokesonly = not includereststrokes if userid==0: userid = request.user.id workouts = [] if not ids: return JSONResponse({ "script":'', "div":'No data found' }) for id in ids: try: workouts.append(Workout.objects.get(id=id)) except Workout.DoesNotExist: pass labeldict = { int(w.id): w.__str__() for w in workouts } datemapping = { w.id:w.date for w in workouts } fieldlist,fielddict = dataprep.getstatsfields() fieldlist = [plotfield,'workoutid','spm','driveenergy', 'workoutstate'] # prepare data frame datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist) datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) datadf = dataprep.filter_df(datadf,'spm',spmmin, largerthan=True) datadf = dataprep.filter_df(datadf,'spm',spmmax, largerthan=False) datadf = dataprep.filter_df(datadf,'driveenergy',workmin, largerthan=True) datadf = dataprep.filter_df(datadf,'driveneergy',workmax, largerthan=False) datadf.dropna(axis=0,how='any',inplace=True) datadf['workoutid'].replace(datemapping,inplace=True) datadf.rename(columns={"workoutid":"date"},inplace=True) datadf = datadf.sort_values(['date']) if userid == 0: extratitle = '' else: u = User.objects.get(id=userid) extratitle = ' '+u.first_name+' '+u.last_name script,div = interactive_boxchart(datadf,plotfield, extratitle=extratitle) scripta = script.split('\n')[2:-1] script = ''.join(scripta) return JSONResponse({ "script":script, "div":div, }) @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", redirect_field_name=None) def boxplot_view(request,userid=0, options={ 'includereststrokes':False, 'rankingonly':False, }): if 'options' in request.session: options = request.session['options'] else: options = {} try: includereststrokes = options['includereststrokes'] except KeyError: includereststrokes = False options['includereststrokes'] = False try: rankingonly = options['rankingonly'] except KeyError: rankingonly = False options['rankingonly'] = False workstrokesonly = not includereststrokes if userid==0: userid = request.user.id if request.method == 'POST' and 'workouts' in request.POST: form = WorkoutMultipleCompareForm(request.POST) chartform = BoxPlotChoiceForm(request.POST) if form.is_valid() and chartform.is_valid(): cd = form.cleaned_data workouts = cd['workouts'] plotfield = chartform.cleaned_data['yparam'] includereststrokes = chartform.cleaned_data['includereststrokes'] request.session['includereststrokes'] = includereststrokes workstrokesonly = not includereststrokes spmmin = chartform.cleaned_data['spmmin'] spmmax = chartform.cleaned_data['spmmax'] workmin = chartform.cleaned_data['workmin'] workmax = chartform.cleaned_data['workmax'] ids = [int(w.id) for w in workouts] request.session['ids'] = ids else: url = reverse(user_boxplot_select,kwargs={'userid':userid}) return HttpResponseRedirect(url) elif request.method == 'POST' and 'ids' in request.session: chartform = BoxPlotChoiceForm(request.POST) if chartform.is_valid(): plotfield = chartform.cleaned_data['yparam'] includereststrokes = chartform.cleaned_data['includereststrokes'] spmmin = chartform.cleaned_data['spmmin'] spmmax = chartform.cleaned_data['spmmax'] workmin = chartform.cleaned_data['workmin'] workmax = chartform.cleaned_data['workmax'] request.session['includereststrokes'] = includereststrokes workstrokesonly = not includereststrokes ids = request.session['ids'] request.session['ids'] = ids else: url = reverse(user_boxplot_select,kwargs={'userid':userid}) return HttpResponseRedirect(url) else: url = reverse(user_boxplot_select,kwargs={'userid':userid}) return HttpResponseRedirect(url) div = get_call() options['spmmin'] = spmmin options['spmmax'] = spmmax options['workmin'] = workmin options['workmax'] = workmax options['ids'] = ids options['userid'] = userid options['plotfield'] = plotfield options['rankingonly'] = rankingonly request.session['options'] = options r = getrequestrower(request,userid=userid) breadcrumbs = [ { 'url':'/rowers/Analysis', 'name':'Analysis' }, { 'url':reverse(user_boxplot_select,kwargs={'userid':userid}), 'name': 'BoxPlot Select' }, { 'url':reverse(boxplot_view,kwargs={'userid':userid}), 'name': 'BoxPlot Select' }, ] return render(request,'boxplot.html', {'interactiveplot':'', 'the_div':div, 'rower':r, 'breadcrumbs':breadcrumbs, 'active':'nav-analysis', 'chartform':chartform, 'userid':userid, 'teams':get_my_teams(request.user), }) # Cumulative stats page @user_passes_test(ispromember,login_url="/rowers/paidplans",message="This functionality requires a Pro plan or higher",redirect_field_name=None) def cumstats(request,theuser=0, startdate=timezone.now()-datetime.timedelta(days=30), enddate=timezone.now(), deltadays=-1, startdatestring="", enddatestring="", options={ 'includereststrokes':False, 'workouttypes':['rower','dynamic','slides'], 'waterboattype':mytypes.waterboattype, 'rankingonly':False, }): r = getrequestrower(request,userid=theuser) theuser = r.user if 'waterboattype' in request.session: waterboattype = request.session['waterboattype'] else: waterboattype = mytypes.waterboattype if 'rankingonly' in request.session: rankingonly = request.session['rankingonly'] else: rankingonly = False if 'modalities' in request.session: modalities = request.session['modalities'] if len(modalities) > 1: modality = 'all' else: modality = modalities[0] else: modalities = [m[0] for m in mytypes.workouttypes] modality = 'all' try: rankingonly = options['rankingonly'] except KeyError: rankingonly = False try: includereststrokes = options['includereststrokes'] except KeyError: includereststrokes = False workstrokesonly = not includereststrokes waterboattype = mytypes.waterboattype if startdatestring != "": startdate = iso8601.parse_date(startdatestring) if enddatestring != "": enddate = iso8601.parse_date(enddatestring) if enddate < startdate: s = enddate enddate = startdate startdate = s # get all indoor rows of in date range # process form if request.method == 'POST': form = DateRangeForm(request.POST) modalityform = TrendFlexModalForm(request.POST) if form.is_valid(): startdate = form.cleaned_data['startdate'] enddate = form.cleaned_data['enddate'] if startdate > enddate: s = enddate enddate = startdate startdate = s startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') if modalityform.is_valid(): modality = modalityform.cleaned_data['modality'] waterboattype = modalityform.cleaned_data['waterboattype'] rankingonly = modalityform.cleaned_data['rankingonly'] if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: modalities = [modality] if modality != 'water': waterboattype = [b[0] for b in mytypes.boattypes] request.session['modalities'] = modalities request.session['waterboattype'] = waterboattype request.session['rankingonly'] = rankingonly form = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) else: form = DateRangeForm(initial={ 'startdate': startdate, 'enddate': enddate, }) includereststrokes = False workstrokesonly = not includereststrokes modalityform = TrendFlexModalForm( initial={ 'modality':modality, 'waterboattype':waterboattype, 'rankingonly':rankingonly, } ) negtypes = [] for b in mytypes.boattypes: if b[0] not in waterboattype: negtypes.append(b[0]) script = '' div = get_call() js_resources = '' css_resources = '' options = { 'modality': modality, 'theuser': theuser.id, 'waterboattype':waterboattype, 'startdatestring':startdatestring, 'enddatestring':enddatestring, 'rankingonly':rankingonly, 'includereststrokes':includereststrokes, } request.session['options'] = options if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] else: modalities = [modality] try: startdate = iso8601.parse_date(startdatestring) except ParseError: startdate = timezone.now()-datetime.timedelta(days=7) try: enddate = iso8601.parse_date(enddatestring) except ParseError: enddate = timezone.now() if enddate < startdate: s = enddate enddate = startdate startdate = s promember=0 if theuser == 0: theuser = request.user.id if not request.user.is_anonymous(): r = getrower(request.user) result = request.user.is_authenticated() and ispromember(request.user) if result: promember=1 r2 = getrower(theuser) if rankingonly: rankingpiece = [True,] else: rankingpiece = [True,False] allworkouts = Workout.objects.filter( user=r2, workouttype__in=modalities, boattype__in=waterboattype, startdatetime__gte=startdate, startdatetime__lte=enddate, rankingpiece__in=rankingpiece ).order_by("-date", "-starttime") ids = [int(workout.id) for workout in allworkouts] datemapping = { w.id:w.date for w in allworkouts } fieldlist,fielddict = dataprep.getstatsfields() # prepare data frame datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist) datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) request.session['rowerid'] = r.id if datadf.empty: stats = {} cordict = {} response = render(request, 'cumstats.html', { 'stats':stats, 'teams':get_my_teams(request.user), 'options':options, 'active':'nav-analysis', 'rower':r, 'id':theuser, 'theuser':theuser, 'startdate':startdate, 'enddate':enddate, 'form':form, 'optionsform':modalityform, 'cordict':cordict, }) request.session['options'] = options return response # Create stats stats = {} fielddict.pop('workoutstate') fielddict.pop('workoutid') for field,verbosename in fielddict.iteritems(): thedict = { 'mean':datadf[field].mean(), 'min': datadf[field].min(), 'std': datadf[field].std(), 'max': datadf[field].max(), 'median': datadf[field].median(), 'firstq':datadf[field].quantile(q=0.25), 'thirdq':datadf[field].quantile(q=0.75), 'verbosename':verbosename, } stats[field] = thedict # Create a dict with correlation values cor = datadf.corr(method='spearman') cor.fillna(value=0,inplace=True) cordict = {} for field1,verbosename in fielddict.iteritems(): thedict = {} for field2,verbosename in fielddict.iteritems(): try: thedict[field2] = cor.loc[field1,field2] except KeyError: thedict[field2] = 0 cordict[field1] = thedict # set options form correctly initial = {} initial['includereststrokes'] = includereststrokes initial['waterboattype'] = waterboattype initial['rankingonly'] = rankingonly response = render(request, 'cumstats.html', { 'stats':stats, 'teams':get_my_teams(request.user), 'active':'nav-analysis', 'rower':r, 'options':options, 'id':theuser, 'theuser':theuser, 'startdate':startdate, 'enddate':enddate, 'form':form, 'optionsform':modalityform, 'cordict':cordict, }) request.session['options'] = options return response def agegroupcpview(request,age,normalize=0): script,div = interactive_agegroupcpchart(age,normalized=normalize) response = render(request,'agegroupcp.html', { 'active': 'nav-analysis', 'interactiveplot':script, 'the_div':div, } ) return response def agegrouprecordview(request,sex='male',weightcategory='hwt', distance=2000,duration=None): if not duration: df = pd.DataFrame( list( C2WorldClassAgePerformance.objects.filter( distance=distance, sex=sex, weightcategory=weightcategory ).values() ) ) else: duration = int(duration)*60 df = pd.DataFrame( list( C2WorldClassAgePerformance.objects.filter( duration=duration, sex=sex, weightcategory=weightcategory ).values() ) ) script,div = interactive_agegroup_plot(df,sex=sex,distance=distance, duration=duration, weightcategory=weightcategory) return render(request, 'agegroupchart.html', { 'interactiveplot':script, 'active':'nav-analysis', 'the_div':div, })