From 219707af0b7dd8e11a94958a14e751a47fa9c27d Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
No erg pieces uploaded yet.
' + + return render(request, 'histoall.html', + {'interactiveplot':script, + 'the_div':div, + 'id':theuser, + 'theuser':u, + }) + +@login_required() +def cum_flex(request,theuser=0, + xparam='spm', + yparam1='power', + yparam2='None', + startdate=timezone.now()-datetime.timedelta(days=10), + enddate=timezone.now()+datetime.timedelta(days=1), + 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 + + promember=0 + if theuser == 0: + theuser = request.user.id + + if not request.user.is_anonymous(): + r = Rower.objects.get(user=request.user) + result = request.user.is_authenticated() and r.rowerplan=='pro' + if result: + promember=1 + + if not promember: + return HttpResponseRedirect("/rowers/about/") + + # get all indoor rows of in date range + + # process form + if request.method == 'POST' and "daterange" in request.POST: + form = DateRangeForm(request.POST) + deltaform = DeltaDaysForm(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 + elif request.method == 'POST' and "datedelta" in request.POST: + deltaform = DeltaDaysForm(request.POST) + if deltaform.is_valid(): + deltadays = deltaform.cleaned_data['deltadays'] + if deltadays != 0: + enddate = timezone.now() + startdate = enddate-datetime.timedelta(days=deltadays) + if startdate > enddate: + s = enddate + enddate = startdate + startdate = s + form = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) + + else: + form = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) + deltaform = DeltaDaysForm() + + try: + r2 = Rower.objects.get(user=theuser) + allergworkouts = Workout.objects.filter(user=r2, + workouttype__in=['rower','dynamic','slides'], + startdatetime__gte=startdate, + startdatetime__lte=enddate) + + except Rower.DoesNotExist: + allergworkouts = [] + r2=0 + + try: + u = User.objects.get(id=theuser) + except User.DoesNotExist: + u = '' + + if allergworkouts: + res = interactive_cum_flex_chart2(allergworkouts,xparam=xparam, + yparam1=yparam1, + yparam2=yparam2, + promember=promember) + script = res[0] + div = res[1] + js_resources = res[2] + css_resources = res[3] + else: + script = '' + div = 'No erg pieces uploaded for this date range.
' + js_resources = '' + css_resources = '' + + return render(request, 'cum_flex.html', + {'interactiveplot':script, + 'the_div':div, + 'js_res': js_resources, + 'css_res':css_resources, + 'id':theuser, + 'theuser':u, + 'startdate':startdate, + 'enddate':enddate, + 'form':form, + 'deltaform':deltaform, + 'xparam':xparam, + 'yparam1':yparam1, + 'yparam2':yparam2, + 'promember':promember, + }) + + +@login_required() +def histo(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 + + promember=0 + if theuser == 0: + theuser = request.user.id + + if not request.user.is_anonymous(): + r = Rower.objects.get(user=request.user) + result = request.user.is_authenticated() and r.rowerplan=='pro' + if result: + promember=1 + + if not promember: + return HttpResponseRedirect("/rowers/about/") + + # get all indoor rows of in date range + + # process form + if request.method == 'POST' and "daterange" in request.POST: + form = DateRangeForm(request.POST) + deltaform = DeltaDaysForm(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 + elif request.method == 'POST' and "datedelta" in request.POST: + deltaform = DeltaDaysForm(request.POST) + if deltaform.is_valid(): + deltadays = deltaform.cleaned_data['deltadays'] + if deltadays != 0: + enddate = timezone.now() + startdate = enddate-datetime.timedelta(days=deltadays) + if startdate > enddate: + s = enddate + enddate = startdate + startdate = s + form = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) + + else: + form = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) + deltaform = DeltaDaysForm() + + try: + r2 = Rower.objects.get(user=theuser) + allergworkouts = Workout.objects.filter(user=r2, + workouttype__in=['rower','dynamic','slides'], + startdatetime__gte=startdate, + startdatetime__lte=enddate) + + except Rower.DoesNotExist: + allergworkouts = [] + r2=0 + + try: + u = User.objects.get(id=theuser) + except User.DoesNotExist: + u = '' + + if allergworkouts: + res = interactive_histoall(allergworkouts) + script = res[0] + div = res[1] + else: + script = '' + div = 'No erg pieces uploaded for this date range.
' + + + return render(request, 'histo.html', + {'interactiveplot':script, + 'the_div':div, + 'id':theuser, + 'theuser':u, + 'startdate':startdate, + 'enddate':enddate, + 'form':form, + 'deltaform':deltaform, + }) + +@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 = Rower.objects.get(user=request.user) + result = request.user.is_authenticated() and r.rowerplan=='pro' + if result: + promember=1 + + # get all indoor rows of 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 != 0: + 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(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) + deltaform = DeltaDaysForm() + + # get all 2k (if any) - this rower, in date range + try: + r = Rower.objects.get(user=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)) + + rankingdistances = [100,500,1000,2000,5000,6000,10000,21097,42195,100000] + rankingdurations = [] + rankingdurations.append(datetime.time(minute=1)) + rankingdurations.append(datetime.time(minute=4)) + rankingdurations.append(datetime.time(minute=30)) + rankingdurations.append(datetime.time(hour=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'], + 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', + 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(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'] + pieceunit = form.cleaned_data['pieceunit'] + if pieceunit == 'd': + rankingdistances.append(value) + else: + rankingdurations.append(datetime.time(minute=value)) + 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) + + + + 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, + 'message':message, + 'startdate':startdate, + 'enddate':enddate, + }) + +@login_required() +def workout_recalcsummary_view(request,id=0): + row = Workout.objects.get(id=id) + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + filename = row.csvfilename + rowdata = rdata(filename) + row.summary = rowdata.allstats() + row.save() + successmessage = "Summary Updated" + url = reverse(workout_edit_view, + kwargs = { + 'id':str(id), + 'successmessage':str(successmessage), + }) + + return HttpResponseRedirect(url) + + +@login_required() +def workouts_view(request,message='',successmessage=''): + try: + r = Rower.objects.get(user=request.user) + # res = mailprocessing.safeprocessattachments() + #if len(res)>0 and np.cumsum(np.array(res)).max()>0: + # successmessage = 'New Workouts have been created from email' + + workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime") + + return render(request, 'list_workouts.html', + {'workouts': workouts, + 'message': message, + 'successmessage':successmessage, + }) + except Rower.DoesNotExist: + return HttpResponse("Admin has no rower instance") + +@user_passes_test(promember,login_url="/login") +def workout_comparison_list(request,id=0,message='',successmessage=''): + try: + r = Rower.objects.get(user=request.user) + u = User.objects.get(id=r.user.id) + workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime").exclude(id=id) + row = Workout.objects.get(id=id) + + return render(request, 'comparison_list.html', + {'id':id, + 'workout':row, + 'workouts': workouts, + 'last_name':u.last_name, + 'first_name':u.first_name, + 'message': message, + 'successmessage':successmessage, + }) + except Rower.DoesNotExist: + return HttpResponse("Admin has no rower instance") + +def workout_view(request,id=0): + try: + # check if valid ID exists (workout exists) + row = Workout.objects.get(id=id) + g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") + r = Rower.objects.get(id=row.user.id) + u = User.objects.get(id=r.user.id) + + + # create interactive plot + res = interactive_chart(id) + script = res[0] + div = res[1] + + + # render page + if (len(g)<=3): + return render(request, 'workout_view.html', + {'workout':row, + 'graphs1':g[0:3], + 'last_name':u.last_name, + 'first_name':u.first_name, + 'interactiveplot':script, + 'the_div':div}) + else: + return render(request, 'workout_view.html', + {'workout':row, + 'graphs1':g[0:3], + 'graphs2':g[3:6], + 'last_name':u.last_name, + 'first_name':u.first_name, + 'interactiveplot':script, + 'the_div':div}) + + + except Workout.DoesNotExist: + return HttpResponse("Workout doesn't exist") + + +@user_passes_test(promember,login_url="/login") +def workout_undo_smoothenpace_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + filename = row.csvfilename + row = rdata(filename) + if row == 0: + return HttpResponse("Error: CSV Data File Not Found") + + if 'originalvelo' in row.df: + velo = row.df['originalvelo'].values + row.df[' Stroke500mPace (sec/500m)'] = 500./velo + + row.write_csv(filename) + + url = "/rowers/workout/"+str(id)+"/advanced" + + return HttpResponseRedirect(url) + + + +@user_passes_test(promember,login_url="/login") +def workout_smoothenpace_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + filename = row.csvfilename + row = rdata(filename) + if row == 0: + return HttpResponse("Error: CSV Data File Not Found") + + pace = row.df[' Stroke500mPace (sec/500m)'].values + velo = 500./pace + + if not 'originalvelo' in row.df: + row.df['originalvelo'] = velo + + velo2 = stravastuff.ewmovingaverage(velo,5) + + pace2 = 500./abs(velo2) + + row.df[' Stroke500mPace (sec/500m)'] = pace2 + + row.df = row.df.fillna(0) + + row.write_csv(filename) + + url = "/rowers/workout/"+str(id)+"/advanced" + + return HttpResponseRedirect(url) + +@user_passes_test(promember,login_url="/login") +def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + if request.method == 'POST': + form = CNsummaryForm(request.POST,request.FILES) + if form.is_valid(): + f = request.FILES['file'] + res = handle_uploaded_file(f) + fname = res[1] + try: + sumd = summarydata(fname) + row.summary = sumd.allstats() + row.save() + os.remove(fname) + successmessage = "CrewNerd summary added" + url = reverse(workout_edit_view, + kwargs = { + 'id':str(id), + 'successmessage':str(successmessage), + }) + + return HttpResponseRedirect(url) + except: + os.remove(fname) + message = "Something went wrong (workout_crewnerd_summary_view)" + url = reverse(workout_edit_view, + kwargs = { + 'id':str(id), + 'message':str(message), + }) + return HttpResponseRedirect(url) + else: + return render(request, + "cn_form.html", + {'form':form, + 'id':row.id}) + else: + form = CNsummaryForm() + + return render(request, + "cn_form.html", + {'form':form, + 'id':row.id}) + +@user_passes_test(promember,login_url="/login") +def workout_downloadwind_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + f1 = row.csvfilename + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + # create bearing + rowdata = rdata(f1) + if rowdata == 0: + return HttpResponse("Error: CSV Data File Not Found") + + try: + bearing = rowdata.df.ix[:,'bearing'].values + except KeyError: + rowdata.add_bearing() + rowdata.write_csv(f1) + + # get wind + try: + avglat = rowdata.df[' latitude'].mean() + avglon = rowdata.df[' longitude'].mean() + avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.ix[0,'TimeStamp (sec)']) + startdatetime = dateutil.parser.parse("{}, {}".format(row.date, + row.starttime)) + + starttimeunix = int(mktime(startdatetime.timetuple())) + avgtime = starttimeunix+avgtime + winddata = get_wind_data(avglat,avglon,avgtime) + windspeed = winddata[0] + windbearing = winddata[1] + message = winddata[2] + row.notes += "\n"+message + row.save() + rowdata.add_wind(windspeed,windbearing) + rowdata.write_csv(f1) + + kwargs = {'successmessage':str(message), + 'id':str(id)} + + url = reverse(workout_wind_view,kwargs=kwargs) + response = HttpResponseRedirect(url) + except KeyError: + message = "No latitude/longitude data" + kwargs = {'message':str(message), + 'id':str(id)} + url = reverse(workout_wind_view,kwargs=kwargs) + response = HttpResponseRedirect(url) + + + + return response + + +@user_passes_test(promember,login_url="/login") +def workout_wind_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + + # get data + f1 = row.csvfilename + u = request.user + r = Rower.objects.get(user=u) + + # create bearing + rowdata = rdata(f1) + if row == 0: + return HttpResponse("Error: CSV Data File Not Found") + + + hascoordinates = 1 + try: + latitude = rowdata.df.ix[:,' latitude'] + except KeyError: + hascoordinates = 0 + + try: + bearing = rowdata.df.ix[:,'bearing'].values + except KeyError: + rowdata.add_bearing() + rowdata.write_csv(f1) + + + + + if request.method == 'POST': + # process form + form = UpdateWindForm(request.POST) + + if form.is_valid(): + + vwind1 = form.cleaned_data['vwind1'] + vwind2 = form.cleaned_data['vwind2'] + dist1 = form.cleaned_data['dist1'] + dist2 = form.cleaned_data['dist2'] + winddirection1 = form.cleaned_data['winddirection1'] + winddirection2 = form.cleaned_data['winddirection2'] + windunit = form.cleaned_data['windunit'] + + rowdata.update_wind(vwind1,vwind2, + winddirection1, + winddirection2, + dist1,dist2, + units=windunit) + + rowdata.write_csv(f1) + + + else: + message = "Invalid Form" + kwargs = {'message':str(message), + 'id':str(id)} + url = reverse(workout_wind_view,kwargs=kwargs) + response = HttpResponseRedirect(url) + + else: + form = UpdateWindForm() + + # create interactive plot + res = interactive_windchart(id,promember=1) + script = res[0] + div = res[1] + + if hascoordinates: + res = googlemap_chart(rowdata.df[' latitude'], + rowdata.df[' longitude'], + row.name) + gmscript = res[0] + gmdiv = res[1] + else: + gmscript = "" + gmdiv = "No GPS data available" + + return render(request, + 'windedit.html', + {'workout':row, + 'message': message, + 'successmessage': successmessage, + 'interactiveplot':script, + 'form':form, + 'the_div':div, + 'gmap':gmscript, + 'gmapdiv':gmdiv}) + + +@user_passes_test(promember,login_url="/login") +def workout_stream_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + + # create interactive plot + f1 = row.csvfilename + u = request.user + r = Rower.objects.get(user=u) + + rowdata = rdata(f1) + if rowdata == 0: + return HttpResponse("Error: CSV Data File Not Found") + + if request.method == 'POST': + # process form + form = UpdateStreamForm(request.POST) + + if form.is_valid(): + + dist1 = form.cleaned_data['dist1'] + dist2 = form.cleaned_data['dist2'] + stream1 = form.cleaned_data['stream1'] + stream2 = form.cleaned_data['stream2'] + streamunit = form.cleaned_data['streamunit'] + + rowdata.update_stream(stream1,stream2,dist1,dist2, + units=streamunit) + + rowdata.write_csv(f1) + + + else: + message = "Invalid Form" + kwargs = {'message':str(message), + 'id':str(id)} + url = reverse(workout_wind_view,kwargs=kwargs) + response = HttpResponseRedirect(url) + + else: + form = UpdateStreamForm() + + # create interactive plot + res = interactive_streamchart(id,promember=1) + script = res[0] + div = res[1] + + return render(request, + 'streamedit.html', + {'workout':row, + 'message': message, + 'successmessage': successmessage, + 'interactiveplot':script, + 'form':form, + 'the_div':div}) + + +@user_passes_test(promember, login_url="/login") +def workout_otwsetpower_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + + if request.method == 'POST': + # process form + form = AdvancedWorkoutForm(request.POST) + + if form.is_valid(): + boattype = form.cleaned_data['boattype'] + weightvalue = form.cleaned_data['weightvalue'] + row.boattype = boattype + row.weightvalue = weightvalue + row.save() + + # load row data & create power/wind/bearing columns if not set + f1 = row.csvfilename + rowdata = rdata(f1) + if rowdata == 0: + return HttpResponse("Error: CSV Data File Not Found") + try: + vstream = rowdata.df['vstream'] + except KeyError: + rowdata.add_stream(0) + rowdata.write_csv(f1) + + try: + bearing = rowdata.df['bearing'] + except KeyError: + rowdata.add_bearing() + rowdata.write_csv(f1) + + try: + vwind = rowdata.df['vwind'] + except KeyError: + rowdata.add_wind(0,0) + rowdata.write_csv(f1) + + # do power calculation (asynchronous) + u = request.user + first_name = u.first_name + last_name = u.last_name + emailaddress = u.email + + if settings.DEBUG: + res = handle_otwsetpower.delay(f1,boattype,weightvalue, + first_name,last_name,emailaddress,id) + else: + res = queuelow.enqueue(handle_otwsetpower,f1,boattype, + weightvalue, + first_name,last_name,emailaddress,id) + + + successmessage = "Your calculations have been submitted. You will receive an email when they are done." + kwargs = {'successmessage':str(successmessage), + 'id':str(id)} + + url = reverse(workout_advanced_view,kwargs=kwargs) + response = HttpResponseRedirect(url) + return response + + else: + message = "Invalid Form" + kwargs = {'message':str(message), + 'id':str(id)} + url = reverse(workout_otwsetpower_view,kwargs=kwargs) + response = HttpResponseRedirect(url) + + else: + form = AdvancedWorkoutForm(instance=row) + + return render(request, + 'otwsetpower.html', + {'workout':row, + 'message': message, + 'successmessage': successmessage, + 'form':form, + }) + + +@login_required() +def workout_geeky_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + form = WorkoutForm(instance=row) + g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") + # check if user is owner of this workout + + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + + # create interactive plot + f1 = row.csvfilename + u = request.user + r = Rower.objects.get(user=u) + + # create interactive plot + try: + res = interactive_chart(id,promember=1) + script = res[0] + div = res[1] + except ValueError: + pass + + if row.workouttype=='water': + return render(request, + 'otwgeeky.html', + {'workout':row, + 'message': message, + 'successmessage': successmessage, + 'interactiveplot':script, + 'the_div':div}) + else: + return render(request, + 'advancededit.html', + {'workout':row, + 'message': message, + 'successmessage': successmessage, + 'interactiveplot':script, + 'the_div':div}) + +#@user_passes_test(promember,login_url="/login") +@login_required() +def workout_advanced_view(request,id=0,message="",successmessage=""): + row = Workout.objects.get(id=id) + form = WorkoutForm(instance=row) + g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") + # check if user is owner of this workout + + if (checkworkoutuser(request.user,row)==False): + message = "You are not allowed to edit this workout" + url = reverse(workouts_view,args=[str(message)]) + + return HttpResponseRedirect(url) + + + # create interactive plot + f1 = row.csvfilename + u = request.user + r = Rower.objects.get(user=u) + + # create interactive plot + try: + res = interactive_chart(id,promember=1) + script = res[0] + div = res[1] + except ValueError: + pass + + if row.workouttype=='water': + return render(request, + 'advancedotw.html', + {'workout':row, + 'message': message, + 'successmessage': successmessage, + 'interactiveplot':script, + 'the_div':div}) + else: + return render(request, + 'advancededit.html', + {'workout':row, + 'message': message, + 'successmessage': successmessage, + 'interactiveplot':script, + 'the_div':div}) + +def workout_comparison_view(request,id1=0,id2=0,xparam='distance',yparam='spm'): + promember=0 + if not request.user.is_anonymous(): + r = Rower.objects.get(user=request.user) + result = request.user.is_authenticated() and r.rowerplan=='pro' + if result: + promember=1 + + # create interactive plot + res = interactive_comparison_chart(id1,id2,xparam=xparam,yparam=yparam, + promember=promember) + script = res[0] + div = res[1] + + + return render(request, + 'comparisonchart.html', + {'interactiveplot':script, + 'the_div':div, + 'id1':id1, + 'id2':id2, + 'xparam':xparam, + 'yparam':yparam, + }) + +def workout_comparison_view2(request,id1=0,id2=0,xparam='distance', + yparam='spm',plottype='line'): + promember=0 + if not request.user.is_anonymous(): + r = Rower.objects.get(user=request.user) + result = request.user.is_authenticated() and r.rowerplan=='pro' + if result: + promember=1 + + # create interactive plot + res = interactive_comparison_chart(id1,id2,xparam=xparam,yparam=yparam, + promember=promember,plottype=plottype) + script = res[0] + div = res[1] + + return render(request, + 'comparisonchart2.html', + {'interactiveplot':script, + 'the_div':div, + 'id1':id1, + 'id2':id2, + 'xparam':xparam, + 'yparam':yparam, + 'plottype':plottype, + 'promember':promember, + }) + + + +def workout_flexchart3_view(request,id=0,xparam='distance',yparam1='pace', + yparam2='hr',plottype='line', + promember=0): + + if request.method == 'POST': + workstrokesonly = request.POST['workstrokesonly'] + if workstrokesonly == 'True': + workstrokesonly = True + else: + workstrokesonly = False + else: + workstrokesonly = False + + row = Workout.objects.get(id=id) + promember=0 + mayedit=0 + if not request.user.is_anonymous(): + r = Rower.objects.get(user=request.user) + result = request.user.is_authenticated() and r.rowerplan=='pro' + if result: + promember=1 + if request.user == row.user.user: + mayedit=1 + + # create interactive plot + res = interactive_flex_chart2(id,xparam=xparam,yparam1=yparam1, + yparam2=yparam2, + promember=promember,plottype=plottype, + workstrokesonly=workstrokesonly) + script = res[0] + div = res[1] + js_resources = res[2] + css_resources = res[3] + + return render(request, + 'flexchart3.html', + {'the_script':script, + 'the_div':div, + 'js_res': js_resources, + 'css_res':css_resources, + 'id':id, + 'xparam':xparam, + 'yparam1':yparam1, + 'yparam2':yparam2, + 'plottype':plottype, + 'mayedit':mayedit, + 'promember':promember, + 'workstrokesonly': not workstrokesonly, + }) + +def testbokeh(request): + + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' + + x = np.array(range(51))/10. + y = x**2. + z = (2*(x-2.5))**2 + data = dict( + x = x, + y = y, + z = z, + ) + + df = pd.DataFrame(data) + filtered_df = df + + source = ColumnDataSource( + df + ) + + source2 = ColumnDataSource( + filtered_df + ) + + plot = Figure(tools=TOOLS) + plot.circle('x','y',source=source2) + plot.xaxis.axis_label = "X" + plot.yaxis.axis_label = "Y" + plot.x_range = Range1d(-1,6) + plot.y_range = Range1d(-5,30) + + callback = CustomJS(args = dict(source=source,source2=source2), code=""" + var data = source.data + var data2 = source2.data + var x1 = data['x'] + var y1 = data['y'] + var z1 = data['z'] + var mina = mina.value + var maxa = maxa.value + var minz = minz.value + var maxz = maxz.value + data2['x'] = [] + data2['y'] = [] + data2['z'] = [] + + for (i=0; iNo non-zero data in selection
','',''] + + + datadf['x1'] = datadf.ix[:,xparam] + + datadf['y1'] = datadf.ix[:,yparam1] + if yparam2 != 'None': + datadf['y2'] = datadf.ix[:,yparam2] + else: + datadf['y2'] = datadf['y1'] + + + if xparam=='distance': + xaxmax = datadf['x1'].max() + xaxmin = datadf['x1'].min() + else: + xaxmax = yaxmaxima[xparam] + xaxmin = yaxminima[xparam] + + # average values + x1mean = datadf['x1'].mean() + + y1mean = datadf['y1'].mean() + y2mean = datadf['y2'].mean() + + + xvals = pd.Series(xaxmin+np.arange(100)*(xaxmax-xaxmin)/100.) + + x_axis_type = 'linear' + y_axis_type = 'linear' + + datadf['xname'] = xparam + datadf['yname1'] = yparam1 + if yparam2 != 'None': + datadf['yname2'] = yparam2 + else: + datadf['yname2'] = yparam1 + + source = ColumnDataSource( + datadf + ) + + source2 = ColumnDataSource( + datadf.copy() + ) + + # Add hover to this comma-separated string and see what changes + if (promember==1): + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' + else: + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' + + plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, + tools=TOOLS, + toolbar_location="above", + toolbar_sticky=False) + + x1means = Span(location=x1mean,dimension='height',line_color='green', + line_dash=[6,6], line_width=2) + + y1means = Span(location=y1mean,dimension='width',line_color='blue', + line_dash=[6,6],line_width=2) + y2means = y1means + + xlabel = Label(x=370,y=130,x_units='screen',y_units='screen', + text=xparam+": {x1mean:6.2f}".format(x1mean=x1mean), + background_fill_alpha=.7, + text_color='green', + ) + + + plot.add_layout(x1means) + plot.add_layout(xlabel) + + plot.add_layout(y1means) + + y1label = Label(x=370,y=100,x_units='screen',y_units='screen', + text=yparam1+": {y1mean:6.2f}".format(y1mean=y1mean), + background_fill_alpha=.7, + text_color='blue', + ) + + plot.add_layout(y1label) + + y2label = y1label + plot.circle('x1','y1',source=source2,fill_alpha=0.3,line_color=None, + legend=yparamname1, + ) + + plot.xaxis.axis_label = axlabels[xparam] + plot.yaxis.axis_label = axlabels[yparam1] + + + yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1]) + plot.y_range = yrange1 + + xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) + plot.x_range = xrange1 + + + if yparam2 != 'None': + yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) + plot.extra_y_ranges = {"yax2": yrange2} + + plot.circle('x1','y2',color="red",y_range_name="yax2", + legend=yparamname2, + source=source2,fill_alpha=0.3,line_color=None) + + plot.add_layout(LinearAxis(y_range_name="yax2", + axis_label=axlabels[yparam2]),'right') + + y2means = Span(location=y2mean,dimension='width',line_color='red', + line_dash=[6,6],line_width=2,y_range_name="yax2") + + + plot.add_layout(y2means) + y2label = Label(x=370,y=70,x_units='screen',y_units='screen', + text=yparam2+": {y2mean:6.2f}".format(y2mean=y2mean), + background_fill_alpha=.7, + text_color='red', + ) + if yparam2 != 'pace' and yparam2 != 'time': + plot.add_layout(y2label) + + + callback = CustomJS(args = dict(source=source,source2=source2, + x1means=x1means, + y1means=y1means, + y1label=y1label, + y2label=y2label, + xlabel=xlabel, + y2means=y2means), code=""" + var data = source.data + var data2 = source2.data + var x1 = data['x1'] + var y1 = data['y1'] + var y2 = data['y2'] + var spm1 = data['spm'] + var distance1 = data['distance'] + var xname = data['xname'][0] + var yname1 = data['yname1'][0] + var yname2 = data['yname2'][0] + + var minspm = minspm.value + var maxspm = maxspm.value + var mindist = mindist.value + var maxdist = maxdist.value + var xm = 0 + var ym1 = 0 + var ym2 = 0 + + data2['x1'] = [] + data2['y1'] = [] + data2['y2'] = [] + data2['spm'] = [] + data2['distance'] = [] + data2['x1mean'] = [] + data2['y1mean'] = [] + data2['y2mean'] = [] + data2['xvals'] = [] + data2['y1vals'] = [] + data2['y2vals'] = [] + + for (i=0; iNo erg pieces uploaded yet.
' - - return render(request, 'histoall.html', - {'interactiveplot':script, - 'the_div':div, - 'id':theuser, - 'theuser':u, - }) - -@login_required() -def cum_flex(request,theuser=0, - xparam='spm', - yparam1='power', - yparam2='None', - startdate=timezone.now()-datetime.timedelta(days=10), - enddate=timezone.now()+datetime.timedelta(days=1), - 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 - - promember=0 - if theuser == 0: - theuser = request.user.id - - if not request.user.is_anonymous(): - r = Rower.objects.get(user=request.user) - result = request.user.is_authenticated() and r.rowerplan=='pro' - if result: - promember=1 - - if not promember: - return HttpResponseRedirect("/rowers/about/") - - # get all indoor rows of in date range - - # process form - if request.method == 'POST' and "daterange" in request.POST: - form = DateRangeForm(request.POST) - deltaform = DeltaDaysForm(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 - elif request.method == 'POST' and "datedelta" in request.POST: - deltaform = DeltaDaysForm(request.POST) - if deltaform.is_valid(): - deltadays = deltaform.cleaned_data['deltadays'] - if deltadays != 0: - enddate = timezone.now() - startdate = enddate-datetime.timedelta(days=deltadays) - if startdate > enddate: - s = enddate - enddate = startdate - startdate = s - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - - else: - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - deltaform = DeltaDaysForm() - - try: - r2 = Rower.objects.get(user=theuser) - allergworkouts = Workout.objects.filter(user=r2, - workouttype__in=['rower','dynamic','slides'], - startdatetime__gte=startdate, - startdatetime__lte=enddate) - - except Rower.DoesNotExist: - allergworkouts = [] - r2=0 - - try: - u = User.objects.get(id=theuser) - except User.DoesNotExist: - u = '' - - if allergworkouts: - res = interactive_cum_flex_chart2(allergworkouts,xparam=xparam, - yparam1=yparam1, - yparam2=yparam2, - promember=promember) - script = res[0] - div = res[1] - js_resources = res[2] - css_resources = res[3] - else: - script = '' - div = 'No erg pieces uploaded for this date range.
' - js_resources = '' - css_resources = '' - - return render(request, 'cum_flex.html', - {'interactiveplot':script, - 'the_div':div, - 'js_res': js_resources, - 'css_res':css_resources, - 'id':theuser, - 'theuser':u, - 'startdate':startdate, - 'enddate':enddate, - 'form':form, - 'deltaform':deltaform, - 'xparam':xparam, - 'yparam1':yparam1, - 'yparam2':yparam2, - 'promember':promember, - }) - - -@login_required() -def histo(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 - - promember=0 - if theuser == 0: - theuser = request.user.id - - if not request.user.is_anonymous(): - r = Rower.objects.get(user=request.user) - result = request.user.is_authenticated() and r.rowerplan=='pro' - if result: - promember=1 - - if not promember: - return HttpResponseRedirect("/rowers/about/") - - # get all indoor rows of in date range - - # process form - if request.method == 'POST' and "daterange" in request.POST: - form = DateRangeForm(request.POST) - deltaform = DeltaDaysForm(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 - elif request.method == 'POST' and "datedelta" in request.POST: - deltaform = DeltaDaysForm(request.POST) - if deltaform.is_valid(): - deltadays = deltaform.cleaned_data['deltadays'] - if deltadays != 0: - enddate = timezone.now() - startdate = enddate-datetime.timedelta(days=deltadays) - if startdate > enddate: - s = enddate - enddate = startdate - startdate = s - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - - else: - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - deltaform = DeltaDaysForm() - - try: - r2 = Rower.objects.get(user=theuser) - allergworkouts = Workout.objects.filter(user=r2, - workouttype__in=['rower','dynamic','slides'], - startdatetime__gte=startdate, - startdatetime__lte=enddate) - - except Rower.DoesNotExist: - allergworkouts = [] - r2=0 - - try: - u = User.objects.get(id=theuser) - except User.DoesNotExist: - u = '' - - if allergworkouts: - res = interactive_histoall(allergworkouts) - script = res[0] - div = res[1] - else: - script = '' - div = 'No erg pieces uploaded for this date range.
' - - - return render(request, 'histo.html', - {'interactiveplot':script, - 'the_div':div, - 'id':theuser, - 'theuser':u, - 'startdate':startdate, - 'enddate':enddate, - 'form':form, - 'deltaform':deltaform, - }) - -@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 = Rower.objects.get(user=request.user) - result = request.user.is_authenticated() and r.rowerplan=='pro' - if result: - promember=1 - - # get all indoor rows of 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 != 0: - 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(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - deltaform = DeltaDaysForm() - - # get all 2k (if any) - this rower, in date range - try: - r = Rower.objects.get(user=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)) - - rankingdistances = [100,500,1000,2000,5000,6000,10000,21097,42195,100000] - rankingdurations = [] - rankingdurations.append(datetime.time(minute=1)) - rankingdurations.append(datetime.time(minute=4)) - rankingdurations.append(datetime.time(minute=30)) - rankingdurations.append(datetime.time(hour=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'], - 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', - 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(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'] - pieceunit = form.cleaned_data['pieceunit'] - if pieceunit == 'd': - rankingdistances.append(value) - else: - rankingdurations.append(datetime.time(minute=value)) - 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) - - - - 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, - 'message':message, - 'startdate':startdate, - 'enddate':enddate, - }) - -@login_required() -def workout_recalcsummary_view(request,id=0): - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - filename = row.csvfilename - rowdata = rdata(filename) - row.summary = rowdata.allstats() - row.save() - successmessage = "Summary Updated" - url = reverse(workout_edit_view, - kwargs = { - 'id':str(id), - 'successmessage':str(successmessage), - }) - - return HttpResponseRedirect(url) - - -@login_required() -def workouts_view(request,message='',successmessage=''): - try: - r = Rower.objects.get(user=request.user) - # res = mailprocessing.safeprocessattachments() - #if len(res)>0 and np.cumsum(np.array(res)).max()>0: - # successmessage = 'New Workouts have been created from email' - - workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime") - - return render(request, 'list_workouts.html', - {'workouts': workouts, - 'message': message, - 'successmessage':successmessage, - }) - except Rower.DoesNotExist: - return HttpResponse("Admin has no rower instance") - -@user_passes_test(promember,login_url="/login") -def workout_comparison_list(request,id=0,message='',successmessage=''): - try: - r = Rower.objects.get(user=request.user) - u = User.objects.get(id=r.user.id) - workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime").exclude(id=id) - row = Workout.objects.get(id=id) - - return render(request, 'comparison_list.html', - {'id':id, - 'workout':row, - 'workouts': workouts, - 'last_name':u.last_name, - 'first_name':u.first_name, - 'message': message, - 'successmessage':successmessage, - }) - except Rower.DoesNotExist: - return HttpResponse("Admin has no rower instance") - -def workout_view(request,id=0): - try: - # check if valid ID exists (workout exists) - row = Workout.objects.get(id=id) - g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") - r = Rower.objects.get(id=row.user.id) - u = User.objects.get(id=r.user.id) - - - # create interactive plot - res = interactive_chart(id) - script = res[0] - div = res[1] - - - # render page - if (len(g)<=3): - return render(request, 'workout_view.html', - {'workout':row, - 'graphs1':g[0:3], - 'last_name':u.last_name, - 'first_name':u.first_name, - 'interactiveplot':script, - 'the_div':div}) - else: - return render(request, 'workout_view.html', - {'workout':row, - 'graphs1':g[0:3], - 'graphs2':g[3:6], - 'last_name':u.last_name, - 'first_name':u.first_name, - 'interactiveplot':script, - 'the_div':div}) - - - except Workout.DoesNotExist: - return HttpResponse("Workout doesn't exist") - - -@user_passes_test(promember,login_url="/login") -def workout_undo_smoothenpace_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - filename = row.csvfilename - row = rdata(filename) - if row == 0: - return HttpResponse("Error: CSV Data File Not Found") - - if 'originalvelo' in row.df: - velo = row.df['originalvelo'].values - row.df[' Stroke500mPace (sec/500m)'] = 500./velo - - row.write_csv(filename) - - url = "/rowers/workout/"+str(id)+"/advanced" - - return HttpResponseRedirect(url) - - - -@user_passes_test(promember,login_url="/login") -def workout_smoothenpace_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - filename = row.csvfilename - row = rdata(filename) - if row == 0: - return HttpResponse("Error: CSV Data File Not Found") - - pace = row.df[' Stroke500mPace (sec/500m)'].values - velo = 500./pace - - if not 'originalvelo' in row.df: - row.df['originalvelo'] = velo - - velo2 = stravastuff.ewmovingaverage(velo,5) - - pace2 = 500./abs(velo2) - - row.df[' Stroke500mPace (sec/500m)'] = pace2 - - row.df = row.df.fillna(0) - - row.write_csv(filename) - - url = "/rowers/workout/"+str(id)+"/advanced" - - return HttpResponseRedirect(url) - -@user_passes_test(promember,login_url="/login") -def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - if request.method == 'POST': - form = CNsummaryForm(request.POST,request.FILES) - if form.is_valid(): - f = request.FILES['file'] - res = handle_uploaded_file(f) - fname = res[1] - try: - sumd = summarydata(fname) - row.summary = sumd.allstats() - row.save() - os.remove(fname) - successmessage = "CrewNerd summary added" - url = reverse(workout_edit_view, - kwargs = { - 'id':str(id), - 'successmessage':str(successmessage), - }) - - return HttpResponseRedirect(url) - except: - os.remove(fname) - message = "Something went wrong (workout_crewnerd_summary_view)" - url = reverse(workout_edit_view, - kwargs = { - 'id':str(id), - 'message':str(message), - }) - return HttpResponseRedirect(url) - else: - return render(request, - "cn_form.html", - {'form':form, - 'id':row.id}) - else: - form = CNsummaryForm() - - return render(request, - "cn_form.html", - {'form':form, - 'id':row.id}) - -@user_passes_test(promember,login_url="/login") -def workout_downloadwind_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - f1 = row.csvfilename - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - # create bearing - rowdata = rdata(f1) - if rowdata == 0: - return HttpResponse("Error: CSV Data File Not Found") - - try: - bearing = rowdata.df.ix[:,'bearing'].values - except KeyError: - rowdata.add_bearing() - rowdata.write_csv(f1) - - # get wind - try: - avglat = rowdata.df[' latitude'].mean() - avglon = rowdata.df[' longitude'].mean() - avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.ix[0,'TimeStamp (sec)']) - startdatetime = dateutil.parser.parse("{}, {}".format(row.date, - row.starttime)) - - starttimeunix = int(mktime(startdatetime.timetuple())) - avgtime = starttimeunix+avgtime - winddata = get_wind_data(avglat,avglon,avgtime) - windspeed = winddata[0] - windbearing = winddata[1] - message = winddata[2] - row.notes += "\n"+message - row.save() - rowdata.add_wind(windspeed,windbearing) - rowdata.write_csv(f1) - - kwargs = {'successmessage':str(message), - 'id':str(id)} - - url = reverse(workout_wind_view,kwargs=kwargs) - response = HttpResponseRedirect(url) - except KeyError: - message = "No latitude/longitude data" - kwargs = {'message':str(message), - 'id':str(id)} - url = reverse(workout_wind_view,kwargs=kwargs) - response = HttpResponseRedirect(url) - - - - return response - - -@user_passes_test(promember,login_url="/login") -def workout_wind_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - - # get data - f1 = row.csvfilename - u = request.user - r = Rower.objects.get(user=u) - - # create bearing - rowdata = rdata(f1) - if row == 0: - return HttpResponse("Error: CSV Data File Not Found") - - - hascoordinates = 1 - try: - latitude = rowdata.df.ix[:,' latitude'] - except KeyError: - hascoordinates = 0 - - try: - bearing = rowdata.df.ix[:,'bearing'].values - except KeyError: - rowdata.add_bearing() - rowdata.write_csv(f1) - - - - - if request.method == 'POST': - # process form - form = UpdateWindForm(request.POST) - - if form.is_valid(): - - vwind1 = form.cleaned_data['vwind1'] - vwind2 = form.cleaned_data['vwind2'] - dist1 = form.cleaned_data['dist1'] - dist2 = form.cleaned_data['dist2'] - winddirection1 = form.cleaned_data['winddirection1'] - winddirection2 = form.cleaned_data['winddirection2'] - windunit = form.cleaned_data['windunit'] - - rowdata.update_wind(vwind1,vwind2, - winddirection1, - winddirection2, - dist1,dist2, - units=windunit) - - rowdata.write_csv(f1) - - - else: - message = "Invalid Form" - kwargs = {'message':str(message), - 'id':str(id)} - url = reverse(workout_wind_view,kwargs=kwargs) - response = HttpResponseRedirect(url) - - else: - form = UpdateWindForm() - - # create interactive plot - res = interactive_windchart(id,promember=1) - script = res[0] - div = res[1] - - if hascoordinates: - res = googlemap_chart(rowdata.df[' latitude'], - rowdata.df[' longitude'], - row.name) - gmscript = res[0] - gmdiv = res[1] - else: - gmscript = "" - gmdiv = "No GPS data available" - - return render(request, - 'windedit.html', - {'workout':row, - 'message': message, - 'successmessage': successmessage, - 'interactiveplot':script, - 'form':form, - 'the_div':div, - 'gmap':gmscript, - 'gmapdiv':gmdiv}) - - -@user_passes_test(promember,login_url="/login") -def workout_stream_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - - # create interactive plot - f1 = row.csvfilename - u = request.user - r = Rower.objects.get(user=u) - - rowdata = rdata(f1) - if rowdata == 0: - return HttpResponse("Error: CSV Data File Not Found") - - if request.method == 'POST': - # process form - form = UpdateStreamForm(request.POST) - - if form.is_valid(): - - dist1 = form.cleaned_data['dist1'] - dist2 = form.cleaned_data['dist2'] - stream1 = form.cleaned_data['stream1'] - stream2 = form.cleaned_data['stream2'] - streamunit = form.cleaned_data['streamunit'] - - rowdata.update_stream(stream1,stream2,dist1,dist2, - units=streamunit) - - rowdata.write_csv(f1) - - - else: - message = "Invalid Form" - kwargs = {'message':str(message), - 'id':str(id)} - url = reverse(workout_wind_view,kwargs=kwargs) - response = HttpResponseRedirect(url) - - else: - form = UpdateStreamForm() - - # create interactive plot - res = interactive_streamchart(id,promember=1) - script = res[0] - div = res[1] - - return render(request, - 'streamedit.html', - {'workout':row, - 'message': message, - 'successmessage': successmessage, - 'interactiveplot':script, - 'form':form, - 'the_div':div}) - - -@user_passes_test(promember, login_url="/login") -def workout_otwsetpower_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - - if request.method == 'POST': - # process form - form = AdvancedWorkoutForm(request.POST) - - if form.is_valid(): - boattype = form.cleaned_data['boattype'] - weightvalue = form.cleaned_data['weightvalue'] - row.boattype = boattype - row.weightvalue = weightvalue - row.save() - - # load row data & create power/wind/bearing columns if not set - f1 = row.csvfilename - rowdata = rdata(f1) - if rowdata == 0: - return HttpResponse("Error: CSV Data File Not Found") - try: - vstream = rowdata.df['vstream'] - except KeyError: - rowdata.add_stream(0) - rowdata.write_csv(f1) - - try: - bearing = rowdata.df['bearing'] - except KeyError: - rowdata.add_bearing() - rowdata.write_csv(f1) - - try: - vwind = rowdata.df['vwind'] - except KeyError: - rowdata.add_wind(0,0) - rowdata.write_csv(f1) - - # do power calculation (asynchronous) - u = request.user - first_name = u.first_name - last_name = u.last_name - emailaddress = u.email - - if settings.DEBUG: - res = handle_otwsetpower.delay(f1,boattype,weightvalue, - first_name,last_name,emailaddress,id) - else: - res = queuelow.enqueue(handle_otwsetpower,f1,boattype, - weightvalue, - first_name,last_name,emailaddress,id) - - - successmessage = "Your calculations have been submitted. You will receive an email when they are done." - kwargs = {'successmessage':str(successmessage), - 'id':str(id)} - - url = reverse(workout_advanced_view,kwargs=kwargs) - response = HttpResponseRedirect(url) - return response - - else: - message = "Invalid Form" - kwargs = {'message':str(message), - 'id':str(id)} - url = reverse(workout_otwsetpower_view,kwargs=kwargs) - response = HttpResponseRedirect(url) - - else: - form = AdvancedWorkoutForm(instance=row) - - return render(request, - 'otwsetpower.html', - {'workout':row, - 'message': message, - 'successmessage': successmessage, - 'form':form, - }) - - -@login_required() -def workout_geeky_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - form = WorkoutForm(instance=row) - g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") - # check if user is owner of this workout - - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - - # create interactive plot - f1 = row.csvfilename - u = request.user - r = Rower.objects.get(user=u) - - # create interactive plot - try: - res = interactive_chart(id,promember=1) - script = res[0] - div = res[1] - except ValueError: - pass - - if row.workouttype=='water': - return render(request, - 'otwgeeky.html', - {'workout':row, - 'message': message, - 'successmessage': successmessage, - 'interactiveplot':script, - 'the_div':div}) - else: - return render(request, - 'advancededit.html', - {'workout':row, - 'message': message, - 'successmessage': successmessage, - 'interactiveplot':script, - 'the_div':div}) - -#@user_passes_test(promember,login_url="/login") -@login_required() -def workout_advanced_view(request,id=0,message="",successmessage=""): - row = Workout.objects.get(id=id) - form = WorkoutForm(instance=row) - g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") - # check if user is owner of this workout - - if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" - url = reverse(workouts_view,args=[str(message)]) - - return HttpResponseRedirect(url) - - - # create interactive plot - f1 = row.csvfilename - u = request.user - r = Rower.objects.get(user=u) - - # create interactive plot - try: - res = interactive_chart(id,promember=1) - script = res[0] - div = res[1] - except ValueError: - pass - - if row.workouttype=='water': - return render(request, - 'advancedotw.html', - {'workout':row, - 'message': message, - 'successmessage': successmessage, - 'interactiveplot':script, - 'the_div':div}) - else: - return render(request, - 'advancededit.html', - {'workout':row, - 'message': message, - 'successmessage': successmessage, - 'interactiveplot':script, - 'the_div':div}) - -def workout_comparison_view(request,id1=0,id2=0,xparam='distance',yparam='spm'): - promember=0 - if not request.user.is_anonymous(): - r = Rower.objects.get(user=request.user) - result = request.user.is_authenticated() and r.rowerplan=='pro' - if result: - promember=1 - - # create interactive plot - res = interactive_comparison_chart(id1,id2,xparam=xparam,yparam=yparam, - promember=promember) - script = res[0] - div = res[1] - - - return render(request, - 'comparisonchart.html', - {'interactiveplot':script, - 'the_div':div, - 'id1':id1, - 'id2':id2, - 'xparam':xparam, - 'yparam':yparam, - }) - -def workout_comparison_view2(request,id1=0,id2=0,xparam='distance', - yparam='spm',plottype='line'): - promember=0 - if not request.user.is_anonymous(): - r = Rower.objects.get(user=request.user) - result = request.user.is_authenticated() and r.rowerplan=='pro' - if result: - promember=1 - - # create interactive plot - res = interactive_comparison_chart(id1,id2,xparam=xparam,yparam=yparam, - promember=promember,plottype=plottype) - script = res[0] - div = res[1] - - return render(request, - 'comparisonchart2.html', - {'interactiveplot':script, - 'the_div':div, - 'id1':id1, - 'id2':id2, - 'xparam':xparam, - 'yparam':yparam, - 'plottype':plottype, - 'promember':promember, - }) - - - -def workout_flexchart3_view(request,id=0,xparam='distance',yparam1='pace', - yparam2='hr',plottype='line', - promember=0): - - if request.method == 'POST': - workstrokesonly = request.POST['workstrokesonly'] - if workstrokesonly == 'True': - workstrokesonly = True - else: - workstrokesonly = False - else: - workstrokesonly = False - - row = Workout.objects.get(id=id) - promember=0 - mayedit=0 - if not request.user.is_anonymous(): - r = Rower.objects.get(user=request.user) - result = request.user.is_authenticated() and r.rowerplan=='pro' - if result: - promember=1 - if request.user == row.user.user: - mayedit=1 - - # create interactive plot - res = interactive_flex_chart2(id,xparam=xparam,yparam1=yparam1, - yparam2=yparam2, - promember=promember,plottype=plottype, - workstrokesonly=workstrokesonly) - script = res[0] - div = res[1] - js_resources = res[2] - css_resources = res[3] - - return render(request, - 'flexchart3.html', - {'the_script':script, - 'the_div':div, - 'js_res': js_resources, - 'css_res':css_resources, - 'id':id, - 'xparam':xparam, - 'yparam1':yparam1, - 'yparam2':yparam2, - 'plottype':plottype, - 'mayedit':mayedit, - 'promember':promember, - 'workstrokesonly': not workstrokesonly, - }) - -def testbokeh(request): - - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' - - x = np.array(range(51))/10. - y = x**2. - z = (2*(x-2.5))**2 - data = dict( - x = x, - y = y, - z = z, - ) - - df = pd.DataFrame(data) - filtered_df = df - - source = ColumnDataSource( - df - ) - - source2 = ColumnDataSource( - filtered_df - ) - - plot = Figure(tools=TOOLS) - plot.circle('x','y',source=source2) - plot.xaxis.axis_label = "X" - plot.yaxis.axis_label = "Y" - plot.x_range = Range1d(-1,6) - plot.y_range = Range1d(-5,30) - - callback = CustomJS(args = dict(source=source,source2=source2), code=""" - var data = source.data - var data2 = source2.data - var x1 = data['x'] - var y1 = data['y'] - var z1 = data['z'] - var mina = mina.value - var maxa = maxa.value - var minz = minz.value - var maxz = maxz.value - data2['x'] = [] - data2['y'] = [] - data2['z'] = [] - - for (i=0; iDirect link for other Pro users: - http://rowsandall.com/rowers/{{ id }}/histo/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }} + https://rowsandall.com/rowers/{{ id }}/histo/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}
Summary of the past 12 months for {{ theuser.first_name }} {{ theuser.last_name }}
Direct link for other Pro users: - http://rowsandall.com/rowers/{{ id }}/histo-all + https://rowsandall.com/rowers/{{ id }}/histo-all
Direct link for other users: - http://rowsandall.com/rowers/{{ id }}/ote-bests/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }} + https://rowsandall.com/rowers/{{ id }}/ote-bests/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}
The table gives the best efforts achieved on the official Concept2 ranking pieces in the selected date range.
diff --git a/rowers/templates/summary_edit.html b/rowers/templates/summary_edit.html index de042397..5d7c98e3 100644 --- a/rowers/templates/summary_edit.html +++ b/rowers/templates/summary_edit.html @@ -48,12 +48,12 @@No non-zero data in selection
','',''] - datadf['x1'] = datadf.ix[:,xparam] - - datadf['y1'] = datadf.ix[:,yparam1] + # datadf['x1'] = datadf.ix[:,xparam] + datadf = datadf.rename(columns={ + xparam:'x1', + yparam1:'y1', + }) + + # datadf['y1'] = datadf.ix[:,yparam1] if yparam2 != 'None': - datadf['y2'] = datadf.ix[:,yparam2] + # datadf['y2'] = datadf.ix[:,yparam2] + datadf = datadf.rename(columns={yparam2:'y2'}) else: datadf['y2'] = datadf['y1'] @@ -674,6 +680,8 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, datadf.copy() ) + print "jet",timezone.now() + # Add hover to this comma-separated string and see what changes if (promember==1): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' diff --git a/rowers/templates/comparison_list.html b/rowers/templates/comparison_list.html index a0fbcadb..9db40a2a 100644 --- a/rowers/templates/comparison_list.html +++ b/rowers/templates/comparison_list.html @@ -30,6 +30,14 @@No workouts found
{% endif %} + +diff --git a/rowers/templates/list_workouts.html b/rowers/templates/list_workouts.html index 0b4334ef..31c1ce88 100644 --- a/rowers/templates/list_workouts.html +++ b/rowers/templates/list_workouts.html @@ -5,8 +5,10 @@ {% block title %}Workouts{% endblock %} {% block content %} +
| Weight Category: | {{ workout.weightcategory }} |
|---|
+
+ ++