diff --git a/cvkbrno/models.py b/cvkbrno/models.py index d8b0900f..6fe437a1 100644 --- a/cvkbrno/models.py +++ b/cvkbrno/models.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# -*- Coding: utf-8 -*- from __future__ import unicode_literals from django.db import models @@ -18,86 +18,86 @@ class BoatCategory(models.Model): club = models.CharField(_("Club"),max_length=30) class Meta: - verbose_name = _("boat category") - verbose_name_plural = _("boat categories") - ordering = ['name'] + verbose_name = _("boat category") + verbose_name_plural = _("boat categories") + ordering = ['name'] def __str__(self): - str = self.name + str = self.name - return str + return str def __unicode__(self): - str = self.name + str = self.name - return str + return str class Member(models.Model): statuses = ( - ("coach", _("coach")), - ("member", _("member")), - ("administrator", _("administrator")), - ) + ("coach", _("coach")), + ("member", _("member")), + ("administrator", _("administrator")), + ) class Meta: - verbose_name = _("member") - verbose_name_plural = _("members") - ordering = ['user'] + verbose_name = _("member") + verbose_name_plural = _("members") + ordering = ['user'] - user = models.OneToOneField(User) + user = models.OneToOneField(User,on_delete=models.CASCADE) contributions = models.BooleanField(default=True) status = models.CharField(default="member", - choices=statuses, - max_length=30) + choices=statuses, + max_length=30) categories = models.ManyToManyField(BoatCategory, - verbose_name=_("Boat Categories")) + verbose_name=_("Boat Categories")) club = models.CharField(_("Club"),max_length=30) hoursworked = models.FloatField(_("Hours Worked")) def __str__(self): - str = self.user.first_name+' '+self.user.last_name - return str + str = self.user.first_name+' '+self.user.last_name + return str def __unicode__(self): - str = self.user.first_name+' '+self.user.last_name - return str + str = self.user.first_name+' '+self.user.last_name + return str class Boat(models.Model): class Meta: - verbose_name = _("boat") - verbose_name_plural = _("boats") - ordering = ['boatcode'] + verbose_name = _("boat") + verbose_name_plural = _("boats") + ordering = ['boatcode'] boatname = models.CharField(_("Boat Name"),max_length=30) boatcode = models.CharField(_("Boat Code"),max_length=10) categories = models.ManyToManyField(BoatCategory) nrseats = models.IntegerField(_("Nr of Seats")) statuses = ( - ("water",_("water")), - ("hangar",_("hangar")), - ("damaged",_("damaged")), - ("races",_("races")), - ) + ("water",_("water")), + ("hangar",_("hangar")), + ("damaged",_("damaged")), + ("races",_("races")), + ) status = models.CharField(default="hangar", - choices=statuses, - max_length=30) + choices=statuses, + max_length=30) comment = models.CharField(_("Comment"),blank=True,max_length=100) def __str__(self): - str = self.boatcode+' '+self.boatname + str = self.boatcode+' '+self.boatname - return str + return str def __unicode__(self): - str = self.boatcode+' '+self.boatname + str = self.boatcode+' '+self.boatname - return str + return str class MemberWork(models.Model): class Meta: - verbose_name = _("member work") - verbose_name_plural = _("member work") + verbose_name = _("member work") + verbose_name_plural = _("member work") date = models.DateField(_("Date")) hours = models.FloatField(_("Hours")) @@ -105,16 +105,16 @@ class MemberWork(models.Model): comment = models.CharField(_("Comment"),blank=True,max_length=100) worker = models.ManyToManyField(Member,_("Worker")) statuses = ( - ("planned",_("planned")), - ("executed",_("executed")) - ) + ("planned",_("planned")), + ("executed",_("executed")) + ) status = models.CharField(default="planned", - choices=statuses, - max_length=30) + choices=statuses, + max_length=30) class Races(models.Model): class Meta: - verbose_name = _("race") - verbose_name_plural = _("races") + verbose_name = _("race") + verbose_name_plural = _("races") name = models.CharField(max_length = 30) @@ -124,20 +124,20 @@ class Races(models.Model): transportboats = models.ManyToManyField(Boat) def __str__(self): - str = self.name - str = str+' '+self.startdatetime.strftime('%Y-%m-%d %H:%M:%S') - return str + str = self.name + str = str+' '+self.startdatetime.strftime('%Y-%m-%d %H:%M:%S') + return str def __unicode__(self): - str = self.name - str = str+' '+self.startdatetime.strftime('%Y-%m-%d %H:%M:%S') - return str + str = self.name + str = str+' '+self.startdatetime.strftime('%Y-%m-%d %H:%M:%S') + return str class Outing(models.Model): class Meta: - verbose_name = _("outing") - verbose_name_plural = _("outings") + verbose_name = _("outing") + verbose_name_plural = _("outings") starttime = models.DateTimeField(verbose_name = _("Start Time"),default=timezone.now) @@ -145,27 +145,27 @@ class Outing(models.Model): distance = models.FloatField(_("Distance (km)"),default=12) comment = models.CharField(_("Comment"),blank=True,max_length=100) statuses = ( - ("reservation",_("reservation")), - ("active", _("active")), - ("completed", _("completed")), - ("race", _("race")), - ) - boat = models.ForeignKey(Boat) - rower = models.ForeignKey(Member) + ("reservation",_("reservation")), + ("active", _("active")), + ("completed", _("completed")), + ("race", _("race")), + ) + boat = models.ForeignKey(Boat,on_delete=models.CASCADE) + rower = models.ForeignKey(Member,on_delete=models.CASCADE) race = models.ManyToManyField(Races,blank=True) otherrowers = models.ManyToManyField(Member,related_name="otherrowers") status = models.CharField(_("Status"),default="active", - choices=statuses, - max_length=30) + choices=statuses, + max_length=30) def __str__(self): - str = self.boat.boatcode - str = str+' '+self.starttime.strftime('%Y-%m-%d %H:%M:%S') - return str + str = self.boat.boatcode + str = str+' '+self.starttime.strftime('%Y-%m-%d %H:%M:%S') + return str def __unicode__(self): - str = self.boat.boatcode - str = str+' '+self.starttime.strftime('%Y-%m-%d %H:%M:%S') - return str + str = self.boat.boatcode + str = str+' '+self.starttime.strftime('%Y-%m-%d %H:%M:%S') + return str diff --git a/cvkbrno/tasks.py b/cvkbrno/tasks.py index 751a2f12..c507f6e8 100644 --- a/cvkbrno/tasks.py +++ b/cvkbrno/tasks.py @@ -1,4 +1,4 @@ -from celery import Celery,app +from .celery import Celery,app import os import time import gc diff --git a/rowers/__init__.py b/rowers/__init__.py index 03d28f5e..4a44fb0d 100644 --- a/rowers/__init__.py +++ b/rowers/__init__.py @@ -1,5 +1,5 @@ -from __future__ import absolute_import - -from .tasks import app as celery_app +from __future__ import absolute_import, unicode_literals +from rowers.celery import app as celery_app +__all__ = ('celery_app',) diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 88e7d46e..d69960f1 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # The interactions with the Concept2 logbook API # All C2 related functions should be defined here # (There is still some stuff defined directly in views.py. Need to @@ -6,7 +7,7 @@ from rowers.imports import * import datetime from requests import Request, Session -import mytypes +import rowers.mytypes as mytypes from rowers.mytypes import otwtypes from iso8601 import ParseError @@ -19,7 +20,7 @@ import django_rq queue = django_rq.get_queue('default') queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low') -from utils import myqueue +from rowers.utils import myqueue oauth_data = { 'client_id': C2_CLIENT_ID, @@ -41,19 +42,19 @@ oauth_data = { def c2_open(user): r = Rower.objects.get(user=user) if (r.c2token == '') or (r.c2token is None): - s = "Token doesn't exist. Need to authorize" - raise NoTokenError("User has no token") + s = "Token doesn't exist. Need to authorize" + raise NoTokenError("User has no token") else: - if (timezone.now()>r.tokenexpirydate): - res = rower_c2_token_refresh(user) + if (timezone.now()>r.tokenexpirydate): + res = rower_c2_token_refresh(user) if res == None: raise NoTokenError("User has no token") if res[0] != None: thetoken = res[0] else: raise NoTokenError("User has no token") - else: - thetoken = r.c2token + else: + thetoken = r.c2token return thetoken @@ -61,11 +62,11 @@ def add_stroke_data(user,c2id,workoutid,startdatetime,csvfilename, workouttype='rower'): r = Rower.objects.get(user=user) if (r.c2token == '') or (r.c2token is None): - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" elif (timezone.now()>r.tokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: starttimeunix = arrow.get(startdatetime).timestamp @@ -179,9 +180,9 @@ def makeseconds(t): # convert our weight class code to Concept2 weight class code def c2wc(weightclass): if (weightclass=="lwt"): - res = "L" + res = "L" else: - res = "H" + res = "H" return res @@ -343,17 +344,17 @@ def createc2workoutdata_as_splits(w): hr = df[' HRCur (bpm)'].astype(int) split_data = [] for i in range(len(t)): - thisrecord = {"time":t[i],"distance":d[i],"stroke_rate":spm[i], - "heart_rate":{ - "average:":hr[i] - } - } - split_data.append(thisrecord) + thisrecord = {"time":t[i],"distance":d[i],"stroke_rate":spm[i], + "heart_rate":{ + "average:":hr[i] + } + } + split_data.append(thisrecord) try: - durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S.%f") + durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S.%f") except ValueError: - durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S") + durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S") try: newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com' @@ -365,19 +366,19 @@ def createc2workoutdata_as_splits(w): wtype = 'water' data = { - "type": wtype, - "date": w.startdatetime.isoformat(), - "distance": int(w.distance), - "time": int(10*makeseconds(durationstr)), - "timezone": w.timezone, - "weight_class": c2wc(w.weightcategory), - "comments": newnotes, - "heart_rate": { - "average": averagehr, - "max": maxhr, - }, - "splits": split_data, - } + "type": wtype, + "date": w.startdatetime.isoformat(), + "distance": int(w.distance), + "time": int(10*makeseconds(durationstr)), + "timezone": w.timezone, + "weight_class": c2wc(w.weightcategory), + "comments": newnotes, + "heart_rate": { + "average": averagehr, + "max": maxhr, + }, + "splits": split_data, + } return data @@ -418,13 +419,13 @@ def createc2workoutdata(w): hr = 0*d stroke_data = [] for i in range(len(t)): - thisrecord = {"t":t[i],"d":d[i],"p":p[i],"spm":spm[i],"hr":hr[i]} - stroke_data.append(thisrecord) + thisrecord = {"t":t[i],"d":d[i],"p":p[i],"spm":spm[i],"hr":hr[i]} + stroke_data.append(thisrecord) try: - durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S.%f") + durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S.%f") except ValueError: - durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S") + durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S") workouttype = w.workouttype if workouttype in otwtypes: @@ -436,19 +437,19 @@ def createc2workoutdata(w): startdate = datetime.datetime.combine(w.date,datetime.time()) data = { - "type": mytypes.c2mapping[workouttype], - "date": w.startdatetime.isoformat(), - "timezone": w.timezone, - "distance": int(w.distance), - "time": int(10*makeseconds(durationstr)), - "weight_class": c2wc(w.weightcategory), - "comments": w.notes, - "heart_rate": { - "average": averagehr, - "max": maxhr, - }, - "stroke_data": stroke_data, - } + "type": mytypes.c2mapping[workouttype], + "date": w.startdatetime.isoformat(), + "timezone": w.timezone, + "distance": int(w.distance), + "time": int(10*makeseconds(durationstr)), + "weight_class": c2wc(w.weightcategory), + "comments": w.notes, + "heart_rate": { + "average": averagehr, + "max": maxhr, + }, + "stroke_data": stroke_data, + } return data @@ -458,10 +459,10 @@ def do_refresh_token(refreshtoken): scope = "results:write,user:read" client_auth = requests.auth.HTTPBasicAuth(C2_CLIENT_ID, C2_CLIENT_SECRET) post_data = {"grant_type": "refresh_token", - "client_secret": C2_CLIENT_SECRET, - "client_id":C2_CLIENT_ID, - "refresh_token": refreshtoken, - } + "client_secret": C2_CLIENT_SECRET, + "client_id":C2_CLIENT_ID, + "refresh_token": refreshtoken, + } headers = {'user-agent': 'sanderroosendaal'} url = "https://log.concept2.com/oauth/access_token" s = Session() @@ -498,9 +499,9 @@ def get_token(code): post_data = {"grant_type": "authorization_code", "code": code, "redirect_uri": C2_REDIRECT_URI, - "client_secret": C2_CLIENT_SECRET, - "client_id":C2_CLIENT_ID, - } + "client_secret": C2_CLIENT_SECRET, + "client_id":C2_CLIENT_ID, + } headers = {'user-agent': 'sanderroosendaal'} url = "https://log.concept2.com/oauth/access_token" s = Session() @@ -554,19 +555,19 @@ def make_authorization_url(request): def get_workout(user,c2id): r = Rower.objects.get(user=user) if (r.c2token == '') or (r.c2token is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) ,0 + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) ,0 elif (timezone.now()>r.tokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s),0 + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s),0 else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.c2token) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://log.concept2.com/api/users/me/results/"+str(c2id) - s = requests.get(url,headers=headers) + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.c2token) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://log.concept2.com/api/users/me/results/"+str(c2id) + s = requests.get(url,headers=headers) data = s.json()['data'] @@ -583,9 +584,9 @@ def get_workout(user,c2id): # Check if workout has stroke data, and get the stroke data if data['stroke_data']: - res2 = get_c2_workout_strokes(user,c2id) - if res2.status_code == 200: - strokedata = pd.DataFrame.from_dict(res2.json()['data']) + res2 = get_c2_workout_strokes(user,c2id) + if res2.status_code == 200: + strokedata = pd.DataFrame.from_dict(res2.json()['data']) else: strokedata = pd.DataFrame() else: @@ -597,19 +598,19 @@ def get_workout(user,c2id): def get_c2_workout_strokes(user,c2id): r = Rower.objects.get(user=user) if (r.c2token == '') or (r.c2token is None): - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" elif (timezone.now()>r.tokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.c2token) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes" - s = requests.get(url,headers=headers) + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.c2token) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes" + s = requests.get(url,headers=headers) return s @@ -618,21 +619,21 @@ def get_c2_workout_strokes(user,c2id): def get_c2_workout_list(user,page=1): r = Rower.objects.get(user=user) if (r.c2token == '') or (r.c2token is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) elif (timezone.now()>r.tokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.c2token) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://log.concept2.com/api/users/me/results" + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.c2token) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://log.concept2.com/api/users/me/results" url += "?page={page}".format(page=page) - s = requests.get(url,headers=headers) + s = requests.get(url,headers=headers) return s @@ -642,8 +643,8 @@ def get_c2_workout_list(user,page=1): def get_username(access_token): authorizationstring = str('Bearer ' + access_token) headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} import urllib url = "https://log.concept2.com/api/users/me" response = requests.get(url,headers=headers) @@ -664,8 +665,8 @@ def get_username(access_token): def get_userid(access_token): authorizationstring = str('Bearer ' + access_token) headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} import urllib url = "https://log.concept2.com/api/users/me" response = requests.get(url,headers=headers) @@ -706,40 +707,40 @@ def workout_c2_upload(user,w): # ready to upload. Hurray if (checkworkoutuser(user,w)): - c2userid = get_userid(r.c2token) + c2userid = get_userid(r.c2token) if not c2userid: raise NoTokenError - data = createc2workoutdata(w) + data = createc2workoutdata(w) if data == 0: return "Error: No data file. Contact info@rowsandall.com if the problem persists",0 - authorizationstring = str('Bearer ' + r.c2token) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - import urllib - url = "https://log.concept2.com/api/users/%s/results" % (c2userid) - response = requests.post(url,headers=headers,data=json.dumps(data)) + authorizationstring = str('Bearer ' + r.c2token) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + import urllib + url = "https://log.concept2.com/api/users/%s/results" % (c2userid) + response = requests.post(url,headers=headers,data=json.dumps(data)) if (response.status_code == 409 ): - message = "Concept2 Duplicate error" - w.uploadedtoc2 = -1 + message = "Concept2 Duplicate error" + w.uploadedtoc2 = -1 c2id = -1 - w.save() + w.save() elif (response.status_code == 201 or response.status_code == 200): try: -# s= json.loads(response.text) +# s= json.loads(response.text) s = response.json() - c2id = s['data']['id'] - w.uploadedtoc2 = c2id - w.save() + c2id = s['data']['id'] + w.uploadedtoc2 = c2id + w.save() message = "Upload to Concept2 was successful" except: message = "Something went wrong in workout_c2_upload_view. Response code 200/201 but C2 sync failed: "+response.text c2id = 0 - else: + else: message = "Something went wrong in workout_c2_upload_view. Response code 200/201 but C2 sync failed: "+response.text c2id = 0 @@ -776,41 +777,41 @@ def add_workout_from_data(user,importid,data,strokedata, workouttype = 'rower' if workouttype not in [x[0] for x in Workout.workouttypes]: - workouttype = 'other' + workouttype = 'other' try: - comments = data['comments'] + comments = data['comments'] except: - comments = ' ' + comments = ' ' try: - thetimezone = tz(data['timezone']) + thetimezone = tz(data['timezone']) except: - thetimezone = 'UTC' + thetimezone = 'UTC' r = Rower.objects.get(user=user) try: - rowdatetime = iso8601.parse_date(data['date_utc']) + rowdatetime = iso8601.parse_date(data['date_utc']) except KeyError: - rowdatetime = iso8601.parse_date(data['start_date']) + rowdatetime = iso8601.parse_date(data['start_date']) except ParseError: - rowdatetime = iso8601.parse_date(data['date']) + rowdatetime = iso8601.parse_date(data['date']) - + try: c2intervaltype = data['workout_type'] - + except KeyError: - c2intervaltype = '' - + c2intervaltype = '' + try: - title = data['name'] + title = data['name'] except KeyError: - title = "" - try: - t = data['comments'].split('\n', 1)[0] - title += t[:20] - except: - title = 'Imported' + title = "" + try: + t = data['comments'].split('\n', 1)[0] + title += t[:20] + except: + title = 'Imported' starttimeunix = arrow.get(rowdatetime).timestamp @@ -825,17 +826,17 @@ def add_workout_from_data(user,importid,data,strokedata, nr_rows = len(unixtime) try: - latcoord = strokedata.loc[:,'lat'] - loncoord = strokedata.loc[:,'lon'] + latcoord = strokedata.loc[:,'lat'] + loncoord = strokedata.loc[:,'lon'] except: - latcoord = np.zeros(nr_rows) - loncoord = np.zeros(nr_rows) + latcoord = np.zeros(nr_rows) + loncoord = np.zeros(nr_rows) try: - strokelength = strokedata.loc[:,'strokelength'] + strokelength = strokedata.loc[:,'strokelength'] except: - strokelength = np.zeros(nr_rows) + strokelength = np.zeros(nr_rows) dist2 = 0.1*strokedata.loc[:,'d'] @@ -862,27 +863,27 @@ def add_workout_from_data(user,importid,data,strokedata, # save csv # Create data frame with all necessary data to write to csv df = pd.DataFrame({'TimeStamp (sec)':unixtime, - ' Horizontal (meters)': dist2, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' longitude':loncoord, - ' latitude':latcoord, - ' Stroke500mPace (sec/500m)':pace, - ' Power (watts)':power, - ' DragFactor':np.zeros(nr_rows), - ' DriveLength (meters)':np.zeros(nr_rows), - ' StrokeDistance (meters)':strokelength, - ' DriveTime (ms)':np.zeros(nr_rows), - ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), - ' AverageDriveForce (lbs)':np.zeros(nr_rows), - ' PeakDriveForce (lbs)':np.zeros(nr_rows), - ' lapIdx':lapidx, - ' ElapsedTime (sec)':seconds - }) + ' Horizontal (meters)': dist2, + ' Cadence (stokes/min)':spm, + ' HRCur (bpm)':hr, + ' longitude':loncoord, + ' latitude':latcoord, + ' Stroke500mPace (sec/500m)':pace, + ' Power (watts)':power, + ' DragFactor':np.zeros(nr_rows), + ' DriveLength (meters)':np.zeros(nr_rows), + ' StrokeDistance (meters)':strokelength, + ' DriveTime (ms)':np.zeros(nr_rows), + ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), + ' AverageDriveForce (lbs)':np.zeros(nr_rows), + ' PeakDriveForce (lbs)':np.zeros(nr_rows), + ' lapIdx':lapidx, + ' ElapsedTime (sec)':seconds + }) df.sort_values(by='TimeStamp (sec)',ascending=True) - + timestr = strftime("%Y%m%d-%H%M%S") diff --git a/rowers/courses.py b/rowers/courses.py index 606e9471..f89dabb2 100644 --- a/rowers/courses.py +++ b/rowers/courses.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # All the Courses related methods # Python @@ -28,7 +29,7 @@ import pandas as pd import numpy as np from timezonefinder import TimezoneFinder -import dataprep +import rowers.dataprep as dataprep from rowers.utils import geo_distance ns = {'opengis': 'http://www.opengis.net/kml/2.2'} @@ -47,7 +48,7 @@ from rowers.models import ( polygon_to_path,coordinate_in_path ) -from utils import geo_distance + from rowers.courseutils import coursetime_paths, coursetime_first,time_in_path diff --git a/rowers/courseutils.py b/rowers/courseutils.py index 2ce31fb3..37686b27 100644 --- a/rowers/courseutils.py +++ b/rowers/courseutils.py @@ -5,10 +5,10 @@ def coordinate_in_path(latitude,longitude, p): class InvalidTrajectoryError(Exception): def __init__(self,value): - self.value=value + self.value=value def __str__(self): - return repr(self.value) + return repr(self.value) def time_in_path(df,p,maxmin='max',getall=False): diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 066a4579..31b18475 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -1,5 +1,6 @@ # All the data preparation, data cleaning and data mangling should # be defined here +from __future__ import unicode_literals, absolute_import from rowers.models import Workout, StrokeData,Team import pytz @@ -55,7 +56,7 @@ import pandas as pd import numpy as np import itertools import math -from tasks import ( +from rowers.tasks import ( handle_sendemail_unrecognized, handle_sendemail_breakthrough, handle_sendemail_hard, handle_updatecp,handle_updateergcp, handle_calctrimp, @@ -65,9 +66,9 @@ from django.conf import settings from sqlalchemy import create_engine import sqlalchemy as sa import sys -import utils -import datautils -from utils import lbstoN,myqueue,is_ranking_piece,wavg +import rowers.utils as utils +import rowers.datautils as datautils +from rowers.utils import lbstoN,myqueue,is_ranking_piece,wavg from timezonefinder import TimezoneFinder @@ -638,7 +639,7 @@ def deletecpdata_sql(rower_id,table='cpdata'): try: result = conn.execute(query) except: - print "Database locked" + print("Database locked") conn.close() engine.dispose() @@ -855,7 +856,7 @@ def create_row_df(r,distance,duration,startdatetime,workouttype='rower', return (id, message) -from utils import totaltime_sec_to_string +from rowers.utils import totaltime_sec_to_string # Processes painsled CSV file to database def save_workout_database(f2, r, dosmooth=True, workouttype='rower', @@ -1564,7 +1565,7 @@ def compare_data(id): res = conn.execute(query) l2 = res.fetchall()[0][0] except: - print "Database Locked" + print("Database Locked") conn.close() engine.dispose() lfile = l1 @@ -1583,13 +1584,13 @@ def repair_data(verbose=False): test, ldb, lfile = compare_data(w.id) if not test: if verbose: - print w.id, lfile, ldb + print(w.id, lfile, ldb) try: rowdata = rdata(w.csvfilename) if rowdata and len(rowdata.df): update_strokedata(w.id, rowdata.df) - except IOError, AttributeError: + except (IOError, AttributeError): pass if lfile == 0: @@ -1618,10 +1619,10 @@ def repair_data(verbose=False): def rdata(file, rower=rrower()): try: res = rrdata(csvfile=file, rower=rower) - except IOError, IndexError: + except (IOError, IndexError): try: res = rrdata(csvfile=file + '.gz', rower=rower) - except IOError, IndexError: + except (IOError, IndexError): res = rrdata() except: res = rrdata() @@ -1640,7 +1641,7 @@ def delete_strokedata(id): try: result = conn.execute(query) except: - print "Database Locked" + print("Database Locked") conn.close() engine.dispose() @@ -1792,7 +1793,7 @@ def prepmultipledata(ids, verbose=False): for id in res: rowdata, row = getrowdata(id=id) if verbose: - print id + print(id) if rowdata and len(rowdata.df): data = dataprep(rowdata.df, id=id, bands=True, barchart=True, otwpower=True) @@ -2029,7 +2030,7 @@ def fix_newtons(id=0, limit=3000): peakforce = rowdata['peakforce'] if peakforce.mean() > limit: w = Workout.objects.get(id=id) - print "fixing ", id + print("fixing ", id) rowdata = rdata(w.csvfilename) if rowdata and len(rowdata.df): update_strokedata(w.id, rowdata.df) diff --git a/rowers/dataprepnodjango.py b/rowers/dataprepnodjango.py index a6e23bf0..6e742590 100644 --- a/rowers/dataprepnodjango.py +++ b/rowers/dataprepnodjango.py @@ -18,7 +18,7 @@ import sqlalchemy as sa from rowsandall_app.settings import DATABASES from rowsandall_app.settings_dev import DATABASES as DEV_DATABASES -from utils import lbstoN +from rowers.utils import lbstoN try: @@ -83,33 +83,33 @@ import datetime def niceformat(values): out = [] for v in values: - formattedv = strfdelta(v) - out.append(formattedv) - + formattedv = strfdelta(v) + out.append(formattedv) + return out def strfdelta(tdelta): try: - minutes,seconds = divmod(tdelta.seconds,60) - tenths = int(tdelta.microseconds/1e5) + minutes,seconds = divmod(tdelta.seconds,60) + tenths = int(tdelta.microseconds/1e5) except AttributeError: - minutes,seconds = divmod(tdelta.view(np.int64),60e9) - seconds,rest = divmod(seconds,1e9) - tenths = int(rest/1e8) + minutes,seconds = divmod(tdelta.view(np.int64),60e9) + seconds,rest = divmod(seconds,1e9) + tenths = int(rest/1e8) res = "{minutes:0>2}:{seconds:0>2}.{tenths:0>1}".format( - minutes=minutes, - seconds=seconds, - tenths=tenths, - ) + minutes=minutes, + seconds=seconds, + tenths=tenths, + ) return res def nicepaceformat(values): out = [] for v in values: - formattedv = strfdelta(v) - out.append(formattedv) - + formattedv = strfdelta(v) + out.append(formattedv) + return out @@ -124,16 +124,16 @@ def timedeltaconv(x): def rdata(file,rower=rrower()): try: - res = rrdata(file,rower=rower) + res = rrdata(file,rower=rower) except IOError: try: res = rrdata(file+'.gz',rower=rower) except IOError: - res = 0 + res = 0 return res -from utils import totaltime_sec_to_string +from rowers.utils import totaltime_sec_to_string # Creates C2 stroke data @@ -175,22 +175,22 @@ def create_c2_stroke_data_db( df = pd.DataFrame({ 'TimeStamp (sec)': unixtime, - ' Horizontal (meters)': d, + ' Horizontal (meters)': d, ' Cadence (stokes/min)': spm, ' Stroke500mPace (sec/500m)':pace, ' ElapsedTime (sec)':elapsed, ' Power (watts)':power, - ' HRCur (bpm)':np.zeros(nr_strokes), - ' longitude':np.zeros(nr_strokes), - ' latitude':np.zeros(nr_strokes), - ' DragFactor':np.zeros(nr_strokes), - ' DriveLength (meters)':np.zeros(nr_strokes), - ' StrokeDistance (meters)':np.zeros(nr_strokes), - ' DriveTime (ms)':np.zeros(nr_strokes), - ' StrokeRecoveryTime (ms)':np.zeros(nr_strokes), - ' AverageDriveForce (lbs)':np.zeros(nr_strokes), - ' PeakDriveForce (lbs)':np.zeros(nr_strokes), - ' lapIdx':np.zeros(nr_strokes), + ' HRCur (bpm)':np.zeros(nr_strokes), + ' longitude':np.zeros(nr_strokes), + ' latitude':np.zeros(nr_strokes), + ' DragFactor':np.zeros(nr_strokes), + ' DriveLength (meters)':np.zeros(nr_strokes), + ' StrokeDistance (meters)':np.zeros(nr_strokes), + ' DriveTime (ms)':np.zeros(nr_strokes), + ' StrokeRecoveryTime (ms)':np.zeros(nr_strokes), + ' AverageDriveForce (lbs)':np.zeros(nr_strokes), + ' PeakDriveForce (lbs)':np.zeros(nr_strokes), + ' lapIdx':np.zeros(nr_strokes), 'cum_dist': d }) @@ -220,17 +220,17 @@ def add_c2_stroke_data_db(strokedata,workoutid,starttimeunix,csvfilename, nr_rows = len(unixtime) try: - latcoord = strokedata.ix[:,'lat'] - loncoord = strokedata.ix[:,'lon'] + latcoord = strokedata.ix[:,'lat'] + loncoord = strokedata.ix[:,'lon'] except: - latcoord = np.zeros(nr_rows) - loncoord = np.zeros(nr_rows) + latcoord = np.zeros(nr_rows) + loncoord = np.zeros(nr_rows) try: - strokelength = strokedata.ix[:,'strokelength'] + strokelength = strokedata.ix[:,'strokelength'] except: - strokelength = np.zeros(nr_rows) + strokelength = np.zeros(nr_rows) dist2 = 0.1*strokedata.ix[:,'d'] @@ -258,28 +258,28 @@ def add_c2_stroke_data_db(strokedata,workoutid,starttimeunix,csvfilename, # save csv # Create data frame with all necessary data to write to csv df = pd.DataFrame({'TimeStamp (sec)':unixtime, - ' Horizontal (meters)': dist2, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' longitude':loncoord, - ' latitude':latcoord, - ' Stroke500mPace (sec/500m)':pace, - ' Power (watts)':power, - ' DragFactor':np.zeros(nr_rows), - ' DriveLength (meters)':np.zeros(nr_rows), - ' StrokeDistance (meters)':strokelength, - ' DriveTime (ms)':np.zeros(nr_rows), - ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), - ' AverageDriveForce (lbs)':np.zeros(nr_rows), - ' PeakDriveForce (lbs)':np.zeros(nr_rows), - ' lapIdx':lapidx, - ' ElapsedTime (sec)':seconds, + ' Horizontal (meters)': dist2, + ' Cadence (stokes/min)':spm, + ' HRCur (bpm)':hr, + ' longitude':loncoord, + ' latitude':latcoord, + ' Stroke500mPace (sec/500m)':pace, + ' Power (watts)':power, + ' DragFactor':np.zeros(nr_rows), + ' DriveLength (meters)':np.zeros(nr_rows), + ' StrokeDistance (meters)':strokelength, + ' DriveTime (ms)':np.zeros(nr_rows), + ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), + ' AverageDriveForce (lbs)':np.zeros(nr_rows), + ' PeakDriveForce (lbs)':np.zeros(nr_rows), + ' lapIdx':lapidx, + ' ElapsedTime (sec)':seconds, 'cum_dist': dist2 - }) + }) df.sort_values(by='TimeStamp (sec)',ascending=True) - + timestr = strftime("%Y%m%d-%H%M%S") @@ -312,8 +312,8 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower', # make workout and put in database rr = rrower(hrmax=r.max,hrut2=r.ut2, - hrut1=r.ut1,hrat=r.at, - hrtr=r.tr,hran=r.an,ftp=r.ftp, + hrut1=r.ut1,hrat=r.at, + hrtr=r.tr,hran=r.an,ftp=r.ftp, powerperc=powerperc,powerzones=r.powerzones) row = rdata(f2,rower=rr) @@ -329,7 +329,7 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower', if row == 0: - return (0,'Error: CSV data file not found') + return (0,'Error: CSV data file not found') if dosmooth: # auto smoothing @@ -342,12 +342,12 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower', else: windowsize = 1 if not 'originalvelo' in row.df: - row.df['originalvelo'] = velo + row.df['originalvelo'] = velo if windowsize > 3 and windowsize 3 and windowsize=4: try: - p1, success = optimize.leastsq(errfunc, p0[:], args = (thesecs,theavpower)) + p1, success = optimize.leastsq(errfunc, p0[:], args = (thesecs,theavpower)) except: - factor = fitfunc(p0,thesecs.mean())/theavpower.mean() - p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]] + factor = fitfunc(p0,thesecs.mean())/theavpower.mean() + p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]] else: - factor = fitfunc(p0,thesecs.mean())/theavpower.mean() - p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]] + factor = fitfunc(p0,thesecs.mean())/theavpower.mean() + p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]] p1 = [abs(p) for p in p1] diff --git a/rowers/forms.py b/rowers/forms.py index acabc5b4..5dd3d149 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import from django import forms from django.contrib.admin.widgets import FilteredSelectMultiple from rowers.models import ( @@ -9,15 +10,16 @@ from rowers.rows import validate_file_extension,must_be_csv,validate_image_exten from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from django.contrib.admin.widgets import AdminDateWidget -from django.forms.extras.widgets import SelectDateWidget +from django.forms.widgets import SelectDateWidget +#from django.forms.extras.widgets import SelectDateWidget from django.utils import timezone,translation from django.forms import ModelForm, Select -import dataprep -import mytypes +import rowers.dataprep as dataprep +import rowers.mytypes as mytypes import datetime from django.forms import formset_factory -from utils import landingpages -from metrics import axes +from rowers.utils import landingpages +from rowers.metrics import axes class FlexibleDecimalField(forms.DecimalField): @@ -84,7 +86,7 @@ for key, value in disqualificationreasons: class DisqualificationForm(forms.Form): reason = forms.ChoiceField(required=True, - choices=disqualificationreasons, + choices=disqualificationreasons, widget = forms.RadioSelect,) message = forms.CharField(required=True,widget=forms.Textarea) @@ -139,10 +141,10 @@ class CourseForm(forms.Form): class DocumentsForm(forms.Form): title = forms.CharField(required=False) file = forms.FileField(required=False, - validators=[validate_file_extension]) + validators=[validate_file_extension]) workouttype = forms.ChoiceField(required=True, - choices=Workout.workouttypes) + choices=Workout.workouttypes) boattype = forms.ChoiceField(required=True, choices=mytypes.boattypes, @@ -150,19 +152,19 @@ class DocumentsForm(forms.Form): notes = forms.CharField(required=False, - widget=forms.Textarea) + widget=forms.Textarea) offline = forms.BooleanField(initial=False,required=False, label='Process in Background') class Meta: - fields = ['title','file','workouttype','boattype','fileformat','offline'] + fields = ['title','file','workouttype','boattype','fileformat','offline'] def __init__(self, *args, **kwargs): from django.forms.widgets import HiddenInput super(DocumentsForm, self).__init__(*args, **kwargs) # self.fields['offline'].widget = HiddenInput() -from utils import ( +from rowers.utils import ( workflowleftpanel,workflowmiddlepanel, defaultleft,defaultmiddle ) @@ -267,14 +269,14 @@ class LandingPageForm(forms.Form): class UploadOptionsForm(forms.Form): plotchoices = ( - ('timeplot','Time Plot'), - ('distanceplot','Distance Plot'), - ('pieplot','Heart Rate Pie Chart'), - ) + ('timeplot','Time Plot'), + ('distanceplot','Distance Plot'), + ('pieplot','Heart Rate Pie Chart'), + ) make_plot = forms.BooleanField(initial=False,required=False) plottype = forms.ChoiceField(required=False, - choices=plotchoices, - initial='timeplot', + choices=plotchoices, + initial='timeplot', label='Plot Type') upload_to_C2 = forms.BooleanField(initial=False,required=False, label='Export to Concept2 logbook') @@ -303,7 +305,7 @@ class UploadOptionsForm(forms.Form): label='After Upload, go to') class Meta: - fields = ['make_plot','plottype','upload_toc2','makeprivate'] + fields = ['make_plot','plottype','upload_toc2','makeprivate'] def __init__(self, *args, **kwargs): self.request = kwargs.pop('request',None) @@ -332,18 +334,18 @@ class UploadOptionsForm(forms.Form): # a team member class TeamUploadOptionsForm(forms.Form): plotchoices = ( - ('timeplot','Time Plot'), - ('distanceplot','Distance Plot'), - ('pieplot','Pie Chart'), - ) + ('timeplot','Time Plot'), + ('distanceplot','Distance Plot'), + ('pieplot','Pie Chart'), + ) make_plot = forms.BooleanField(initial=False,required=False) plottype = forms.ChoiceField(required=False, - choices=plotchoices, - initial='timeplot', + choices=plotchoices, + initial='timeplot', label='Plot Type') class Meta: - fields = ['make_plot','plottype'] + fields = ['make_plot','plottype'] # This form is used on the Workout Split page class WorkoutSplitForm(forms.Form): @@ -392,9 +394,9 @@ class OteWorkoutTypeForm(forms.Form): class PredictedPieceForm(forms.Form): unitchoices = ( - ('t','minutes'), - ('d','meters'), - ) + ('t','minutes'), + ('d','meters'), + ) rankingdistancechoices = [] rankingdurationchoices = [] @@ -422,10 +424,10 @@ class PredictedPieceForm(forms.Form): value = forms.FloatField(initial=10,label='Free ranking piece (minutes)') pieceunit = forms.ChoiceField(required=True,choices=unitchoices, - initial='t',label='Unit') + initial='t',label='Unit') class Meta: - fields = ['value','pieceunit'] + fields = ['value','pieceunit'] class PredictedPieceFormNoDistance(forms.Form): @@ -450,76 +452,76 @@ class PredictedPieceFormNoDistance(forms.Form): # On the Geeky side, to update stream information for river dwellers class UpdateStreamForm(forms.Form): unitchoices = ( - ('m','m/s'), - ('f','foot/s'), - ('k','knots'), - ('p','pace difference (sec/500m)'), - ) + ('m','m/s'), + ('f','foot/s'), + ('k','knots'), + ('p','pace difference (sec/500m)'), + ) dist1 = forms.FloatField(initial=0,label = 'Distance 1') dist2 = forms.FloatField(initial=1000,label = 'Distance 2') stream1 = forms.FloatField(initial=0,label = 'Stream velocity 1') stream2 = forms.FloatField(initial=0,label = 'Stream velocity 2') streamunit = forms.ChoiceField(required=True, - choices=unitchoices, - initial='m', - label='Unit') + choices=unitchoices, + initial='m', + label='Unit') class Meta: - fields = ['dist1','dist2','stream1', 'stream2','streamunit'] + fields = ['dist1','dist2','stream1', 'stream2','streamunit'] # add wind information to your workout class UpdateWindForm(forms.Form): unitchoices = ( - ('m','m/s'), - ('k','knots'), - ('b','beaufort'), - ('kmh','km/h'), - ('mph','miles/hour'), - ) + ('m','m/s'), + ('k','knots'), + ('b','beaufort'), + ('kmh','km/h'), + ('mph','miles/hour'), + ) dist1 = forms.FloatField(initial=0,label = 'Distance 1') dist2 = forms.FloatField(initial=1000,label = 'Distance 2') vwind1 = forms.FloatField(initial=0,required=False,label = 'Wind Speed 1') vwind2 = forms.FloatField(initial=0,required=False,label = 'Wind Speed 2') windunit = forms.ChoiceField(required=True, - choices=unitchoices, - initial='m', - label='Unit') + choices=unitchoices, + initial='m', + label='Unit') winddirection1 = forms.IntegerField(initial=0,required=False, - label = 'Wind Direction 1') + label = 'Wind Direction 1') winddirection2 = forms.IntegerField(initial=0,required=False, - label = 'Wind Direction 2') + label = 'Wind Direction 2') class Meta: - fields = ['dist1','dist2', - 'vwind1','vwind2', - 'windunit', - 'winddirection1','winddirection2'] + fields = ['dist1','dist2', + 'vwind1','vwind2', + 'windunit', + 'winddirection1','winddirection2'] # Form to select a data range to show workouts from a certain time period class DateRangeForm(forms.Form): startdate = forms.DateField( initial=timezone.now()-datetime.timedelta(days=365), - # widget=SelectDateWidget(years=range(1990,2050)), + # widget=SelectDateWidget(years=range(1990,2050)), widget=AdminDateWidget(), - label='Start Date') + label='Start Date') enddate = forms.DateField( initial=timezone.now(), widget=AdminDateWidget(), - label='End Date') + label='End Date') class Meta: - fields = ['startdate','enddate'] + fields = ['startdate','enddate'] class FitnessMetricForm(forms.Form): startdate = forms.DateField( initial=timezone.now()-datetime.timedelta(days=365), - # widget=SelectDateWidget(years=range(1990,2050)), + # widget=SelectDateWidget(years=range(1990,2050)), widget=AdminDateWidget(), - label='Start Date') + label='Start Date') enddate = forms.DateField( initial=timezone.now(), widget=AdminDateWidget(), - label='End Date') + label='End Date') modechoices = ( ('rower','indoor rower'), @@ -533,7 +535,7 @@ class FitnessMetricForm(forms.Form): ) class Meta: - fields = ['startdate','enddate','mode'] + fields = ['startdate','enddate','mode'] class SessionDateShiftForm(forms.Form): shiftstartdate = forms.DateField( @@ -599,7 +601,7 @@ class RegistrationFormSex(RegistrationFormUniqueEmail): weightcategories = ( ('hwt','heavy-weight'), - ('lwt','light-weight'), + ('lwt','light-weight'), ) adaptivecategories = mytypes.adaptivetypes @@ -637,8 +639,8 @@ class RegistrationFormSex(RegistrationFormUniqueEmail): class MyTimeField(forms.TimeField): def __init__(self, *args, **kwargs): - super(MyTimeField, self).__init__(*args, **kwargs) - supports_microseconds = True + super(MyTimeField, self).__init__(*args, **kwargs) + supports_microseconds = True # Form used to automatically define intervals by pace or power class PowerIntervalUpdateForm(forms.Form): @@ -660,28 +662,28 @@ class PowerIntervalUpdateForm(forms.Form): class IntervalUpdateForm(forms.Form): def __init__(self, *args, **kwargs): - typechoices = ( - (1,'single time'), - (2,'single distance'), - (3,'rest (time based)'), - (3,'rest (distance based)'), - (4,'work (time based)'), - (5,'work (distance based)'), - ) - aantal = int(kwargs.pop('aantal')) - super(IntervalUpdateForm, self).__init__(*args, **kwargs) + typechoices = ( + (1,'single time'), + (2,'single distance'), + (3,'rest (time based)'), + (3,'rest (distance based)'), + (4,'work (time based)'), + (5,'work (distance based)'), + ) + aantal = int(kwargs.pop('aantal')) + super(IntervalUpdateForm, self).__init__(*args, **kwargs) - for i in range(aantal): - self.fields['intervalt_%s' % i] = forms.DurationField(label='Time '+str(i+1)) - self.fields['intervald_%s' % i] = forms.IntegerField(label='Distance '+str(i+1)) - self.fields['type_%s' % i] = forms.ChoiceField(choices=typechoices, - required=True, - initial=4, - label = 'Type '+str(i+1)) - self.fields['intervalt_%s' % i].widget.attrs['style'] = 'width:76px; height: 16px;' - self.fields['intervald_%s' % i].widget.attrs['style'] = 'width:76px; height: 16px;' - self.fields['type_%s' % i].widget.attrs['style'] = 'width:156px; height: 22px;' - self.fields['intervald_%s' % i].widget = forms.TimeInput(format='%H:%M:%S.%f') + for i in range(aantal): + self.fields['intervalt_%s' % i] = forms.DurationField(label='Time '+str(i+1)) + self.fields['intervald_%s' % i] = forms.IntegerField(label='Distance '+str(i+1)) + self.fields['type_%s' % i] = forms.ChoiceField(choices=typechoices, + required=True, + initial=4, + label = 'Type '+str(i+1)) + self.fields['intervalt_%s' % i].widget.attrs['style'] = 'width:76px; height: 16px;' + self.fields['intervald_%s' % i].widget.attrs['style'] = 'width:76px; height: 16px;' + self.fields['type_%s' % i].widget.attrs['style'] = 'width:156px; height: 22px;' + self.fields['intervald_%s' % i].widget = forms.TimeInput(format='%H:%M:%S.%f') boattypes = mytypes.boattypes workouttypes = mytypes.workouttypes @@ -824,7 +826,7 @@ formaxlabelsmultiflex.pop('distance') formaxlabelsmultiflex['workoutid'] = 'Workout' parchoicesmultiflex = list(sorted(formaxlabelsmultiflex.items(), key = lambda x:x[1])) -from utils import palettes +from rowers.utils import palettes palettechoices = tuple((p,p) for p in palettes.keys()) @@ -950,7 +952,7 @@ class RaceResultFilterForm(forms.Form): weightcategories = ( ('hwt','heavy-weight'), - ('lwt','light-weight'), + ('lwt','light-weight'), ) adaptivecategories = mytypes.adaptivetypes diff --git a/rowers/imports.py b/rowers/imports.py index d49625f3..c39064e6 100644 --- a/rowers/imports.py +++ b/rowers/imports.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # All the functionality to connect to SportTracks # Python @@ -16,7 +17,7 @@ from dateutil import parser import time from time import strftime -import dataprep +import rowers.dataprep as dataprep import math from math import sin,cos,atan2,sqrt import os,sys @@ -38,7 +39,7 @@ from django.contrib.auth.decorators import login_required from rowingdata import rowingdata, make_cumvalues import pandas as pd from rowers.models import Rower,Workout,checkworkoutuser -from rowers import mytypes +import rowers.mytypes as mytypes from rowsandall_app.settings import ( C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, @@ -46,7 +47,7 @@ from rowsandall_app.settings import ( SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI ) -from utils import ( +from rowers.utils import ( NoTokenError, custom_exception_handler, ewmovingaverage, geo_distance,isprorower,uniqify ) @@ -59,9 +60,9 @@ def splitstdata(lijst): t = [] latlong = [] while len(lijst)>=2: - t.append(lijst[0]) - latlong.append(lijst[1]) - lijst = lijst[2:] + t.append(lijst[0]) + latlong.append(lijst[1]) + lijst = lijst[2:] return [np.array(t),np.array(latlong)] @@ -103,7 +104,6 @@ def imports_open(user,oauth_data): oauth_data, ) elif tokenexpirydate is None and expirydatename is not None and 'strava' in expirydatename: - print 'noot' token = imports_token_refresh( user, tokenname, @@ -124,13 +124,13 @@ def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''): ) post_data = {"grant_type": "refresh_token", - "client_secret": oauth_data['client_secret'], - "client_id": oauth_data['client_id'], - "refresh_token": refreshtoken, - } + "client_secret": oauth_data['client_secret'], + "client_id": oauth_data['client_id'], + "refresh_token": refreshtoken, + } headers = {'user-agent': 'sanderroosendaal', - 'Accept': 'application/json', - 'Content-Type': oauth_data['content_type']} + 'Accept': 'application/json', + 'Content-Type': oauth_data['content_type']} # for Strava if 'grant_type' in oauth_data: @@ -147,11 +147,11 @@ def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''): if 'json' in oauth_data['content_type']: response = requests.post(baseurl, data=json.dumps(post_data), - headers=headers) + headers=headers) else: response = requests.post(baseurl, data=post_data, - headers=headers) + headers=headers) @@ -174,9 +174,9 @@ def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''): except KeyError: expires_in = 0 try: - refresh_token = token_json['refresh_token'] + refresh_token = token_json['refresh_token'] except KeyError: - refresh_token = refreshtoken + refresh_token = refreshtoken try: expires_in = int(expires_in) except (TypeError,ValueError): @@ -204,16 +204,16 @@ def imports_get_token( post_data = {"grant_type": "authorization_code", "code": code, "redirect_uri": redirect_uri, - "client_secret": client_secret, - "client_id": client_id, - } + "client_secret": client_secret, + "client_id": client_id, + } try: headers = oauth_data['headers'] except KeyError: headers = {'Accept': 'application/json', 'Api-Key': client_id, - 'Content-Type': 'application/json', + 'Content-Type': 'application/json', 'user-agent': 'sanderroosendaal'} if 'grant_type' in oauth_data: @@ -229,12 +229,12 @@ def imports_get_token( response = requests.post( base_uri, data=json.dumps(post_data), - headers=headers) + headers=headers) else: response = requests.post( base_uri, data=post_data, - headers=headers) + headers=headers) if response.status_code == 200 or response.status_code == 201: token_json = response.json() @@ -243,9 +243,9 @@ def imports_get_token( except KeyError: return [0,0,0] try: - refresh_token = token_json['refresh_token'] + refresh_token = token_json['refresh_token'] except KeyError: - refresh_token = '' + refresh_token = '' try: expires_in = token_json['expires_in'] except KeyError: @@ -270,8 +270,8 @@ def imports_make_authorization_url(oauth_data): params = {"client_id": oauth_data['client_id'], "response_type": "code", "redirect_uri": oauth_data['redirect_uri'], - "scope":oauth_data['scope'], - "state":state} + "scope":oauth_data['scope'], + "state":state} import urllib diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index b17fdc7d..3e95147a 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -27,7 +27,7 @@ from bokeh.io import output_file, show, vplot from bokeh.models import ( GMapPlot, GMapOptions, ColumnDataSource, Circle, DataRange1d, PanTool, WheelZoomTool, BoxSelectTool, - SaveTool, ResizeTool, ResetTool, TapTool,CrosshairTool,BoxZoomTool, + SaveTool, ResizeTool, ResetTool, TapTool,CrosshairTool,BoxZoomTool, Span, Label ) from bokeh.models.glyphs import ImageURL @@ -38,7 +38,7 @@ from bokeh.core.properties import value from collections import OrderedDict from django.conf import settings -from courses import ( +from rowers.courses import ( course_coord_center,course_coord_maxmin, polygon_coord_center ) @@ -62,7 +62,7 @@ from scipy.signal import savgol_filter from scipy.interpolate import griddata -import stravastuff +import rowers.stravastuff as stravastuff from rowers.dataprep import rdata import rowers.dataprep as dataprep @@ -70,9 +70,9 @@ import rowers.metrics as metrics from rowers.metrics import axes,axlabels,yaxminima,yaxmaxima -from utils import lbstoN -from datautils import p0 -import datautils +from rowers.utils import lbstoN +from rowers.datautils import p0 +import rowers.datautils as datautils watermarkurl = "/static/img/logo7.png" watermarksource = ColumnDataSource(dict( @@ -180,7 +180,7 @@ def interactive_boxchart(datadf,fieldname,extratitle=''): title=axlabels[fieldname]+' '+extratitle, outliers=False, tools=TOOLS, - toolbar_location="above", + toolbar_location="above", toolbar_sticky=False, x_mapper_type='datetime',plot_width=920) @@ -215,10 +215,10 @@ def interactive_boxchart(datadf,fieldname,extratitle=''): ) if fieldname == 'pace': - plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + plot.yaxis[0].formatter = DatetimeTickFormatter( + seconds = ["%S"], + minutes = ["%M"] + ) plot.xaxis.major_label_orientation = pi/4 @@ -226,9 +226,9 @@ def interactive_boxchart(datadf,fieldname,extratitle=''): hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ - ('Value','@y'), + ('Value','@y'), ('Date','@x'), - ]) + ]) hover.mode = 'mouse' @@ -320,8 +320,8 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type'): d2 = enddate.strftime("%Y-%m-%d"), ), stack=stack, - plot_width=350, - plot_height=250, + plot_width=350, + plot_height=250, toolbar_location = None, ) @@ -369,13 +369,13 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False): workoutstatetransition = [0,2,10,11,12,13] if workstrokesonly: - try: - rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)] - except KeyError: - pass + try: + rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)] + except KeyError: + pass if rowdata.empty: - return "","No Valid Data Available","","" + return "","No Valid Data Available","","" try: catchav = rowdata['catch'].mean() @@ -435,7 +435,7 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False): ) plot = Figure(tools=TOOLS, - toolbar_sticky=False) + toolbar_sticky=False) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -577,20 +577,20 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False): for (i=0; i=minspm && spm1[i]<=maxspm) { - if (distance1[i]>=mindist && distance1[i]<=maxdist) { + if (spm1[i]>=minspm && spm1[i]<=maxspm) { + if (distance1[i]>=mindist && distance1[i]<=maxdist) { if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) { - catchav += c[i] - finishav += finish[i] - slipav += slip[i] - washav += wash[i] - peakforceangleav += peakforceangle[i] - averageforceav += averageforce[i] + catchav += c[i] + finishav += finish[i] + slipav += slip[i] + washav += wash[i] + peakforceangleav += peakforceangle[i] + averageforceav += averageforce[i] peakforceav += peakforce[i] count += 1 } - } - } + } + } } catchav /= count @@ -617,43 +617,43 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False): """) slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1, - title="Min SPM",callback=callback) + title="Min SPM",callback=callback) callback.args["minspm"] = slider_spm_min slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1, - title="Max SPM",callback=callback) + title="Max SPM",callback=callback) callback.args["maxspm"] = slider_spm_max slider_work_min = Slider(start=0, end=1500,value=0, step=10, - title="Min Work per Stroke",callback=callback) + title="Min Work per Stroke",callback=callback) callback.args["minwork"] = slider_work_min slider_work_max = Slider(start=0, end=1500,value=1500, step=10, - title="Max Work per Stroke",callback=callback) + title="Max Work per Stroke",callback=callback) callback.args["maxwork"] = slider_work_max distmax = 100+100*int(rowdata['distance'].max()/100.) slider_dist_min = Slider(start=0,end=distmax,value=0,step=1, - title="Min Distance",callback=callback) + title="Min Distance",callback=callback) callback.args["mindist"] = slider_dist_min slider_dist_max = Slider(start=0,end=distmax,value=distmax, - step=1, - title="Max Distance",callback=callback) + step=1, + title="Max Distance",callback=callback) callback.args["maxdist"] = slider_dist_max layout = layoutrow([layoutcolumn([slider_spm_min, - slider_spm_max, - slider_dist_min, - slider_dist_max, + slider_spm_max, + slider_dist_min, + slider_dist_max, slider_work_min, slider_work_max, - ], - ), - plot]) + ], + ), + plot]) layout.sizing_mode = 'scale_width' @@ -814,7 +814,7 @@ def interactive_histoall(theworkouts): rowdata.dropna(axis=0,how='any',inplace=True) if rowdata.empty: - return "","No Valid Data Available","","" + return "","No Valid Data Available","","" try: histopwr = rowdata['power'].values @@ -829,9 +829,9 @@ def interactive_histoall(theworkouts): histopwr = histopwr[histopwr < 1000] plot = Figure(tools=TOOLS,plot_width=900, - toolbar_sticky=False, - toolbar_location="above" - ) + toolbar_sticky=False, + toolbar_location="above" + ) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -856,13 +856,13 @@ def interactive_histoall(theworkouts): hist_norm = 100.*hist/float(hist.sum()) source = ColumnDataSource( - data = dict( - left = edges[:-1], - right = edges[1:], - histsum = histsum, - hist_norm = hist_norm, - ) - ) + data = dict( + left = edges[:-1], + right = edges[1:], + histsum = histsum, + hist_norm = hist_norm, + ) + ) # plot.quad(top='hist_norm',bottom=0,left=edges[:-1],right=edges[1:]) @@ -876,18 +876,18 @@ def interactive_histoall(theworkouts): hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ - ('Power(W)','@left{int}'), - ('% of strokes','@hist_norm'), - ('Cumulative %','@histsum{int}'), - ]) + ('Power(W)','@left{int}'), + ('% of strokes','@hist_norm'), + ('Cumulative %','@histsum{int}'), + ]) hover.mode = 'mouse' plot.extra_y_ranges["fraction"] = Range1d(start=0,end=105) plot.line('right','histsum',source=source,color="red", - y_range_name="fraction") + y_range_name="fraction") plot.add_layout(LinearAxis(y_range_name="fraction", - axis_label="Cumulative % of strokes"),'right') + axis_label="Cumulative % of strokes"),'right') plot.sizing_mode = 'scale_width' script, div = components(plot) @@ -958,18 +958,18 @@ def course_map(course): var streets = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.streets' + maxZoom: 18, + id: 'mapbox.streets' }}), satellite = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.satellite' + maxZoom: 18, + id: 'mapbox.satellite' }}), outdoors = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.outdoors' + maxZoom: 18, + id: 'mapbox.outdoors' }}); @@ -1076,18 +1076,18 @@ def leaflet_chart(lat,lon,name=""): var streets = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.streets' + maxZoom: 18, + id: 'mapbox.streets' }}), satellite = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.satellite' + maxZoom: 18, + id: 'mapbox.satellite' }}), outdoors = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.outdoors' + maxZoom: 18, + id: 'mapbox.outdoors' }}); @@ -1197,18 +1197,18 @@ def leaflet_chart2(lat,lon,name=""): var streets = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.streets' + maxZoom: 18, + id: 'mapbox.streets' }}), satellite = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.satellite' + maxZoom: 18, + id: 'mapbox.satellite' }}), outdoors = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ - maxZoom: 18, - id: 'mapbox.outdoors' + maxZoom: 18, + id: 'mapbox.outdoors' }}); @@ -1272,7 +1272,7 @@ def leaflet_chart2(lat,lon,name=""): return script,div - + def interactive_agegroupcpchart(age,normalized=False): durations = [1,4,30,60] distances = [100,500,1000,2000,5000,6000,10000,21097,42195] @@ -1531,9 +1531,9 @@ def interactive_otwcpchart(powerdf,promember=0,rowername=""): powerdf = powerdf[~(powerdf == 0).any(axis=1)] # plot tools if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' x_axis_type = 'log' @@ -1556,7 +1556,7 @@ def interactive_otwcpchart(powerdf,promember=0,rowername=""): message = "" #if len(fitpower[fitpower<0]) > 0: - # message = "CP model fit didn't give correct results" + # message = "CP model fit didn't give correct results" deltas = fitt.apply(lambda x: timedeltaconv(x)) @@ -1573,9 +1573,9 @@ def interactive_otwcpchart(powerdf,promember=0,rowername=""): # making the plot plot = Figure(tools=TOOLS,x_axis_type=x_axis_type, - plot_width=900, - toolbar_location="above", - toolbar_sticky=False) + plot_width=900, + toolbar_location="above", + toolbar_sticky=False) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -1592,7 +1592,7 @@ def interactive_otwcpchart(powerdf,promember=0,rowername=""): ) plot.circle('Delta','CP',source=source,fill_color='red',size=15, - legend='Power Data') + legend='Power Data') plot.xaxis.axis_label = "Duration (seconds)" plot.yaxis.axis_label = "Power (W)" @@ -1604,18 +1604,18 @@ def interactive_otwcpchart(powerdf,promember=0,rowername=""): hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ - ('Duration ','@ftime'), - ('Power (W)','@CP{int}'), - ('Power (W) upper','@CPmax{int}'), - ]) + ('Duration ','@ftime'), + ('Power (W)','@CP{int}'), + ('Power (W) upper','@CPmax{int}'), + ]) hover.mode = 'mouse' plot.line('duration','CP',source=sourcecomplex,legend="CP Model", - color='green') + color='green') plot.line('duration','CPmax',source=sourcecomplex,legend="CP Model", - color='red') + color='red') script, div = components(plot) @@ -1693,15 +1693,15 @@ def interactive_agegroup_plot(df,distance=2000,duration=None, return script,div def interactive_cpchart(rower,thedistances,thesecs,theavpower, - theworkouts,promember=0, + theworkouts,promember=0, wcpower=[],wcdurations=[]): message = 0 # plot tools if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' x_axis_type = 'log' @@ -1715,25 +1715,25 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) source = ColumnDataSource( - data = dict( - dist = thedistances, - duration = thesecs, - spm = 0*theavpower, - tim = niceformat( - thesecs.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ), - - power = theavpower, - fpace = nicepaceformat(p2), - ) - ) + data = dict( + dist = thedistances, + duration = thesecs, + spm = 0*theavpower, + tim = niceformat( + thesecs.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) + ), + + power = theavpower, + fpace = nicepaceformat(p2), + ) + ) # fitting the data to Paul if len(thedistances)>=2: - paulslope, paulintercept,r,p,stderr = linregress(np.log10(thedistances),p) + paulslope, paulintercept,r,p,stderr = linregress(np.log10(thedistances),p) else: - paulslope = 5.0/np.log10(2.0) - paulintercept = p[0]-paulslope*np.log10(thedistances[0]) + paulslope = 5.0/np.log10(2.0) + paulintercept = p[0]-paulslope*np.log10(thedistances[0]) fitx = pd.Series(np.arange(100)*2*max(np.log10(thedistances))/100.) @@ -1747,17 +1747,17 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, sourcepaul = ColumnDataSource( - data = dict( - dist = 10**fitx, - duration = fitt, - power = fitpower, - spm = 0*fitpower, - tim = niceformat( - fitt.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ), - fpace = nicepaceformat(fitp2), - ) - ) + data = dict( + dist = 10**fitx, + duration = fitt, + power = fitpower, + spm = 0*fitpower, + tim = niceformat( + fitt.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) + ), + fpace = nicepaceformat(fitp2), + ) + ) fitfunc = lambda pars,x: pars[0]/(1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) @@ -1779,10 +1779,10 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, success = 0 p1 = p0 if len(thesecs)>=4: - p1, success = optimize.leastsq(errfunc, p0[:], args = (thesecs,theavpower)) + p1, success = optimize.leastsq(errfunc, p0[:], args = (thesecs,theavpower)) else: - factor = fitfunc(p0,thesecs.mean())/theavpower.mean() - p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]] + factor = fitfunc(p0,thesecs.mean())/theavpower.mean() + p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]] success = 0 @@ -1833,7 +1833,7 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, message = "" if len(fitpower[fitpower<0]) > 0: - message = "CP model fit didn't give correct results" + message = "CP model fit didn't give correct results" fitvelo = (fitpower/2.8)**(1./3.) fitdist = fitt*fitvelo @@ -1841,30 +1841,30 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, fitp2 = fitp.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) sourcecomplex = ColumnDataSource( - data = dict( - dist = fitdist, - duration = fitt, - tim = niceformat( - fitt.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ), - spm = 0*fitpower, - power = fitpower, + data = dict( + dist = fitdist, + duration = fitt, + tim = niceformat( + fitt.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) + ), + spm = 0*fitpower, + power = fitpower, fitpowerwc = fitpowerwc, fitpowerexcellent = fitpowerexcellent, fitpowergood = fitpowergood, fitpowerfair = fitpowerfair, fitpoweraverage = fitpoweraverage, - fpace = nicepaceformat(fitp2), - ) - ) + fpace = nicepaceformat(fitp2), + ) + ) # making the plot plot = Figure(tools=TOOLS,x_axis_type=x_axis_type, - plot_width=900, - toolbar_location="above", - toolbar_sticky=False) + plot_width=900, + toolbar_location="above", + toolbar_sticky=False) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -1881,7 +1881,7 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, ) plot.circle('duration','power',source=source,fill_color='red',size=15, - legend='Power') + legend='Power') plot.xaxis.axis_label = "Duration (seconds)" plot.yaxis.axis_label = "Power (W)" @@ -1915,29 +1915,29 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) source2 = ColumnDataSource( - data = dict( - duration = cpdata['delta'], - power = cpdata['cp'], - tim = niceformat( - cpdata['delta'].fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - ), - dist = cpdata['distance'], - pace = nicepaceformat(p2), - ) - ) + data = dict( + duration = cpdata['delta'], + power = cpdata['cp'], + tim = niceformat( + cpdata['delta'].fillna(method='ffill').apply(lambda x: timedeltaconv(x)) + ), + dist = cpdata['distance'], + pace = nicepaceformat(p2), + ) + ) plot.circle('duration','power',source=source2, - fill_color='blue',size=3, - legend = 'Power from segments') + fill_color='blue',size=3, + legend = 'Power from segments') hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ - ('Duration ','@tim'), - ('Power (W)','@power{int}'), - ('Distance (m)','@dist{int}'), - ('Pace (/500m)','@fpace'), - ]) + ('Duration ','@tim'), + ('Power (W)','@power{int}'), + ('Distance (m)','@dist{int}'), + ('Pace (/500m)','@fpace'), + ]) hover.mode = 'mouse' @@ -1948,7 +1948,7 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, plot.line('duration','power',source=sourcepaul,legend="Paul's Law") plot.line('duration','power',source=sourcecomplex,legend="CP Model", - color='green') + color='green') if p1wc is not None: plot.line('duration','fitpowerwc',source=sourcecomplex, legend="World Class", @@ -1982,7 +1982,7 @@ def interactive_windchart(id=0,promember=0): # g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") f1 = row.csvfilename - + # create interactive plot plot = Figure(plot_width=400,plot_height=300) @@ -1994,26 +1994,26 @@ def interactive_windchart(id=0,promember=0): rr = rrower(hrmax=r.max,hrut2=r.ut2, - hrut1=r.ut1,hrat=r.at, - hrtr=r.tr,hran=r.an,ftp=r.ftp) + hrut1=r.ut1,hrat=r.at, + hrtr=r.tr,hran=r.an,ftp=r.ftp) rowdata = rdata(f1,rower=rr) if rowdata == 0: - return 0 + return 0 dist = rowdata.df.loc[:,'cum_dist'] try: - vwind = rowdata.df.loc[:,'vwind'] - winddirection = rowdata.df.loc[:,'winddirection'] - bearing = rowdata.df.loc[:,'bearing'] + vwind = rowdata.df.loc[:,'vwind'] + winddirection = rowdata.df.loc[:,'winddirection'] + bearing = rowdata.df.loc[:,'bearing'] except KeyError: - rowdata.add_wind(0,0) - rowdata.add_bearing() - vwind = rowdata.df.loc[:,'vwind'] - winddirection = rowdata.df.loc[:,'winddirection'] - bearing = rowdata.df.loc[:,'winddirection'] - rowdata.write_csv(f1,gzip=True) + rowdata.add_wind(0,0) + rowdata.add_bearing() + vwind = rowdata.df.loc[:,'vwind'] + winddirection = rowdata.df.loc[:,'winddirection'] + bearing = rowdata.df.loc[:,'winddirection'] + rowdata.write_csv(f1,gzip=True) dataprep.update_strokedata(id,rowdata.df) winddirection = winddirection % 360 @@ -2023,27 +2023,27 @@ def interactive_windchart(id=0,promember=0): source = ColumnDataSource( - data = dict( - dist=dist, - vwind=vwind, - tw=tw, - winddirection=winddirection, - ) - ) + data = dict( + dist=dist, + vwind=vwind, + tw=tw, + winddirection=winddirection, + ) + ) # plot tools if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' # making the plot plot = Figure(tools=TOOLS,plot_width=400,height=500, -# toolbar_location="below", - toolbar_sticky=False, - ) +# toolbar_location="below", + toolbar_sticky=False, + ) plot.line('dist','vwind',source=source,legend="Wind Speed (m/s)") plot.line('dist','tw',source=source,legend="Tail (+)/Head (-) Wind (m/s)",color='black') plot.title.text = row.name @@ -2057,8 +2057,8 @@ def interactive_windchart(id=0,promember=0): plot.extra_y_ranges = {"winddirection": Range1d(start=0,end=360)} plot.line('dist','winddirection',source=source, - legend='Wind Direction',color="red", - y_range_name="winddirection") + legend='Wind Direction',color="red", + y_range_name="winddirection") plot.add_layout(LinearAxis(y_range_name="winddirection",axis_label="Wind Direction (degree)"),'right') @@ -2072,10 +2072,10 @@ def interactive_streamchart(id=0,promember=0): # g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") f1 = row.csvfilename - + # create interactive plot plot = Figure(plot_width=400, - ) + ) # get user # u = User.objects.get(id=row.user.id) r = row.user @@ -2084,36 +2084,36 @@ def interactive_streamchart(id=0,promember=0): rr = rrower(hrmax=r.max,hrut2=r.ut2, - hrut1=r.ut1,hrat=r.at, - hrtr=r.tr,hran=r.an,ftp=r.ftp) + hrut1=r.ut1,hrat=r.at, + hrtr=r.tr,hran=r.an,ftp=r.ftp) rowdata = rdata(f1,rower=rr) if rowdata == 0: - return "","No Valid Data Available" + return "","No Valid Data Available" dist = rowdata.df.loc[:,'cum_dist'] try: - vstream = rowdata.df.loc[:,'vstream'] + vstream = rowdata.df.loc[:,'vstream'] except KeyError: - rowdata.add_stream(0) - vstream = rowdata.df.loc[:,'vstream'] - rowdata.write_csv(f1,gzip=True) + rowdata.add_stream(0) + vstream = rowdata.df.loc[:,'vstream'] + rowdata.write_csv(f1,gzip=True) dataprep.update_strokedata(id,rowdata.df) # plot tools if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' # making the plot plot = Figure(tools=TOOLS,plot_width=400,height=500, -# toolbar_location="below", - toolbar_sticky=False, - ) +# toolbar_location="below", + toolbar_sticky=False, + ) plot.line(dist,vstream,legend="River Stream Velocity (m/s)") plot.title.text = row.name plot.title.text_font_size=value("1.0em") @@ -2130,9 +2130,9 @@ def interactive_streamchart(id=0,promember=0): def interactive_chart(id=0,promember=0,intervaldata = {}): # Add hover to this comma-separated string and see what changes if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' columns = ['time','pace','hr','fpace','ftime'] @@ -2142,7 +2142,7 @@ def interactive_chart(id=0,promember=0,intervaldata = {}): row = Workout.objects.get(id=id) if datadf.empty: - return "","No Valid Data Available" + return "","No Valid Data Available" else: try: datadf.sort_values(by='time',ascending=True,inplace=True) @@ -2161,17 +2161,17 @@ def interactive_chart(id=0,promember=0,intervaldata = {}): #datadf,row = dataprep.getrowdata_db(id=id) #if datadf.empty: - #return "","No Valid Data Available" + #return "","No Valid Data Available" source = ColumnDataSource( - datadf - ) + datadf + ) plot = Figure(x_axis_type="datetime",y_axis_type="datetime", - plot_width=400, - plot_height=400, - toolbar_sticky=False, - tools=TOOLS) + plot_width=400, + plot_height=400, + toolbar_sticky=False, + tools=TOOLS) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -2195,30 +2195,30 @@ def interactive_chart(id=0,promember=0,intervaldata = {}): plot.xaxis.axis_label = "Time" plot.yaxis.axis_label = "Pace (/500m)" plot.xaxis[0].formatter = DatetimeTickFormatter( - hours = ["%H"], - minutes = ["%M"], - seconds = ["%S"], - days = ["0"], - months = [""], - years = [""] - ) + hours = ["%H"], + minutes = ["%M"], + seconds = ["%S"], + days = ["0"], + months = [""], + years = [""] + ) plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + seconds = ["%S"], + minutes = ["%M"] + ) ymax = 90. ymin = 150. if row.workouttype == 'water': - ymax = 90. - ymin = 210. + ymax = 90. + ymin = 210. plot.y_range = Range1d(1.e3*ymin,1.e3*ymax) plot.extra_y_ranges["spmax"] = Range1d(start=10,end=45) plot.line('time','spm',source=source,color="red", - y_range_name="spmax", legend="Stroke Rate",name="spm") + y_range_name="spmax", legend="Stroke Rate",name="spm") plot.add_layout(LinearAxis(y_range_name="spmax",axis_label="SPM"),'right') plot.legend.location = "bottom_right" @@ -2250,11 +2250,11 @@ def interactive_chart(id=0,promember=0,intervaldata = {}): hover.tooltips = OrderedDict([ - ('Time','@ftime'), - ('Pace','@fpace'), - ('HR','@hr{int}'), - ('SPM','@spm{1.1}'), - ]) + ('Time','@ftime'), + ('Pace','@fpace'), + ('HR','@hr{int}'), + ('SPM','@spm{1.1}'), + ]) hover.mode = 'mouse' hover.names = ["spm","pace"] @@ -2297,8 +2297,8 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='', if xparam=='distance': - xaxmax = datadf[xparam].max() - xaxmin = datadf[xparam].min() + xaxmax = datadf[xparam].max() + xaxmin = datadf[xparam].min() elif xparam=='time': tseconds = datadf.loc[:,'time'] xaxmax = tseconds.max() @@ -2307,12 +2307,12 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='', xaxmax = datadf[xparam].max()-5 xaxmin = datadf[xparam].min()+5 else: - xaxmax = yaxmaxima[xparam] - xaxmin = yaxminima[xparam] + xaxmax = yaxmaxima[xparam] + xaxmin = yaxminima[xparam] if yparam=='distance': - yaxmax = datadf[yparam].max() - yaxmin = datadf[yparam].min() + yaxmax = datadf[yparam].max() + yaxmin = datadf[yparam].min() elif yparam=='time': tseconds = datadf.loc[:,'time'] yaxmax = tseconds.max() @@ -2321,8 +2321,8 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='', yaxmax = datadf[yparam].max()-5 yaxmin = datadf[yparam].min()+5 else: - yaxmax = yaxmaxima[yparam] - yaxmin = yaxminima[yparam] + yaxmax = yaxmaxima[yparam] + yaxmin = yaxminima[yparam] x_axis_type = 'linear' y_axis_type = 'linear' @@ -2362,9 +2362,9 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='', plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, - tools=TOOLS, - toolbar_location="above", - toolbar_sticky=False,plot_width=920) + tools=TOOLS, + toolbar_location="above", + toolbar_sticky=False,plot_width=920) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -2453,10 +2453,10 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='', plot.x_range = xrange1 if yparam == 'pace': - plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + plot.yaxis[0].formatter = DatetimeTickFormatter( + seconds = ["%S"], + minutes = ["%M"] + ) script,div = components(plot) @@ -2513,7 +2513,7 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, # check if dataframe not empty if datadf.empty: - return ['','

No non-zero data in selection

','',''] + return ['','

No non-zero data in selection

','',''] try: @@ -2536,37 +2536,37 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, return ['','

No non-zero data in selection

','',''] if yparam2 != 'None': try: - datadf['y2'] = datadf.loc[:,yparam2] + datadf['y2'] = datadf.loc[:,yparam2] except KeyError: datadf['y2'] = datadf['y1'] else: - datadf['y2'] = datadf['y1'] + datadf['y2'] = datadf['y1'] if xparam=='distance': - xaxmax = datadf['x1'].max() - xaxmin = datadf['x1'].min() + xaxmax = datadf['x1'].max() + xaxmin = datadf['x1'].min() else: - xaxmax = yaxmaxima[xparam] - xaxmin = yaxminima[xparam] + 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' if xparam == 'time': - x_axis_type = 'datetime' + x_axis_type = 'datetime' if yparam1 == 'pace': - y_axis_type = 'datetime' - y1mean = datadf.loc[:,'pace'].mean() + y_axis_type = 'datetime' + y1mean = datadf.loc[:,'pace'].mean() datadf['xname'] = axlabels[xparam] datadf['yname1'] = axlabels[yparam1] @@ -2577,23 +2577,23 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, source = ColumnDataSource( - datadf - ) + datadf + ) source2 = ColumnDataSource( - datadf.copy() - ) + 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' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, - tools=TOOLS, - toolbar_location="above", - toolbar_sticky=False) + tools=TOOLS, + toolbar_location="above", + toolbar_sticky=False) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -2612,10 +2612,10 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, ) x1means = Span(location=x1mean,dimension='height',line_color='green', - line_dash=[6,6], line_width=2) + line_dash=[6,6], line_width=2) y1means = Span(location=y1mean,dimension='width',line_color='blue', - line_dash=[6,6],line_width=2) + line_dash=[6,6],line_width=2) y2means = y1means xlabel = Label(x=100,y=130,x_units='screen',y_units='screen', @@ -2643,9 +2643,9 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, y2label = y1label plot.circle('x1','y1',source=source2,fill_alpha=0.3,line_color=None, - legend=yparamname1, - ) - + legend=yparamname1, + ) + plot.xaxis.axis_label = axlabels[xparam] plot.yaxis.axis_label = axlabels[yparam1] @@ -2657,27 +2657,27 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, plot.x_range = xrange1 if yparam1 == 'pace': - plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + plot.yaxis[0].formatter = DatetimeTickFormatter( + seconds = ["%S"], + minutes = ["%M"] + ) if yparam2 != 'None': - yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) - plot.extra_y_ranges["yax2"] = yrange2 + 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') + 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") + y2means = Span(location=y2mean,dimension='width',line_color='red', + line_dash=[6,6],line_width=2,y_range_name="yax2") - plot.add_layout(y2means) + plot.add_layout(y2means) y2label = Label(x=100,y=70,x_units='screen',y_units='screen', text=axlabels[yparam2]+": {y2mean:6.2f}".format(y2mean=y2mean), background_fill_alpha=.7, @@ -2689,12 +2689,12 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, callback = CustomJS(args = dict(source=source,source2=source2, - x1means=x1means, - y1means=y1means, + x1means=x1means, + y1means=y1means, y1label=y1label, y2label=y2label, xlabel=xlabel, - y2means=y2means), code=""" + y2means=y2means), code=""" var data = source.data var data2 = source2.data var x1 = data['x1'] @@ -2730,21 +2730,21 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, data2['y2vals'] = [] for (i=0; i=minspm && spm1[i]<=maxspm) { - if (distance1[i]>=mindist && distance1[i]<=maxdist) { + if (spm1[i]>=minspm && spm1[i]<=maxspm) { + if (distance1[i]>=mindist && distance1[i]<=maxdist) { if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) { - data2['x1'].push(x1[i]) - data2['y1'].push(y1[i]) - data2['y2'].push(y2[i]) - data2['spm'].push(spm1[i]) - data2['distance'].push(distance1[i]) + data2['x1'].push(x1[i]) + data2['y1'].push(y1[i]) + data2['y2'].push(y2[i]) + data2['spm'].push(spm1[i]) + data2['distance'].push(distance1[i]) - xm += x1[i] - ym1 += y1[i] - ym2 += y2[i] + xm += x1[i] + ym1 += y1[i] + ym2 += y2[i] } - } - } + } + } } xm /= data2['x1'].length @@ -2765,21 +2765,21 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, """) slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1, - title="Min SPM",callback=callback) + title="Min SPM",callback=callback) callback.args["minspm"] = slider_spm_min slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1, - title="Max SPM",callback=callback) + title="Max SPM",callback=callback) callback.args["maxspm"] = slider_spm_max slider_work_min = Slider(start=0.0, end=1500,value=0.0, step=10, - title="Min Work per Stroke",callback=callback) + title="Min Work per Stroke",callback=callback) callback.args["minwork"] = slider_work_min slider_work_max = Slider(start=0.0, end=1500,value=1500.0, step=10, - title="Max Work per Stroke",callback=callback) + title="Max Work per Stroke",callback=callback) callback.args["maxwork"] = slider_work_max try: @@ -2788,23 +2788,23 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, distmax = 1000. slider_dist_min = Slider(start=0,end=distmax,value=0,step=1, - title="Min Distance",callback=callback) + title="Min Distance",callback=callback) callback.args["mindist"] = slider_dist_min slider_dist_max = Slider(start=0,end=distmax,value=distmax, - step=1, - title="Max Distance",callback=callback) + step=1, + title="Max Distance",callback=callback) callback.args["maxdist"] = slider_dist_max layout = layoutrow([layoutcolumn([slider_spm_min, - slider_spm_max, - slider_dist_min, - slider_dist_max, + slider_spm_max, + slider_dist_min, + slider_dist_max, slider_work_min, slider_work_max, - ], - ), - plot]) + ], + ), + plot]) layout.sizing_mode = 'scale_width' @@ -2820,11 +2820,11 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, def interactive_flex_chart2(id=0,promember=0, - xparam='time', - yparam1='pace', - yparam2='hr', - plottype='line', - workstrokesonly=False): + xparam='time', + yparam1='pace', + yparam2='hr', + plottype='line', + workstrokesonly=False): #rowdata,row = dataprep.getrowdata_db(id=id) columns = [xparam,yparam1,yparam2, @@ -2878,7 +2878,7 @@ def interactive_flex_chart2(id=0,promember=0, row = Workout.objects.get(id=id) if rowdata.empty: - return "","No valid data",'','',workstrokesonly + return "","No valid data",'','',workstrokesonly else: try: rowdata.sort_values(by='time',ascending=True,inplace=True) @@ -2890,10 +2890,10 @@ def interactive_flex_chart2(id=0,promember=0, workoutstatetransition = [0,2,10,11,12,13] if workstrokesonly: - try: - rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)] - except KeyError: - pass + try: + rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)] + except KeyError: + pass try: tseconds = rowdata.loc[:,'time'] @@ -2916,59 +2916,59 @@ def interactive_flex_chart2(id=0,promember=0, if yparam2 != 'None': try: - rowdata['y2'] = rowdata.loc[:,yparam2] + rowdata['y2'] = rowdata.loc[:,yparam2] rowmin = rowdata[yparam2].min() except KeyError: rowdata['y2'] = 0*rowdata.loc[:,'time'] rowdata[yparam2] = rowdata['y2'] else: - rowdata['y2'] = rowdata['y1'] + rowdata['y2'] = rowdata['y1'] if xparam=='time': - xaxmax = tseconds.max() - xaxmin = tseconds.min() + xaxmax = tseconds.max() + xaxmin = tseconds.min() elif xparam=='distance' or xparam=='cumdist': - xaxmax = rowdata['x1'].max() - xaxmin = rowdata['x1'].min() + xaxmax = rowdata['x1'].max() + xaxmin = rowdata['x1'].min() else: try: - xaxmax = yaxmaxima[xparam] - xaxmin = yaxminima[xparam] + xaxmax = yaxmaxima[xparam] + xaxmin = yaxminima[xparam] except KeyError: - xaxmax = rowdata['x1'].max() - xaxmin = rowdata['x1'].min() + xaxmax = rowdata['x1'].max() + xaxmin = rowdata['x1'].min() # average values if xparam != 'time': try: - x1mean = rowdata['x1'].mean() + x1mean = rowdata['x1'].mean() except TypeError: x1mean = 0 else: - x1mean = 0 - + x1mean = 0 + y1mean = rowdata['y1'].mean() y2mean = rowdata['y2'].mean() if xparam != 'time': - xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100. + xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100. else: - xvals = np.arange(100) + xvals = np.arange(100) # constant power plot if yparam1 == 'driveenergy': - if xparam == 'spm': - yconstantpower = rowdata['y1'].mean()*rowdata['x1'].mean()/xvals - + if xparam == 'spm': + yconstantpower = rowdata['y1'].mean()*rowdata['x1'].mean()/xvals + x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': - x_axis_type = 'datetime' + x_axis_type = 'datetime' if yparam1 == 'pace': - y_axis_type = 'datetime' + y_axis_type = 'datetime' try: - y1mean = rowdata.loc[:,'pace'].mean() + y1mean = rowdata.loc[:,'pace'].mean() except KeyError: y1mean = 0 @@ -2991,26 +2991,26 @@ def interactive_flex_chart2(id=0,promember=0, # prepare data source = ColumnDataSource( - rowdata - ) + rowdata + ) # second source for filtering source2 = ColumnDataSource( - rowdata.copy() - ) + rowdata.copy() + ) # Add hover to this comma-separated string and see what changes if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' + 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_sticky=False - ) + tools=TOOLS, + toolbar_sticky=False + ) @@ -3031,10 +3031,10 @@ def interactive_flex_chart2(id=0,promember=0, ) x1means = Span(location=x1mean,dimension='height',line_color='green', - line_dash=[6,6], line_width=2) + line_dash=[6,6], line_width=2) y1means = Span(location=y1mean,dimension='width',line_color='blue', - line_dash=[6,6],line_width=2) + line_dash=[6,6],line_width=2) y2means = y1means try: @@ -3060,7 +3060,7 @@ def interactive_flex_chart2(id=0,promember=0, if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'): - plot.add_layout(x1means) + plot.add_layout(x1means) plot.add_layout(xlabel) @@ -3089,14 +3089,14 @@ def interactive_flex_chart2(id=0,promember=0, # average values if yparam1 == 'driveenergy': - if xparam == 'spm': - plot.line(xvals,yconstantpower,color="green",legend="Constant Power") + if xparam == 'spm': + plot.line(xvals,yconstantpower,color="green",legend="Constant Power") if plottype=='line': - plot.line('x1','y1',source=source2,legend=yaxlabel) + plot.line('x1','y1',source=source2,legend=yaxlabel) elif plottype=='scatter': - plot.scatter('x1','y1',source=source2,legend=yaxlabel,fill_alpha=0.4, - line_color=None) + plot.scatter('x1','y1',source=source2,legend=yaxlabel,fill_alpha=0.4, + line_color=None) plot.title.text = row.name plot.title.text_font_size=value("1.0em") @@ -3109,7 +3109,7 @@ def interactive_flex_chart2(id=0,promember=0, try: - yrange1 = Range1d(start=yaxminima[yparam1], + yrange1 = Range1d(start=yaxminima[yparam1], end=yaxmaxima[yparam1]) except KeyError: yrange1 = Range1d(start=rowdata[yparam1].min(), @@ -3119,67 +3119,67 @@ def interactive_flex_chart2(id=0,promember=0, if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'): try: - xrange1 = Range1d(start=yaxminima[xparam], + xrange1 = Range1d(start=yaxminima[xparam], end=yaxmaxima[xparam]) except KeyError: xrange1 = Range1d(start=rowdata[xparam].min(), end=rowdata[xparam].max()) - plot.x_range = xrange1 + plot.x_range = xrange1 if xparam == 'time': - xrange1 = Range1d(start=xaxmin,end=xaxmax) - plot.x_range = xrange1 - plot.xaxis[0].formatter = DatetimeTickFormatter( - hours = ["%H"], - minutes = ["%M"], - seconds = ["%S"], - days = ["0"], - months = [""], - years = [""] - ) + xrange1 = Range1d(start=xaxmin,end=xaxmax) + plot.x_range = xrange1 + plot.xaxis[0].formatter = DatetimeTickFormatter( + hours = ["%H"], + minutes = ["%M"], + seconds = ["%S"], + days = ["0"], + months = [""], + years = [""] + ) if yparam1 == 'pace': - plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + plot.yaxis[0].formatter = DatetimeTickFormatter( + seconds = ["%S"], + minutes = ["%M"] + ) if yparam2 != 'None': try: - yrange2 = Range1d(start=yaxminima[yparam2], + yrange2 = Range1d(start=yaxminima[yparam2], end=yaxmaxima[yparam2]) except KeyError: yrange2 = Range1d(start=rowdata[yparam2].min(), end=rowdata[yparam2].max()) - plot.extra_y_ranges["yax2"] = yrange2 + plot.extra_y_ranges["yax2"] = yrange2 #= {"yax2": yrange2} try: axlegend = axlabels[yparam2] except KeyError: axlegend = str(yparam2)+' ' - if plottype=='line': - plot.line('x1','y2',color="red",y_range_name="yax2", - legend=axlegend, - source=source2) + if plottype=='line': + plot.line('x1','y2',color="red",y_range_name="yax2", + legend=axlegend, + source=source2) - elif plottype=='scatter': - plot.scatter('x1','y2',source=source2,legend=axlegend, - fill_alpha=0.4, - line_color=None,color="red",y_range_name="yax2") - - plot.add_layout(LinearAxis(y_range_name="yax2", - axis_label=axlegend),'right') + elif plottype=='scatter': + plot.scatter('x1','y2',source=source2,legend=axlegend, + fill_alpha=0.4, + line_color=None,color="red",y_range_name="yax2") + + plot.add_layout(LinearAxis(y_range_name="yax2", + axis_label=axlegend),'right') - y2means = Span(location=y2mean,dimension='width',line_color='red', - line_dash=[6,6],line_width=2,y_range_name="yax2") + y2means = Span(location=y2mean,dimension='width',line_color='red', + line_dash=[6,6],line_width=2,y_range_name="yax2") - plot.add_layout(y2means) + plot.add_layout(y2means) y2label = Label(x=100,y=70,x_units='screen',y_units='screen', text=axlegend+": {y2mean:6.2f}".format(y2mean=y2mean), background_fill_alpha=.7, @@ -3193,25 +3193,25 @@ def interactive_flex_chart2(id=0,promember=0, hover.tooltips = OrderedDict([ - ('Time','@ftime'), - ('Distance','@distance{int}'), - ('Pace','@fpace'), - ('HR','@hr{int}'), - ('SPM','@spm{1.1}'), - ('Power','@power{int}'), - ]) + ('Time','@ftime'), + ('Distance','@distance{int}'), + ('Pace','@fpace'), + ('HR','@hr{int}'), + ('SPM','@spm{1.1}'), + ('Power','@power{int}'), + ]) hover.mode = 'mouse' callback = CustomJS(args = dict(source=source,source2=source2, - x1means=x1means, - y1means=y1means, + x1means=x1means, + y1means=y1means, y1label=y1label, y2label=y2label, xlabel=xlabel, annolabel=annolabel, - y2means=y2means, + y2means=y2means, ), code=""" var data = source.data var data2 = source2.data @@ -3259,26 +3259,26 @@ def interactive_flex_chart2(id=0,promember=0, data2['y2vals'] = [] for (i=0; i=minspm && spm1[i]<=maxspm) { - if (distance1[i]>=mindist && distance1[i]<=maxdist) { + if (spm1[i]>=minspm && spm1[i]<=maxspm) { + if (distance1[i]>=mindist && distance1[i]<=maxdist) { if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) { - data2['x1'].push(x1[i]) - data2['y1'].push(y1[i]) - data2['y2'].push(y2[i]) - data2['spm'].push(spm1[i]) - data2['time'].push(time1[i]) + data2['x1'].push(x1[i]) + data2['y1'].push(y1[i]) + data2['y2'].push(y2[i]) + data2['spm'].push(spm1[i]) + data2['time'].push(time1[i]) data2['fpace'].push(fpace1[i]) - data2['pace'].push(pace1[i]) - data2['hr'].push(hr1[i]) - data2['distance'].push(distance1[i]) - data2['power'].push(power1[i]) + data2['pace'].push(pace1[i]) + data2['hr'].push(hr1[i]) + data2['distance'].push(distance1[i]) + data2['power'].push(power1[i]) - xm += x1[i] - ym1 += y1[i] - ym2 += y2[i] + xm += x1[i] + ym1 += y1[i] + ym2 += y2[i] } - } - } + } + } } xm /= data2['x1'].length @@ -3304,21 +3304,21 @@ def interactive_flex_chart2(id=0,promember=0, callback.args["annotation"] = annotation slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1, - title="Min SPM",callback=callback) + title="Min SPM",callback=callback) callback.args["minspm"] = slider_spm_min slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1, - title="Max SPM",callback=callback) + title="Max SPM",callback=callback) callback.args["maxspm"] = slider_spm_max slider_work_min = Slider(start=0.0, end=1500,value=0.0, step=10, - title="Min Work per Stroke",callback=callback) + title="Min Work per Stroke",callback=callback) callback.args["minwork"] = slider_work_min slider_work_max = Slider(start=0.0, end=1500,value=1500.0, step=10, - title="Max Work per Stroke",callback=callback) + title="Max Work per Stroke",callback=callback) callback.args["maxwork"] = slider_work_max try: @@ -3327,22 +3327,22 @@ def interactive_flex_chart2(id=0,promember=0, distmax = 100 slider_dist_min = Slider(start=0,end=distmax,value=0,step=1, - title="Min Distance",callback=callback) + title="Min Distance",callback=callback) callback.args["mindist"] = slider_dist_min slider_dist_max = Slider(start=0,end=distmax,value=distmax, - step=1, - title="Max Distance",callback=callback) + step=1, + title="Max Distance",callback=callback) callback.args["maxdist"] = slider_dist_max thesliders = layoutcolumn([annotation, slider_spm_min, - slider_spm_max, - slider_dist_min, - slider_dist_max, + slider_spm_max, + slider_dist_min, + slider_dist_max, slider_work_min, slider_work_max, - ]) + ]) thesliders.sizing_mode = 'scale_width' @@ -3369,7 +3369,7 @@ def thumbnails_set(r,id,favorites): try: rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=True) except: - return [ + return [ {'script':"", 'div':"", 'notes':"" @@ -3383,7 +3383,7 @@ def thumbnails_set(r,id,favorites): rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=False, workstrokesonly=False) except: - return [ + return [ {'script':"", 'div':"", 'notes':"" @@ -3430,11 +3430,11 @@ def thumbnails_set(r,id,favorites): def thumbnail_flex_chart(rowdata,id=0,promember=0, - xparam='time', - yparam1='pace', - yparam2='hr', - plottype='line', - workstrokesonly=False): + xparam='time', + yparam1='pace', + yparam2='hr', + plottype='line', + workstrokesonly=False): try: @@ -3467,30 +3467,30 @@ def thumbnail_flex_chart(rowdata,id=0,promember=0, if yparam2 != 'None': try: - rowdata['y2'] = rowdata.loc[:,yparam2] + rowdata['y2'] = rowdata.loc[:,yparam2] except KeyError: rowdata['y2'] = 0*rowdata.loc[:,'time'] else: - rowdata['y2'] = rowdata['y1'] + rowdata['y2'] = rowdata['y1'] if xparam=='time': - xaxmax = tseconds.max() - xaxmin = tseconds.min() + xaxmax = tseconds.max() + xaxmin = tseconds.min() elif xparam=='distance' or xparam=='cumdist': - xaxmax = rowdata['x1'].max() - xaxmin = rowdata['x1'].min() + xaxmax = rowdata['x1'].max() + xaxmin = rowdata['x1'].min() else: - xaxmax = yaxmaxima[xparam] - xaxmin = yaxminima[xparam] + xaxmax = yaxmaxima[xparam] + xaxmin = yaxminima[xparam] x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': - x_axis_type = 'datetime' + x_axis_type = 'datetime' if yparam1 == 'pace': - y_axis_type = 'datetime' - y1mean = rowdata.loc[:,'pace'].mean() + y_axis_type = 'datetime' + y1mean = rowdata.loc[:,'pace'].mean() rowdata['xname'] = axlabels[xparam] @@ -3506,14 +3506,14 @@ def thumbnail_flex_chart(rowdata,id=0,promember=0, # prepare data source = ColumnDataSource( - rowdata - ) + rowdata + ) sizing_mode = 'fixed' # 'scale_width' also looks nice with this example plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, plot_width=200,plot_height=150, - ) + ) @@ -3528,10 +3528,10 @@ def thumbnail_flex_chart(rowdata,id=0,promember=0, plot.yaxis.major_label_text_font_size = "7pt" if plottype=='line': - plot.line('x1','y1',source=source) + plot.line('x1','y1',source=source) elif plottype=='scatter': - plot.scatter('x1','y1',source=source,fill_alpha=0.4, - line_color=None) + plot.scatter('x1','y1',source=source,fill_alpha=0.4, + line_color=None) try: plot.xaxis.axis_label = axlabels[xparam] @@ -3551,45 +3551,45 @@ def thumbnail_flex_chart(rowdata,id=0,promember=0, plot.y_range = yrange1 if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'): - xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) - plot.x_range = xrange1 + xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) + plot.x_range = xrange1 if xparam == 'time': - xrange1 = Range1d(start=xaxmin,end=xaxmax) - plot.x_range = xrange1 - plot.xaxis[0].formatter = DatetimeTickFormatter( - hours = ["%H"], - minutes = ["%M"], - seconds = ["%S"], - days = ["0"], - months = [""], - years = [""] - ) + xrange1 = Range1d(start=xaxmin,end=xaxmax) + plot.x_range = xrange1 + plot.xaxis[0].formatter = DatetimeTickFormatter( + hours = ["%H"], + minutes = ["%M"], + seconds = ["%S"], + days = ["0"], + months = [""], + years = [""] + ) if yparam1 == 'pace': - plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + plot.yaxis[0].formatter = DatetimeTickFormatter( + seconds = ["%S"], + minutes = ["%M"] + ) if yparam2 != 'None': - yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) - plot.extra_y_ranges["yax2"] = yrange2 + yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) + plot.extra_y_ranges["yax2"] = yrange2 #= {"yax2": yrange2} - if plottype=='line': - plot.line('x1','y2',color="red",y_range_name="yax2", - source=source) + if plottype=='line': + plot.line('x1','y2',color="red",y_range_name="yax2", + source=source) - elif plottype=='scatter': - plot.scatter('x1','y2',source=source, - fill_alpha=0.4, - line_color=None,color="red",y_range_name="yax2") - - plot.add_layout(LinearAxis(y_range_name="yax2", - axis_label=axlabels[yparam2], + elif plottype=='scatter': + plot.scatter('x1','y2',source=source, + fill_alpha=0.4, + line_color=None,color="red",y_range_name="yax2") + + plot.add_layout(LinearAxis(y_range_name="yax2", + axis_label=axlabels[yparam2], major_label_text_font_size="7pt", axis_label_text_font_size="7pt", ),'right', @@ -3608,22 +3608,22 @@ def interactive_bar_chart(id=0,promember=0): rowdata.dropna(axis=0,how='any',inplace=True) if rowdata.empty: - return "","No Valid Data Available" + return "","No Valid Data Available" # Add hover to this comma-separated string and see what changes if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' source = ColumnDataSource( - rowdata - ) + rowdata + ) plot = Figure(x_axis_type="datetime",y_axis_type="datetime", - toolbar_sticky=False, - plot_width=920, - tools=TOOLS) + toolbar_sticky=False, + plot_width=920, + tools=TOOLS) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -3646,25 +3646,25 @@ def interactive_bar_chart(id=0,promember=0): plot.xaxis.axis_label = "Time" plot.yaxis.axis_label = "Pace (/500m)" plot.xaxis[0].formatter = DatetimeTickFormatter( - hours ="", - minutes = ["%M"], - seconds = ["%S"], - days = ["0"], - months = [""], - years = [""] - ) + hours ="", + minutes = ["%M"], + seconds = ["%S"], + days = ["0"], + months = [""], + years = [""] + ) plot.yaxis[0].formatter = DatetimeTickFormatter( - hours = "", - seconds = ["%S"], - minutes = ["%M"], - ) + hours = "", + seconds = ["%S"], + minutes = ["%M"], + ) ymax = 1.0e3*90 ymin = 1.0e3*180 if row.workouttype == 'water': - ymax = 1.0e3*90 - ymin = 1.0e3*210 + ymax = 1.0e3*90 + ymin = 1.0e3*210 plot.y_range = Range1d(ymin,ymax) @@ -3673,33 +3673,33 @@ def interactive_bar_chart(id=0,promember=0): hover.tooltips = OrderedDict([ - ('Time','@ftime'), - ('Pace','@fpace'), - ('HR','@hr{int}'), - ('SPM','@spm{1.1}'), - ]) + ('Time','@ftime'), + ('Pace','@fpace'), + ('HR','@hr{int}'), + ('SPM','@spm{1.1}'), + ]) hover.mode = 'mouse' plot.extra_y_ranges["hr"] = Range1d(start=100,end=200) plot.quad(left='time',top='hr_ut2',bottom='hr_bottom', - right='x_right',source=source,color="gray", - y_range_name="hr", legend=" 0] - + #datadf = datadf[datadf[xparam] > 0] - + # check if dataframe not empty if datadf.empty: - return ['','

No non-zero data in selection

','','No non-zero data in selection'] + return ['','

No non-zero data in selection

','','No non-zero data in selection'] if xparam != 'distance' and xparam != 'time' and xparam != 'cumdist': - xaxmax = yaxmaxima[xparam] - xaxmin = yaxminima[xparam] + xaxmax = yaxmaxima[xparam] + xaxmin = yaxminima[xparam] elif xparam == 'time': - xaxmax = tseconds.max() - xaxmin = tseconds.min() + xaxmax = tseconds.max() + xaxmin = tseconds.min() else: xaxmax = datadf['distance'].max() - xaxmin = datadf['distance'].min() + xaxmin = datadf['distance'].min() if yparam == 'distance': yaxmin = datadf['distance'].min() @@ -3771,28 +3771,28 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line', # 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' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair' if yparam == 'pace': - y_axis_type = 'datetime' + y_axis_type = 'datetime' yaxmax = 90.*1e3 yaxmin = 150.*1e3 if xparam == 'time': - x_axis_type = 'datetime' + x_axis_type = 'datetime' if xparam != 'time': - xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100. + xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100. else: - xvals = np.arange(100) + xvals = np.arange(100) plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, - tools=TOOLS, - toolbar_location="above", + tools=TOOLS, + toolbar_location="above", plot_width=920,plot_height=500, - toolbar_sticky=False) + toolbar_sticky=False) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -3848,12 +3848,12 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line', ) TIPS = OrderedDict([ - ('time','@ftime'), + ('time','@ftime'), ('pace','@fpace'), - ('hr','@hr'), - ('spm','@spm{1.1}'), - ('distance','@distance{5}'), - ]) + ('hr','@hr'), + ('spm','@spm{1.1}'), + ('distance','@distance{5}'), + ]) hover = plot.select(type=HoverTool) hover.tooltips = TIPS @@ -3877,30 +3877,30 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line', plot.yaxis.axis_label = axlabels[yparam] if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'): - xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) - plot.x_range = xrange1 + xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) + plot.x_range = xrange1 yrange1 = Range1d(start=yaxmin,end=yaxmax) plot.y_range = yrange1 if xparam == 'time': - xrange1 = Range1d(start=xaxmin,end=xaxmax) - plot.x_range = xrange1 - plot.xaxis[0].formatter = DatetimeTickFormatter( - hours = ["%H"], - minutes = ["%M"], - seconds = ["%S"], - days = ["0"], - months = [""], - years = [""] - ) + xrange1 = Range1d(start=xaxmin,end=xaxmax) + plot.x_range = xrange1 + plot.xaxis[0].formatter = DatetimeTickFormatter( + hours = ["%H"], + minutes = ["%M"], + seconds = ["%S"], + days = ["0"], + months = [""], + years = [""] + ) if yparam == 'pace': - plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + plot.yaxis[0].formatter = DatetimeTickFormatter( + seconds = ["%S"], + minutes = ["%M"] + ) script, div = components(plot) @@ -3909,7 +3909,7 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line', def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', - promember=0,plottype='line'): + promember=0,plottype='line'): @@ -3944,12 +3944,12 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', row2 = Workout.objects.get(id=id2) if rowdata1.empty: - return "","No Valid Data Available" + return "","No Valid Data Available" else: rowdata1.sort_values(by='time',ascending=True,inplace=True) if rowdata2.empty: - return "","No Valid Data Available" + return "","No Valid Data Available" else: rowdata2.sort_values(by='time',ascending=True,inplace=True) @@ -3965,16 +3965,16 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': - x_axis_type = 'datetime' + x_axis_type = 'datetime' if yparam == 'pace': - y_axis_type = 'datetime' - ymax = 1.0e3*90 - ymin = 1.0e3*180 + y_axis_type = 'datetime' + ymax = 1.0e3*90 + ymin = 1.0e3*180 - if row1.workouttype == 'water': - ymax = 1.0e3*90 - ymin = 1.0e3*210 + if row1.workouttype == 'water': + ymax = 1.0e3*90 + ymin = 1.0e3*210 ftime1 = rowdata1.loc[:,'ftime'] ftime2 = rowdata2.loc[:,'ftime'] @@ -3993,53 +3993,53 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', spm2 = rowdata2.loc[:,'spm'] if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' data1 = pd.DataFrame( - dict( - x1=x1, - y1=y1, - ftime1=ftime1, - fpace1=fpace1, - hr1 = hr1, - spm1 = spm1, - distance1=distance1, - ) - ).dropna() + dict( + x1=x1, + y1=y1, + ftime1=ftime1, + fpace1=fpace1, + hr1 = hr1, + spm1 = spm1, + distance1=distance1, + ) + ).dropna() data2 = pd.DataFrame( - dict( - x2=x2, - y2=y2, - ftime2=ftime2, - fpace2=fpace2, - hr2 = hr2, - spm2 = spm2, - distance2=distance2, - ) - ).dropna() + dict( + x2=x2, + y2=y2, + ftime2=ftime2, + fpace2=fpace2, + hr2 = hr2, + spm2 = spm2, + distance2=distance2, + ) + ).dropna() source1 = ColumnDataSource( - data1 - ) + data1 + ) source2 = ColumnDataSource( - data2 - ) + data2 + ) ymean1 = data1['y1'].mean() ymean2 = data2['y2'].mean() # create interactive plot plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, - tools=TOOLS, - plot_width=920, - toolbar_sticky=False) + tools=TOOLS, + plot_width=920, + toolbar_sticky=False) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -4058,19 +4058,19 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', ) TIPS = OrderedDict([ - ('time','@ftime1'), + ('time','@ftime1'), ('pace','@fpace1'), - ('hr','@hr1'), - ('spm','@spm1{1.1}'), - ('distance','@distance1{5}'), - ]) + ('hr','@hr1'), + ('spm','@spm1{1.1}'), + ('distance','@distance1{5}'), + ]) TIPS2 = OrderedDict([ - ('time','@ftime2'), + ('time','@ftime2'), ('pace','@fpace2'), - ('hr','@hr2'), - ('spm','@spm2{1.1}'), - ('distance','@distance2{5}'), - ]) + ('hr','@hr2'), + ('spm','@spm2{1.1}'), + ('distance','@distance2{5}'), + ]) @@ -4081,19 +4081,19 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', if plottype=='line': - l1 = plot.line('x1','y1',source=source1, + l1 = plot.line('x1','y1',source=source1, color="blue",legend=row1.name, ) - l2 = plot.line('x2','y2',source=source2, + l2 = plot.line('x2','y2',source=source2, color="red",legend=row2.name, ) elif plottype=='scatter': - l1 = plot.scatter('x1','y1',source=source1,legend=row1.name, + l1 = plot.scatter('x1','y1',source=source1,legend=row1.name, fill_alpha=0.4, - line_color=None) - l2 = plot.scatter('x2','y2',source=source2,legend=row2.name, + line_color=None) + l2 = plot.scatter('x2','y2',source=source2,legend=row2.name, fill_alpha=0.4, - line_color=None,color="red") + line_color=None,color="red") plot.add_tools(HoverTool(renderers=[l1],tooltips=TIPS)) plot.add_tools(HoverTool(renderers=[l2],tooltips=TIPS2)) @@ -4124,21 +4124,21 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', plot.add_layout(ylabel2) if xparam == 'time': - plot.xaxis[0].formatter = DatetimeTickFormatter( - hours = ["%H"], - minutes = ["%M"], - seconds = ["%S"], - days = ["0"], - months = [""], - years = [""] - ) + plot.xaxis[0].formatter = DatetimeTickFormatter( + hours = ["%H"], + minutes = ["%M"], + seconds = ["%S"], + days = ["0"], + months = [""], + years = [""] + ) if yparam == 'pace': - plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + plot.yaxis[0].formatter = DatetimeTickFormatter( + seconds = ["%S"], + minutes = ["%M"] + ) plot.y_range = Range1d(ymin,ymax) @@ -4154,23 +4154,23 @@ def interactive_otw_advanced_pace_chart(id=0,promember=0): rowdata.dropna(axis=0,how='any',inplace=True) if rowdata.empty: - return "","No Valid Data Available" + return "","No Valid Data Available" # Add hover to this comma-separated string and see what changes if (promember==1): - TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' else: - TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' + TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' source = ColumnDataSource( - rowdata - ) + rowdata + ) plot = Figure(x_axis_type="datetime",y_axis_type="datetime", - tools=TOOLS, - plot_width=920, - toolbar_sticky=False) + tools=TOOLS, + plot_width=920, + toolbar_sticky=False) # add watermark plot.extra_y_ranges = {"watermark": watermarkrange} @@ -4193,17 +4193,17 @@ def interactive_otw_advanced_pace_chart(id=0,promember=0): plot.xaxis.axis_label = "Time" plot.yaxis.axis_label = "Pace (/500m)" plot.xaxis[0].formatter = DatetimeTickFormatter( - hours = ["%H"], - minutes = ["%M"], - seconds = ["%S"], - days = ["0"], - months = [""], - years = [""] - ) + hours = ["%H"], + minutes = ["%M"], + seconds = ["%S"], + days = ["0"], + months = [""], + years = [""] + ) plot.yaxis[0].formatter = DatetimeTickFormatter( - seconds = ["%S"], - minutes = ["%M"] - ) + seconds = ["%S"], + minutes = ["%M"] + ) ymax = 1.0e3*90 ymin = 1.0e3*210 @@ -4217,12 +4217,12 @@ def interactive_otw_advanced_pace_chart(id=0,promember=0): plot.line('time','nowindpace',source=source,legend="Corrected Pace",color="red") hover.tooltips = OrderedDict([ - ('Time','@ftime'), - ('Pace','@fpace'), - ('Corrected Pace','@fnowindpace'), - ('HR','@hr{int}'), - ('SPM','@spm{1.1}'), - ]) + ('Time','@ftime'), + ('Pace','@fpace'), + ('Corrected Pace','@fnowindpace'), + ('HR','@hr{int}'), + ('SPM','@spm{1.1}'), + ]) hover.mode = 'mouse' diff --git a/rowers/longtask.py b/rowers/longtask.py index fda8bf90..c9380bea 100644 --- a/rowers/longtask.py +++ b/rowers/longtask.py @@ -72,7 +72,7 @@ def longtask2(aantal,jobid=None,debug=False,secret=''): counter = 0 progress = int(100.*i/aantal) if debug: - print progress + print(progress) if jobid != None: if debug: url = SITE_URL_DEV @@ -83,8 +83,8 @@ def longtask2(aantal,jobid=None,debug=False,secret=''): post_data = {"secret":secret} s = requests.post(url, data=post_data) if debug: - print url - print s + print(url) + print(s) return 1 diff --git a/rowers/mailprocessing.py b/rowers/mailprocessing.py index 95077670..ade6419d 100644 --- a/rowers/mailprocessing.py +++ b/rowers/mailprocessing.py @@ -92,7 +92,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False): fileformat = fileformat[2] if testing: - print 'Fileformat = ',fileformat + print('Fileformat = ',fileformat) if fileformat == 'unknown': # extension = datafilename[-4:].lower() diff --git a/rowers/metrics.py b/rowers/metrics.py index f2a53c0f..c5682b0e 100644 --- a/rowers/metrics.py +++ b/rowers/metrics.py @@ -1,6 +1,7 @@ -from utils import lbstoN +from __future__ import absolute_import +from rowers.utils import lbstoN import numpy as np -from models import C2WorldClassAgePerformance +from rowers.models import C2WorldClassAgePerformance import pandas as pd from scipy import optimize from django.utils import timezone diff --git a/rowers/models.py b/rowers/models.py index ac7b00d1..df06502a 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -1,4 +1,4 @@ -from __future__ import unicode_literals +from __future__ import unicode_literals, absolute_import from django.db import models,IntegrityError from django.contrib.auth.models import User @@ -7,8 +7,8 @@ from django.core.exceptions import ValidationError from django import forms from django.forms import ModelForm from django.dispatch import receiver -from django.forms.widgets import SplitDateTimeWidget -from django.forms.extras.widgets import SelectDateWidget +from django.forms.widgets import SplitDateTimeWidget,SelectDateWidget +#from django.forms.extras.widgets import SelectDateWidget from django.forms.formsets import BaseFormSet from django.contrib.admin.widgets import AdminDateWidget,AdminTimeWidget,AdminSplitDateTime from datetimewidget.widgets import DateTimeWidget @@ -35,7 +35,7 @@ from rowers.rows import validate_file_extension from collections import OrderedDict from timezonefinder import TimezoneFinder -import mytypes +import rowers.mytypes as mytypes from matplotlib import path from rowsandall_app.settings import ( @@ -216,7 +216,7 @@ def update_records(url=c2url,verbose=True): ) try: if verbose: - print record + print(record) record.save() except: if verbose: @@ -228,9 +228,9 @@ def update_records(url=c2url,verbose=True): class CalcAgePerformance(models.Model): weightcategories = ( - ('hwt','heavy-weight'), - ('lwt','light-weight'), - ) + ('hwt','heavy-weight'), + ('lwt','light-weight'), + ) sexcategories = ( ('male','male'), @@ -261,7 +261,7 @@ class PowerTimeFitnessMetric(models.Model): date = models.DateField(default=current_day) last_workout = models.IntegerField(default=0) - user = models.ForeignKey(User) + user = models.ForeignKey(User,on_delete=models.CASCADE) PowerFourMin = models.FloatField(default=0) PowerTwoK = models.FloatField(default=0) PowerOneHour = models.FloatField(default=0) @@ -272,9 +272,9 @@ class PowerTimeFitnessMetric(models.Model): class C2WorldClassAgePerformance(models.Model): weightcategories = ( - ('hwt','heavy-weight'), - ('lwt','light-weight'), - ) + ('hwt','heavy-weight'), + ('lwt','light-weight'), + ) sexcategories = ( ('male','male'), @@ -334,7 +334,7 @@ class Team(models.Model): name = models.CharField(max_length=150,unique=True,verbose_name='Team Name') notes = models.CharField(blank=True,max_length=200,verbose_name='Team Purpose') - manager = models.ForeignKey(User, null=True,) # validators=[is_not_basic]) + manager = models.ForeignKey(User, null=True,on_delete=models.CASCADE) # validators=[is_not_basic]) private = models.CharField(max_length=30,choices=choices,default='open', verbose_name='Team Type') @@ -366,13 +366,13 @@ class TeamForm(ModelForm): class Meta: model = Team fields = ['name','notes','private','viewing'] - widgets = { - 'notes': forms.Textarea, - } + widgets = { + 'notes': forms.Textarea, + } class TeamInvite(models.Model): - team = models.ForeignKey(Team) - user = models.ForeignKey(User,null=True) + team = models.ForeignKey(Team,on_delete=models.CASCADE) + user = models.ForeignKey(User,null=True,on_delete=models.CASCADE) issuedate = models.DateField(default=current_day) code = models.CharField(max_length=150,unique=True) email = models.CharField(max_length=150,null=True,blank=True) @@ -388,17 +388,17 @@ class TeamInviteForm(ModelForm): class TeamRequest(models.Model): - team = models.ForeignKey(Team) - user = models.ForeignKey(User,null=True) + team = models.ForeignKey(Team,on_delete=models.CASCADE) + user = models.ForeignKey(User,null=True,on_delete=models.CASCADE) issuedate = models.DateField(default=current_day) code = models.CharField(max_length=150,unique=True) -from utils import ( +from rowers.utils import ( workflowleftpanel,workflowmiddlepanel, defaultleft,defaultmiddle,landingpages ) -from utils import geo_distance +from rowers.utils import geo_distance def polygon_coord_center(polygon): @@ -675,7 +675,7 @@ class Rower(models.Model): ('Workout','Workout'), ('Yoga','Yoga'), ) - user = models.OneToOneField(User) + user = models.OneToOneField(User,on_delete=models.CASCADE) #billing details country = CountryField(default=None, null=True, blank=True) @@ -688,7 +688,7 @@ class Rower(models.Model): blank=True,max_length=200) rowerplan = models.CharField(default='basic',max_length=30, - choices=plans) + choices=plans) paymenttype = models.CharField( default='single',max_length=30, verbose_name='Payment Type', @@ -699,7 +699,7 @@ class Rower(models.Model): null=True,blank=True, default='braintree') - paidplan = models.ForeignKey(PaidPlan,null=True,default=None) + paidplan = models.ForeignKey(PaidPlan,null=True,default=None,on_delete=models.SET_NULL) planexpires = models.DateField(default=current_day) teamplanexpires = models.DateField(default=current_day) @@ -726,8 +726,8 @@ class Rower(models.Model): # Weight Category (for sync to C2) weightcategory = models.CharField(default="hwt", - max_length=30, - choices=weightcategories) + max_length=30, + choices=weightcategories) sex = models.CharField(default="not specified", max_length=30, @@ -788,23 +788,23 @@ class Rower(models.Model): sporttrackstoken = models.CharField(default='',max_length=200,blank=True,null=True) sporttrackstokenexpirydate = models.DateTimeField(blank=True,null=True) sporttracksrefreshtoken = models.CharField(default='',max_length=200, - blank=True,null=True) + blank=True,null=True) sporttracks_auto_export = models.BooleanField(default=False) underarmourtoken = models.CharField(default='',max_length=200,blank=True,null=True) underarmourtokenexpirydate = models.DateTimeField(blank=True,null=True) underarmourrefreshtoken = models.CharField(default='',max_length=200, - blank=True,null=True) + blank=True,null=True) mapmyfitness_auto_export = models.BooleanField(default=False) tptoken = models.CharField(default='',max_length=1000,blank=True,null=True) tptokenexpirydate = models.DateTimeField(blank=True,null=True) tprefreshtoken = models.CharField(default='',max_length=1000, - blank=True,null=True) + blank=True,null=True) trainingpeaks_auto_export = models.BooleanField(default=False) polartoken = models.CharField(default='',max_length=1000,blank=True,null=True) polartokenexpirydate = models.DateTimeField(blank=True,null=True) polarrefreshtoken = models.CharField(default='',max_length=1000, - blank=True,null=True) + blank=True,null=True) polaruserid = models.IntegerField(default=0) polar_auto_import = models.BooleanField(default=False) @@ -813,8 +813,8 @@ class Rower(models.Model): stravarefreshtoken = models.CharField(default='',max_length=1000, blank=True,null=True) stravaexportas = models.CharField(default="Rowing", - max_length=30, - choices=stravatypes, + max_length=30, + choices=stravatypes, verbose_name="Export Workouts to Strava as") strava_auto_export = models.BooleanField(default=False) @@ -840,7 +840,7 @@ class Rower(models.Model): # Friends/Team friends = models.ManyToManyField("self",blank=True) - mycoachgroup = models.ForeignKey(CoachingGroup,related_name='coachingrole',null=True) + mycoachgroup = models.ForeignKey(CoachingGroup,related_name='coachingrole',null=True,on_delete=models.SET_NULL) coachinggroups = models.ManyToManyField(CoachingGroup,related_name='coaches') privacy = models.CharField(default='visible',max_length=30, choices=privacychoices) @@ -857,7 +857,7 @@ class Rower(models.Model): verbose_name='Show Notes for Favorite Charts') def __str__(self): - return self.user.first_name+' '+self.user.last_name + return self.user.first_name+' '+self.user.last_name def __unicode__(self): return self.user.first_name+' '+self.user.last_name @@ -881,15 +881,15 @@ class DeleteUserForm(forms.ModelForm): # requestor is user class CoachRequest(models.Model): - coach = models.ForeignKey(Rower) - user = models.ForeignKey(User,null=True) + coach = models.ForeignKey(Rower,on_delete=models.CASCADE) + user = models.ForeignKey(User,null=True,on_delete=models.CASCADE) issuedate = models.DateField(default=current_day) code = models.CharField(max_length=150,unique=True) # requestor is coach class CoachOffer(models.Model): - coach = models.ForeignKey(Rower) - user = models.ForeignKey(User,null=True) + coach = models.ForeignKey(Rower,on_delete=models.CASCADE) + user = models.ForeignKey(User,null=True,on_delete=models.CASCADE) issuedate = models.DateField(default=current_day) code = models.CharField(max_length=150,unique=True) @@ -956,7 +956,7 @@ class FavoriteChart(models.Model): reststrokes = models.BooleanField(default=True,verbose_name="Incl. Rest") notes = models.CharField(max_length=300,verbose_name='Chart Notes', default='Flex Chart Notes',blank=True) - user = models.ForeignKey(Rower) + user = models.ForeignKey(Rower,on_delete=models.CASCADE) class FavoriteForm(ModelForm): @@ -965,8 +965,8 @@ class FavoriteForm(ModelForm): fields = ['xparam','yparam1','yparam2', 'plottype','workouttype','reststrokes','notes'] # widgets = { -# 'notes': forms.Textarea, -# } +# 'notes': forms.Textarea, +# } # To generate favorite chart forms on the fly @@ -1009,7 +1009,7 @@ def checkworkoutuser(user,workout): if user.is_anonymous(): return False try: - r = Rower.objects.get(user=user) + r = Rower.objects.get(user=user) if workout.user == r: return True coaches = [] @@ -1022,14 +1022,14 @@ def checkworkoutuser(user,workout): else: return False except Rower.DoesNotExist: - return False + return False # Check if workout may be viewed by this user def checkworkoutuserview(user,workout): if user.is_anonymous(): return False try: - r = Rower.objects.get(user=user) + r = Rower.objects.get(user=user) if workout.user == r: return True teams = workout.user.team.all() @@ -1039,7 +1039,7 @@ def checkworkoutuserview(user,workout): return True return False except Rower.DoesNotExist: - return False + return False return False @@ -1049,7 +1049,7 @@ def checkviewworkouts(user,rower): if rower == r: return True teams = Team.objects.filter(manager=user) - print Rower.objects.filter(team__in=teams) + print(Rower.objects.filter(team__in=teams)) if rower in Rower.objects.filter(team__in=teams): return True except Rower.DoesNotExist: @@ -1087,7 +1087,7 @@ def checkaccessuser(user,rower): else: return False except Rower.DoesNotExist: - return False + return False timezones = ( (x,x) for x in pytz.common_timezones @@ -1096,7 +1096,7 @@ timezones = ( # models related to geo data (points, polygon, courses) class GeoCourse(models.Model): - manager = models.ForeignKey(Rower) + manager = models.ForeignKey(Rower,null=True,on_delete=models.SET_NULL) distance = models.IntegerField(default=0) name = models.CharField(max_length=150,blank=True) country = models.CharField(max_length=150,blank=True) @@ -1127,7 +1127,7 @@ class GeoCourseEditForm(ModelForm): class GeoPolygon(models.Model): name = models.CharField(max_length=150,blank=True) - course = models.ForeignKey(GeoCourse, blank=True) + course = models.ForeignKey(GeoCourse, blank=True,on_delete=models.CASCADE) order_in_course = models.IntegerField(default=0) def __unicode__(self): @@ -1146,7 +1146,7 @@ class GeoPolygon(models.Model): class GeoPoint(models.Model): latitude = models.FloatField(default=0) longitude = models.FloatField(default=0) - polygon = models.ForeignKey(GeoPolygon,blank=True) + polygon = models.ForeignKey(GeoPolygon,blank=True,on_delete=models.CASCADE) order_in_poly = models.IntegerField(default=0) # need error checking to "insert" new point into existing polygon? This affects order_in_poly @@ -1159,7 +1159,7 @@ class GeoPoint(models.Model): class TrainingTarget(models.Model): rowers = models.ManyToManyField(Rower, related_name='targetathletes', verbose_name='Athletes') - manager = models.ForeignKey(Rower,related_name='targetmanager',null=True) + manager = models.ForeignKey(Rower,related_name='targetmanager',null=True,on_delete=models.CASCADE) name = models.CharField(max_length=150,blank=True) date = models.DateField( default=half_year_from_now) @@ -1191,9 +1191,9 @@ class TrainingTargetForm(ModelForm): model = TrainingTarget fields = ['name','date','notes','rowers'] - widgets = { - 'date': AdminDateWidget() - } + widgets = { + 'date': AdminDateWidget() + } def __init__(self,*args, **kwargs): user = kwargs.pop('user',None) @@ -1227,10 +1227,10 @@ class TrainingPlan(models.Model): rowers = models.ManyToManyField(Rower,related_name='planathletes', verbose_name='Athletes') - manager = models.ForeignKey(Rower,related_name='planmanager',null=True) + manager = models.ForeignKey(Rower,related_name='planmanager',null=True,on_delete=models.SET_NULL) name = models.CharField(max_length=150,blank=True) status = models.BooleanField(default=True,verbose_name='Active') - target = models.ForeignKey(TrainingTarget,blank=True,null=True) + target = models.ForeignKey(TrainingTarget,blank=True,null=True,on_delete=models.SET_NULL) startdate = models.DateField(default=current_day) enddate = models.DateField( default=half_year_from_now) @@ -1310,10 +1310,10 @@ class TrainingPlanForm(ModelForm): model = TrainingPlan fields = ['name','target','startdate','enddate','status','rowers'] - widgets = { - 'startdate': AdminDateWidget(), - 'enddate': AdminDateWidget() - } + widgets = { + 'startdate': AdminDateWidget(), + 'enddate': AdminDateWidget() + } def __init__(self,*args, **kwargs): targets = kwargs.pop('targets',None) @@ -1600,7 +1600,7 @@ def macrocyclecheckdates(plan): cycles = cycles[1:] class TrainingMacroCycle(models.Model): - plan = models.ForeignKey(TrainingPlan) + plan = models.ForeignKey(TrainingPlan,on_delete=models.CASCADE) name = models.CharField(max_length=150,blank=True) startdate = models.DateField(default=current_day) enddate = models.DateField( @@ -1682,13 +1682,13 @@ class TrainingMacroCycleForm(ModelForm): model = TrainingMacroCycle fields = ['name','startdate','enddate','notes'] - widgets = { - 'startdate': AdminDateWidget(), - 'enddate': AdminDateWidget() - } + widgets = { + 'startdate': AdminDateWidget(), + 'enddate': AdminDateWidget() + } class TrainingMesoCycle(models.Model): - plan = models.ForeignKey(TrainingMacroCycle) + plan = models.ForeignKey(TrainingMacroCycle,on_delete=models.CASCADE) name = models.CharField(max_length=150,blank=True) startdate = models.DateField(default=current_day) enddate = models.DateField( @@ -1764,7 +1764,7 @@ class TrainingMesoCycle(models.Model): class TrainingMicroCycle(models.Model): - plan = models.ForeignKey(TrainingMesoCycle) + plan = models.ForeignKey(TrainingMesoCycle,on_delete=models.CASCADE) name = models.CharField(max_length=150,blank=True) startdate = models.DateField(default=current_day) enddate = models.DateField( @@ -1834,20 +1834,20 @@ class TrainingMesoCycleForm(ModelForm): model = TrainingMesoCycle fields = ['name','startdate','enddate','notes'] - widgets = { - 'startdate': AdminDateWidget(), - 'enddate': AdminDateWidget() - } + widgets = { + 'startdate': AdminDateWidget(), + 'enddate': AdminDateWidget() + } class TrainingMicroCycleForm(ModelForm): class Meta: model = TrainingMicroCycle fields = ['name','startdate','enddate','notes'] - widgets = { - 'startdate': AdminDateWidget(), - 'enddate': AdminDateWidget() - } + widgets = { + 'startdate': AdminDateWidget(), + 'enddate': AdminDateWidget() + } regularsessiontypechoices = ( ('session','Training Session'), @@ -1903,9 +1903,9 @@ class PlannedSession(models.Model): ('None',None), ) - manager = models.ForeignKey(User) + manager = models.ForeignKey(User,on_delete=models.PROTECT) course = models.ForeignKey(GeoCourse,blank=True,null=True, - verbose_name='OTW Course') + verbose_name='OTW Course',on_delete=models.SET_NULL) name = models.CharField(max_length=150,blank=True, verbose_name='Name') @@ -1972,7 +1972,7 @@ class PlannedSession(models.Model): n = name, ) - return stri + return stri def save(self, *args, **kwargs): if self.sessionvalue <= 0: @@ -2075,7 +2075,7 @@ class VirtualRace(PlannedSession): n = name, ) - return stri + return stri def save(self, *args, **kwargs): @@ -2111,7 +2111,7 @@ class VirtualRace(PlannedSession): class RaceLogo(models.Model): filename = models.CharField(default='',max_length=150) creationdatetime = models.DateTimeField() - user = models.ForeignKey(User) + user = models.ForeignKey(User,on_delete=models.PROTECT) width = models.IntegerField(default=1200) height = models.IntegerField(default=600) race = models.ManyToManyField(VirtualRace,related_name='logos') @@ -2121,7 +2121,7 @@ class RaceLogo(models.Model): def delete(self, *args, **kwargs): os.remove(self.filename) - print 'file deleted' + print('file deleted') super(RaceLogo,self).delete(*args, **kwargs) # Date input utility @@ -2150,12 +2150,12 @@ class PlannedSessionForm(ModelForm): 'autoclose': True, } - widgets = { - 'comment': forms.Textarea, - 'startdate': AdminDateWidget(), - 'enddate': AdminDateWidget(), - 'preferreddate': AdminDateWidget(), - } + widgets = { + 'comment': forms.Textarea, + 'startdate': AdminDateWidget(), + 'enddate': AdminDateWidget(), + 'preferreddate': AdminDateWidget(), + } def __init__(self,*args,**kwargs): super(PlannedSessionForm, self).__init__(*args, **kwargs) @@ -2350,15 +2350,15 @@ class VirtualRaceForm(ModelForm): 'autoclose': True, } - widgets = { - 'comment': forms.Textarea, - 'startdate': AdminDateWidget(), - 'enddate': AdminDateWidget(), + widgets = { + 'comment': forms.Textarea, + 'startdate': AdminDateWidget(), + 'enddate': AdminDateWidget(), 'start_time': AdminTimeWidget(), 'end_time': AdminTimeWidget(), 'registration_closure':AdminSplitDateTime(), 'evaluation_closure':AdminSplitDateTime(), - } + } def __init__(self,*args,**kwargs): super(VirtualRaceForm, self).__init__(*args, **kwargs) @@ -2469,10 +2469,10 @@ class PlannedSessionFormSmall(ModelForm): 'autoclose': True, } - widgets = { - 'startdate': DateInput(attrs={'size':10}), - 'enddate': DateInput(attrs={'size':10}), - 'preferreddate': DateInput(attrs={'size':10}), + widgets = { + 'startdate': DateInput(attrs={'size':10}), + 'enddate': DateInput(attrs={'size':10}), + 'preferreddate': DateInput(attrs={'size':10}), 'name': forms.TextInput(attrs={'size':10}), 'sessionvalue': forms.TextInput(attrs={'style':'width:5em', 'type':'number'}), @@ -2492,10 +2492,10 @@ class Workout(models.Model): privacychoices = mytypes.privacychoices adaptivetypes = mytypes.adaptivetypes - user = models.ForeignKey(Rower) + user = models.ForeignKey(Rower,on_delete=models.CASCADE) team = models.ManyToManyField(Team,blank=True) plannedsession = models.ForeignKey(PlannedSession, blank=True,null=True, - verbose_name='Session') + verbose_name='Session',on_delete=models.SET_NULL) name = models.CharField(max_length=150,blank=True,null=True) date = models.DateField() workouttype = models.CharField(choices=workouttypes,max_length=50, @@ -2503,8 +2503,8 @@ class Workout(models.Model): workoutsource = models.CharField(max_length=100, default='unknown') boattype = models.CharField(choices=boattypes,max_length=50, - default='1x', - verbose_name = 'Boat Type') + default='1x', + verbose_name = 'Boat Type') adaptiveclass = models.CharField(choices=adaptivetypes,max_length=50, default='None', verbose_name='Adaptive Classification') @@ -2557,8 +2557,8 @@ class Workout(models.Model): def __unicode__(self): - date = self.date - name = self.name + date = self.date + name = self.name distance = str(self.distance) ownerfirst = self.user.user.first_name ownerlast = self.user.user.last_name @@ -2588,7 +2588,7 @@ class Workout(models.Model): ownerlast = ownerlast, ) - return stri + return stri # delete files belonging to workout instance # related GraphImage objects should be deleted automatically @@ -2596,11 +2596,11 @@ class Workout(models.Model): def auto_delete_file_on_delete(sender, instance, **kwargs): # delete CSV file if instance.csvfilename: - if os.path.isfile(instance.csvfilename): - os.remove(instance.csvfilename) + if os.path.isfile(instance.csvfilename): + os.remove(instance.csvfilename) if instance.csvfilename+'.gz': - if os.path.isfile(instance.csvfilename+'.gz'): - os.remove(instance.csvfilename+'.gz') + if os.path.isfile(instance.csvfilename+'.gz'): + os.remove(instance.csvfilename+'.gz') @receiver(models.signals.post_delete,sender=Workout) def update_duplicates_on_delete(sender, instance, **kwargs): @@ -2649,7 +2649,7 @@ def auto_delete_strokedata_on_delete(sender, instance, **kwargs): try: result = conn.execute(query) except: - print "Database Locked" + print("Database Locked") conn.close() engine.dispose() @@ -2667,7 +2667,7 @@ class VirtualRaceResult(models.Model): adaptiveclass = models.CharField(default="None",max_length=50, choices=mytypes.adaptivetypes, verbose_name="Adaptive Class") - race = models.ForeignKey(VirtualRace) + race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE) duration = models.TimeField(default=datetime.time(1,0)) distance = models.IntegerField(default=0) boatclass = models.CharField(choices=boatclasses, @@ -2726,7 +2726,7 @@ class IndoorVirtualRaceResult(models.Model): adaptiveclass = models.CharField(default="None",max_length=50, choices=mytypes.adaptivetypes, verbose_name="Adaptive Class") - race = models.ForeignKey(VirtualRace) + race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE) duration = models.TimeField(default=datetime.time(1,0)) distance = models.IntegerField(default=0) boatclass = models.CharField(choices=boatclasses, @@ -2769,15 +2769,15 @@ class IndoorVirtualRaceResult(models.Model): class CourseTestResult(models.Model): userid = models.IntegerField(default=0) workoutid = models.IntegerField(null=True) - plannedsession = models.ForeignKey(PlannedSession) + plannedsession = models.ForeignKey(PlannedSession,on_delete=models.CASCADE) duration = models.TimeField(default=datetime.time(1,0)) distance = models.IntegerField(default=0) coursecompleted = models.BooleanField(default=False) class IndoorVirtualRaceResultForm(ModelForm): class Meta: - model = IndoorVirtualRaceResult - fields = ['teamname','weightcategory','boatclass','age','adaptiveclass'] + model = IndoorVirtualRaceResult + fields = ['teamname','weightcategory','boatclass','age','adaptiveclass'] def __init__(self, *args, **kwargs): @@ -2786,8 +2786,8 @@ class IndoorVirtualRaceResultForm(ModelForm): class VirtualRaceResultForm(ModelForm): class Meta: - model = VirtualRaceResult - fields = ['teamname','weightcategory','boatclass','boattype', + model = VirtualRaceResult + fields = ['teamname','weightcategory','boatclass','boattype', 'age','adaptiveclass'] @@ -2903,32 +2903,32 @@ class ergcpdata(models.Model): class GraphImage(models.Model): filename = models.CharField(default='',max_length=150,blank=True,null=True) creationdatetime = models.DateTimeField() - workout = models.ForeignKey(Workout) + workout = models.ForeignKey(Workout,on_delete=models.CASCADE) width = models.IntegerField(default=1200) height = models.IntegerField(default=600) def __str__(self): - return self.filename + return self.filename # delete related file object when image is deleted @receiver(models.signals.post_delete,sender=GraphImage) def auto_delete_image_on_delete(sender,instance, **kwargs): if instance.filename: - if os.path.isfile(instance.filename): + if os.path.isfile(instance.filename): others = GraphImage.objects.filter(filename=instance.filename) if len(others) == 0: - os.remove(instance.filename) - else: - print "couldn't find the file "+instance.filename + os.remove(instance.filename) + else: + print("couldn't find the file "+instance.filename) # Form to update Workout data class WorkoutForm(ModelForm): # duration = forms.TimeInput(format='%H:%M:%S.%f') class Meta: - model = Workout - fields = ['name', + model = Workout + fields = ['name', 'date', 'starttime', 'timezone', @@ -2942,11 +2942,11 @@ class WorkoutForm(ModelForm): 'rankingpiece', 'duplicate', 'plannedsession'] - widgets = { - 'date': AdminDateWidget(), - 'notes': forms.Textarea, - 'duration': forms.TimeInput(format='%H:%M:%S.%f'), - } + widgets = { + 'date': AdminDateWidget(), + 'notes': forms.Textarea, + 'duration': forms.TimeInput(format='%H:%M:%S.%f'), + } def __init__(self, *args, **kwargs): super(WorkoutForm, self).__init__(*args, **kwargs) @@ -2984,8 +2984,8 @@ class AdvancedWorkoutForm(ModelForm): quick_calc = forms.BooleanField(initial=True,required=False) class Meta: - model = Workout - fields = ['boattype','weightvalue','quick_calc'] + model = Workout + fields = ['boattype','weightvalue','quick_calc'] class RowerExportForm(ModelForm): class Meta: @@ -3006,8 +3006,8 @@ class RowerExportForm(ModelForm): # Simple form to set rower's Functional Threshold Power class RowerPowerForm(ModelForm): class Meta: - model = Rower - fields = ['hrftp','ftp','otwslack'] + model = Rower + fields = ['hrftp','ftp','otwslack'] # Form to set rower's Power zones, including test routines # to enable consistency @@ -3209,8 +3209,8 @@ class AccountRowerForm(ModelForm): 'defaultlandingpage', 'offercoaching'] - widgets = { - 'birthdate': SelectDateWidget( + widgets = { + 'birthdate': SelectDateWidget( years=range( timezone.now().year-100,timezone.now().year-10)), } @@ -3259,165 +3259,165 @@ class UserForm(ModelForm): # to enable consistency class RowerForm(ModelForm): class Meta: - model = Rower - fields = ['rest','ut2','ut1','at','tr','an','max'] + model = Rower + fields = ['rest','ut2','ut1','at','tr','an','max'] def clean_rest(self): - rest = self.cleaned_data['rest'] + rest = self.cleaned_data['rest'] - if rest<10: - self.data['rest']=10 - raise forms.ValidationError("Resting heart rate should be higher than 10 bpm") - + if rest<10: + self.data['rest']=10 + raise forms.ValidationError("Resting heart rate should be higher than 10 bpm") + - if rest>250: - self.data['rest'] = 250 - raise forms.ValidationError("Resting heart rate should be lower than 250 bpm") + if rest>250: + self.data['rest'] = 250 + raise forms.ValidationError("Resting heart rate should be lower than 250 bpm") - return rest + return rest def clean_ut2(self): - ut2 = self.cleaned_data['ut2'] + ut2 = self.cleaned_data['ut2'] - if ut2<10: - raise forms.ValidationError("UT2 heart rate should be higher than 10 bpm") + if ut2<10: + raise forms.ValidationError("UT2 heart rate should be higher than 10 bpm") - if ut2>250: - raise forms.ValidationError("UT2 heart rate should be lower than 250 bpm") + if ut2>250: + raise forms.ValidationError("UT2 heart rate should be lower than 250 bpm") - return ut2 + return ut2 def clean_ut1(self): - ut1 = self.cleaned_data['ut1'] + ut1 = self.cleaned_data['ut1'] - if ut1<10: - raise forms.ValidationError("UT1 heart rate should be higher than 10 bpm") + if ut1<10: + raise forms.ValidationError("UT1 heart rate should be higher than 10 bpm") - if ut1>250: - raise forms.ValidationError("Resting heart rate should be lower than 250 bpm") + if ut1>250: + raise forms.ValidationError("Resting heart rate should be lower than 250 bpm") - return ut1 + return ut1 def clean_at(self): - at = self.cleaned_data['at'] + at = self.cleaned_data['at'] - if at<10: - raise forms.ValidationError("AT heart rate should be higher than 10 bpm") + if at<10: + raise forms.ValidationError("AT heart rate should be higher than 10 bpm") - if at>250: - raise forms.ValidationError("AT heart rate should be lower than 250 bpm") + if at>250: + raise forms.ValidationError("AT heart rate should be lower than 250 bpm") - return at + return at def clean_tr(self): - tr = self.cleaned_data['tr'] + tr = self.cleaned_data['tr'] - if tr<10: - raise forms.ValidationError("TR heart rate should be higher than 10 bpm") + if tr<10: + raise forms.ValidationError("TR heart rate should be higher than 10 bpm") - if tr>250: - raise forms.ValidationError("TR heart rate should be lower than 250 bpm") + if tr>250: + raise forms.ValidationError("TR heart rate should be lower than 250 bpm") - return tr + return tr def clean_an(self): - an = self.cleaned_data['an'] + an = self.cleaned_data['an'] - if an<10: - raise forms.ValidationError("AN heart rate should be higher than 10 bpm") + if an<10: + raise forms.ValidationError("AN heart rate should be higher than 10 bpm") - if an>250: - raise forms.ValidationError("AN heart rate should be lower than 250 bpm") + if an>250: + raise forms.ValidationError("AN heart rate should be lower than 250 bpm") - return an + return an def clean_max(self): - max = self.cleaned_data['max'] + max = self.cleaned_data['max'] - if max<10: - raise forms.ValidationError("Max heart rate should be higher than 10 bpm") + if max<10: + raise forms.ValidationError("Max heart rate should be higher than 10 bpm") - if max>250: - raise forms.ValidationError("Max heart rate should be lower than 250 bpm") + if max>250: + raise forms.ValidationError("Max heart rate should be lower than 250 bpm") - return max + return max def clean(self): - - try: - rest = self.cleaned_data['rest'] - except: + + try: + rest = self.cleaned_data['rest'] + except: try: - rest = int(self.data['rest']) + rest = int(self.data['rest']) except ValueError: rest = 0 - try: - ut2 = self.cleaned_data['ut2'] - except: + try: + ut2 = self.cleaned_data['ut2'] + except: try: - ut2 = self.data['ut2'] + ut2 = self.data['ut2'] except ValueError: ut2 = 0 - try: - ut1 = self.cleaned_data['ut1'] - except: + try: + ut1 = self.cleaned_data['ut1'] + except: try: - ut1 = self.data['ut1'] + ut1 = self.data['ut1'] except ValueError: ut1 = 0 - try: - at = self.cleaned_data['at'] - except: + try: + at = self.cleaned_data['at'] + except: try: - at = self.data['at'] + at = self.data['at'] except ValueError: at = 0 - try: - an = self.cleaned_data['an'] - except: + try: + an = self.cleaned_data['an'] + except: try: - an = self.data['an'] + an = self.data['an'] except ValueError: an = 0 - try: - tr = self.cleaned_data['tr'] - except: + try: + tr = self.cleaned_data['tr'] + except: try: - tr = self.data['tr'] + tr = self.data['tr'] except ValueError: tr = 0 - try: - max = self.cleaned_data['max'] - except: + try: + max = self.cleaned_data['max'] + except: try: - max = self.data['max'] + max = self.data['max'] except ValueError: max = 0 - - if rest>=ut2: - raise forms.ValidationError("Resting heart rate should be lower than UT2") - if ut2>=ut1: - raise forms.ValidationError("UT2 should be lower than UT1") - if ut2>=ut1: - raise forms.ValidationError("UT2 should be lower than UT1") - if ut1>=at: - raise forms.ValidationError("UT1 should be lower than AT") - if at>=tr: - raise forms.ValidationError("AT should be lower than TR") - if tr>=an: - raise forms.ValidationError("TR should be lower than AN") - if an>=max: - raise forms.ValidationError("AN should be lower than Max") + + if rest>=ut2: + raise forms.ValidationError("Resting heart rate should be lower than UT2") + if ut2>=ut1: + raise forms.ValidationError("UT2 should be lower than UT1") + if ut2>=ut1: + raise forms.ValidationError("UT2 should be lower than UT1") + if ut1>=at: + raise forms.ValidationError("UT1 should be lower than AT") + if at>=tr: + raise forms.ValidationError("AT should be lower than TR") + if tr>=an: + raise forms.ValidationError("TR should be lower than AN") + if an>=max: + raise forms.ValidationError("AN should be lower than Max") # An announcement that goes to the right of the workouts list @@ -3450,8 +3450,8 @@ class WorkoutComment(models.Model): created = models.DateTimeField(default=timezone.now) read = models.BooleanField(default=False) notification = models.BooleanField(default=True,verbose_name="Subscribe to new comment notifications") - user = models.ForeignKey(User) - workout = models.ForeignKey(Workout) + user = models.ForeignKey(User,on_delete=models.PROTECT) + workout = models.ForeignKey(Workout,on_delete=models.CASCADE) def __unicode__(self): return u'Comment to: {w} by {u1} {u2}'.format( @@ -3465,9 +3465,9 @@ class WorkoutCommentForm(ModelForm): class Meta: model = WorkoutComment fields = ['comment','notification'] - widgets = { - 'comment': forms.Textarea, - } + widgets = { + 'comment': forms.Textarea, + } # A comment by a user on a training class PlannedSessionComment(models.Model): @@ -3475,8 +3475,8 @@ class PlannedSessionComment(models.Model): created = models.DateTimeField(default=timezone.now) read = models.BooleanField(default=False) notification = models.BooleanField(default=True,verbose_name="Subscribe to new comment notifications") - user = models.ForeignKey(User) - plannedsession = models.ForeignKey(PlannedSession) + user = models.ForeignKey(User,on_delete=models.PROTECT) + plannedsession = models.ForeignKey(PlannedSession,on_delete=models.CASCADE) def __unicode__(self): return u'Comment to: {w} by {u1} {u2}'.format( @@ -3490,8 +3490,8 @@ class PlannedSessionCommentForm(ModelForm): class Meta: model = PlannedSessionComment fields = ['comment','notification'] - widgets = { - 'comment': forms.Textarea, - } + widgets = { + 'comment': forms.Textarea, + } diff --git a/rowers/mytypes.py b/rowers/mytypes.py index 662481a9..3eb903d2 100644 --- a/rowers/mytypes.py +++ b/rowers/mytypes.py @@ -1,3 +1,5 @@ +from six import iteritems + workouttypes = ( ('water','Standard Racing Shell'), ('rower','Indoor Rower'), @@ -208,15 +210,15 @@ c2mapping = { } -c2mappinginv = {value:key for key,value in c2mapping.iteritems() if value is not None} +c2mappinginv = {value:key for key,value in iteritems(c2mapping) if value is not None} -stravamappinginv = {value:key for key,value in stravamapping.iteritems() if value is not None} +stravamappinginv = {value:key for key,value in iteritems(stravamapping) if value is not None} -stmappinginv = {value:key for key,value in stmapping.iteritems() if value is not None} +stmappinginv = {value:key for key,value in iteritems(stmapping) if value is not None} -rkmappinginv = {value:key for key,value in rkmapping.iteritems() if value is not None} +rkmappinginv = {value:key for key,value in iteritems(rkmapping) if value is not None} -polarmappinginv = {value:key for key,value in polarmapping.iteritems() if value is not None} +polarmappinginv = {value:key for key,value in iteritems(polarmapping) if value is not None} otwtypes = ( 'water', diff --git a/rowers/ownapistuff.py b/rowers/ownapistuff.py index 8f5ec305..2164b2cb 100644 --- a/rowers/ownapistuff.py +++ b/rowers/ownapistuff.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # Interactions with Rowsandall.com API. Not fully complete. # Python @@ -15,7 +16,7 @@ import math from math import sin,cos,atan2,sqrt import urllib -import c2stuff +import rowers.c2stuff as c2stuff # Django from django.shortcuts import render_to_response @@ -41,13 +42,13 @@ TEST_REDIRECT_URI = "http://localhost:8000/rowers/test_callback" def custom_exception_handler(exc,message): response = { - "errors": [ - { - "code": str(exc), - "detail": message, - } - ] - } + "errors": [ + { + "code": str(exc), + "detail": message, + } + ] + } res = HttpResponse(message) res.status_code = 401 @@ -58,27 +59,27 @@ def custom_exception_handler(exc,message): def do_refresh_token(refreshtoken): client_auth = requests.auth.HTTPBasicAuth(TEST_CLIENT_ID, TEST_CLIENT_SECRET) post_data = {"grant_type": "refresh_token", - "client_secret": TEST_CLIENT_SECRET, - "client_id":TEST_CLIENT_ID, - "refresh_token": refreshtoken, - } + "client_secret": TEST_CLIENT_SECRET, + "client_id":TEST_CLIENT_ID, + "refresh_token": refreshtoken, + } headers = {'user-agent': 'sanderroosendaal', - 'Accept': 'application/json', - 'Content-Type': 'application/json'} + 'Accept': 'application/json', + 'Content-Type': 'application/json'} url = "http://localhost:8000/rowers/o/token" response = requests.post(url, data=json.dumps(post_data), - headers=headers) + headers=headers) token_json = response.json() thetoken = token_json['access_token'] expires_in = token_json['expires_in'] try: - refresh_token = token_json['refresh_token'] + refresh_token = token_json['refresh_token'] except KeyError: - refresh_token = refreshtoken + refresh_token = refreshtoken return [thetoken,expires_in,refresh_token] @@ -88,18 +89,18 @@ def get_token(code): post_data = {"grant_type": "authorization_code", "code": code, "redirect_uri": "http://localhost:8000/rowers/test_callback", - "client_secret": "aapnootmies", - "client_id":1, - } + "client_secret": "aapnootmies", + "client_id":1, + } headers = {'Accept': 'application/json', - 'Content-Type': 'application/json'} + 'Content-Type': 'application/json'} url = "http://localhost:8000/rowers/o/token/" response = requests.post(url, data=json.dumps(post_data), - headers=headers) + headers=headers) token_json = response.json() thetoken = token_json['access_token'] @@ -118,8 +119,8 @@ def make_authorization_url(request): params = {"client_id": TEST_CLIENT_ID, "response_type": "code", "redirect_uri": TEST_REDIRECT_URI, - "scope":"write", - "state":state} + "scope":"write", + "state":state} import urllib @@ -147,19 +148,19 @@ def rower_ownapi_token_refresh(user): def get_ownapi_workout_list(user): r = Rower.objects.get(user=user) if (r.ownapitoken == '') or (r.ownapitoken is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) elif (timezone.now()>r.ownapitokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.ownapitoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.ownapi.mobi/api/v2/fitnessActivities" - s = requests.get(url,headers=headers) + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.ownapitoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://api.ownapi.mobi/api/v2/fitnessActivities" + s = requests.get(url,headers=headers) return s @@ -167,19 +168,19 @@ def get_ownapi_workout_list(user): def get_ownapi_workout(user,ownapiid): r = Rower.objects.get(user=user) if (r.ownapitoken == '') or (r.ownapitoken is None): - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" elif (timezone.now()>r.ownapitokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.ownapitoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.ownapi.mobi/api/v2/fitnessActivities/"+str(ownapiid) - s = requests.get(url,headers=headers) + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.ownapitoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://api.ownapi.mobi/api/v2/fitnessActivities/"+str(ownapiid) + s = requests.get(url,headers=headers) return s @@ -203,16 +204,16 @@ def createownapiworkoutdata(w): haslatlon=1 try: - lat = row.df[' latitude'].values - lon = row.df[' longitude'].values + lat = row.df[' latitude'].values + lon = row.df[' longitude'].values except KeyError: - haslatlon = 0 + haslatlon = 0 haspower = 1 try: - power = row.df[' Power (watts)'].values + power = row.df[' Power (watts)'].values except KeyError: - haspower = 0 + haspower = 0 locdata = [] hrdata = [] @@ -221,54 +222,54 @@ def createownapiworkoutdata(w): powerdata = [] for i in range(len(t)): - hrdata.append(t[i]) - hrdata.append(hr[i]) - distancedata.append(t[i]) - distancedata.append(d[i]) - spmdata.append(t[i]) - spmdata.append(spm[i]) - if haslatlon: - locdata.append(t[i]) - locdata.append([lat[i],lon[i]]) - if haspower: - powerdata.append(t[i]) - powerdata.append(power[i]) + hrdata.append(t[i]) + hrdata.append(hr[i]) + distancedata.append(t[i]) + distancedata.append(d[i]) + spmdata.append(t[i]) + spmdata.append(spm[i]) + if haslatlon: + locdata.append(t[i]) + locdata.append([lat[i],lon[i]]) + if haspower: + powerdata.append(t[i]) + powerdata.append(power[i]) if haslatlon: - data = { - "type": "Rowing", - "name": w.name, -# "start_time": str(w.date)+"T"+str(w.starttime)+"Z", - "start_time": w.startdatetime.isoformat(), - "total_distance": int(w.distance), - "duration": int(max(t)), - "notes": w.notes, - "avg_heartrate": averagehr, - "max_heartrate": maxhr, - "location": locdata, - "distance": distancedata, - "cadence": spmdata, - "heartrate": hrdata, - } + data = { + "type": "Rowing", + "name": w.name, +# "start_time": str(w.date)+"T"+str(w.starttime)+"Z", + "start_time": w.startdatetime.isoformat(), + "total_distance": int(w.distance), + "duration": int(max(t)), + "notes": w.notes, + "avg_heartrate": averagehr, + "max_heartrate": maxhr, + "location": locdata, + "distance": distancedata, + "cadence": spmdata, + "heartrate": hrdata, + } else: - data = { - "type": "Rowing", - "name": w.name, -# "start_time": str(w.date)+"T"+str(w.starttime)+"Z", - "start_time": w.startdatetime.isoformat(), - "total_distance": int(w.distance), - "duration": int(max(t)), - "notes": w.notes, - "avg_heartrate": averagehr, - "max_heartrate": maxhr, - "distance": distancedata, - "cadence": spmdata, - "heartrate": hrdata, - } + data = { + "type": "Rowing", + "name": w.name, +# "start_time": str(w.date)+"T"+str(w.starttime)+"Z", + "start_time": w.startdatetime.isoformat(), + "total_distance": int(w.distance), + "duration": int(max(t)), + "notes": w.notes, + "avg_heartrate": averagehr, + "max_heartrate": maxhr, + "distance": distancedata, + "cadence": spmdata, + "heartrate": hrdata, + } if haspower: - data['power'] = powerdata + data['power'] = powerdata return data diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index c8a2e2a8..76ffccd6 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # Python from django.utils import timezone from datetime import datetime @@ -10,7 +11,7 @@ import uuid from django.conf import settings import pytz from dateutil import parser -from utils import myqueue,calculate_age,totaltime_sec_to_string +from rowers.utils import myqueue,calculate_age,totaltime_sec_to_string import re import django_rq queue = django_rq.get_queue('default') @@ -30,10 +31,10 @@ from rowers.emails import htmlstrip,htmlstripnobr import rowers.mytypes as mytypes -import metrics +import rowers.metrics as metrics import numpy as np -import dataprep -import courses +import rowers.dataprep as dataprep +import rowers.courses as courses import iso8601 from iso8601 import ParseError from rowers.tasks import handle_check_race_course diff --git a/rowers/plots.py b/rowers/plots.py index 7760346c..bdd216c1 100644 --- a/rowers/plots.py +++ b/rowers/plots.py @@ -2,14 +2,14 @@ from matplotlib.ticker import MultipleLocator,FuncFormatter,NullFormatter import matplotlib.pyplot as plt import numpy as np -from rows import format_pace_tick, format_pace, format_time, format_time_tick +from rowers.rows import format_pace_tick, format_pace, format_time, format_time_tick # Formatting the distance tick marks #def format_dist_tick(x,pos=None): -# km = x/1000. -# template='%6.3f' -# return template % (km) +# km = x/1000. +# template='%6.3f' +# return template % (km) # Utility to select reasonable y axis range @@ -32,23 +32,23 @@ def y_axis_range(ydata,miny=0,padding=.1,ultimate=[-1e9,1e9]): if (yrange == 0): - if ymin == 0: - yrangemin = -padding - else: - yrangemin = ymin-ymin*padding - if ymax == 0: - yrangemax = padding - else: - yrangemax = ymax+ymax*padding + if ymin == 0: + yrangemin = -padding + else: + yrangemin = ymin-ymin*padding + if ymax == 0: + yrangemax = padding + else: + yrangemax = ymax+ymax*padding else: - yrangemin = ymin-padding*yrange - yrangemax = ymax+padding*yrange + yrangemin = ymin-padding*yrange + yrangemax = ymax+padding*yrange if (yrangemin < ultimate[0]): - yrangemin = ultimate[0] + yrangemin = ultimate[0] if (yrangemax > ultimate[1]): - yrangemax = ultimate[1] + yrangemax = ultimate[1] @@ -70,7 +70,7 @@ def mkplot(row,title): ax1.set_ylabel('(sec/500)') yrange = y_axis_range(df.loc[:,' Stroke500mPace (sec/500m)'], - ultimate = [85,190]) + ultimate = [85,190]) plt.axis([0,end_time,yrange[1],yrange[0]]) ax1.set_xticks(range(1000,end_time,1000)) @@ -80,11 +80,11 @@ def mkplot(row,title): majorFormatter = FuncFormatter(format_pace_tick) majorLocator = (5) timeTickFormatter = NullFormatter() - + ax1.yaxis.set_major_formatter(majorFormatter) for tl in ax1.get_yticklabels(): - tl.set_color('b') + tl.set_color('b') ax2 = ax1.twinx() ax2.plot(t,hr,'r-') @@ -94,7 +94,7 @@ def mkplot(row,title): ax2.xaxis.set_major_formatter(majorTimeFormatter) ax2.patch.set_alpha(0.0) for tl in ax2.get_yticklabels(): - tl.set_color('r') + tl.set_color('r') plt.subplots_adjust(hspace=0) diff --git a/rowers/polarstuff.py b/rowers/polarstuff.py index 83c1b6d1..3793fa28 100644 --- a/rowers/polarstuff.py +++ b/rowers/polarstuff.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # All the functionality needed to connect to Strava # Python @@ -33,8 +34,8 @@ from rowingdata import rowingdata import pandas as pd from rowers.models import Rower,Workout from rowers.models import checkworkoutuser -import dataprep -from dataprep import columndict +import rowers.dataprep as dataprep +from rowers.dataprep import columndict from io import StringIO @@ -51,8 +52,8 @@ from rowsandall_app.settings import ( baseurl = 'https://polaraccesslink.com/v3' -from utils import NoTokenError, custom_exception_handler -import mytypes +from rowers.utils import NoTokenError, custom_exception_handler +import rowers.mytypes as mytypes # Exchange access code for long-lived access token def get_token(code): @@ -126,7 +127,7 @@ from rowers.utils import isprorower def get_all_new_workouts(available_data,testing=False): for record in available_data: if testing: - print record + print(record) if record['data-type'] == 'EXERCISE': try: r = Rower.objects.get(polaruserid=record['user-id']) @@ -134,7 +135,7 @@ def get_all_new_workouts(available_data,testing=False): if r.polar_auto_import and isprorower(r): exercise_list = get_polar_workouts(u) if testing: - print exercise_list + print(exercise_list) except Rower.DoesNotExist: pass @@ -313,8 +314,6 @@ def get_polar_workout(user,id,transactionid): response = requests.get(url,headers = headers2) if response.status_code == 200: - print response.text - result = response.text # commit transaction response = requests.put(url,headers=headers) diff --git a/rowers/rows.py b/rowers/rows.py index 642b0593..faba7aee 100644 --- a/rowers/rows.py +++ b/rowers/rows.py @@ -6,29 +6,29 @@ from django.core.exceptions import ValidationError def format_pace_tick(x,pos=None): minu=int(x/60) - sec=int(x-minu*60.) - sec_str=str(sec).zfill(2) - template='%d:%s' - return template % (minu,sec_str) + sec=int(x-minu*60.) + sec_str=str(sec).zfill(2) + template='%d:%s' + return template % (minu,sec_str) def format_time_tick(x,pos=None): - hour=int(x/3600) - min=int((x-hour*3600.)/60) - min_str=str(min).zfill(2) - template='%d:%s' - return template % (hour,min_str) + hour=int(x/3600) + min=int((x-hour*3600.)/60) + min_str=str(min).zfill(2) + template='%d:%s' + return template % (hour,min_str) def format_pace(x,pos=None): if isinf(x) or isnan(x): - x=0 - + x=0 + min=int(x/60) sec=(x-min*60.) str1 = "{min:0>2}:{sec:0>4.1f}".format( - min = min, - sec = sec - ) + min = min, + sec = sec + ) return str1 @@ -39,9 +39,9 @@ def format_time(x,pos=None): sec = int(x-min*60) str1 = "{min:0>2}:{sec:0>4.1f}".format( - min=min, - sec=sec, - ) + min=min, + sec=sec, + ) return str1 @@ -67,14 +67,14 @@ def must_be_csv(value): ext = os.path.splitext(value.name)[1] valid_extensions = ['.csv','.CSV'] if not ext in valid_extensions: - raise ValidationError(u'File not supported!') + raise ValidationError(u'File not supported!') def validate_kml(value): import os ext = os.path.splitext(value.name)[1] valid_extensions = ['.kml','.KML'] if not ext in valid_extensions: - raise ValidationError(u'File not supported!') + raise ValidationError(u'File not supported!') def handle_uploaded_image(i): @@ -83,7 +83,7 @@ def handle_uploaded_image(i): import os from django.core.files import File image_str = "" - for chunk in i.chunks(): + for chunk in i.chunks(): image_str += chunk imagefile = StringIO.StringIO(image_str) @@ -133,8 +133,8 @@ def handle_uploaded_file(f): fname = timestr+'-'+fname fname2 = 'media/'+fname with open(fname2,'wb+') as destination: - for chunk in f.chunks(): - destination.write(chunk) + for chunk in f.chunks(): + destination.write(chunk) return fname,fname2 diff --git a/rowers/runkeeperstuff.py b/rowers/runkeeperstuff.py index 7bfa2207..83f7060a 100644 --- a/rowers/runkeeperstuff.py +++ b/rowers/runkeeperstuff.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # All the functionality needed to connect to Runkeeper from rowers.imports import * import re @@ -61,16 +62,16 @@ def make_authorization_url(request): def get_runkeeper_workout_list(user): r = Rower.objects.get(user=user) if (r.runkeepertoken == '') or (r.runkeepertoken is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.runkeepertoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.runkeeper.com/fitnessActivities" - s = requests.get(url,headers=headers) + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.runkeepertoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://api.runkeeper.com/fitnessActivities" + s = requests.get(url,headers=headers) return s @@ -78,16 +79,16 @@ def get_runkeeper_workout_list(user): def get_workout(user,runkeeperid): r = Rower.objects.get(user=user) if (r.runkeepertoken == '') or (r.runkeepertoken is None): - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.runkeepertoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.runkeeper.com/fitnessActivities/"+str(runkeeperid) - s = requests.get(url,headers=headers) + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.runkeepertoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://api.runkeeper.com/fitnessActivities/"+str(runkeeperid) + s = requests.get(url,headers=headers) try: data = s.json() @@ -131,12 +132,12 @@ def createrunkeeperworkoutdata(w): haslatlon=1 try: - lat = row.df[' latitude'].values - lon = row.df[' longitude'].values + lat = row.df[' latitude'].values + lon = row.df[' longitude'].values if not lat.std() and not lon.std(): haslatlon = 0 except KeyError: - haslatlon = 0 + haslatlon = 0 # path data if haslatlon: @@ -172,32 +173,32 @@ def createrunkeeperworkoutdata(w): newnotes = 'from '+w.workoutsource+' via rowsandall.com' if haslatlon: - data = { - "type": "Rowing", - "start_time": start_time, - "total_distance": int(w.distance), - "duration": duration, - "notes": newnotes, - "average_heart_rate": averagehr, - "path": locdata, - "distance": distancedata, - "heart_rate": hrdata, + data = { + "type": "Rowing", + "start_time": start_time, + "total_distance": int(w.distance), + "duration": duration, + "notes": newnotes, + "average_heart_rate": averagehr, + "path": locdata, + "distance": distancedata, + "heart_rate": hrdata, "post_to_twitter":"false", "post_to_facebook":"false", - } + } else: - data = { - "type": "Rowing", - "start_time": start_time, - "total_distance": int(w.distance), - "duration": duration, - "notes": newnotes, - "avg_heartrate": averagehr, - "distance": distancedata, - "heart_rate": hrdata, + data = { + "type": "Rowing", + "start_time": start_time, + "total_distance": int(w.distance), + "duration": duration, + "notes": newnotes, + "avg_heartrate": averagehr, + "distance": distancedata, + "heart_rate": hrdata, "post_to_twitter":"false", "post_to_facebook":"false", - } + } return data @@ -215,8 +216,8 @@ def getidfromresponse(response): def geturifromid(access_token,id): authorizationstring = str('Bearer ' + access_token) headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} import urllib url = "https://api.runkeeper.com/fitnessActivities/"+str(id) response = requests.get(url,headers=headers) @@ -238,8 +239,8 @@ def geturifromid(access_token,id): def get_userid(access_token): authorizationstring = str('Bearer ' + access_token) headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} import urllib url = "https://api.runkeeper.com/user" response = requests.get(url,headers=headers) @@ -269,42 +270,42 @@ def workout_runkeeper_upload(user,w): # ready to upload. Hurray if (checkworkoutuser(user,w)): - data = createrunkeeperworkoutdata(w) + data = createrunkeeperworkoutdata(w) if not data: message = "Data error in Runkeeper Upload" rkid = 0 return message, rkid - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json', + authorizationstring = str('Bearer ' + thetoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json', 'Content-Length':'nnn'} - url = "https://api.runkeeper.com/fitnessActivities" - response = requests.post(url,headers=headers,data=json.dumps(data)) + url = "https://api.runkeeper.com/fitnessActivities" + response = requests.post(url,headers=headers,data=json.dumps(data)) - # check for duplicate error first - if (response.status_code == 409 ): - message = "Duplicate error" - w.uploadedtorunkeeper = -1 + # check for duplicate error first + if (response.status_code == 409 ): + message = "Duplicate error" + w.uploadedtorunkeeper = -1 rkid = -1 - w.save() + w.save() return message, rkid - elif (response.status_code == 201 or response.status_code==200): - rkid = getidfromresponse(response) + elif (response.status_code == 201 or response.status_code==200): + rkid = getidfromresponse(response) rkuri = geturifromid(thetoken,rkid) - w.uploadedtorunkeeper = rkid - w.save() + w.uploadedtorunkeeper = rkid + w.save() return 'Successfully synchronized to Runkeeper',rkid - else: - s = response - message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text) + else: + s = response + message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text) rkid = 0 return message, rkid - + else: - message = "You are not authorized to upload this workout" + message = "You are not authorized to upload this workout" rkid = 0 return message, rkid @@ -316,41 +317,41 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper', # To Do - add utcoffset to time workouttype = data['type'] if workouttype not in [x[0] for x in Workout.workouttypes]: - workouttype = 'other' + workouttype = 'other' try: - comments = data['notes'] + comments = data['notes'] except: - comments = '' + comments = '' try: - utcoffset = tz(data['utcoffset']) + utcoffset = tz(data['utcoffset']) except: - utcoffset = 0 + utcoffset = 0 r = Rower.objects.get(user=user) try: - rowdatetime = iso8601.parse_date(data['start_time']) + rowdatetime = iso8601.parse_date(data['start_time']) except iso8601.ParseError: - try: - rowdatetime = datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except ValueError: - try: - rowdatetime = parser.parse(data['start_time']) - #rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except: - rowdatetime = datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + try: + rowdatetime = datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S") + rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + except ValueError: + try: + rowdatetime = parser.parse(data['start_time']) + #rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + except: + rowdatetime = datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") + rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) starttimeunix = arrow.get(rowdatetime).timestamp #starttimeunix = mktime(rowdatetime.utctimetuple()) starttimeunix += utcoffset*3600 - + try: - title = data['name'] + title = data['name'] except: - title = "Imported data" + title = "Imported data" @@ -360,35 +361,35 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper', times_distance = res[0] try: - l = data['path'] + l = data['path'] - res = splitrunkeeperlatlongdata(l,'timestamp','latitude','longitude') - times_location = res[0] - latcoord = res[1] - loncoord = res[2] + res = splitrunkeeperlatlongdata(l,'timestamp','latitude','longitude') + times_location = res[0] + latcoord = res[1] + loncoord = res[2] except: - times_location = times_distance - latcoord = np.zeros(len(times_distance)) - loncoord = np.zeros(len(times_distance)) + times_location = times_distance + latcoord = np.zeros(len(times_distance)) + loncoord = np.zeros(len(times_distance)) if workouttype in types.otwtypes: workouttype = 'rower' - + try: - res = splitrunkeeperdata(data['cadence'],'timestamp','cadence') - times_spm = res[0] - spm = res[1] + res = splitrunkeeperdata(data['cadence'],'timestamp','cadence') + times_spm = res[0] + spm = res[1] except KeyError: - times_spm = times_distance - spm = 0*times_distance + times_spm = times_distance + spm = 0*times_distance try: - res = splitrunkeeperdata(data['heart_rate'],'timestamp','heart_rate') - hr = res[1] - times_hr = res[0] + res = splitrunkeeperdata(data['heart_rate'],'timestamp','heart_rate') + hr = res[1] + times_hr = res[0] except KeyError: - times_hr = times_distance - hr = 0*times_distance + times_hr = times_distance + hr = 0*times_distance # create data series and remove duplicates @@ -417,12 +418,12 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper', # Create dicts and big dataframe d = { - ' Horizontal (meters)': distseries, - ' latitude': latseries, - ' longitude': lonseries, - ' Cadence (stokes/min)': spmseries, - ' HRCur (bpm)' : hrseries, - } + ' Horizontal (meters)': distseries, + ' latitude': latseries, + ' longitude': lonseries, + ' Cadence (stokes/min)': spmseries, + ' HRCur (bpm)' : hrseries, + } @@ -469,7 +470,7 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper', df = df.fillna(0) df.sort_values(by='TimeStamp (sec)',ascending=True) - + timestr = strftime("%Y%m%d-%H%M%S") # csvfilename ='media/Import_'+str(importid)+'.csv' diff --git a/rowers/serializers.py b/rowers/serializers.py index 3ecbdd49..6ecef2a3 100644 --- a/rowers/serializers.py +++ b/rowers/serializers.py @@ -74,20 +74,20 @@ class WorkoutSerializer(serializers.ModelSerializer): t.second) w = Workout(user=r, name=validated_data['name'], - date=validated_data['date'], + date=validated_data['date'], workouttype=validated_data['workouttype'], - duration=validated_data['duration'], + duration=validated_data['duration'], distance=validated_data['distance'], - weightcategory=r.weightcategory, - adaptiveclass=r.adaptiveclass, - starttime=validated_data['starttime'], - csvfilename='', + weightcategory=r.weightcategory, + adaptiveclass=r.adaptiveclass, + starttime=validated_data['starttime'], + csvfilename='', notes=validated_data['notes'], - uploadedtoc2=0, + uploadedtoc2=0, summary=validated_data['summary'], - averagehr=validated_data['averagehr'], + averagehr=validated_data['averagehr'], maxhr=validated_data['maxhr'], - startdatetime=rowdatetime, + startdatetime=rowdatetime, timezone=validated_data['timezone'], forceunit=validated_data['forceunit'], inboard=validated_data['inboard'], @@ -109,16 +109,16 @@ class WorkoutSerializer(serializers.ModelSerializer): instance.name=validated_data['name'] - instance.date=validated_data['date'] + instance.date=validated_data['date'] instance.workouttype=validated_data['workouttype'] - instance.duration=validated_data['duration'] + instance.duration=validated_data['duration'] instance.distance=validated_data['distance'] - instance.starttime=validated_data['starttime'] + instance.starttime=validated_data['starttime'] instance.notes=validated_data['notes'] instance.summary=validated_data['summary'] - instance.averagehr=validated_data['averagehr'] + instance.averagehr=validated_data['averagehr'] instance.maxhr=validated_data['maxhr'] - instance.startdatetime=rowdatetime + instance.startdatetime=rowdatetime instance.timezone=validated_data['timezone'] instance.forceunit=validated_data['forceunit'] instance.inboard=validated_data['inboard'] @@ -140,7 +140,6 @@ class StrokeDataSerializer(serializers.Serializer): """ # do something - print "fake serializer" return 1 diff --git a/rowers/sporttracksstuff.py b/rowers/sporttracksstuff.py index 4cf0e668..191f8e01 100644 --- a/rowers/sporttracksstuff.py +++ b/rowers/sporttracksstuff.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # All the functionality to connect to SportTracks from rowers.imports import * @@ -9,7 +10,7 @@ from rowsandall_app.settings import ( SPORTTRACKS_REDIRECT_URI ) -import mytypes +import rowers.mytypes as mytypes oauth_data = { 'client_id': SPORTTRACKS_CLIENT_ID, @@ -64,19 +65,19 @@ def rower_sporttracks_token_refresh(user): def get_sporttracks_workout_list(user): r = Rower.objects.get(user=user) if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) elif (timezone.now()>r.sporttrackstokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.sporttrackstoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.sporttracks.mobi/api/v2/fitnessActivities" - s = requests.get(url,headers=headers) + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.sporttrackstoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://api.sporttracks.mobi/api/v2/fitnessActivities" + s = requests.get(url,headers=headers) return s @@ -84,19 +85,19 @@ def get_sporttracks_workout_list(user): def get_workout(user,sporttracksid): r = Rower.objects.get(user=user) if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" elif (timezone.now()>r.sporttrackstokenexpirydate): - s = "Token expired. Needs to refresh." - return custom_exception_handler(401,s) + s = "Token expired. Needs to refresh." + return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.sporttrackstoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.sporttracks.mobi/api/v2/fitnessActivities/"+str(sporttracksid) - s = requests.get(url,headers=headers) + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.sporttrackstoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://api.sporttracks.mobi/api/v2/fitnessActivities/"+str(sporttracksid) + s = requests.get(url,headers=headers) data = s.json() @@ -139,19 +140,19 @@ def createsporttracksworkoutdata(w): haslatlon=1 try: - lat = row.df[' latitude'].values - lon = row.df[' longitude'].values + lat = row.df[' latitude'].values + lon = row.df[' longitude'].values if not lat.std() and not lon.std(): haslatlon = 0 except KeyError: - haslatlon = 0 + haslatlon = 0 haspower = 1 try: - power = row.df[' Power (watts)'].astype(int).values + power = row.df[' Power (watts)'].astype(int).values except KeyError: - haspower = 0 + haspower = 0 locdata = [] hrdata = [] @@ -160,18 +161,18 @@ def createsporttracksworkoutdata(w): powerdata = [] for i in range(len(t)): - hrdata.append(t[i]) - hrdata.append(hr[i]) - distancedata.append(t[i]) - distancedata.append(d[i]) - spmdata.append(t[i]) - spmdata.append(spm[i]) - if haslatlon: - locdata.append(t[i]) - locdata.append([lat[i],lon[i]]) - if haspower: - powerdata.append(t[i]) - powerdata.append(power[i]) + hrdata.append(t[i]) + hrdata.append(hr[i]) + distancedata.append(t[i]) + distancedata.append(d[i]) + spmdata.append(t[i]) + spmdata.append(spm[i]) + if haslatlon: + locdata.append(t[i]) + locdata.append([lat[i],lon[i]]) + if haspower: + powerdata.append(t[i]) + powerdata.append(power[i]) try: @@ -183,37 +184,37 @@ def createsporttracksworkoutdata(w): st = st.replace(microsecond=0) if haslatlon: - data = { - "type": "Rowing", - "name": w.name, - "start_time": st.isoformat(), - "total_distance": int(w.distance), - "duration": duration, - "notes": w.notes, - "avg_heartrate": averagehr, - "max_heartrate": maxhr, - "location": locdata, - "distance": distancedata, - "cadence": spmdata, - "heartrate": hrdata, - } + data = { + "type": "Rowing", + "name": w.name, + "start_time": st.isoformat(), + "total_distance": int(w.distance), + "duration": duration, + "notes": w.notes, + "avg_heartrate": averagehr, + "max_heartrate": maxhr, + "location": locdata, + "distance": distancedata, + "cadence": spmdata, + "heartrate": hrdata, + } else: - data = { - "type": "Rowing", - "name": w.name, - "start_time": st.isoformat(), - "total_distance": int(w.distance), - "duration": duration, - "notes": w.notes, - "avg_heartrate": averagehr, - "max_heartrate": maxhr, - "distance": distancedata, - "cadence": spmdata, - "heartrate": hrdata, - } + data = { + "type": "Rowing", + "name": w.name, + "start_time": st.isoformat(), + "total_distance": int(w.distance), + "duration": duration, + "notes": w.notes, + "avg_heartrate": averagehr, + "max_heartrate": maxhr, + "distance": distancedata, + "cadence": spmdata, + "heartrate": hrdata, + } if haspower: - data['power'] = powerdata + data['power'] = powerdata return data @@ -239,41 +240,41 @@ def workout_sporttracks_upload(user,w): thetoken = sporttracks_open(user) if (checkworkoutuser(user,w)): - data = createsporttracksworkoutdata(w) + data = createsporttracksworkoutdata(w) if not data: message = "Data error" stid = 0 return message,stid - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + authorizationstring = str('Bearer ' + thetoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} - url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" - response = requests.post(url,headers=headers,data=json.dumps(data)) + url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" + response = requests.post(url,headers=headers,data=json.dumps(data)) - # check for duplicate error first - if (response.status_code == 409 ): - message = "Duplicate error" - w.uploadedtosporttracks = -1 + # check for duplicate error first + if (response.status_code == 409 ): + message = "Duplicate error" + w.uploadedtosporttracks = -1 stid = -1 - w.save() + w.save() return message, stid - elif (response.status_code == 201 or response.status_code==200): - s= response.json() - stid = getidfromresponse(response) - w.uploadedtosporttracks = stid - w.save() + elif (response.status_code == 201 or response.status_code==200): + s= response.json() + stid = getidfromresponse(response) + w.uploadedtosporttracks = stid + w.save() return 'Successfully synced to SportTracks',stid - else: - s = response - message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason + else: + s = response + message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason stid = 0 return message,stid - + else: - message = "You are not authorized to upload this workout" + message = "You are not authorized to upload this workout" stid = 0 return message,stid @@ -289,33 +290,33 @@ def add_workout_from_data(user,importid,data,strokedata,source='sporttracks', workouttype = 'other' if workouttype not in [x[0] for x in Workout.workouttypes]: - workouttype = 'other' + workouttype = 'other' try: - comments = data['comments'] + comments = data['comments'] except: - comments = '' + comments = '' r = Rower.objects.get(user=user) try: - rowdatetime = iso8601.parse_date(data['start_time']) + rowdatetime = iso8601.parse_date(data['start_time']) except iso8601.ParseError: - try: - rowdatetime = datetime.datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except: - try: - rowdatetime = dateutil.parser.parse(data['start_time']) - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except: - rowdatetime = datetime.datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + try: + rowdatetime = datetime.datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S") + rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + except: + try: + rowdatetime = dateutil.parser.parse(data['start_time']) + rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + except: + rowdatetime = datetime.datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") + rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) starttimeunix = arrow.get(rowdatetime).timestamp try: - title = data['name'] + title = data['name'] except: - title = "Imported data" + title = "Imported data" try: res = splitstdata(data['distance']) @@ -331,41 +332,41 @@ def add_workout_from_data(user,importid,data,strokedata,source='sporttracks', try: - l = data['location'] + l = data['location'] - res = splitstdata(l) - times_location = res[0] - latlong = res[1] - latcoord = [] - loncoord = [] + res = splitstdata(l) + times_location = res[0] + latlong = res[1] + latcoord = [] + loncoord = [] - for coord in latlong: - lat = coord[0] - lon = coord[1] - latcoord.append(lat) - loncoord.append(lon) + for coord in latlong: + lat = coord[0] + lon = coord[1] + latcoord.append(lat) + loncoord.append(lon) except: - times_location = times_distance - latcoord = np.zeros(len(times_distance)) - loncoord = np.zeros(len(times_distance)) + times_location = times_distance + latcoord = np.zeros(len(times_distance)) + loncoord = np.zeros(len(times_distance)) if workouttype in mytypes.otwtypes: workouttype = 'rower' - + try: - res = splitstdata(data['cadence']) - times_spm = res[0] - spm = res[1] + res = splitstdata(data['cadence']) + times_spm = res[0] + spm = res[1] except KeyError: - times_spm = times_distance - spm = 0*times_distance + times_spm = times_distance + spm = 0*times_distance try: - res = splitstdata(data['heartrate']) - hr = res[1] - times_hr = res[0] + res = splitstdata(data['heartrate']) + hr = res[1] + times_hr = res[0] except KeyError: - times_hr = times_distance - hr = 0*times_distance + times_hr = times_distance + hr = 0*times_distance # create data series and remove duplicates @@ -383,12 +384,12 @@ def add_workout_from_data(user,importid,data,strokedata,source='sporttracks', # Create dicts and big dataframe d = { - ' Horizontal (meters)': distseries, - ' latitude': latseries, - ' longitude': lonseries, - ' Cadence (stokes/min)': spmseries, - ' HRCur (bpm)' : hrseries, - } + ' Horizontal (meters)': distseries, + ' latitude': latseries, + ' longitude': lonseries, + ' Cadence (stokes/min)': spmseries, + ' HRCur (bpm)' : hrseries, + } @@ -432,7 +433,7 @@ def add_workout_from_data(user,importid,data,strokedata,source='sporttracks', df = df.fillna(0) df.sort_values(by='TimeStamp (sec)',ascending=True) - + timestr = strftime("%Y%m%d-%H%M%S") # csvfilename ='media/Import_'+str(importid)+'.csv' diff --git a/rowers/stravastuff.py b/rowers/stravastuff.py index 2c8a9505..c8fc5e40 100644 --- a/rowers/stravastuff.py +++ b/rowers/stravastuff.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals, absolute_import + # All the functionality needed to connect to Strava from scipy import optimize from scipy.signal import savgol_filter @@ -10,15 +12,15 @@ queue = django_rq.get_queue('default') queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low') -from dataprep import columndict +from rowers.dataprep import columndict import stravalib from stravalib.exc import ActivityUploadFailed,TimeoutExceeded from iso8601 import ParseError -from utils import myqueue +from rowers.utils import myqueue -import mytypes +import rowers.mytypes as mytypes import gzip from rowsandall_app.settings import ( @@ -35,7 +37,7 @@ from rowers.imports import * headers = {'Accept': 'application/json', 'Api-Key': STRAVA_CLIENT_ID, - 'Content-Type': 'application/json', + 'Content-Type': 'application/json', 'user-agent': 'sanderroosendaal'} @@ -89,26 +91,26 @@ def make_authorization_url(request): def get_strava_workout_list(user,limit_n=0): r = Rower.objects.get(user=user) if (r.stravatoken == '') or (r.stravatoken is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) elif (r.stravatokenexpirydate is None or timezone.now()+timedelta(seconds=3599)>r.stravatokenexpirydate): s = "Token expired. Needs to refresh." return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.stravatoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.stravatoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} - url = "https://www.strava.com/api/v3/athlete/activities" + url = "https://www.strava.com/api/v3/athlete/activities" if limit_n==0: params = {} else: params = {'per_page':limit_n} - s = requests.get(url,headers=headers,params=params) + s = requests.get(url,headers=headers,params=params) return s @@ -200,27 +202,27 @@ def create_async_workout(alldata,user,stravaid,debug=False): thetimezone = 'UTC' try: - rowdatetime = iso8601.parse_date(data['date_utc']) + rowdatetime = iso8601.parse_date(data['date_utc']) except KeyError: - rowdatetime = iso8601.parse_date(data['start_date']) + rowdatetime = iso8601.parse_date(data['start_date']) except ParseError: - rowdatetime = iso8601.parse_date(data['date']) + rowdatetime = iso8601.parse_date(data['date']) try: c2intervaltype = data['workout_type'] - + except KeyError: - c2intervaltype = '' - + c2intervaltype = '' + try: - title = data['name'] + title = data['name'] except KeyError: - title = "" - try: - t = data['comments'].split('\n', 1)[0] - title += t[:20] - except: - title = 'Imported' + title = "" + try: + t = data['comments'].split('\n', 1)[0] + title += t[:20] + except: + title = 'Imported' workoutdate = rowdatetime.astimezone( pytz.timezone(thetimezone) @@ -259,7 +261,7 @@ def create_async_workout(alldata,user,stravaid,debug=False): return 1 -from utils import get_strava_stream +from rowers.utils import get_strava_stream @@ -273,26 +275,26 @@ def get_workout(user,stravaid): r = Rower.objects.get(user=user) if (r.stravatoken == '') or (r.stravatoken is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) elif (r.stravatokenexpirydate is not None and timezone.now()>r.stravatokenexpirydate): s = "Token expired. Needs to refresh." return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - fetchresolution = 'high' + # ready to fetch. Hurray + fetchresolution = 'high' series_type = 'time' - authorizationstring = str('Bearer ' + r.stravatoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json', - 'resolution': 'medium',} - url = "https://www.strava.com/api/v3/activities/"+str(stravaid) - workoutsummary = requests.get(url,headers=headers).json() + authorizationstring = str('Bearer ' + r.stravatoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json', + 'resolution': 'medium',} + url = "https://www.strava.com/api/v3/activities/"+str(stravaid) + workoutsummary = requests.get(url,headers=headers).json() - workoutsummary['timezone'] = "Etc/UTC" + workoutsummary['timezone'] = "Etc/UTC" try: - startdatetime = workoutsummary['start_date'] + startdatetime = workoutsummary['start_date'] except KeyError: startdatetime = timezone.now() @@ -306,9 +308,9 @@ def get_workout(user,stravaid): try: - t = np.array(timejson.json()[0]['data']) - nr_rows = len(t) - d = np.array(distancejson.json()[1]['data']) + t = np.array(timejson.json()[0]['data']) + nr_rows = len(t) + d = np.array(distancejson.json()[1]['data']) if nr_rows == 0: return (0,"Error: Time data had zero length") @@ -318,70 +320,70 @@ def get_workout(user,stravaid): except KeyError: return (0,"something went wrong with the Strava import") - try: - spm = np.array(spmjson.json()[1]['data']) - except: - spm = np.zeros(nr_rows) + try: + spm = np.array(spmjson.json()[1]['data']) + except: + spm = np.zeros(nr_rows) try: power = np.array(powerjson.json()[1]['data']) except IndexError: power = np.zeros(nr_rows) - try: - hr = np.array(hrjson.json()[1]['data']) - except IndexError: - hr = np.zeros(nr_rows) + try: + hr = np.array(hrjson.json()[1]['data']) + except IndexError: + hr = np.zeros(nr_rows) except KeyError: - hr = np.zeros(nr_rows) + hr = np.zeros(nr_rows) - try: - velo = np.array(velojson.json()[1]['data']) - except IndexError: - velo = np.zeros(nr_rows) + try: + velo = np.array(velojson.json()[1]['data']) + except IndexError: + velo = np.zeros(nr_rows) except KeyError: velo = np.zeros(nr_rows) - dt = np.diff(t).mean() - wsize = round(5./dt) + dt = np.diff(t).mean() + wsize = round(5./dt) - velo2 = ewmovingaverage(velo,wsize) - coords = np.array(latlongjson.json()[0]['data']) - try: - lat = coords[:,0] - lon = coords[:,1] - except IndexError: - lat = np.zeros(len(t)) - lon = np.zeros(len(t)) + velo2 = ewmovingaverage(velo,wsize) + coords = np.array(latlongjson.json()[0]['data']) + try: + lat = coords[:,0] + lon = coords[:,1] + except IndexError: + lat = np.zeros(len(t)) + lon = np.zeros(len(t)) except KeyError: - lat = np.zeros(len(t)) - lon = np.zeros(len(t)) + lat = np.zeros(len(t)) + lon = np.zeros(len(t)) - strokelength = velo*60./(spm) - strokelength[np.isinf(strokelength)] = 0.0 + strokelength = velo*60./(spm) + strokelength[np.isinf(strokelength)] = 0.0 - pace = 500./(1.0*velo2) - pace[np.isinf(pace)] = 0.0 + pace = 500./(1.0*velo2) + pace[np.isinf(pace)] = 0.0 - df = pd.DataFrame({'t':10*t, - 'd':10*d, - 'p':10*pace, - 'spm':spm, - 'hr':hr, - 'lat':lat, - 'lon':lon, + df = pd.DataFrame({'t':10*t, + 'd':10*d, + 'p':10*pace, + 'spm':spm, + 'hr':hr, + 'lat':lat, + 'lon':lon, 'power':power, - 'strokelength':strokelength, - }) + 'strokelength':strokelength, + }) - # startdatetime = datetime.datetime.strptime(startdatetime,"%Y-%m-%d-%H:%M:%S") + # startdatetime = datetime.datetime.strptime(startdatetime,"%Y-%m-%d-%H:%M:%S") - return [workoutsummary,df] + return [workoutsummary,df] # Generate Workout data for Strava (a TCX file) def createstravaworkoutdata(w,dozip=True): @@ -478,41 +480,41 @@ def add_workout_from_data(user,importid,data,strokedata, workouttype = 'water' if workouttype not in [x[0] for x in Workout.workouttypes]: - workouttype = 'other' + workouttype = 'other' try: - comments = data['comments'] + comments = data['comments'] except: - comments = ' ' + comments = ' ' try: - thetimezone = tz(data['timezone']) + thetimezone = tz(data['timezone']) except: - thetimezone = 'UTC' + thetimezone = 'UTC' r = Rower.objects.get(user=user) try: - rowdatetime = iso8601.parse_date(data['date_utc']) + rowdatetime = iso8601.parse_date(data['date_utc']) except KeyError: - rowdatetime = iso8601.parse_date(data['start_date']) + rowdatetime = iso8601.parse_date(data['start_date']) except ParseError: - rowdatetime = iso8601.parse_date(data['date']) + rowdatetime = iso8601.parse_date(data['date']) - + try: intervaltype = data['workout_type'] - + except KeyError: - intervaltype = '' - + intervaltype = '' + try: - title = data['name'] + title = data['name'] except KeyError: - title = "" - try: - t = data['comments'].split('\n', 1)[0] - title += t[:20] - except: - title = 'Imported' + title = "" + try: + t = data['comments'].split('\n', 1)[0] + title += t[:20] + except: + title = 'Imported' starttimeunix = arrow.get(rowdatetime).timestamp @@ -526,17 +528,17 @@ def add_workout_from_data(user,importid,data,strokedata, nr_rows = len(unixtime) try: - latcoord = strokedata.loc[:,'lat'] - loncoord = strokedata.loc[:,'lon'] + latcoord = strokedata.loc[:,'lat'] + loncoord = strokedata.loc[:,'lon'] except: - latcoord = np.zeros(nr_rows) - loncoord = np.zeros(nr_rows) + latcoord = np.zeros(nr_rows) + loncoord = np.zeros(nr_rows) try: - strokelength = strokedata.loc[:,'strokelength'] + strokelength = strokedata.loc[:,'strokelength'] except: - strokelength = np.zeros(nr_rows) + strokelength = np.zeros(nr_rows) dist2 = 0.1*strokedata.loc[:,'d'] @@ -566,28 +568,28 @@ def add_workout_from_data(user,importid,data,strokedata, # save csv # Create data frame with all necessary data to write to csv df = pd.DataFrame({'TimeStamp (sec)':unixtime, - ' Horizontal (meters)': dist2, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' longitude':loncoord, - ' latitude':latcoord, - ' Stroke500mPace (sec/500m)':pace, - ' Power (watts)':power, - ' DragFactor':np.zeros(nr_rows), - ' DriveLength (meters)':np.zeros(nr_rows), - ' StrokeDistance (meters)':strokelength, - ' DriveTime (ms)':np.zeros(nr_rows), - ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), - ' AverageDriveForce (lbs)':np.zeros(nr_rows), - ' PeakDriveForce (lbs)':np.zeros(nr_rows), - ' lapIdx':lapidx, - ' ElapsedTime (sec)':seconds - }) + ' Horizontal (meters)': dist2, + ' Cadence (stokes/min)':spm, + ' HRCur (bpm)':hr, + ' longitude':loncoord, + ' latitude':latcoord, + ' Stroke500mPace (sec/500m)':pace, + ' Power (watts)':power, + ' DragFactor':np.zeros(nr_rows), + ' DriveLength (meters)':np.zeros(nr_rows), + ' StrokeDistance (meters)':strokelength, + ' DriveTime (ms)':np.zeros(nr_rows), + ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), + ' AverageDriveForce (lbs)':np.zeros(nr_rows), + ' PeakDriveForce (lbs)':np.zeros(nr_rows), + ' lapIdx':lapidx, + ' ElapsedTime (sec)':seconds + }) df.sort_values(by='TimeStamp (sec)',ascending=True) - + timestr = strftime("%Y%m%d-%H%M%S") @@ -623,34 +625,34 @@ def workout_strava_upload(user,w): r = Rower.objects.get(user=user) res = -1 if (r.stravatoken == '') or (r.stravatoken is None): - s = "Token doesn't exist. Need to authorize" + s = "Token doesn't exist. Need to authorize" raise NoTokenError("Your hovercraft is full of eels") else: - if (checkworkoutuser(user,w)): + if (checkworkoutuser(user,w)): try: - tcxfile,tcxmesg = createstravaworkoutdata(w) + tcxfile,tcxmesg = createstravaworkoutdata(w) if tcxfile: - with open(tcxfile,'rb') as f: - res,mes = handle_stravaexport( + with open(tcxfile,'rb') as f: + res,mes = handle_stravaexport( f,w.name, - r.stravatoken, - description=w.notes+'\n from '+w.workoutsource+' via rowsandall.com', + r.stravatoken, + description=w.notes+'\n from '+w.workoutsource+' via rowsandall.com', activity_type=r.stravaexportas) if res==0: - message = mes - w.uploadedtostrava = -1 + message = mes + w.uploadedtostrava = -1 stravaid = -1 - w.save() + w.save() try: - os.remove(tcxfile) + os.remove(tcxfile) except WindowsError: pass return message,stravaid - w.uploadedtostrava = res - w.save() + w.uploadedtostrava = res + w.save() try: - os.remove(tcxfile) + os.remove(tcxfile) except WindowsError: pass message = mes @@ -663,14 +665,14 @@ def workout_strava_upload(user,w): w.save() return message, stravaid - except ActivityUploadFailed as e: - message = "Strava Upload error: %s" % e - w.uploadedtostrava = -1 + except ActivityUploadFailed as e: + message = "Strava Upload error: %s" % e + w.uploadedtostrava = -1 stravaid = -1 - w.save() - os.remove(tcxfile) + w.save() + os.remove(tcxfile) return message,stravaid - return message,stravaid + return message,stravaid return message,stravaid @@ -688,9 +690,9 @@ def handle_strava_import_stroke_data(title, series_type = 'time' authorizationstring = str('Bearer ' + stravatoken) headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json', - 'resolution': 'medium',} + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json', + 'resolution': 'medium',} url = "https://www.strava.com/api/v3/activities/"+str(stravaid) workoutsummary = requests.get(url,headers=headers).json() @@ -708,9 +710,9 @@ def handle_strava_import_stroke_data(title, wattsjson = get_strava_stream(r,'watts',stravaid) try: - t = np.array(timejson.json()[0]['data']) - nr_rows = len(t) - d = np.array(distancejson.json()[1]['data']) + t = np.array(timejson.json()[0]['data']) + nr_rows = len(t) + d = np.array(distancejson.json()[1]['data']) if nr_rows == 0: return 0 except IndexError: @@ -720,9 +722,9 @@ def handle_strava_import_stroke_data(title, return 0 try: - spm = np.array(spmjson.json()[1]['data']) + spm = np.array(spmjson.json()[1]['data']) except: - spm = np.zeros(nr_rows) + spm = np.zeros(nr_rows) try: watts = np.array(wattsjson.json()[1]['data']) @@ -730,16 +732,16 @@ def handle_strava_import_stroke_data(title, watts = np.zeros(nr_rows) try: - hr = np.array(hrjson.json()[1]['data']) + hr = np.array(hrjson.json()[1]['data']) except IndexError: - hr = np.zeros(nr_rows) + hr = np.zeros(nr_rows) except KeyError: - hr = np.zeros(nr_rows) + hr = np.zeros(nr_rows) try: - velo = np.array(velojson.json()[1]['data']) + velo = np.array(velojson.json()[1]['data']) except IndexError: - velo = np.zeros(nr_rows) + velo = np.zeros(nr_rows) except KeyError: velo = np.zeros(nr_rows) @@ -756,14 +758,14 @@ def handle_strava_import_stroke_data(title, coords = np.array(latlongjson.json()[0]['data']) try: - lat = coords[:,0] - lon = coords[:,1] + lat = coords[:,0] + lon = coords[:,1] except IndexError: - lat = np.zeros(len(t)) - lon = np.zeros(len(t)) + lat = np.zeros(len(t)) + lon = np.zeros(len(t)) except KeyError: - lat = np.zeros(len(t)) - lon = np.zeros(len(t)) + lat = np.zeros(len(t)) + lon = np.zeros(len(t)) strokelength = velo*60./(spm) strokelength[np.isinf(strokelength)] = 0.0 @@ -779,22 +781,22 @@ def handle_strava_import_stroke_data(title, df = pd.DataFrame({'TimeStamp (sec)':unixtime, ' ElapsedTime (sec)':t, - ' Horizontal (meters)':d, - ' Stroke500mPace (sec/500m)':pace, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' latitude':lat, - ' longitude':lon, - ' StrokeDistance (meters)':strokelength, + ' Horizontal (meters)':d, + ' Stroke500mPace (sec/500m)':pace, + ' Cadence (stokes/min)':spm, + ' HRCur (bpm)':hr, + ' latitude':lat, + ' longitude':lon, + ' StrokeDistance (meters)':strokelength, 'cum_dist':d, - ' DragFactor':np.zeros(nr_strokes), - ' DriveLength (meters)':np.zeros(nr_strokes), - ' StrokeDistance (meters)':strokedistance, - ' DriveTime (ms)':np.zeros(nr_strokes), - ' StrokeRecoveryTime (ms)':np.zeros(nr_strokes), - ' AverageDriveForce (lbs)':np.zeros(nr_strokes), - ' PeakDriveForce (lbs)':np.zeros(nr_strokes), - ' lapIdx':np.zeros(nr_strokes), + ' DragFactor':np.zeros(nr_strokes), + ' DriveLength (meters)':np.zeros(nr_strokes), + ' StrokeDistance (meters)':strokedistance, + ' DriveTime (ms)':np.zeros(nr_strokes), + ' StrokeRecoveryTime (ms)':np.zeros(nr_strokes), + ' AverageDriveForce (lbs)':np.zeros(nr_strokes), + ' PeakDriveForce (lbs)':np.zeros(nr_strokes), + ' lapIdx':np.zeros(nr_strokes), ' Power (watts)':watts, }) diff --git a/rowers/tasks.py b/rowers/tasks.py index efc0cf44..4123b531 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -1,4 +1,5 @@ """ Background tasks done by Celery (develop) or QR (production) """ +from __future__ import absolute_import import os import time import gc @@ -16,7 +17,10 @@ from rowingdata import rowingdata as rdata from datetime import timedelta from sqlalchemy import create_engine -from celery import app +#from celery import app +from rowers.celery import app +from celery import shared_task + import datetime import pytz import iso8601 @@ -39,10 +43,11 @@ from django_rq import job from django.utils import timezone from django.utils.html import strip_tags -from utils import deserialize_list,ewmovingaverage,wavg -from emails import htmlstrip +from rowers.utils import deserialize_list,ewmovingaverage,wavg +from rowers.emails import htmlstrip -from HTMLParser import HTMLParser +#from HTMLParser import HTMLParser +from html.parser import HTMLParser class MLStripper(HTMLParser): def __init__(self): self.reset() @@ -80,13 +85,13 @@ from django.db.utils import OperationalError from jinja2 import Template,Environment,FileSystemLoader env = Environment(loader = FileSystemLoader(["rowers/templates"])) -import datautils -import utils +import rowers.datautils as datautils +import rowers.utils as utils import requests -import longtask +import rowers.longtask as longtask import arrow -from utils import get_strava_stream +from rowers.utils import get_strava_stream siteurl = SITE_URL @@ -128,9 +133,9 @@ def handle_c2_import_stroke_data(c2token, return 1 else: - url = "https://log.concept2.com/api/users/me/results/"+str(c2id) + url = "https://log.concept2.com/api/users/me/results/{id}".format(id=c2id) - s = requests.get(url,headers=headers) + s = requests.get(url,headers=headers) if s.status_code == 200: workoutdata = s.json()['data'] @@ -1238,21 +1243,21 @@ def handle_zip_file(emailfrom, subject, file,**kwargs): debug = False if debug: - print message + print(message) email = EmailMessage(subject, message, emailfrom, ['workouts@rowsandall.com']) email.attach_file(file) if debug: - print "attaching" + print("attaching") res = email.send() if debug: - print "sent" + print("sent") time.sleep(60) return 1 @@ -1490,9 +1495,8 @@ def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs): rowdata = rdata(f1 + '.gz') except IOError: rowdata = 0 - - if rowdata != 0: - therows.append(rowdata) + if rowdata != 0: + therows.append(rowdata) cpdata = rowingdata.cumcpdata(therows) cpdata.columns = cpdata.columns.str.lower() diff --git a/rowers/teams.py b/rowers/teams.py index 8980e8a8..8d2dfbce 100644 --- a/rowers/teams.py +++ b/rowers/teams.py @@ -10,7 +10,7 @@ from django.db import IntegrityError import uuid from django.conf import settings -from utils import myqueue +from rowers.utils import myqueue import django_rq queue = django_rq.get_queue('default') diff --git a/rowers/tpstuff.py b/rowers/tpstuff.py index 776b5722..442bd820 100644 --- a/rowers/tpstuff.py +++ b/rowers/tpstuff.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import # All the functionality needed to connect to Runkeeper from rowers.imports import * @@ -149,12 +150,6 @@ def uploadactivity(access_token,filename,description='', headers=headers) if resp.status_code != 200: - if settings.DEBUG: - print resp.status_code - print resp.reason - print "" - print headers - print "" return 0,resp.reason,resp.status_code,headers else: return resp.json()[0]["Id"],"ok",200,"" diff --git a/rowers/underarmourstuff.py b/rowers/underarmourstuff.py index f5169f45..cbe1db96 100644 --- a/rowers/underarmourstuff.py +++ b/rowers/underarmourstuff.py @@ -1,6 +1,7 @@ +from __future__ import unicode_literals, absolute_import from rowers.imports import * -import mytypes +import rowers.mytypes as mytypes from rowers.mytypes import otwtypes from rowsandall_app.settings import ( @@ -45,18 +46,18 @@ def make_authorization_url(request): def get_underarmour_workout_list(user): r = Rower.objects.get(user=user) if (r.underarmourtoken == '') or (r.underarmourtoken is None): - s = "Token doesn't exist. Need to authorize" - return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.underarmourtoken) - headers = {'Authorization': authorizationstring, + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.underarmourtoken) + headers = {'Authorization': authorizationstring, 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.ua.com/v7.1/workout/?user="+str(get_userid(r.underarmourtoken))+"&order_by=-start_datetime" + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://api.ua.com/v7.1/workout/?user="+str(get_userid(r.underarmourtoken))+"&order_by=-start_datetime" - s = requests.get(url,headers=headers) + s = requests.get(url,headers=headers) return s @@ -65,17 +66,17 @@ def get_underarmour_workout_list(user): def get_workout(user,underarmourid): r = Rower.objects.get(user=user) if (r.underarmourtoken == '') or (r.underarmourtoken is None): - return custom_exception_handler(401,s) - s = "Token doesn't exist. Need to authorize" + return custom_exception_handler(401,s) + s = "Token doesn't exist. Need to authorize" else: - # ready to fetch. Hurray - authorizationstring = str('Bearer ' + r.underarmourtoken) - headers = {'Authorization': authorizationstring, + # ready to fetch. Hurray + authorizationstring = str('Bearer ' + r.underarmourtoken) + headers = {'Authorization': authorizationstring, 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} - url = "https://api.ua.com/v7.1/workout/"+str(underarmourid)+"/?field_set=time_series" - s = requests.get(url,headers=headers) + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} + url = "https://api.ua.com/v7.1/workout/"+str(underarmourid)+"/?field_set=time_series" + s = requests.get(url,headers=headers) data = s.json() @@ -135,12 +136,12 @@ def createunderarmourworkoutdata(w): haslatlon=1 try: - lat = row.df[' latitude'] - lon = row.df[' longitude'] + lat = row.df[' latitude'] + lon = row.df[' longitude'] if not lat.std() and not lon.std(): haslatlon = 0 except KeyError: - haslatlon = 0 + haslatlon = 0 @@ -201,7 +202,7 @@ def createunderarmourworkoutdata(w): timeseries["position"] = locdata data = { - "start_datetime": start_time, + "start_datetime": start_time, "name": name, "has_time_series": True, "time_series": timeseries, @@ -236,8 +237,8 @@ def refresh_ua_actlist(user): authorizationstring = str('Bearer ' + r.underarmourtoken) headers = {'Authorization': authorizationstring, 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} url = "https://api.ua.com/v7.1/activity_type/" response = requests.get(url,headers=headers) @@ -263,8 +264,8 @@ def get_typefromid(typeid,user): authorizationstring = str('Bearer ' + r.underarmourtoken) headers = {'Authorization': authorizationstring, 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} url = "https://api.ua.com/v7.1/activity_type/"+str(typeid) response = requests.get(url,headers=headers) @@ -285,8 +286,8 @@ def get_userid(access_token): authorizationstring = str('Bearer ' + access_token) headers = {'Authorization': authorizationstring, 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} url = "https://api.ua.com/v7.1/user/self/" response = requests.get(url,headers=headers) @@ -311,42 +312,42 @@ def workout_ua_upload(user,w): # ready to upload. Hurray if (checkworkoutuser(user,w)): - data = createunderarmourworkoutdata(w) + data = createunderarmourworkoutdata(w) # return HttpResponse(json.dumps(data)) if not data: message = "Data error" uaid = 0 return message, uaid - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, + authorizationstring = str('Bearer ' + thetoken) + headers = {'Authorization': authorizationstring, 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json', + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json', } - url = "https://api.ua.com/v7.1/workout/" - response = requests.post(url,headers=headers,data=json.dumps(data)) + url = "https://api.ua.com/v7.1/workout/" + response = requests.post(url,headers=headers,data=json.dumps(data)) - # check for duplicate error first - if (response.status_code == 409 ): - message = "Duplicate error" - w.uploadedtounderarmour = -1 + # check for duplicate error first + if (response.status_code == 409 ): + message = "Duplicate error" + w.uploadedtounderarmour = -1 uaid = -1 - w.save() - elif (response.status_code == 201 or response.status_code==200): - uaid = getidfromresponse(response) - w.uploadedtounderarmour = uaid - w.save() + w.save() + elif (response.status_code == 201 or response.status_code==200): + uaid = getidfromresponse(response) + w.uploadedtounderarmour = uaid + w.save() return 'Successfully synchronized with MapMyFitness',uaid - else: - s = response - message = "Something went wrong in workout_underarmour_upload_view: %s - %s" % (s.reason,s.text) + else: + s = response + message = "Something went wrong in workout_underarmour_upload_view: %s - %s" % (s.reason,s.text) uaid = 0 return message, uaid - + else: - message = "You are not authorized to upload this workout" + message = "You are not authorized to upload this workout" uaid = 0 return message, uaid @@ -360,36 +361,36 @@ def add_workout_from_data(user,importid,data,strokedata, workouttype = 'water' try: - comments = data['notes'] + comments = data['notes'] except: - comments = '' + comments = '' try: - thetimezone = tz(data['start_locale_timezone']) + thetimezone = tz(data['start_locale_timezone']) except: - thetimezone = 'UTC' + thetimezone = 'UTC' r = Rower.objects.get(user=user) try: - rowdatetime = iso8601.parse_date(data['start_datetime']) + rowdatetime = iso8601.parse_date(data['start_datetime']) except iso8601.ParseError: - try: - rowdatetime = datetime.strptime(data['start_datetime'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except: - try: - rowdatetime = parser.parse(data['start_datetime']) - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) - except: - rowdatetime = datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") - rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + try: + rowdatetime = datetime.strptime(data['start_datetime'],"%Y-%m-%d %H:%M:%S") + rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + except: + try: + rowdatetime = parser.parse(data['start_datetime']) + rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) + except: + rowdatetime = datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S") + rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc) starttimeunix = arrow.get(rowdatetime).timestamp - + try: - title = data['name'] + title = data['name'] except: - title = "Imported data" + title = "Imported data" timeseries = data['time_series'] @@ -403,41 +404,41 @@ def add_workout_from_data(user,importid,data,strokedata, try: - l = timeseries['position'] + l = timeseries['position'] - res = splituadata(l) - times_location = res[0] - latlong = res[1] - latcoord = [] - loncoord = [] + res = splituadata(l) + times_location = res[0] + latlong = res[1] + latcoord = [] + loncoord = [] - for coord in latlong: - lat = coord['lat'] - lon = coord['lng'] - latcoord.append(lat) - loncoord.append(lon) + for coord in latlong: + lat = coord['lat'] + lon = coord['lng'] + latcoord.append(lat) + loncoord.append(lon) except: - times_location = times_distance - latcoord = np.zeros(len(times_distance)) - loncoord = np.zeros(len(times_distance)) + times_location = times_distance + latcoord = np.zeros(len(times_distance)) + loncoord = np.zeros(len(times_distance)) if workouttype in otwtypes: workouttype = 'rower' - + try: - res = splituadata(timeseries['cadence']) - times_spm = res[0] - spm = res[1] + res = splituadata(timeseries['cadence']) + times_spm = res[0] + spm = res[1] except KeyError: - times_spm = times_distance - spm = 0*times_distance + times_spm = times_distance + spm = 0*times_distance try: - res = splituadata(timeseries['heartrate']) - hr = res[1] - times_hr = res[0] + res = splituadata(timeseries['heartrate']) + hr = res[1] + times_hr = res[0] except KeyError: - times_hr = times_distance - hr = 0*times_distance + times_hr = times_distance + hr = 0*times_distance # create data series and remove duplicates @@ -455,12 +456,12 @@ def add_workout_from_data(user,importid,data,strokedata, # Create dicts and big dataframe d = { - ' Horizontal (meters)': distseries, - ' latitude': latseries, - ' longitude': lonseries, - ' Cadence (stokes/min)': spmseries, - ' HRCur (bpm)' : hrseries, - } + ' Horizontal (meters)': distseries, + ' latitude': latseries, + ' longitude': lonseries, + ' Cadence (stokes/min)': spmseries, + ' HRCur (bpm)' : hrseries, + } @@ -499,7 +500,7 @@ def add_workout_from_data(user,importid,data,strokedata, df = df.fillna(0) df.sort_values(by='TimeStamp (sec)',ascending=True) - + timestr = strftime("%Y%m%d-%H%M%S") csvfilename ='media/{code}_{importid}.csv'.format( diff --git a/rowers/uploads.py b/rowers/uploads.py index 06f2f43e..ae86ae2c 100644 --- a/rowers/uploads.py +++ b/rowers/uploads.py @@ -26,12 +26,13 @@ queue = django_rq.get_queue('default') queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low') -from mytypes import workouttypes,boattypes,otwtypes,workoutsources +from rowers.mytypes import workouttypes,boattypes,otwtypes,workoutsources try: from cStringIO import StringIO except: - from StringIO import StringIO + from io import StringIO + from rowers.utils import ( geo_distance,serialize_list,deserialize_list,uniqify, @@ -403,34 +404,34 @@ def make_plot(r,w,f1,f2,plottype,title,imagename='',plotnr=0): ftp = ftp*(100.-r.otwslack)/100. hrpwrdata = { - 'hrmax':r.max, - 'hrut2':r.ut2, - 'hrut1':r.ut1, - 'hrat':r.at, - 'hrtr':r.tr, - 'hran':r.an, - 'ftp':ftp, + 'hrmax':r.max, + 'hrut2':r.ut2, + 'hrut1':r.ut1, + 'hrat':r.at, + 'hrtr':r.tr, + 'hran':r.an, + 'ftp':ftp, 'powerperc':serialize_list(powerperc), 'powerzones':serialize_list(r.powerzones), } # make plot - asynchronous task plotnrs = { - 'timeplot':1, - 'distanceplot':2, - 'pieplot':3, + 'timeplot':1, + 'distanceplot':2, + 'pieplot':3, } if plotnr == 0: plotnr = plotnrs[plottype] if w.workouttype in otwtypes: - plotnr = plotnr+3 + plotnr = plotnr+3 job = myqueue(queue,handle_makeplot,f1,f2, - title,hrpwrdata, - plotnr,imagename) + title,hrpwrdata, + plotnr,imagename) try: width,height = Image.open(fullpathimagename).size @@ -451,8 +452,12 @@ def make_plot(r,w,f1,f2,plottype,title,imagename='',plotnr=0): return i.id,job.id -import c2stuff,stravastuff,sporttracksstuff,runkeeperstuff -import underarmourstuff,tpstuff +import rowers.c2stuff as c2stuff +import rowers.stravastuff as stravastuff +import rowers.sporttracksstuff as sporttracksstuff +import rowers.runkeeperstuff as runkeeperstuff +import rowers.underarmourstuff as underarmourstuff +import rowers.tpstuff as tpstuff def set_workouttype(w,options): try: diff --git a/rowers/urls.py b/rowers/urls.py index d517f694..60287e59 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -2,7 +2,7 @@ from django.conf import settings from django.conf.urls import url, include from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required, permission_required -from models import Workout,Rower,StrokeData,FavoriteChart +from rowers.models import Workout,Rower,StrokeData,FavoriteChart from rest_framework import routers, serializers, viewsets,permissions from rest_framework.urlpatterns import format_suffix_patterns diff --git a/rowers/utils.py b/rowers/utils.py index 11905555..6b5484a8 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -439,10 +439,10 @@ def ewmovingaverage(interval,window_size): # Custom error class - to raise a NoTokenError class NoTokenError(Exception): def __init__(self,value): - self.value=value + self.value=value def __str__(self): - return repr(self.value) + return repr(self.value) class ProcessorCustomerError(Exception): def __init__(self, value): diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index 6cc5bf52..1bda5a80 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -1,13 +1,14 @@ -from statements import * +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, + 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={ @@ -59,30 +60,30 @@ def histo(request,theuser=0, if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s - + # get all indoor rows of in date range # process form if request.method == 'POST': - form = DateRangeForm(request.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 + 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(): @@ -102,14 +103,14 @@ def histo(request,theuser=0, request.session['waterboattype'] = waterboattype request.session['rankingonly'] = rankingonly form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) + 'startdate': startdate, + 'enddate': enddate, + }) else: - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) + form = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) includereststrokes = False workstrokesonly = not includereststrokes @@ -159,18 +160,18 @@ def histo(request,theuser=0, request.session['options'] = options return render(request, 'histo.html', - {'interactiveplot':script, - 'the_div':div, - 'id':theuser, + {'interactiveplot':script, + 'the_div':div, + 'id':theuser, 'active':'nav-analysis', - 'theuser':theuser, + 'theuser':theuser, 'rower':r, - 'startdate':startdate, - 'enddate':enddate, - 'form':form, + '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() @@ -226,19 +227,19 @@ def cum_flex_data( if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s promember=0 if theuser == 0: - theuser = request.user.id + 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 + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 r2 = getrower(theuser) @@ -248,24 +249,24 @@ def cum_flex_data( rankingpiece = [True,False] allworkouts = Workout.objects.filter(user=r2, - workouttype__in=modalities, + workouttype__in=modalities, boattype__in=waterboattype, - startdatetime__gte=startdate, - startdatetime__lte=enddate, + 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, + res = interactive_cum_flex_chart2(allworkouts,xparam=xparam, + yparam1=yparam1, + yparam2=yparam2, + promember=promember, workstrokesonly=workstrokesonly, ) - script = res[0] - div = res[1] + script = res[0] + div = res[1] else: - script = '' - div = '

No pieces uploaded for this date range.

' + script = '' + div = '

No pieces uploaded for this date range.

' scripta = script.split('\n')[2:-1] script = ''.join(scripta) @@ -324,19 +325,19 @@ def histo_data( if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s promember=0 if theuser == 0: - theuser = request.user.id + 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 + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 r2 = getrower(theuser) @@ -346,19 +347,19 @@ def histo_data( rankingpiece = [True,False] allworkouts = Workout.objects.filter(user=r2, - workouttype__in=modalities, + workouttype__in=modalities, boattype__in=waterboattype, - startdatetime__gte=startdate, - startdatetime__lte=enddate, + startdatetime__gte=startdate, + startdatetime__lte=enddate, rankingpiece__in=rankingpiece) if allworkouts: res = interactive_histoall(allworkouts) - script = res[0] - div = res[1] + script = res[0] + div = res[1] else: - script = '' - div = '

No pieces uploaded for this date range.

' + script = '' + div = '

No pieces uploaded for this date range.

' scripta = script.split('\n')[2:-1] script = ''.join(scripta) @@ -375,12 +376,12 @@ def histo_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, + 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={ @@ -433,31 +434,31 @@ def cum_flex(request,theuser=0, if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s - + # get all indoor rows of in date range # process form if request.method == 'POST': - form = DateRangeForm(request.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 + 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(): @@ -477,18 +478,18 @@ def cum_flex(request,theuser=0, request.session['waterboattype'] = waterboattype request.session['rankingonly'] = rankingonly form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) + '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, - }) + form = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) includereststrokes = False workstrokesonly = not includereststrokes @@ -548,25 +549,25 @@ def cum_flex(request,theuser=0, return render(request, 'cum_flex.html', - {'interactiveplot':script, - 'the_div':div, - 'js_res': js_resources, - 'css_res':css_resources, - 'id':theuser, + {'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, + 'theuser':theuser, + 'startdate':startdate, + 'enddate':enddate, + 'form':form, 'optionsform':modalityform, - 'xparam':xparam, - 'yparam1':yparam1, - 'yparam2':yparam2, - 'promember':promember, + 'xparam':xparam, + 'yparam1':yparam1, + 'yparam2':yparam2, + 'promember':promember, 'teams':get_my_teams(request.user), 'flexaxesform':flexaxesform, - }) + }) def planrequired_view(request): @@ -619,32 +620,32 @@ def fitnessmetric_view(request,id=0,mode='rower', # 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=""): + startdate=timezone.now()-datetime.timedelta(days=365), + enddate=timezone.now(), + deltadays=-1, + startdatestring="", + enddatestring=""): if deltadays>0: - startdate = enddate-datetime.timedelta(days=int(deltadays)) + startdate = enddate-datetime.timedelta(days=int(deltadays)) if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s if theuser == 0: - theuser = request.user.id + theuser = request.user.id promember=0 if not request.user.is_anonymous(): - r = getrower(request.user) + r = getrower(request.user) if r.birthdate: age = calculate_age(r.birthdate) worldclasspower = int(metrics.getagegrouprecord( @@ -655,61 +656,61 @@ def rankings_view(request,theuser=0, else: worldclasspower = None - result = request.user.is_authenticated() and ispromember(request.user) - if result: - promember=1 + 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 + 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, - }) + 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() + dateform = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) + deltaform = DeltaDaysForm() # get all 2k (if any) - this rower, in date range try: - r = getrower(theuser) + r = getrower(theuser) except Rower.DoesNotExist: - allergworkouts = [] - r=0 + allergworkouts = [] + r=0 - + try: - uu = User.objects.get(id=theuser) + uu = User.objects.get(id=theuser) except User.DoesNotExist: - uu = '' + uu = '' # test to fix bug @@ -726,43 +727,43 @@ def rankings_view(request,theuser=0, for rankingdistance in rankingdistances: - workouts = Workout.objects.filter( + workouts = Workout.objects.filter( user=r,distance=rankingdistance, - workouttype__in=['rower','dynamic','slides'], + workouttype__in=['rower','dynamic','slides'], rankingpiece=True, - startdatetime__gte=startdate, - startdatetime__lte=enddate + startdatetime__gte=startdate, + startdatetime__lte=enddate ).order_by('duration') - if workouts: - thedistances.append(rankingdistance) - theworkouts.append(workouts[0]) + 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) + 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( + workouts = Workout.objects.filter( user=r,duration=rankingduration, - workouttype='rower', + workouttype='rower', rankingpiece=True, - startdatetime__gte=startdate, - startdatetime__lte=enddate + startdatetime__gte=startdate, + startdatetime__lte=enddate ).order_by('-distance') - if workouts: - thedistances.append(workouts[0].distance) - theworkouts.append(workouts[0]) + 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) + 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) @@ -773,39 +774,39 @@ def rankings_view(request,theuser=0, # create interactive plot if len(thedistances) !=0 : - res = interactive_cpchart( + res = interactive_cpchart( r,thedistances,thesecs,theavpower, - theworkouts,promember=promember + theworkouts,promember=promember ) - script = res[0] - div = res[1] - paulslope = res[2] - paulintercept = res[3] - p1 = res[4] - message = res[5] + 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 = "" + 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'] + 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))) + 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() + form = PredictedPieceForm() rankingdistances.sort() rankingdurations.sort() @@ -816,118 +817,118 @@ def rankings_view(request,theuser=0, 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) + # 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]) + # 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 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 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 + 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) + 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 + t = 3600.*rankingduration.hour + t += 60.*rankingduration.minute + t += rankingduration.second + t += rankingduration.microsecond/1.e6 - # Paul's model - ratio = paulintercept/paulslope + # Paul's model + ratio = paulintercept/paulslope - u = ((2**(2+ratio))*(5.**(3+ratio))*t*np.log(10))/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 + 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) + 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]) + # CP model + pwr = p1[0]/(1+t/p1[2]) + pwr += p1[1]/(1+t/p1[3]) - if pwr <= 0: - pwr = 50. + if pwr <= 0: + pwr = 50. - velo = (pwr/2.8)**(1./3.) + 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 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, + {'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, + 'dateform':dateform, + 'deltaform':deltaform, 'worldclasspower':worldclasspower, - 'id': theuser, - 'theuser':uu, - 'startdate':startdate, - 'enddate':enddate, + 'id': theuser, + 'theuser':uu, + 'startdate':startdate, + 'enddate':enddate, 'teams':get_my_teams(request.user), - }) + }) @login_required() def ajax_agegrouprecords(request, @@ -969,28 +970,28 @@ def ajax_agegrouprecords(request, # 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=""): + startdate=timezone.now()-datetime.timedelta(days=365), + enddate=timezone.now(), + deltadays=-1, + startdatestring="", + enddatestring=""): if deltadays>0: - startdate = enddate-datetime.timedelta(days=int(deltadays)) + startdate = enddate-datetime.timedelta(days=int(deltadays)) if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s if theuser == 0: - theuser = request.user.id + theuser = request.user.id else: lastupdated = "01-01-1900" @@ -1063,61 +1064,61 @@ def rankings_view2(request,theuser=0, request.session['options'] = options - result = request.user.is_authenticated() and ispromember(request.user) - if result: - promember=1 + 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 + 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, - }) + 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() + dateform = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) + deltaform = DeltaDaysForm() # get all 2k (if any) - this rower, in date range try: - r = getrower(theuser) + r = getrower(theuser) except Rower.DoesNotExist: - allergworkouts = [] - r=0 + allergworkouts = [] + r=0 - + try: - uu = User.objects.get(id=theuser) + uu = User.objects.get(id=theuser) except User.DoesNotExist: - uu = '' + uu = '' # test to fix bug @@ -1137,41 +1138,41 @@ def rankings_view2(request,theuser=0, for rankingdistance in rankingdistances: - workouts = Workout.objects.filter( + workouts = Workout.objects.filter( user=r,distance=rankingdistance, - workouttype__in=['rower','dynamic','slides'], + 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]) + 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) + 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( + workouts = Workout.objects.filter( user=r,duration=rankingduration, - workouttype='rower', + workouttype='rower', rankingpiece=True, - startdatetime__gte=startdate, - startdatetime__lte=enddate).order_by('-distance') - if workouts: - thedistances.append(workouts[0].distance) - theworkouts.append(workouts[0]) + 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) + 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) @@ -1182,45 +1183,45 @@ def rankings_view2(request,theuser=0, # create interactive plot if len(thedistances) !=0 : - res = interactive_cpchart( + res = interactive_cpchart( r,thedistances,thesecs,theavpower, - theworkouts,promember=promember, + 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] + 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 = "" + 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'] + 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))) + 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() + form = PredictedPieceForm() rankingdistances.sort() rankingdurations.sort() @@ -1231,99 +1232,99 @@ def rankings_view2(request,theuser=0, 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) + # 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]) + # 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 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 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 + 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) + 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 + t = 3600.*rankingduration.hour + t += 60.*rankingduration.minute + t += rankingduration.second + t += rankingduration.microsecond/1.e6 - # Paul's model - ratio = paulintercept/paulslope + # Paul's model + ratio = paulintercept/paulslope - u = ((2**(2+ratio))*(5.**(3+ratio))*t*np.log(10))/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 + 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) + 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) + 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]) + # CP model + pwr = p1[0]/(1+t/p1[2]) + pwr += p1[1]/(1+t/p1[3]) - if pwr <= 0: - pwr = 50. + if pwr <= 0: + pwr = 50. - velo = (pwr/2.8)**(1./3.) + 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 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 = [] @@ -1354,27 +1355,27 @@ def rankings_view2(request,theuser=0, 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, + {'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, + 'startdate':startdate, + 'enddate':enddate, 'teams':get_my_teams(request.user), - }) + }) # Show ranking distances including predicted paces @@ -1382,27 +1383,27 @@ def rankings_view2(request,theuser=0, 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=""): + startdate=timezone.now()-datetime.timedelta(days=365), + enddate=timezone.now(), + startdatestring="", + enddatestring=""): if startdatestring != "": try: - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring != "": try: - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) except ParseError: pass if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s if theuser == 0: if 'rowerid' in request.session: @@ -1412,30 +1413,30 @@ def otwrankings_view(request,theuser=0, except Rower.DoesNotExist: theuser = request.user.id else: - theuser = request.user.id + 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 + 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) + 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'] + value = form.cleaned_data['value'] else: value = None trankingdurations = form.cleaned_data['trankingdurations'] @@ -1449,34 +1450,34 @@ def otwrankings_view(request,theuser=0, tvalue = int(60*(tvalue-minutevalue)) if hourvalue >= 24: hourvalue = 23 - trankingdurations.append(datetime.time( + trankingdurations.append(datetime.time( minute=minutevalue, hour=hourvalue, second=tvalue )) else: - form = PredictedPieceFormNoDistance() - dateform = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) + 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) + r = Rower.objects.get(user=theuser) request.session['rowerid'] = r.id except Rower.DoesNotExist: - raise Http404("Rower doesn't exist") - + raise Http404("Rower doesn't exist") + - + try: - uu = User.objects.get(id=theuser) + uu = User.objects.get(id=theuser) except User.DoesNotExist: - uu = '' + uu = '' # test to fix bug @@ -1492,9 +1493,9 @@ def otwrankings_view(request,theuser=0, theworkouts = Workout.objects.filter( user=r,rankingpiece=True, - workouttype='water', - startdatetime__gte=startdate, - startdatetime__lte=enddate + workouttype='water', + startdatetime__gte=startdate, + startdatetime__lte=enddate ).order_by( "-startdatetime" ) @@ -1557,10 +1558,10 @@ def otwrankings_view(request,theuser=0, 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] + 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] @@ -1570,14 +1571,14 @@ def otwrankings_view(request,theuser=0, r.save() paulslope = 1 paulintercept = 1 - message = res[4] + message = res[4] else: - script = '' - div = '

No ranking pieces found.

' - paulslope = 1 - paulintercept = 1 - p1 = [1,1,1,1] - message = "" + script = '' + div = '

No ranking pieces found.

' + paulslope = 1 + paulintercept = 1 + p1 = [1,1,1,1] + message = "" @@ -1585,19 +1586,19 @@ def otwrankings_view(request,theuser=0, cpredictions = [] for rankingduration in trankingdurations: - t = 3600.*rankingduration.hour - t += 60.*rankingduration.minute - t += rankingduration.second - t += rankingduration.microsecond/1.e6 + 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]) + # CP model + pwr = p1[0]/(1+t/p1[2]) + pwr += p1[1]/(1+t/p1[3]) - if pwr <= 0: - pwr = 50. + if pwr <= 0: + pwr = 50. if not np.isnan(pwr): @@ -1607,10 +1608,10 @@ def otwrankings_view(request,theuser=0, pwr2 = pwr a = { - 'duration':timedeltaconv(t), - 'power':int(pwr), + 'duration':timedeltaconv(t), + 'power':int(pwr), 'upper':int(pwr2)} - cpredictions.append(a) + cpredictions.append(a) @@ -1621,22 +1622,22 @@ def otwrankings_view(request,theuser=0, messages.error(request,message) return render(request, 'otwrankings.html', - {'rankingworkouts':theworkouts, - 'interactiveplot':script, - 'the_div':div, - 'cpredictions':cpredictions, + {'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, + '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, @@ -1648,13 +1649,13 @@ def otecp_toadmin_view(request,theuser=0, if startdatestring != "": try: - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring != "": try: - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) except ParseError: pass @@ -1669,13 +1670,13 @@ def otecp_toadmin_view(request,theuser=0, theworkouts = Workout.objects.filter( user=r,rankingpiece=True, - workouttype__in=[ + workouttype__in=[ 'rower', 'dynamic', 'slides' ], - startdatetime__gte=startdate, - startdatetime__lte=enddate + startdatetime__gte=startdate, + startdatetime__lte=enddate ).order_by("-startdatetime") @@ -1722,13 +1723,13 @@ def otwcp_toadmin_view(request,theuser=0, if startdatestring != "": try: - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring != "": try: - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) except ParseError: pass @@ -1744,8 +1745,8 @@ def otwcp_toadmin_view(request,theuser=0, theworkouts = Workout.objects.filter( user=r,rankingpiece=True, workouttype='water', - startdatetime__gte=startdate, - startdatetime__lte=enddate + startdatetime__gte=startdate, + startdatetime__lte=enddate ).order_by("-startdatetime") @@ -1787,27 +1788,27 @@ def otwcp_toadmin_view(request,theuser=0, 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=""): + startdate=timezone.now()-datetime.timedelta(days=365), + enddate=timezone.now(), + startdatestring="", + enddatestring=""): if startdatestring != "": try: - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) except ParseError: pass if enddatestring != "": try: - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) except ParseError: pass if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s if theuser == 0: if 'rowerid' in request.session: @@ -1817,34 +1818,34 @@ def oterankings_view(request,theuser=0, except Rower.DoesNotExist: theuser = request.user.id else: - theuser = request.user.id + 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 + 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 + 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) + form = PredictedPieceForm(request.POST) if form.is_valid(): - value = form.cleaned_data['value'] + value = form.cleaned_data['value'] pieceunit = form.cleaned_data['pieceunit'] else: value = None @@ -1874,17 +1875,17 @@ def oterankings_view(request,theuser=0, if pieceunit == 'd': trankingdistances.append(value) else: - trankingdurations.append(datetime.time( + trankingdurations.append(datetime.time( minute=minutevalue, hour=hourvalue, second=tvalue )) else: - form = PredictedPieceForm() - dateform = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) + form = PredictedPieceForm() + dateform = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) workouttypeform = OteWorkoutTypeForm() workouttypes = ['rower','slides','dynamic'] trankingdistances = rankingdistances @@ -1892,17 +1893,17 @@ def oterankings_view(request,theuser=0, # get all 2k (if any) - this rower, in date range try: - r = Rower.objects.get(user=theuser) + r = Rower.objects.get(user=theuser) request.session['rowerid'] = r.id except Rower.DoesNotExist: - allergworkouts = [] + allergworkouts = [] raise Http404("Rower doesn't exist") - + try: - uu = User.objects.get(id=theuser) + uu = User.objects.get(id=theuser) except User.DoesNotExist: - uu = '' + uu = '' # test to fix bug @@ -1917,9 +1918,9 @@ def oterankings_view(request,theuser=0, theworkouts = Workout.objects.filter( user=r,rankingpiece=True, - workouttype__in=workouttypes, - startdatetime__gte=startdate, - startdatetime__lte=enddate + workouttype__in=workouttypes, + startdatetime__gte=startdate, + startdatetime__lte=enddate ).order_by("-startdatetime") @@ -1980,10 +1981,10 @@ def oterankings_view(request,theuser=0, 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] + 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] @@ -1993,15 +1994,15 @@ def oterankings_view(request,theuser=0, r.save() paulslope = 1 paulintercept = 1 - message = res[4] + message = res[4] else: ratio = 1 - script = '' - div = '

No ranking pieces found.

' - paulslope = 1 - paulintercept = 1 - p1 = [1,1,1,1] - message = "" + script = '' + div = '

No ranking pieces found.

' + paulslope = 1 + paulintercept = 1 + p1 = [1,1,1,1] + message = "" @@ -2012,22 +2013,22 @@ def oterankings_view(request,theuser=0, for rankingduration in trankingdurations: - t = 3600.*rankingduration.hour - t += 60.*rankingduration.minute - t += rankingduration.second - t += rankingduration.microsecond/1.e6 + 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]) + # 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 pwr <= 0: + pwr = 50. if not np.isnan(pwr): @@ -2038,12 +2039,12 @@ def oterankings_view(request,theuser=0, a = { 'distance':int(d), - 'duration':timedeltaconv(t), - 'power':int(pwr), + 'duration':timedeltaconv(t), + 'power':int(pwr), 'upper':int(pwr2), 'pace':timedeltaconv(p)} - cpredictions.append(a) + cpredictions.append(a) # initiation - get 10 min power, then use Paul's law @@ -2067,43 +2068,43 @@ def oterankings_view(request,theuser=0, velo = 500./p t = rankingdistance/velo - pwr2 = p1[0]/(1+t/p1[2]) - pwr2 += p1[1]/(1+t/p1[3]) + 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 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 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 + 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 = { + a = { 'distance':rankingdistance, - 'duration':timedeltaconv(t3), - 'power':'--', - 'upper':int(pwr3), + 'duration':timedeltaconv(t3), + 'power':'--', + 'upper':int(pwr3), 'pace':timedeltaconv(p3)} cpredictions.append(a) @@ -2113,23 +2114,23 @@ def oterankings_view(request,theuser=0, messages.error(request,message) return render(request, 'oterankings.html', - {'rankingworkouts':theworkouts, - 'interactiveplot':script, - 'the_div':div, + {'rankingworkouts':theworkouts, + 'interactiveplot':script, + 'the_div':div, 'rower':r, 'active':'nav-analysis', - 'cpredictions':cpredictions, + 'cpredictions':cpredictions, 'avgpower':avgpower, - 'form':form, - 'dateform':dateform, + 'form':form, + 'dateform':dateform, 'workouttypeform':workouttypeform, - 'id': theuser, - 'theuser':uu, - 'startdate':startdate, - 'enddate':enddate, + 'id': theuser, + 'theuser':uu, + 'startdate':startdate, + 'enddate':enddate, 'teams':get_my_teams(request.user), 'workouttype':'rower', - }) + }) @@ -2807,15 +2808,15 @@ def user_boxplot_select(request, if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s if request.method == 'POST': @@ -3199,11 +3200,11 @@ def boxplot_view(request,userid=0, # 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="", + startdate=timezone.now()-datetime.timedelta(days=30), + enddate=timezone.now(), + deltadays=-1, + startdatestring="", + enddatestring="", options={ 'includereststrokes':False, 'workouttypes':['rower','dynamic','slides'], @@ -3253,30 +3254,30 @@ def cumstats(request,theuser=0, if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) + startdate = iso8601.parse_date(startdatestring) if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) + enddate = iso8601.parse_date(enddatestring) if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s - + # get all indoor rows of in date range # process form if request.method == 'POST': - form = DateRangeForm(request.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 + 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(): @@ -3296,14 +3297,14 @@ def cumstats(request,theuser=0, request.session['waterboattype'] = waterboattype request.session['rankingonly'] = rankingonly form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) + 'startdate': startdate, + 'enddate': enddate, + }) else: - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) + form = DateRangeForm(initial={ + 'startdate': startdate, + 'enddate': enddate, + }) includereststrokes = False workstrokesonly = not includereststrokes @@ -3358,19 +3359,19 @@ def cumstats(request,theuser=0, if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s promember=0 if theuser == 0: - theuser = request.user.id + 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 + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 r2 = getrower(theuser) @@ -3381,10 +3382,10 @@ def cumstats(request,theuser=0, allworkouts = Workout.objects.filter( user=r2, - workouttype__in=modalities, + workouttype__in=modalities, boattype__in=waterboattype, - startdatetime__gte=startdate, - startdatetime__lte=enddate, + startdatetime__gte=startdate, + startdatetime__lte=enddate, rankingpiece__in=rankingpiece ).order_by("-date", "-starttime") @@ -3410,18 +3411,18 @@ def cumstats(request,theuser=0, cordict = {} response = render(request, - 'cumstats.html', - { + '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, + 'id':theuser, + 'theuser':theuser, + 'startdate':startdate, + 'enddate':enddate, + 'form':form, 'optionsform':modalityform, 'cordict':cordict, }) @@ -3472,18 +3473,18 @@ def cumstats(request,theuser=0, response = render(request, - 'cumstats.html', - { + '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, + 'id':theuser, + 'theuser':theuser, + 'startdate':startdate, + 'enddate':enddate, + 'form':form, 'optionsform':modalityform, 'cordict':cordict, }) @@ -3536,8 +3537,8 @@ def agegrouprecordview(request,sex='male',weightcategory='hwt', weightcategory=weightcategory) return render(request, 'agegroupchart.html', - { - 'interactiveplot':script, + { + 'interactiveplot':script, 'active':'nav-analysis', - 'the_div':div, - }) + 'the_div':div, + }) diff --git a/rowers/views/apiviews.py b/rowers/views/apiviews.py index 1a0271c9..180e1e9a 100644 --- a/rowers/views/apiviews.py +++ b/rowers/views/apiviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * # Stroke data form to test API upload @@ -18,22 +18,22 @@ def strokedataform(request,id=0): if request.method == 'GET': form = StrokeDataForm() return render(request, 'strokedata_form.html', - { - 'form':form, + { + 'form':form, 'teams':get_my_teams(request.user), 'id':id, 'workout':w, - }) + }) elif request.method == 'POST': form = StrokeDataForm() return render(request, 'strokedata_form.html', - { - 'form':form, + { + 'form':form, 'teams':get_my_teams(request.user), 'id':id, 'workout':w, - }) + }) # Process the POSTed stroke data according to the API definition # Return the GET stroke data according to the API definition @@ -124,30 +124,30 @@ def strokedatajson(request,id): logfile.write(request.user.username+"(POST) \r\n") data = pd.DataFrame({'TimeStamp (sec)':unixtime, - ' Horizontal (meters)': distance, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' DragFactor':dragfactor, - ' Stroke500mPace (sec/500m)':pace, - ' Power (watts)':power, - ' DriveLength (meters)':drivelength, - ' DriveTime (ms)':drivetime, - ' StrokeRecoveryTime (ms)':strokerecoverytime, - ' AverageDriveForce (lbs)':averagedriveforce, - ' PeakDriveForce (lbs)':peakdriveforce, - ' lapIdx':lapidx, - ' ElapsedTime (sec)':time, + ' Horizontal (meters)': distance, + ' Cadence (stokes/min)':spm, + ' HRCur (bpm)':hr, + ' DragFactor':dragfactor, + ' Stroke500mPace (sec/500m)':pace, + ' Power (watts)':power, + ' DriveLength (meters)':drivelength, + ' DriveTime (ms)':drivetime, + ' StrokeRecoveryTime (ms)':strokerecoverytime, + ' AverageDriveForce (lbs)':averagedriveforce, + ' PeakDriveForce (lbs)':peakdriveforce, + ' lapIdx':lapidx, + ' ElapsedTime (sec)':time, 'catch':catch, 'slip':slip, 'finish':finish, 'wash':wash, 'driveenergy':driveenergy, 'peakforceangle':peakforceangle, - }) + }) # Following part should be replaced with dataprep.new_workout_from_df - r = getrower(request.user) + r = getrower(request.user) timestr = row.startdatetime.strftime("%Y%m%d-%H%M%S") csvfilename ='media/Import_'+timestr+'.csv' @@ -167,8 +167,8 @@ def strokedatajson(request,id): ftp = ftp*(100.-r.otwslack)/100. rr = rrower(hrmax=r.max,hrut2=r.ut2, - hrut1=r.ut1,hrat=r.at, - hrtr=r.tr,hran=r.an,ftp=ftp, + hrut1=r.ut1,hrat=r.at, + hrtr=r.tr,hran=r.an,ftp=ftp, powerperc=powerperc,powerzones=r.powerzones) rowdata = rdata(row.csvfilename,rower=rr).df diff --git a/rowers/views/errorviews.py b/rowers/views/errorviews.py index a1c31901..2a46209f 100644 --- a/rowers/views/errorviews.py +++ b/rowers/views/errorviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * # Custom error pages with Rowsandall headers def error500_view(request): diff --git a/rowers/views/exportviews.py b/rowers/views/exportviews.py index a71d9a4f..4c953375 100644 --- a/rowers/views/exportviews.py +++ b/rowers/views/exportviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index dfe4b936..5ae430da 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * # Send workout to TP @@ -71,17 +71,17 @@ def workout_strava_upload_view(request,id=0): return HttpResponseRedirect("/rowers/me/stravaauthorize/") if (r.stravatoken == '') or (r.stravatoken is None): - s = "Token doesn't exist. Need to authorize" - return HttpResponseRedirect("/rowers/me/stravaauthorize/") + s = "Token doesn't exist. Need to authorize" + return HttpResponseRedirect("/rowers/me/stravaauthorize/") else: - # ready to upload. Hurray + # ready to upload. Hurray w = get_workout_permitted(request.user,id) r = w.user - if (checkworkoutuser(request.user,w)): + if (checkworkoutuser(request.user,w)): try: - tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w) + tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w) if tcxfile: - with open(tcxfile,'rb') as f: + with open(tcxfile,'rb') as f: try: newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com' except TypeError: @@ -91,38 +91,38 @@ def workout_strava_upload_view(request,id=0): else: activity_type = mytypes.stravamapping[w.workouttype] - res,mes = stravastuff.handle_stravaexport( + res,mes = stravastuff.handle_stravaexport( f,w.name, - r.stravatoken, - description=newnotes, + r.stravatoken, + description=newnotes, activity_type=activity_type) if res==0: messages.error(request,mes) - w.uploadedtostrava = -1 - w.save() + w.uploadedtostrava = -1 + w.save() try: - os.remove(tcxfile) + os.remove(tcxfile) except WindowsError: pass - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - response = HttpResponseRedirect(url) + url = reverse(r.defaultlandingpage, + kwargs = { + 'id':encoder.encode_hex(w.id), + }) + response = HttpResponseRedirect(url) return response try: - w.uploadedtostrava = res - w.save() + w.uploadedtostrava = res + w.save() try: - os.remove(tcxfile) + os.remove(tcxfile) except WindowsError: pass url = reverse('workout_edit_view',kwargs={'id':w.id}) messages.info(request,mes) - except: + except: with open("media/stravaerrors.log","a") as errorlog: errorstring = str(sys.exc_info()[0]) timestr = strftime("%Y%m%d-%H%M%S") @@ -135,33 +135,33 @@ def workout_strava_upload_view(request,id=0): messages.error(request,message) w.uploadedtostrava = -1 w.save() - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - response = HttpResponseRedirect(url) + url = reverse(r.defaultlandingpage, + kwargs = { + 'id':encoder.encode_hex(w.id), + }) + response = HttpResponseRedirect(url) - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - } - ) - response = HttpResponseRedirect(url) - except ActivityUploadFailed as e: - message = "Strava Upload error: %s" % e + url = reverse(r.defaultlandingpage, + kwargs = { + 'id':encoder.encode_hex(w.id), + } + ) + response = HttpResponseRedirect(url) + except ActivityUploadFailed as e: + message = "Strava Upload error: %s" % e messages.error(request,message) - w.uploadedtostrava = -1 - w.save() - os.remove(tcxfile) - url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) - response = HttpResponseRedirect(url) + w.uploadedtostrava = -1 + w.save() + os.remove(tcxfile) + url = reverse(r.defaultlandingpage, + kwargs = { + 'id':encoder.encode_hex(w.id), + }) + response = HttpResponseRedirect(url) - return response - + return response + # Upload workout to Concept2 logbook @login_required() def workout_c2_upload_view(request,id=0): @@ -199,59 +199,59 @@ def workout_runkeeper_upload_view(request,id=0): r = w.user try: - thetoken = runkeeper_open(r.user) + thetoken = runkeeper_open(r.user) except NoTokenError: - return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") + return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") # ready to upload. Hurray if (checkworkoutuser(request.user,w)): - data = runkeeperstuff.createrunkeeperworkoutdata(w) + data = runkeeperstuff.createrunkeeperworkoutdata(w) if not data: message = "Data error" messages.error(request,message) url = reverse(r.defaultlandingpage, - kwargs = { - 'id':id, - }) + kwargs = { + 'id':id, + }) return HttpResponseRedirect(url) - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json', + authorizationstring = str('Bearer ' + thetoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/vnd.com.runkeeper.NewFitnessActivity+json', 'Content-Length':'nnn'} - url = "https://api.runkeeper.com/fitnessActivities" - response = requests.post(url,headers=headers,data=json.dumps(data)) + url = "https://api.runkeeper.com/fitnessActivities" + response = requests.post(url,headers=headers,data=json.dumps(data)) - # check for duplicate error first - if (response.status_code == 409 ): - message = "Duplicate error" + # check for duplicate error first + if (response.status_code == 409 ): + message = "Duplicate error" messages.error(request,message) - w.uploadedtorunkeeper = -1 - w.save() - elif (response.status_code == 201 or response.status_code==200): - runkeeperid = runkeeperstuff.getidfromresponse(response) - w.uploadedtorunkeeper = runkeeperid - w.save() + w.uploadedtorunkeeper = -1 + w.save() + elif (response.status_code == 201 or response.status_code==200): + runkeeperid = runkeeperstuff.getidfromresponse(response) + w.uploadedtorunkeeper = runkeeperid + w.save() url = reverse('workout_edit_view', kwargs={'id':encoder.encode_hex(w.id)}) - return HttpResponseRedirect(url) - else: - s = response - message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text) + return HttpResponseRedirect(url) + else: + s = response + message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text) messages.error(request,message) - + else: - message = "You are not authorized to upload this workout" + message = "You are not authorized to upload this workout" messages.error(request,message) url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) + kwargs = { + 'id':encoder.encode_hex(w.id), + }) return HttpResponseRedirect(url) @@ -263,59 +263,59 @@ def workout_underarmour_upload_view(request,id=0): r = w.user try: - thetoken = underarmour_open(r.user) + thetoken = underarmour_open(r.user) except NoTokenError: - return HttpResponseRedirect("/rowers/me/underarmourauthorize/") + return HttpResponseRedirect("/rowers/me/underarmourauthorize/") # ready to upload. Hurray if (checkworkoutuser(request.user,w)): - data = underarmourstuff.createunderarmourworkoutdata(w) + data = underarmourstuff.createunderarmourworkoutdata(w) if not data: message = "Data error" messages.error(request,message) url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) + kwargs = { + 'id':encoder.encode_hex(w.id), + }) return HttpResponseRedirect(url) - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, + authorizationstring = str('Bearer ' + thetoken) + headers = {'Authorization': authorizationstring, 'Api-Key': UNDERARMOUR_CLIENT_KEY, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json', + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json', } - url = "https://api.ua.com/v7.1/workout/" - response = requests.post(url,headers=headers,data=json.dumps(data)) + url = "https://api.ua.com/v7.1/workout/" + response = requests.post(url,headers=headers,data=json.dumps(data)) - # check for duplicate error first - if (response.status_code == 409 ): - message = "Duplicate error" + # check for duplicate error first + if (response.status_code == 409 ): + message = "Duplicate error" messages.error(request,message) - w.uploadedtounderarmour = -1 - w.save() - elif (response.status_code == 201 or response.status_code==200): - underarmourid = underarmourstuff.getidfromresponse(response) - w.uploadedtounderarmour = underarmourid - w.save() + w.uploadedtounderarmour = -1 + w.save() + elif (response.status_code == 201 or response.status_code==200): + underarmourid = underarmourstuff.getidfromresponse(response) + w.uploadedtounderarmour = underarmourid + w.save() url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) - return HttpResponseRedirect(url) - else: - s = response - message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason - messages.error(request,message) + return HttpResponseRedirect(url) + else: + s = response + message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason + messages.error(request,message) else: - message = "You are not authorized to upload this workout" + message = "You are not authorized to upload this workout" messages.error(request,message) url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) + kwargs = { + 'id':encoder.encode_hex(w.id), + }) return HttpResponseRedirect(url) @@ -328,64 +328,64 @@ def workout_sporttracks_upload_view(request,id=0): r = w.user try: - thetoken = sporttracks_open(r.user) + thetoken = sporttracks_open(r.user) except NoTokenError: - return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") + return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") if (checkworkoutuser(request.user,w)): - data = sporttracksstuff.createsporttracksworkoutdata(w) + data = sporttracksstuff.createsporttracksworkoutdata(w) if not data: message = "Data error" messages.error(request,message) url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) + kwargs = { + 'id':encoder.encode_hex(w.id), + }) return HttpResponseRedirect(url) - authorizationstring = str('Bearer ' + thetoken) - headers = {'Authorization': authorizationstring, - 'user-agent': 'sanderroosendaal', - 'Content-Type': 'application/json'} + authorizationstring = str('Bearer ' + thetoken) + headers = {'Authorization': authorizationstring, + 'user-agent': 'sanderroosendaal', + 'Content-Type': 'application/json'} - url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" - response = requests.post(url,headers=headers,data=json.dumps(data)) + url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" + response = requests.post(url,headers=headers,data=json.dumps(data)) - # check for duplicate error first - if (response.status_code == 409 ): - message = "Duplicate error" + # check for duplicate error first + if (response.status_code == 409 ): + message = "Duplicate error" messages.error(request,message) - w.uploadedtosporttracks = -1 - w.save() - elif (response.status_code == 201 or response.status_code==200): - s= response.json() - sporttracksid = sporttracksstuff.getidfromresponse(response) - w.uploadedtosporttracks = sporttracksid - w.save() + w.uploadedtosporttracks = -1 + w.save() + elif (response.status_code == 201 or response.status_code==200): + s= response.json() + sporttracksid = sporttracksstuff.getidfromresponse(response) + w.uploadedtosporttracks = sporttracksid + w.save() message = "Upload to SportTracks was successful" messages.info(request,message) url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)}) - return HttpResponseRedirect(url) - else: - s = response - message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason - messages.error(request,message) + return HttpResponseRedirect(url) + else: + s = response + message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason + messages.error(request,message) else: - message = "You are not authorized to upload this workout" + message = "You are not authorized to upload this workout" messages.error(request,message) url = reverse(r.defaultlandingpage, - kwargs = { - 'id':encoder.encode_hex(w.id), - }) + kwargs = { + 'id':encoder.encode_hex(w.id), + }) return HttpResponseRedirect(url) -# Concept2 authorization +# Concept2 authorization @login_required() def rower_c2_authorize(request): # Generate a random string for the state parameter @@ -411,7 +411,7 @@ def rower_strava_authorize(request): params = {"client_id": STRAVA_CLIENT_ID, "response_type": "code", "redirect_uri": STRAVA_REDIRECT_URI, - "scope": "activity:write,activity:read_all"} + "scope": "activity:write,activity:read_all"} url = "https://www.strava.com/oauth/authorize?"+ urllib.urlencode(params) @@ -427,7 +427,7 @@ def rower_polar_authorize(request): "response_type": "code", "redirect_uri": POLAR_REDIRECT_URI, "state": state, -# "scope":"accesslink.read_all" +# "scope":"accesslink.read_all" } url = "https://flow.polar.com/oauth2/authorization?" +urllib.urlencode(params) @@ -445,7 +445,7 @@ def rower_runkeeper_authorize(request): params = {"client_id": RUNKEEPER_CLIENT_ID, "response_type": "code", - "state": state, + "state": state, "redirect_uri": RUNKEEPER_REDIRECT_URI} url = "https://runkeeper.com/apps/authorize?"+ urllib.urlencode(params) @@ -463,7 +463,7 @@ def rower_sporttracks_authorize(request): params = {"client_id": SPORTTRACKS_CLIENT_ID, "response_type": "code", - "state": state, + "state": state, "redirect_uri": SPORTTRACKS_REDIRECT_URI} url = "https://api.sporttracks.mobi/oauth2/authorize?"+ urllib.urlencode(params) @@ -499,7 +499,7 @@ def rower_tp_authorize(request): "response_type": "code", "redirect_uri": TP_REDIRECT_URI, "scope": "file:write", - } + } url = "https://oauth.trainingpeaks.com/oauth/authorize/?" +urllib.urlencode(params) return HttpResponseRedirect(url) @@ -624,16 +624,16 @@ def rower_sporttracks_token_refresh(request): @login_required() def rower_process_callback(request): try: - code = request.GET['code'] - res = c2stuff.get_token(code) + code = request.GET['code'] + res = c2stuff.get_token(code) except MultiValueDictKeyError: - message = "The resource owner or authorization server denied the request" + message = "The resource owner or authorization server denied the request" messages.error(request,message) url = reverse('workouts_view') return HttpResponseRedirect(url) - + access_token = res[0] if access_token == 0: message = res[1] @@ -643,7 +643,7 @@ def rower_process_callback(request): url = reverse('workouts_view') return HttpResponseRedirect(url) - + expires_in = res[1] refresh_token = res[2] @@ -893,24 +893,24 @@ def workout_stravaimport_view(request,message="",userid=0): messages.info(request,"You cannot import other people's workouts from Strava") try: - thetoken = strava_open(request.user) + thetoken = strava_open(request.user) except NoTokenError: - return HttpResponseRedirect("/rowers/me/stravaauthorize/") + return HttpResponseRedirect("/rowers/me/stravaauthorize/") res = stravastuff.get_strava_workout_list(request.user) if (res.status_code != 200): - if (res.status_code == 401): - r = getrower(request.user) - if (r.stravatoken == '') or (r.stravatoken is None): - s = "Token doesn't exist. Need to authorize" - return HttpResponseRedirect("/rowers/me/stravaauthorize/") - message = "Something went wrong in workout_stravaimport_view" + if (res.status_code == 401): + r = getrower(request.user) + if (r.stravatoken == '') or (r.stravatoken is None): + s = "Token doesn't exist. Need to authorize" + return HttpResponseRedirect("/rowers/me/stravaauthorize/") + message = "Something went wrong in workout_stravaimport_view" messages.error(request,message) - url = reverse('workouts_view') - return HttpResponseRedirect(url) + url = reverse('workouts_view') + return HttpResponseRedirect(url) else: workouts = [] r = getrower(request.user) @@ -944,7 +944,7 @@ def workout_stravaimport_view(request,message="",userid=0): ]) newids = [stravaid for stravaid in stravaids if not stravaid in knownstravaids] - for item in res.json(): + for item in res.json(): d = int(float(item['distance'])) i = item['id'] if i in knownstravaids: @@ -956,9 +956,9 @@ def workout_stravaimport_view(request,message="",userid=0): s = item['start_date'] r = item['type'] keys = ['id','distance','duration','starttime','type','name','new'] - values = [i,d,ttot,s,r,n,nnn] - res = dict(zip(keys,values)) - workouts.append(res) + values = [i,d,ttot,s,r,n,nnn] + res = dict(zip(keys,values)) + workouts.append(res) breadcrumbs = [ { @@ -974,13 +974,13 @@ def workout_stravaimport_view(request,message="",userid=0): r = getrower(request.user) - return render(request,'strava_list_import.html', - {'workouts':workouts, + return render(request,'strava_list_import.html', + {'workouts':workouts, 'rower':r, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), - }) + }) return HttpResponse(res) @@ -989,32 +989,32 @@ def workout_stravaimport_view(request,message="",userid=0): def workout_runkeeperimport_view(request,message="",userid=0): res = runkeeperstuff.get_runkeeper_workout_list(request.user) if (res.status_code != 200): - if (res.status_code == 401): - r = getrower(request.user) - if (r.runkeepertoken == '') or (r.runkeepertoken is None): - s = "Token doesn't exist. Need to authorize" - return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") - message = "Something went wrong in workout_runkeeperimport_view" + if (res.status_code == 401): + r = getrower(request.user) + if (r.runkeepertoken == '') or (r.runkeepertoken is None): + s = "Token doesn't exist. Need to authorize" + return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") + message = "Something went wrong in workout_runkeeperimport_view" messages.error(request,message) - if settings.DEBUG: - return HttpResponse(res) - else: - url = reverse('workouts_view') - return HttpResponseRedirect(url) + if settings.DEBUG: + return HttpResponse(res) + else: + url = reverse('workouts_view') + return HttpResponseRedirect(url) workouts = [] for item in res.json()['items']: - d = int(float(item['total_distance'])) - i = getidfromuri(item['uri']) + d = int(float(item['total_distance'])) + i = getidfromuri(item['uri']) ttot = str(datetime.timedelta(seconds=int(float(item['duration'])))) s = item['start_time'] r = item['type'] - keys = ['id','distance','duration','starttime','type'] - values = [i,d,ttot,s,r] + keys = ['id','distance','duration','starttime','type'] + values = [i,d,ttot,s,r] - res = dict(zip(keys,values)) - workouts.append(res) + res = dict(zip(keys,values)) + workouts.append(res) breadcrumbs = [ { @@ -1030,12 +1030,12 @@ def workout_runkeeperimport_view(request,message="",userid=0): r = getrower(request.user) return render(request,'runkeeper_list_import.html', - {'workouts':workouts, + {'workouts':workouts, 'rower':r, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), - }) + }) return HttpResponse(res) @@ -1044,14 +1044,14 @@ def workout_runkeeperimport_view(request,message="",userid=0): def workout_underarmourimport_view(request,message="",userid=0): res = underarmourstuff.get_underarmour_workout_list(request.user) if (res.status_code != 200): - return HttpResponseRedirect("/rowers/me/underarmourauthorize/") + return HttpResponseRedirect("/rowers/me/underarmourauthorize/") workouts = [] items = res.json()['_embedded']['workouts'] for item in items: - s = item['start_datetime'] + s = item['start_datetime'] i,r = underarmourstuff.get_idfromuri(request.user,item['_links']) - n = item['name'] + n = item['name'] try: d = item['aggregates']['distance_total'] except KeyError: @@ -1061,11 +1061,11 @@ def workout_underarmourimport_view(request,message="",userid=0): except KeyError: ttot = 0 - keys = ['id','distance','duration','starttime','type'] - values = [i,d,ttot,s,r] - thedict = dict(zip(keys,values)) + keys = ['id','distance','duration','starttime','type'] + values = [i,d,ttot,s,r] + thedict = dict(zip(keys,values)) - workouts.append(thedict) + workouts.append(thedict) rower = getrower(request.user) breadcrumbs = [ @@ -1080,12 +1080,12 @@ def workout_underarmourimport_view(request,message="",userid=0): ] return render(request,'underarmour_list_import.html', - {'workouts':workouts, + {'workouts':workouts, 'breadcrumbs':breadcrumbs, 'rower':rower, 'active':'nav-workouts', 'teams':get_my_teams(request.user), - }) + }) return HttpResponse(res) @@ -1153,20 +1153,20 @@ def workout_sporttracksimport_view(request,message="",userid=0): res = sporttracksstuff.get_sporttracks_workout_list(request.user) if (res.status_code != 200): - if (res.status_code == 401): - r = getrower(request.user) - if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): - s = "Token doesn't exist. Need to authorize" - return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") + if (res.status_code == 401): + r = getrower(request.user) + if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): + s = "Token doesn't exist. Need to authorize" + return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") else: return HttpResponseRedirect("/rowers/me/sporttracksrefresh/") - message = "Something went wrong in workout_sporttracksimport_view" + message = "Something went wrong in workout_sporttracksimport_view" messages.error(request,message) - if settings.DEBUG: - return HttpResponse(res) - else: - url = reverse('workouts_view') - return HttpResponseRedirect(url) + if settings.DEBUG: + return HttpResponse(res) + else: + url = reverse('workouts_view') + return HttpResponseRedirect(url) workouts = [] r = getrower(request.user) @@ -1177,19 +1177,19 @@ def workout_sporttracksimport_view(request,message="",userid=0): newids = [stid for stid in stids if not stid in knownstids] for item in res.json()['items']: d = int(float(item['total_distance'])) - i = int(getidfromuri(item['uri'])) + i = int(getidfromuri(item['uri'])) if i in knownstids: nnn = '' else: nnn = 'NEW' - n = item['name'] - ttot = str(datetime.timedelta(seconds=int(float(item['duration'])))) - s = item['start_time'] - r = item['type'] - keys = ['id','distance','duration','starttime','type','name','new'] - values = [i,d,ttot,s,r,n,nnn] - res = dict(zip(keys,values)) - workouts.append(res) + n = item['name'] + ttot = str(datetime.timedelta(seconds=int(float(item['duration'])))) + s = item['start_time'] + r = item['type'] + keys = ['id','distance','duration','starttime','type','name','new'] + values = [i,d,ttot,s,r,n,nnn] + res = dict(zip(keys,values)) + workouts.append(res) r = getrower(request.user) @@ -1205,55 +1205,55 @@ def workout_sporttracksimport_view(request,message="",userid=0): ] return render(request,'sporttracks_list_import.html', - {'workouts':workouts, + {'workouts':workouts, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', 'rower':r, 'teams':get_my_teams(request.user), - }) + }) return HttpResponse(res) - + # List of workouts on Concept2 logbook. This view only used for debugging @login_required() def c2listdebug_view(request,page=1,message=""): try: - thetoken = c2_open(request.user) + thetoken = c2_open(request.user) except NoTokenError: - return HttpResponseRedirect("/rowers/me/c2authorize/") + return HttpResponseRedirect("/rowers/me/c2authorize/") r = getrower(request.user) res = c2stuff.get_c2_workout_list(request.user,page=page) if (res.status_code != 200): - message = "Something went wrong in workout_c2import_view (C2 token renewal)" + message = "Something went wrong in workout_c2import_view (C2 token renewal)" messages.error(request,message) - if settings.DEBUG: - return HttpResponse(res) - else: - url = reverse('workouts_view') - return HttpResponseRedirect(url) + if settings.DEBUG: + return HttpResponse(res) + else: + url = reverse('workouts_view') + return HttpResponseRedirect(url) else: - workouts = [] + workouts = [] - for item in res.json()['data']: - d = item['distance'] - i = item['id'] - ttot = item['time_formatted'] - s = item['date'] - r = item['type'] - s2 = item['source'] - c = item['comments'] - keys = ['id','distance','duration','starttime','rowtype','source','comment'] - values = [i,d,ttot,s,r,s2,c] - res = dict(zip(keys,values)) - workouts.append(res) + for item in res.json()['data']: + d = item['distance'] + i = item['id'] + ttot = item['time_formatted'] + s = item['date'] + r = item['type'] + s2 = item['source'] + c = item['comments'] + keys = ['id','distance','duration','starttime','rowtype','source','comment'] + values = [i,d,ttot,s,r,s2,c] + res = dict(zip(keys,values)) + workouts.append(res) - - return render(request, - 'c2_list_import2.html', - {'workouts':workouts, + + return render(request, + 'c2_list_import2.html', + {'workouts':workouts, 'teams':get_my_teams(request.user), }) @@ -1261,14 +1261,14 @@ def c2listdebug_view(request,page=1,message=""): @login_required() def workout_getc2workout_all(request,page=1,message=""): try: - thetoken = c2_open(request.user) + thetoken = c2_open(request.user) except NoTokenError: - return HttpResponseRedirect("/rowers/me/c2authorize/") + return HttpResponseRedirect("/rowers/me/c2authorize/") res = c2stuff.get_c2_workout_list(request.user,page=page) if (res.status_code != 200): - message = "Something went wrong in workout_c2import_view (C2 token refresh)" + message = "Something went wrong in workout_c2import_view (C2 token refresh)" messages.error(request,message) else: r = getrower(request.user) @@ -1302,17 +1302,17 @@ def workout_c2import_view(request,page=1,userid=0,message=""): r = getrower(request.user) try: - thetoken = c2_open(request.user) + thetoken = c2_open(request.user) except NoTokenError: - return HttpResponseRedirect("/rowers/me/c2authorize/") + return HttpResponseRedirect("/rowers/me/c2authorize/") res = c2stuff.get_c2_workout_list(request.user,page=page) if (res.status_code != 200): - message = "Something went wrong in workout_c2import_view (C2 token refresh)" + message = "Something went wrong in workout_c2import_view (C2 token refresh)" messages.error(request,message) - url = reverse('workouts_view') - return HttpResponseRedirect(url) + url = reverse('workouts_view') + return HttpResponseRedirect(url) workouts = [] c2ids = [item['id'] for item in res.json()['data']] @@ -1321,21 +1321,21 @@ def workout_c2import_view(request,page=1,userid=0,message=""): ]) newids = [c2id for c2id in c2ids if not c2id in knownc2ids] for item in res.json()['data']: - d = item['distance'] - i = item['id'] - ttot = item['time_formatted'] - s = item['date'] - r = item['type'] - s2 = item['source'] - c = item['comments'] + d = item['distance'] + i = item['id'] + ttot = item['time_formatted'] + s = item['date'] + r = item['type'] + s2 = item['source'] + c = item['comments'] if i in knownc2ids: nnn = '' else: nnn = 'NEW' - keys = ['id','distance','duration','starttime','rowtype','source','comment','new'] - values = [i,d,ttot,s,r,s2,c,nnn] - res = dict(zip(keys,values)) - workouts.append(res) + keys = ['id','distance','duration','starttime','rowtype','source','comment','new'] + values = [i,d,ttot,s,r,s2,c,nnn] + res = dict(zip(keys,values)) + workouts.append(res) breadcrumbs = [ @@ -1356,8 +1356,8 @@ def workout_c2import_view(request,page=1,userid=0,message=""): r = getrower(request.user) return render(request, - 'c2_list_import2.html', - {'workouts':workouts, + 'c2_list_import2.html', + {'workouts':workouts, 'rower':r, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, @@ -1449,7 +1449,7 @@ def workout_getimportview(request,externalid,source = 'c2'): 'id':encoder.encode_hex(w.id), }) - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) # strokedata not empty - continue id,message = importsources[source].add_workout_from_data( diff --git a/rowers/views/otherviews.py b/rowers/views/otherviews.py index 1b1764d6..4cd0ef48 100644 --- a/rowers/views/otherviews.py +++ b/rowers/views/otherviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * @login_required() diff --git a/rowers/views/paymentviews.py b/rowers/views/paymentviews.py index 03887525..b820b30d 100644 --- a/rowers/views/paymentviews.py +++ b/rowers/views/paymentviews.py @@ -1,5 +1,5 @@ -from statements import * +from rowers.views.statements import * def paidplans_view(request): if not request.user.is_anonymous(): @@ -478,32 +478,32 @@ def rower_register_view(request): nextpage = '/rowers/list-workouts/' if request.method == 'POST': - #form = RegistrationFormUniqueEmail(request.POST) - form = RegistrationFormSex(request.POST) - if form.is_valid(): - first_name = form.cleaned_data['first_name'] - last_name = form.cleaned_data['last_name'] - email = form.cleaned_data['email'] - password = form.cleaned_data['password1'] - username = form.cleaned_data['username'] + #form = RegistrationFormUniqueEmail(request.POST) + form = RegistrationFormSex(request.POST) + if form.is_valid(): + first_name = form.cleaned_data['first_name'] + last_name = form.cleaned_data['last_name'] + email = form.cleaned_data['email'] + password = form.cleaned_data['password1'] + username = form.cleaned_data['username'] sex = form.cleaned_data['sex'] birthdate = form.cleaned_data['birthdate'] weightcategory = form.cleaned_data['weightcategory'] adaptiveclass = form.cleaned_data['adaptiveclass'] nextpage = request.POST['next'] - theuser = User.objects.create_user(username,password=password) - theuser.first_name = first_name - theuser.last_name = last_name - theuser.email = email - theuser.save() + theuser = User.objects.create_user(username,password=password) + theuser.first_name = first_name + theuser.last_name = last_name + theuser.email = email + theuser.save() birthdate = birthdate.replace(tzinfo=None) - therower = Rower(user=theuser,sex=sex,birthdate=birthdate, + therower = Rower(user=theuser,sex=sex,birthdate=birthdate, weightcategory=weightcategory, adaptiveclass=adaptiveclass) - therower.save() + therower.save() # create default favorite charts add_defaultfavorites(therower) @@ -523,8 +523,8 @@ def rower_register_view(request): w.save() # Create and send email - fullemail = first_name + " " + last_name + " " + "<" + email + ">" - subject = "Thank you for registering on rowsandall.com" + fullemail = first_name + " " + last_name + " " + "<" + email + ">" + subject = "Thank you for registering on rowsandall.com" from_address = 'Sander Roosendaal ' d = {'first_name':theuser.first_name} @@ -533,31 +533,31 @@ def rower_register_view(request): subject,'registeremail.html',d) - subject2 = "New User" - message2 = "New user registered.\n" - message2 += fullemail + "\n" - message2 += "User name: "+username + subject2 = "New User" + message2 = "New user registered.\n" + message2 += fullemail + "\n" + message2 += "User name: "+username - send_mail(subject2, message2, - 'Rowsandall Server ', - ['roosendaalsander@gmail.com']) + send_mail(subject2, message2, + 'Rowsandall Server ', + ['roosendaalsander@gmail.com']) theuser = authenticate(username=username,password=password) login(request,theuser) - return HttpResponseRedirect(nextpage) + return HttpResponseRedirect(nextpage) # '/rowers/register/thankyou/') - else: - return render(request, - "registration_form.html", - {'form':form, + else: + return render(request, + "registration_form.html", + {'form':form, 'next':nextpage,}) else: - form = RegistrationFormSex() - return render(request, - "registration_form.html", - {'form':form, + form = RegistrationFormSex() + return render(request, + "registration_form.html", + {'form':form, 'next':nextpage,}) @login_required() diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py index ce698175..ba23042d 100644 --- a/rowers/views/planviews.py +++ b/rowers/views/planviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * @login_required() def plannedsession_comment_view(request,id=0,userid=0): @@ -496,8 +496,6 @@ def plannedsession_multicreate_view(request, for obj in ps_formset.deleted_objects: messages.info(request,"Deleted Planned Session "+str(obj)) obj.delete() - else: - print ps_formset.errors url = reverse(plannedsession_multicreate_view, kwargs = { diff --git a/rowers/views/racesviews.py b/rowers/views/racesviews.py index 438f9033..c74e6059 100644 --- a/rowers/views/racesviews.py +++ b/rowers/views/racesviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * # List Courses @@ -653,7 +653,7 @@ def virtualevent_disqualify_view(request,raceid=0,recordid=0): latitude = rowdata.df[' latitude'] if not latitude.std(): hascoordinates = 0 - except KeyError, AttributeError: + except (KeyError, AttributeError): hascoordinates = 0 else: hascoordinates = 0 diff --git a/rowers/views/statements.py b/rowers/views/statements.py index 3f1ec013..f6b576c0 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -1,7 +1,7 @@ import time import colorsys -import timestring + import zipfile import bleach import arrow @@ -56,7 +56,11 @@ from rowers.forms import ( MetricsForm,DisqualificationForm,disqualificationreasons, disqualifiers,SearchForm,BillingForm,PlanSelectForm ) -from django.core.urlresolvers import reverse, reverse_lazy + +try: + from django.core.urlresolvers import reverse, reverse_lazy +except ModuleNotFoundError: + from django.urls import reverse, reverse_lazy from django.core.exceptions import PermissionDenied from django.template import RequestContext @@ -181,7 +185,10 @@ from rowers.tasks import ( from scipy.signal import savgol_filter from django.shortcuts import render_to_response -from Cookie import SimpleCookie +try: + from Cookie import SimpleCookie +except ModuleNotFoundError: + from http.cookies import SimpleCookie from shutil import copyfile,move import rowers.mytypes as mytypes from rowingdata import rower as rrower @@ -287,7 +294,7 @@ def getrequestrower(request,rowerid=0,userid=0,notpermanent=False): u = User.objects.get(id=userid) r = getrower(u) else: - r = getrower(request.user) + r = getrower(request.user) except Rower.DoesNotExist: raise Http404("Rower doesn't exist") @@ -320,7 +327,7 @@ def getrequestplanrower(request,rowerid=0,userid=0,notpermanent=False): u = User.objects.get(id=userid) r = getrower(u) else: - r = getrower(request.user) + r = getrower(request.user) except Rower.DoesNotExist: raise Http404("Rower doesn't exist") @@ -415,7 +422,7 @@ class SessionTaskListener(threading.Thread): for item in self.pubsub.listen(): if item['data'] == "KILL": self.pubsub.unsubscribe() - print self, "unsubscribed and finished" + print(self, "unsubscribed and finished") break else: self.work(item) @@ -465,7 +472,7 @@ from rowers.interactiveplots import * from rowers.celery import result as celery_result # Define the API documentation -schema_view = get_swagger_view(title='Rowsandall API') +#schema_view = get_swagger_view(title='Rowsandall API') def remove_asynctask(request,id): try: @@ -740,9 +747,9 @@ def get_thumbnails(request,id): r = getrower(request.user) result = request.user.is_authenticated() and ispromember(request.user) if result: - promember=1 + promember=1 if request.user == row.user.user: - mayedit=1 + mayedit=1 comments = WorkoutComment.objects.filter(workout=row) @@ -872,7 +879,7 @@ def rowhascoordinates(row): if not latitude.std(): hascoordinates = 0 - except KeyError,AttributeError: + except (KeyError,AttributeError): hascoordinates = 0 else: @@ -885,11 +892,11 @@ def rowhascoordinates(row): # Checks for CSV file, then for gzipped CSV file, and if all fails, returns 0 def rdata(file,rower=rrower()): try: - res = rrdata(csvfile=file,rower=rower) - except IOError, IndexError: + res = rrdata(csvfile=file,rower=rower) + except (IOError, IndexError): try: res = rrdata(csvfile=file+'.gz',rower=rower) - except IOError, IndexError: + except (IOError, IndexError): res = 0 return res @@ -913,24 +920,24 @@ def get_my_teams(user): # Used for the interval editor - translates seconds to a time object def get_time(second): if (second<=0) or (second>1e9): - hours = 0 - minutes=0 - sec=0 - microsecond = 0 + hours = 0 + minutes=0 + sec=0 + microsecond = 0 elif math.isnan(second): - hours = 0 - minutes=0 - sec=0 - microsecond = 0 + hours = 0 + minutes=0 + sec=0 + microsecond = 0 else: - days = int(second/(24.*3600.)) % (24*3600) - hours = int((second-24.*3600.*days)/3600.) % 24 - minutes = int((second-3600.*(hours+24.*days))/60.) % 60 - sec = int(second-3600.*(hours+24.*days)-60.*minutes) % 60 - microsecond = int(1.0e6*(second-3600.*(hours+24.*days)-60.*minutes-sec)) + days = int(second/(24.*3600.)) % (24*3600) + hours = int((second-24.*3600.*days)/3600.) % 24 + minutes = int((second-3600.*(hours+24.*days))/60.) % 60 + sec = int(second-3600.*(hours+24.*days)-60.*minutes) % 60 + microsecond = int(1.0e6*(second-3600.*(hours+24.*days)-60.*minutes-sec)) return datetime.time(hours,minutes,sec,microsecond) - + # get the workout ID from the SportTracks URI def getidfromsturi(uri,length=8): return uri[len(uri)-length:] @@ -942,7 +949,7 @@ def getidfromuri(uri): return m.group(2) - + from rowers.utils import ( geo_distance,serialize_list,deserialize_list,uniqify, str2bool,range_to_color_hex,absolute,myqueue,get_call, @@ -1041,24 +1048,24 @@ def sendmail(request): if request.method == 'POST': form = EmailForm(request.POST) if form.is_valid(): - firstname = form.cleaned_data['firstname'] - lastname = form.cleaned_data['lastname'] - email = form.cleaned_data['email'] - subject = form.cleaned_data['subject'] - botcheck = form.cleaned_data['botcheck'].lower() - message = form.cleaned_data['message'] - if botcheck == 'yes': - try: - fullemail = firstname + " " + lastname + " " + "<" + email + ">" - send_mail(subject, message, fullemail, ['info@rowsandall.com']) - return HttpResponseRedirect('/rowers/email/thankyou/') - except: - return HttpResponseRedirect('/rowers/email/') - else: + firstname = form.cleaned_data['firstname'] + lastname = form.cleaned_data['lastname'] + email = form.cleaned_data['email'] + subject = form.cleaned_data['subject'] + botcheck = form.cleaned_data['botcheck'].lower() + message = form.cleaned_data['message'] + if botcheck == 'yes': + try: + fullemail = firstname + " " + lastname + " " + "<" + email + ">" + send_mail(subject, message, fullemail, ['info@rowsandall.com']) + return HttpResponseRedirect('/rowers/email/thankyou/') + except: + return HttpResponseRedirect('/rowers/email/') + else: messages.error(request,'You have to answer YES to the question') - return HttpResponseRedirect('/rowers/email/') - else: - return HttpResponseRedirect('/rowers/email/') + return HttpResponseRedirect('/rowers/email/') + else: + return HttpResponseRedirect('/rowers/email/') else: return HttpResponseRedirect('/rowers/email/') @@ -1074,43 +1081,43 @@ def add_workout_from_strokedata(user,importid,data,strokedata, workouttype = 'rower' if workouttype not in [x[0] for x in Workout.workouttypes]: - workouttype = 'other' + workouttype = 'other' try: - comments = data['comments'] + comments = data['comments'] except: - comments = ' ' + comments = ' ' # comments = "Imported data \n %s" % comments # comments = "Imported data \n"+comments # str(comments) try: - thetimezone = tz(data['timezone']) + thetimezone = tz(data['timezone']) except: - thetimezone = 'UTC' + thetimezone = 'UTC' r = getrower(user) try: - rowdatetime = iso8601.parse_date(data['date_utc']) + rowdatetime = iso8601.parse_date(data['date_utc']) except KeyError: - rowdatetime = iso8601.parse_date(data['start_date']) + rowdatetime = iso8601.parse_date(data['start_date']) except ParseError: - rowdatetime = iso8601.parse_date(data['date']) + rowdatetime = iso8601.parse_date(data['date']) - + try: c2intervaltype = data['workout_type'] - + except KeyError: - c2intervaltype = '' - + c2intervaltype = '' + try: - title = data['name'] + title = data['name'] except KeyError: - title = "" - try: - t = data['comments'].split('\n', 1)[0] - title += t[:20] - except: - title = 'Imported' + title = "" + try: + t = data['comments'].split('\n', 1)[0] + title += t[:20] + except: + title = 'Imported' starttimeunix = arrow.get(rowdatetime).timestamp @@ -1125,17 +1132,17 @@ def add_workout_from_strokedata(user,importid,data,strokedata, nr_rows = len(unixtime) try: - latcoord = strokedata.loc[:,'lat'] - loncoord = strokedata.loc[:,'lon'] + latcoord = strokedata.loc[:,'lat'] + loncoord = strokedata.loc[:,'lon'] except: - latcoord = np.zeros(nr_rows) - loncoord = np.zeros(nr_rows) + latcoord = np.zeros(nr_rows) + loncoord = np.zeros(nr_rows) try: - strokelength = strokedata.loc[:,'strokelength'] + strokelength = strokedata.loc[:,'strokelength'] except: - strokelength = np.zeros(nr_rows) + strokelength = np.zeros(nr_rows) dist2 = 0.1*strokedata.loc[:,'d'] @@ -1159,27 +1166,27 @@ def add_workout_from_strokedata(user,importid,data,strokedata, # save csv # Create data frame with all necessary data to write to csv df = pd.DataFrame({'TimeStamp (sec)':unixtime, - ' Horizontal (meters)': dist2, - ' Cadence (stokes/min)':spm, - ' HRCur (bpm)':hr, - ' longitude':loncoord, - ' latitude':latcoord, - ' Stroke500mPace (sec/500m)':pace, - ' Power (watts)':power, - ' DragFactor':np.zeros(nr_rows), - ' DriveLength (meters)':np.zeros(nr_rows), - ' StrokeDistance (meters)':strokelength, - ' DriveTime (ms)':np.zeros(nr_rows), - ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), - ' AverageDriveForce (lbs)':np.zeros(nr_rows), - ' PeakDriveForce (lbs)':np.zeros(nr_rows), - ' lapIdx':lapidx, - ' ElapsedTime (sec)':seconds - }) + ' Horizontal (meters)': dist2, + ' Cadence (stokes/min)':spm, + ' HRCur (bpm)':hr, + ' longitude':loncoord, + ' latitude':latcoord, + ' Stroke500mPace (sec/500m)':pace, + ' Power (watts)':power, + ' DragFactor':np.zeros(nr_rows), + ' DriveLength (meters)':np.zeros(nr_rows), + ' StrokeDistance (meters)':strokelength, + ' DriveTime (ms)':np.zeros(nr_rows), + ' StrokeRecoveryTime (ms)':np.zeros(nr_rows), + ' AverageDriveForce (lbs)':np.zeros(nr_rows), + ' PeakDriveForce (lbs)':np.zeros(nr_rows), + ' lapIdx':lapidx, + ' ElapsedTime (sec)':seconds + }) df.sort_values(by='TimeStamp (sec)',ascending=True) - + timestr = strftime("%Y%m%d-%H%M%S") diff --git a/rowers/views/teamviews.py b/rowers/views/teamviews.py index 821885bf..f8a8429e 100644 --- a/rowers/views/teamviews.py +++ b/rowers/views/teamviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * @login_required() diff --git a/rowers/views/userviews.py b/rowers/views/userviews.py index c80e7ab8..74ff1b49 100644 --- a/rowers/views/userviews.py +++ b/rowers/views/userviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * @login_required() def start_trial_view(request): @@ -22,8 +22,8 @@ def start_trial_view(request): message2 += "User name: "+request.user.username send_mail(subject2, message2, - 'Rowsandall Server ', - ['roosendaalsander@gmail.com']) + 'Rowsandall Server ', + ['roosendaalsander@gmail.com']) return HttpResponseRedirect(url) @@ -50,8 +50,8 @@ def start_plantrial_view(request): message2 += "User name: "+request.user.username send_mail(subject2, message2, - 'Rowsandall Server ', - ['roosendaalsander@gmail.com']) + 'Rowsandall Server ', + ['roosendaalsander@gmail.com']) return HttpResponseRedirect(url) @@ -151,7 +151,7 @@ def rower_exportsettings_view(request,userid=0): ] return render(request, 'rower_exportsettings.html', - {'form':form, + {'form':form, 'rower':r, 'breadcrumbs': breadcrumbs, }) @@ -242,14 +242,14 @@ def rower_edit_view(request,rowerid=0,userid=0,message=""): grants = AccessToken.objects.filter(user=request.user) return render(request, 'rower_form.html', - { + { 'teams':get_my_teams(request.user), 'breadcrumbs':breadcrumbs, 'grants':grants, 'userform':userform, 'accountform':accountform, 'rower':r, - }) + }) # Page where user can set his details @@ -276,43 +276,43 @@ def rower_prefs_view(request,userid=0,message=""): powerzonesform = RowerPowerZonesForm(instance=r) if request.method == 'POST' and "ut2" in request.POST: - form = RowerForm(request.POST) - if form.is_valid(): - # something - cd = form.cleaned_data - hrmax = cd['max'] - ut2 = cd['ut2'] - ut1 = cd['ut1'] - at = cd['at'] - tr = cd['tr'] - an = cd['an'] - rest = cd['rest'] + form = RowerForm(request.POST) + if form.is_valid(): + # something + cd = form.cleaned_data + hrmax = cd['max'] + ut2 = cd['ut2'] + ut1 = cd['ut1'] + at = cd['at'] + tr = cd['tr'] + an = cd['an'] + rest = cd['rest'] - r.max = max(min(hrmax,250),10) - r.ut2 = max(min(ut2,250),10) - r.ut1 = max(min(ut1,250),10) - r.at = max(min(at,250),10) - r.tr = max(min(tr,250),10) - r.an = max(min(an,250),10) - r.rest = max(min(rest,250),10) - r.save() + r.max = max(min(hrmax,250),10) + r.ut2 = max(min(ut2,250),10) + r.ut1 = max(min(ut1,250),10) + r.at = max(min(at,250),10) + r.tr = max(min(tr,250),10) + r.an = max(min(an,250),10) + r.rest = max(min(rest,250),10) + r.save() successmessage = "Your Heart Rate data were changed" messages.info(request,successmessage) elif request.method == 'POST' and "ftp" in request.POST: - powerform = RowerPowerForm(request.POST) - if powerform.is_valid(): - cd = powerform.cleaned_data + powerform = RowerPowerForm(request.POST) + if powerform.is_valid(): + cd = powerform.cleaned_data hrftp = cd['hrftp'] if hrftp == 0: hrftp = int((r.an+r.tr)/2.) - ftp = cd['ftp'] + ftp = cd['ftp'] otwslack = cd['otwslack'] powerfrac = 100*np.array([r.pw_ut2, r.pw_ut1, r.pw_at, r.pw_tr,r.pw_an])/r.ftp - r.ftp = max(min(ftp,650),50) + r.ftp = max(min(ftp,650),50) r.otwslack = max(min(otwslack,50),0) ut2,ut1,at,tr,an = (r.ftp*powerfrac/100.).astype(int) r.pw_ut2 = ut2 @@ -321,14 +321,14 @@ def rower_prefs_view(request,userid=0,message=""): r.pw_tr = tr r.pw_an = an r.hrftp = hrftp - r.save() - message = "FTP and/or OTW slack values changed." + r.save() + message = "FTP and/or OTW slack values changed." messages.info(request,message) elif request.method == 'POST' and "ut3name" in request.POST: - powerzonesform = RowerPowerZonesForm(request.POST) - if powerzonesform.is_valid(): - cd = powerzonesform.cleaned_data + powerzonesform = RowerPowerZonesForm(request.POST) + if powerzonesform.is_valid(): + cd = powerzonesform.cleaned_data pw_ut2 = cd['pw_ut2'] pw_ut1 = cd['pw_ut1'] pw_at = cd['pw_at'] @@ -353,14 +353,14 @@ def rower_prefs_view(request,userid=0,message=""): messages.info(request,successmessage) return render(request, 'rower_preferences.html', - { - 'form':form, + { + 'form':form, 'teams':get_my_teams(request.user), - 'powerform':powerform, + 'powerform':powerform, 'powerzonesform':powerzonesform, 'breadcrumbs':breadcrumbs, 'rower':r, - }) + }) # Revoke an app that you granted access through the API. diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index 73e01c79..120683d9 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -1,4 +1,4 @@ -from statements import * +from rowers.views.statements import * import rowers.teams as teams # Show the EMpower Oarlock generated Stroke Profile @@ -11,22 +11,22 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False): promember=0 mayedit=0 if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: - promember=1 - if request.user == row.user.user: - mayedit=1 + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 + if request.user == row.user.user: + mayedit=1 if not promember: - return HttpResponseRedirect("/rowers/about/") + return HttpResponseRedirect("/rowers/about/") if request.method == 'POST' and 'workstrokesonly' in request.POST: workstrokesonly = request.POST['workstrokesonly'] - if workstrokesonly == 'True': - workstrokesonly = True - else: - workstrokesonly = False + if workstrokesonly == 'True': + workstrokesonly = True + else: + workstrokesonly = False script,div,js_resources,css_resources = interactive_forcecurve([row], workstrokesonly=workstrokesonly) @@ -58,8 +58,8 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False): 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', 'the_div':div, - 'js_res': js_resources, - 'css_res':css_resources, + 'js_res': js_resources, + 'css_res':css_resources, 'id':id, 'mayedit':mayedit, 'workstrokesonly': not workstrokesonly, @@ -87,15 +87,15 @@ def workout_histo_view(request,id=0): promember=0 mayedit=0 if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: - promember=1 - if request.user == w.user.user: - mayedit=1 + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 + if request.user == w.user.user: + mayedit=1 if not promember: - return HttpResponseRedirect("/rowers/about/") + return HttpResponseRedirect("/rowers/about/") res = interactive_histoall([w]) script = res[0] @@ -120,16 +120,16 @@ def workout_histo_view(request,id=0): return render(request, 'histo_single.html', - {'interactiveplot':script, + {'interactiveplot':script, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', 'workout':w, 'rower':r, - 'the_div':div, + 'the_div':div, 'id':id, 'mayedit':mayedit, 'teams':get_my_teams(request.user), - }) + }) @@ -156,17 +156,17 @@ def addmanual_view(request): metricsform = MetricsForm(request.POST) if form.is_valid() and metricsform.is_valid(): # Get values from form - name = form.cleaned_data['name'] + name = form.cleaned_data['name'] if name == '': name = 'Manual Entry' - date = form.cleaned_data['date'] - starttime = form.cleaned_data['starttime'] - workouttype = form.cleaned_data['workouttype'] - duration = form.cleaned_data['duration'] + date = form.cleaned_data['date'] + starttime = form.cleaned_data['starttime'] + workouttype = form.cleaned_data['workouttype'] + duration = form.cleaned_data['duration'] weightcategory = form.cleaned_data['weightcategory'] adaptiveclass = form.cleaned_data['adaptiveclass'] - distance = form.cleaned_data['distance'] - notes = form.cleaned_data['notes'] + distance = form.cleaned_data['distance'] + notes = form.cleaned_data['notes'] thetimezone = form.cleaned_data['timezone'] private = form.cleaned_data['private'] avghr = metricsform.cleaned_data['avghr'] @@ -200,10 +200,10 @@ def addmanual_view(request): else: privacy = 'visible' - startdatetime = (str(date) + ' ' + str(starttime)) - startdatetime = datetime.datetime.strptime(startdatetime, - "%Y-%m-%d %H:%M:%S") - startdatetime = timezone.make_aware(startdatetime) + startdatetime = (str(date) + ' ' + str(starttime)) + startdatetime = datetime.datetime.strptime(startdatetime, + "%Y-%m-%d %H:%M:%S") + startdatetime = timezone.make_aware(startdatetime) startdatetime = startdatetime.astimezone( pytz.timezone(thetimezone) ) @@ -329,11 +329,11 @@ def workout_update_cp_view(request,id=0): row = get_workout(id) if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) row.rankingpiece = True row.save() @@ -356,11 +356,11 @@ def workout_recalcsummary_view(request,id=0): row = get_workout(id) if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) filename = row.csvfilename rowdata = rdata(filename) @@ -370,9 +370,9 @@ def workout_recalcsummary_view(request,id=0): successmessage = "Summary Updated" messages.info(request,successmessage) url = reverse('workout_edit_view', - kwargs = { - 'id':id, - }) + kwargs = { + 'id':id, + }) else: message = "Something went wrong. Could not update summary" messages.error(request,message) @@ -391,9 +391,9 @@ def workout_recalcsummary_view(request,id=0): def workouts_join_view(request): promember=0 if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: promember=1 @@ -444,7 +444,7 @@ def workouts_join_select(request, teamid=0): try: - r = getrower(request.user) + r = getrower(request.user) except Rower.DoesNotExist: raise Http404("Rower doesn't exist") @@ -809,9 +809,9 @@ def virtualevent_compare_view(request,id=0): promember = 0 if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: promember=1 else: r = None @@ -1009,9 +1009,9 @@ def plannedsession_compare_view(request,id=0,userid=0): def multi_compare_view(request,id=0,userid=0): promember=0 if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: promember=1 if request.method == 'POST' and 'workouts' in request.POST: @@ -1372,16 +1372,16 @@ def workout_fusion_list(request,id=0,message='',successmessage='', enddate=timezone.now()): try: - r = getrower(request.user) + r = getrower(request.user) except Rower.DoesNotExist: - raise Http404("User has no rower instance") + raise Http404("User has no rower instance") u = User.objects.get(id=r.user.id) if request.method == 'POST': dateform = DateRangeForm(request.POST) if dateform.is_valid(): - startdate = dateform.cleaned_data['startdate'] - enddate = dateform.cleaned_data['enddate'] + startdate = dateform.cleaned_data['startdate'] + enddate = dateform.cleaned_data['enddate'] else: dateform = DateRangeForm(initial={ 'startdate':startdate, @@ -1398,9 +1398,9 @@ def workout_fusion_list(request,id=0,message='',successmessage='', #enddate = enddate+datetime.timedelta(days=1) if enddate < startdate: - s = enddate - enddate = startdate - startdate = s + s = enddate + enddate = startdate + startdate = s if id: theid = encoder.decode_hex(id) @@ -1453,20 +1453,20 @@ def workout_fusion_list(request,id=0,message='',successmessage='', ] return render(request, 'fusion_list.html', - {'id':id, - 'workout':row, + {'id':id, + 'workout':row, 'rower':r, 'searchform':searchform, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, - 'workouts': workouts, - 'last_name':u.last_name, - 'first_name':u.first_name, + 'workouts': workouts, + 'last_name':u.last_name, + 'first_name':u.first_name, 'dateform':dateform, 'startdate':startdate, 'enddate':enddate, - 'teams':get_my_teams(request.user), - }) + 'teams':get_my_teams(request.user), + }) # Basic view of workout def workout_view(request,id=0): @@ -1501,7 +1501,7 @@ def workout_view(request,id=0): pass - + # create interactive plot res = interactive_chart(encoder.decode_hex(id)) script = res[0] @@ -1516,7 +1516,7 @@ def workout_view(request,id=0): latitude = rowdata.df[' latitude'] if not latitude.std(): hascoordinates = 0 - except KeyError,AttributeError: + except (KeyError,AttributeError): hascoordinates = 0 else: @@ -1551,22 +1551,22 @@ def workout_view(request,id=0): records = VirtualRaceResult.objects.filter(workoutid= row.id) return render(request, 'workout_view.html', - {'workout':row, + {'workout':row, 'rower':rower, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', - 'graphs':g, - 'last_name':u.last_name, + 'graphs':g, + 'last_name':u.last_name, 'records':records, 'recordsindoor':recordsindoor, - 'first_name':u.first_name, - 'interactiveplot':script, + 'first_name':u.first_name, + 'interactiveplot':script, 'aantalcomments':aantalcomments, 'mapscript':mapscript, 'mapdiv':mapdiv, - 'teams':get_my_teams(request.user), - 'the_div':div}) - + 'teams':get_my_teams(request.user), + 'the_div':div}) + # Resets stroke data to raw data (pace) @user_passes_test(ispromember,login_url="/rowers/paidplans", @@ -1579,20 +1579,20 @@ def workout_undo_smoothenpace_view( r = getrower(request.user) if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) filename = row.csvfilename row = rdata(filename) if row == 0: - return HttpResponse("Error: CSV Data File Not Found") + 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 + velo = row.df['originalvelo'].values + row.df[' Stroke500mPace (sec/500m)'] = 500./velo row.write_csv(filename,gzip=True) dataprep.update_strokedata(encoder.decode_hex(id),row.df) @@ -1606,7 +1606,7 @@ def workout_undo_smoothenpace_view( return HttpResponseRedirect(url) - + # Data smoothing of pace data @user_passes_test(ispromember,login_url="/rowers/paidplans", message="This functionality requires a Pro plan or higher", @@ -1619,22 +1619,22 @@ def workout_smoothenpace_view(request,id=0,message="",successmessage=""): r = getrower(request.user) if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) filename = row.csvfilename row = rdata(filename) if row == 0: - return HttpResponse("Error: CSV Data File Not Found") + 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 + row.df['originalvelo'] = velo velo2 = stravastuff.ewmovingaverage(velo,5) @@ -1684,58 +1684,58 @@ def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""): ] 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" + 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" messages.info(request,successmessage) - url = reverse('workout_edit_view', - kwargs = { - 'id':id, - }) + url = reverse('workout_edit_view', + kwargs = { + 'id':id, + }) - return HttpResponseRedirect(url) - except: + return HttpResponseRedirect(url) + except: try: - os.remove(fname) + os.remove(fname) except: pass message = "Something went wrong (workout_crewnerd_summary_view)" messages.error(request,message) - url = reverse('workout_edit_view', - kwargs = { - 'id':id, - }) - return HttpResponseRedirect(url) - else: - return render(request, - "cn_form.html", - {'form':form, + url = reverse('workout_edit_view', + kwargs = { + 'id':id, + }) + return HttpResponseRedirect(url) + else: + return render(request, + "cn_form.html", + {'form':form, 'active':'nav-workouts', 'rower':r, 'workout':row, 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), - 'id':row.id}) + 'id':row.id}) else: - form = CNsummaryForm() - - return render(request, - "cn_form.html", - {'form':form, + form = CNsummaryForm() + + return render(request, + "cn_form.html", + {'form':form, 'active':'nav-workouts', 'rower':r, 'workout':row, 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), - 'id':row.id}) + 'id':row.id}) # Get weather for given location and date/time @user_passes_test(ispromember,login_url="/rowers/paidplans", @@ -1748,59 +1748,59 @@ def workout_downloadwind_view(request,id=0, f1 = row.csvfilename if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) # create bearing rowdata = rdata(f1) if rowdata == 0: - return HttpResponse("Error: CSV Data File Not Found") + return HttpResponse("Error: CSV Data File Not Found") try: - bearing = rowdata.df.loc[:,'bearing'].values + bearing = rowdata.df.loc[:,'bearing'].values except KeyError: - rowdata.add_bearing() - rowdata.write_csv(f1,gzip=True) + rowdata.add_bearing() + rowdata.write_csv(f1,gzip=True) # get wind try: - avglat = rowdata.df[' latitude'].mean() - avglon = rowdata.df[' longitude'].mean() - avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.loc[:,'TimeStamp (sec)'].iloc[0]) - startdatetime = dateutil.parser.parse("{}, {}".format(row.date, - row.starttime)) + avglat = rowdata.df[' latitude'].mean() + avglon = rowdata.df[' longitude'].mean() + avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.loc[:,'TimeStamp (sec)'].iloc[0]) + startdatetime = dateutil.parser.parse("{}, {}".format(row.date, + row.starttime)) starttimeunix = int(arrow.get(row.startdatetime).timestamp) - #starttimeunix = int(mktime(startdatetime.utctimetuple())) - 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,gzip=True) + #starttimeunix = int(mktime(startdatetime.utctimetuple())) + 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,gzip=True) messages.info(request,message) - kwargs = { - 'id':id} + kwargs = { + 'id':id} - url = reverse('workout_wind_view',kwargs=kwargs) - response = HttpResponseRedirect(url) + url = reverse('workout_wind_view',kwargs=kwargs) + response = HttpResponseRedirect(url) except KeyError: - message = "No latitude/longitude data" + message = "No latitude/longitude data" messages.error(request,message) - kwargs = { - 'id':id + kwargs = { + 'id':id } - url = reverse('workout_wind_view',kwargs=kwargs) - response = HttpResponseRedirect(url) + url = reverse('workout_wind_view',kwargs=kwargs) + response = HttpResponseRedirect(url) @@ -1815,58 +1815,58 @@ def workout_downloadmetar_view(request,id=0, f1 = row.csvfilename if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) # create bearing rowdata = rdata(f1) if rowdata == 0: - return HttpResponse("Error: CSV Data File Not Found") + return HttpResponse("Error: CSV Data File Not Found") try: - bearing = rowdata.df.loc[:,'bearing'].values + bearing = rowdata.df.loc[:,'bearing'].values except KeyError: - rowdata.add_bearing() - rowdata.write_csv(f1,gzip=True) + rowdata.add_bearing() + rowdata.write_csv(f1,gzip=True) # get wind try: - avglat = rowdata.df[' latitude'].mean() - avglon = rowdata.df[' longitude'].mean() + avglat = rowdata.df[' latitude'].mean() + avglon = rowdata.df[' longitude'].mean() airportcode = get_airport_code(avglat,avglon)[0] - avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.loc[:,'TimeStamp (sec)'].iloc[0]) - startdatetime = dateutil.parser.parse("{}, {}".format(row.date, - row.starttime)) - + avgtime = int(rowdata.df['TimeStamp (sec)'].mean()-rowdata.df.loc[:,'TimeStamp (sec)'].iloc[0]) + startdatetime = dateutil.parser.parse("{}, {}".format(row.date, + row.starttime)) + starttimeunix = arrow.get(row.startdatetime).timestamp - #starttimeunix = int(mktime(startdatetime.utctimetuple())) - avgtime = starttimeunix +avgtime - winddata = get_metar_data(airportcode,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,gzip=True) + #starttimeunix = int(mktime(startdatetime.utctimetuple())) + avgtime = starttimeunix +avgtime + winddata = get_metar_data(airportcode,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,gzip=True) messages.info(request,message) - kwargs = { - 'id':id} + kwargs = { + 'id':id} - url = reverse('workout_wind_view',kwargs=kwargs) - response = HttpResponseRedirect(url) + url = reverse('workout_wind_view',kwargs=kwargs) + response = HttpResponseRedirect(url) except KeyError: - message = "No latitude/longitude data" + message = "No latitude/longitude data" messages.error(request,message) - kwargs = { - 'id':id + kwargs = { + 'id':id } - url = reverse('workout_wind_view',kwargs=kwargs) - response = HttpResponseRedirect(url) + url = reverse('workout_wind_view',kwargs=kwargs) + response = HttpResponseRedirect(url) @@ -1895,11 +1895,11 @@ def workout_wind_view(request,id=0,message="",successmessage=""): ] if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) # get data @@ -1910,24 +1910,24 @@ def workout_wind_view(request,id=0,message="",successmessage=""): # create bearing rowdata = rdata(f1) if row == 0: - return HttpResponse("Error: CSV Data File Not Found") + return HttpResponse("Error: CSV Data File Not Found") hascoordinates = 1 try: - latitude = rowdata.df.loc[:,' latitude'] + latitude = rowdata.df.loc[:,' latitude'] except KeyError: - hascoordinates = 0 + hascoordinates = 0 if hascoordinates and not latitude.std(): hascoordinates = 0 try: - bearing = rowdata.df.loc[:,'bearing'].values + bearing = rowdata.df.loc[:,'bearing'].values except KeyError: - rowdata.add_bearing() - rowdata.write_csv(f1,gzip=True) - + rowdata.add_bearing() + rowdata.write_csv(f1,gzip=True) + if hascoordinates: avglat = rowdata.df[' latitude'].mean() @@ -1941,39 +1941,39 @@ def workout_wind_view(request,id=0,message="",successmessage=""): if request.method == 'POST': - # process form - form = UpdateWindForm(request.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'] + 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.update_wind(vwind1,vwind2, + winddirection1, + winddirection2, + dist1,dist2, + units=windunit) - rowdata.write_csv(f1,gzip=True) + rowdata.write_csv(f1,gzip=True) - - else: - message = "Invalid Form" + + else: + message = "Invalid Form" messages.error(request,message) - kwargs = { - 'id':id + kwargs = { + 'id':id } - url = reverse('workout_wind_view',kwargs=kwargs) - response = HttpResponseRedirect(url) - + url = reverse('workout_wind_view',kwargs=kwargs) + response = HttpResponseRedirect(url) + else: - form = UpdateWindForm() + form = UpdateWindForm() # create interactive plot res = interactive_windchart(encoder.decode_hex(id),promember=1) @@ -1983,30 +1983,30 @@ def workout_wind_view(request,id=0,message="",successmessage=""): if hascoordinates: gmscript,gmdiv = leaflet_chart( rowdata.df[' latitude'], - rowdata.df[' longitude'], - row.name) + rowdata.df[' longitude'], + row.name) else: - gmscript = "" - gmdiv = "No GPS data available" + gmscript = "" + gmdiv = "No GPS data available" messages.info(request,successmessage) messages.error(request,message) return render(request, - 'windedit.html', - {'workout':row, + 'windedit.html', + {'workout':row, 'rower':r, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', 'teams':get_my_teams(request.user), - 'interactiveplot':script, - 'form':form, + 'interactiveplot':script, + 'form':form, 'airport':airportcode, 'airportdistance':airportdistance, - 'the_div':div, - 'gmap':gmscript, - 'gmapdiv':gmdiv}) + 'the_div':div, + 'gmap':gmscript, + 'gmapdiv':gmdiv}) # Show form to update River stream data (for river dwellers) @@ -2016,11 +2016,11 @@ def workout_stream_view(request,id=0,message="",successmessage=""): r = getrower(request.user) if (checkworkoutuser(request.user,row)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) # create interactive plot @@ -2030,36 +2030,36 @@ def workout_stream_view(request,id=0,message="",successmessage=""): rowdata = rdata(f1) if rowdata == 0: - return HttpResponse("Error: CSV Data File Not Found") + return HttpResponse("Error: CSV Data File Not Found") if request.method == 'POST': - # process form - form = UpdateStreamForm(request.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'] + 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.update_stream(stream1,stream2,dist1,dist2, + units=streamunit) - rowdata.write_csv(f1,gzip=True) + rowdata.write_csv(f1,gzip=True) - - else: - message = "Invalid Form" + + else: + message = "Invalid Form" messages.error(request,message) - kwargs = { - 'id':id} - url = reverse('workout_wind_view',kwargs=kwargs) - response = HttpResponseRedirect(url) - + kwargs = { + 'id':id} + url = reverse('workout_wind_view',kwargs=kwargs) + response = HttpResponseRedirect(url) + else: - form = UpdateStreamForm() + form = UpdateStreamForm() # create interactive plot res = interactive_streamchart(encoder.decode_hex(id),promember=1) @@ -2085,15 +2085,15 @@ def workout_stream_view(request,id=0,message="",successmessage=""): messages.info(request,successmessage) messages.error(request,message) return render(request, - 'streamedit.html', - {'workout':row, + 'streamedit.html', + {'workout':row, 'rower':r, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', 'teams':get_my_teams(request.user), - 'interactiveplot':script, - 'form':form, - 'the_div':div}) + 'interactiveplot':script, + 'form':form, + 'the_div':div}) # Form to set average crew weight and boat type, then run power calcs @user_passes_test(ispromember, login_url="/rowers/paidplans",redirect_field_name=None) @@ -2108,95 +2108,95 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""): mayedit=1 if (checkworkoutuser(request.user,w)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) if request.method == 'POST': - # process form - form = AdvancedWorkoutForm(request.POST) + # process form + form = AdvancedWorkoutForm(request.POST) - if form.is_valid(): + if form.is_valid(): quick_calc = form.cleaned_data['quick_calc'] - boattype = form.cleaned_data['boattype'] - weightvalue = form.cleaned_data['weightvalue'] - w.boattype = boattype - w.weightvalue = weightvalue - w.save() + boattype = form.cleaned_data['boattype'] + weightvalue = form.cleaned_data['weightvalue'] + w.boattype = boattype + w.weightvalue = weightvalue + w.save() - # load row data & create power/wind/bearing columns if not set - f1 = w.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,gzip=True) + # load row data & create power/wind/bearing columns if not set + f1 = w.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,gzip=True) - try: - bearing = rowdata.df['bearing'] - except KeyError: - rowdata.add_bearing() - rowdata.write_csv(f1,gzip=True) + try: + bearing = rowdata.df['bearing'] + except KeyError: + rowdata.add_bearing() + rowdata.write_csv(f1,gzip=True) - try: - vwind = rowdata.df['vwind'] - except KeyError: - rowdata.add_wind(0,0) - rowdata.write_csv(f1,gzip=True) + try: + vwind = rowdata.df['vwind'] + except KeyError: + rowdata.add_wind(0,0) + rowdata.write_csv(f1,gzip=True) - # do power calculation (asynchronous) + # do power calculation (asynchronous) r = w.user u = r.user - first_name = u.first_name - last_name = u.last_name - emailaddress = u.email + first_name = u.first_name + last_name = u.last_name + emailaddress = u.email job = myqueue(queuelow, handle_otwsetpower,f1,boattype, - weightvalue, - first_name,last_name,emailaddress,id, + weightvalue, + first_name,last_name,emailaddress,id, ps=[r.p0,r.p1,r.p2,r.p3], ratio=r.cpratio, quick_calc = quick_calc, emailbounced = r.emailbounced ) - try: + try: request.session['async_tasks'] += [(job.id,'otwsetpower')] except KeyError: request.session['async_tasks'] = [(job.id,'otwsetpower')] - successmessage = 'Your calculations have been submitted. You will receive an email when they are done. You can check the status of your calculations here' + successmessage = 'Your calculations have been submitted. You will receive an email when they are done. You can check the status of your calculations here' messages.info(request,successmessage) - kwargs = { - 'id':id} + kwargs = { + 'id':id} try: url = request.session['referer'] except KeyError: - url = reverse('workout_edit_view',kwargs=kwargs) + url = reverse('workout_edit_view',kwargs=kwargs) - response = HttpResponseRedirect(url) - return response - - else: - message = "Invalid Form" + response = HttpResponseRedirect(url) + return response + + else: + message = "Invalid Form" messages.error(request,message) - kwargs = { - 'id':id} - url = reverse('workout_otwsetpower_view',kwargs=kwargs) - response = HttpResponseRedirect(url) - + kwargs = { + 'id':id} + url = reverse('workout_otwsetpower_view',kwargs=kwargs) + response = HttpResponseRedirect(url) + else: - form = AdvancedWorkoutForm(instance=w) + form = AdvancedWorkoutForm(instance=w) breadcrumbs = [ { @@ -2218,15 +2218,15 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""): messages.error(request,message) messages.info(request,successmessage) return render(request, - 'otwsetpower.html', - {'workout':w, + 'otwsetpower.html', + {'workout':w, 'rower':w, 'mayedit':mayedit, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), - 'form':form, - }) + 'form':form, + }) @login_required() def instroke_view(request,id=0): @@ -2259,11 +2259,11 @@ def instroke_view(request,id=0): # check if user is owner of this workout if (checkworkoutuser(request.user,w)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) rowdata = rrdata(csvfile=w.csvfilename) try: @@ -2274,8 +2274,8 @@ def instroke_view(request,id=0): return render(request, - 'instroke.html', - {'workout':w, + 'instroke.html', + {'workout':w, 'rower':r, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, @@ -2291,11 +2291,11 @@ def instroke_chart(request,id=0,metric=''): w = get_workout(id) if (checkworkoutuser(request.user,w)==False): - message = "You are not allowed to edit this workout" + message = "You are not allowed to edit this workout" messages.error(request,message) - url = reverse('workouts_view') + url = reverse('workouts_view') - return HttpResponseRedirect(url) + return HttpResponseRedirect(url) rowdata = rrdata(csvfile=w.csvfilename) instrokemetrics = rowdata.get_instroke_columns() @@ -2303,11 +2303,11 @@ def instroke_chart(request,id=0,metric=''): if metric in instrokemetrics: f1 = w.csvfilename[6:-4] - timestr = strftime("%Y%m%d-%H%M%S") - imagename = f1+timestr+'.png' + timestr = strftime("%Y%m%d-%H%M%S") + imagename = f1+timestr+'.png' fullpathimagename = 'static/plots/'+imagename u = w.user.user - r = getrower(u) + r = getrower(u) title = w.name fig1 = rowdata.get_plot_instroke(metric) canvas = FigureCanvas(fig1) @@ -2577,7 +2577,7 @@ def workout_stats_view(request,id=0,message="",successmessage=""): 'value': hrdrift, 'unit': '%', } - except ZeroDivisionError,ValueError: + except (ZeroDivisionError,ValueError): pass # TRIMP @@ -2596,8 +2596,8 @@ def workout_stats_view(request,id=0,message="",successmessage=""): } return render(request, - 'workoutstats.html', - { + 'workoutstats.html', + { 'stats':stats, 'teams':get_my_teams(request.user), 'workout':w, @@ -2719,9 +2719,9 @@ def workout_workflow_view(request,id): r = getrower(request.user) result = request.user.is_authenticated() and ispromember(request.user) if result: - promember=1 + promember=1 if request.user == row.user.user: - mayedit=1 + mayedit=1 comments = WorkoutComment.objects.filter(workout=row) @@ -2820,12 +2820,12 @@ def workout_flexchart3_view(request,*args,**kwargs): promember=0 mayedit=0 if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: - promember=1 - if request.user == row.user.user: - mayedit=1 + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 + if request.user == row.user.user: + mayedit=1 if checkworkoutuser(request.user,row): mayedit=1 @@ -2905,7 +2905,7 @@ def workout_flexchart3_view(request,*args,**kwargs): if not request.user.is_anonymous(): workstrokesonly = request.POST['workstrokesonlysave'] reststrokes = not workstrokesonly - r = getrower(request.user) + r = getrower(request.user) try: range = metrics.yaxmaxima[xparam] if yparam1 is not None: @@ -2969,8 +2969,8 @@ def workout_flexchart3_view(request,*args,**kwargs): workstrokesonly ) = interactive_flex_chart2( encoder.decode_hex(id),xparam=xparam,yparam1=yparam1, - yparam2=yparam2, - promember=promember,plottype=plottype, + yparam2=yparam2, + promember=promember,plottype=plottype, workstrokesonly=workstrokesonly ) except ValueError: @@ -2982,9 +2982,9 @@ def workout_flexchart3_view(request,*args,**kwargs): workstrokesonly ) = interactive_flex_chart2( encoder.decode_hex(id),xparam=xparam,yparam1=yparam1, - yparam2=yparam2, - promember=promember,plottype=plottype, - workstrokesonly=workstrokesonly + yparam2=yparam2, + promember=promember,plottype=plottype, + workstrokesonly=workstrokesonly ) js_resources = "" css_resources = "" @@ -3068,35 +3068,35 @@ def workout_flexchart3_view(request,*args,**kwargs): return render(request, - 'flexchart3otw.html', - {'the_script':script, - 'the_div':div, + 'flexchart3otw.html', + {'the_script':script, + 'the_div':div, 'breadcrumbs':breadcrumbs, 'rower':r, 'active':'nav-workouts', 'workout':row, 'chartform':flexaxesform, 'optionsform':flexoptionsform, - 'js_res': js_resources, - 'css_res':css_resources, - 'teams':get_my_teams(request.user), + 'js_res': js_resources, + 'css_res':css_resources, + 'teams':get_my_teams(request.user), 'id':id, - 'xparam':xparam, - 'yparam1':yparam1, - 'yparam2':yparam2, - 'plottype':plottype, + 'xparam':xparam, + 'yparam1':yparam1, + 'yparam2':yparam2, + 'plottype':plottype, 'axchoicesbasic':axchoicesbasic, 'axchoicespro':axchoicespro, 'extrametrics':extrametrics, 'favoritechartnotes':favoritechartnotes, 'noylist':noylist, - 'mayedit':mayedit, - 'promember':promember, - 'workstrokesonly': not workstrokesonly, + 'mayedit':mayedit, + 'promember':promember, + 'workstrokesonly': not workstrokesonly, 'favoritenr':favoritenr, 'maxfav':maxfav, - }) - + }) + # The interactive plot with wind corrected pace for OTW outings @@ -3131,12 +3131,12 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""): promember=0 mayedit=0 if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: - promember=1 - if request.user == w.user.user: - mayedit=1 + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 + if request.user == w.user.user: + mayedit=1 # create interactive plot res = interactive_otw_advanced_pace_chart(encoder.decode_hex(id),promember=promember) @@ -3147,15 +3147,15 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""): messages.info(request,successmessage) return render(request, - 'otwinteractive.html', - {'workout':w, + 'otwinteractive.html', + {'workout':w, 'rower':r, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), - 'interactiveplot':script, - 'the_div':div, - 'mayedit':mayedit}) + 'interactiveplot':script, + 'the_div':div, + 'mayedit':mayedit}) # @@ -3164,7 +3164,7 @@ def workout_unsubscribe_view(request,id=0): w = get_workout(id) if w.privacy == 'private' and w.user.user != request.user: - return HttpResponseForbidden("Permission error") + return HttpResponseForbidden("Permission error") comments = WorkoutComment.objects.filter(workout=w, user=request.user).order_by("created") @@ -3194,7 +3194,7 @@ def workout_comment_view(request,id=0): w = get_workout(id) if w.privacy == 'private' and w.user.user != request.user: - return HttpResponseForbidden("Permission error") + return HttpResponseForbidden("Permission error") comments = WorkoutComment.objects.filter(workout=w).order_by("created") @@ -3229,8 +3229,8 @@ def workout_comment_view(request,id=0): res = myqueue(queuehigh, handle_sendemailnewcomment,r.user.first_name, - r.user.last_name, - r.user.email, + r.user.last_name, + r.user.email, request.user.first_name, request.user.last_name, comment,w.name,w.id, @@ -3299,7 +3299,7 @@ def workout_comment_view(request,id=0): 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', 'teams':get_my_teams(request.user), - 'graphs':g, + 'graphs':g, 'comments':comments, 'form':form, }) @@ -3322,20 +3322,20 @@ def workout_edit_view(request,id=0,message="",successmessage=""): form = WorkoutForm(instance=row) if request.method == 'POST': - # Form was submitted - form = WorkoutForm(request.POST,instance=row) - if form.is_valid(): - # Get values from form - name = form.cleaned_data['name'] - date = form.cleaned_data['date'] - starttime = form.cleaned_data['starttime'] - workouttype = form.cleaned_data['workouttype'] + # Form was submitted + form = WorkoutForm(request.POST,instance=row) + if form.is_valid(): + # Get values from form + name = form.cleaned_data['name'] + date = form.cleaned_data['date'] + starttime = form.cleaned_data['starttime'] + workouttype = form.cleaned_data['workouttype'] weightcategory = form.cleaned_data['weightcategory'] adaptiveclass = form.cleaned_data['adaptiveclass'] - duration = form.cleaned_data['duration'] - distance = form.cleaned_data['distance'] + duration = form.cleaned_data['duration'] + distance = form.cleaned_data['distance'] private = form.cleaned_data['private'] - notes = form.cleaned_data['notes'] + notes = form.cleaned_data['notes'] thetimezone = form.cleaned_data['timezone'] try: @@ -3381,7 +3381,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""): # aware object can be in any timezone out = startdatetime.astimezone(pytz.utc) except (ValueError, TypeError): - startdatetime = timezone.make_aware(startdatetime) + startdatetime = timezone.make_aware(startdatetime) try: startdatetime = startdatetime.astimezone(pytz.timezone(thetimezone)) @@ -3560,7 +3560,7 @@ def workout_map_view(request,id=0): latitude = rowdata.df[' latitude'] if not latitude.std(): hascoordinates = 0 - except KeyError,AttributeError: + except (KeyError,AttributeError): hascoordinates = 0 else: @@ -3577,12 +3577,12 @@ def workout_map_view(request,id=0): mayedit=0 if not request.user.is_anonymous(): - r = getrower(request.user) - result = request.user.is_authenticated() and ispromember(request.user) - if result: - promember=1 - if request.user == w.user.user: - mayedit=1 + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 + if request.user == w.user.user: + mayedit=1 return render(request, 'map_view.html', {'mapscript':mapscript, @@ -3712,13 +3712,13 @@ def workout_add_chart_view(request,id,plotnr=1): plotnr = int(plotnr) if (checkworkoutuser(request.user,w)==False): - raise PermissionDenied("You are not allowed add plots to this workout") + raise PermissionDenied("You are not allowed add plots to this workout") else: - f1 = w.csvfilename[6:-4] - timestr = strftime("%Y%m%d-%H%M%S") - imagename = f1+timestr+'.png' - u = w.user.user - r = getrower(u) + f1 = w.csvfilename[6:-4] + timestr = strftime("%Y%m%d-%H%M%S") + imagename = f1+timestr+'.png' + u = w.user.user + r = getrower(u) title = w.name res,jobid = uploads.make_plot( r,w,f1,w.csvfilename,'timeplot',title,plotnr=plotnr, @@ -3880,15 +3880,15 @@ def workout_upload_view(request, response = {} if request.method == 'POST': - form = DocumentsForm(request.POST,request.FILES) - optionsform = UploadOptionsForm(request.POST,request=request) + form = DocumentsForm(request.POST,request.FILES) + optionsform = UploadOptionsForm(request.POST,request=request) - if form.is_valid(): -# f = request.FILES['file'] + if form.is_valid(): +# f = request.FILES['file'] f = form.cleaned_data['file'] if f is not None: - res = handle_uploaded_file(f) + res = handle_uploaded_file(f) else: messages.error(request, "Something went wrong - no file attached") @@ -3898,8 +3898,8 @@ def workout_upload_view(request, else: return HttpResponseRedirect(url) - t = form.cleaned_data['title'] - workouttype = form.cleaned_data['workouttype'] + t = form.cleaned_data['title'] + workouttype = form.cleaned_data['workouttype'] boattype = form.cleaned_data['boattype'] request.session['docformoptions'] = { @@ -3907,19 +3907,19 @@ def workout_upload_view(request, 'boattype': boattype, } - notes = form.cleaned_data['notes'] + notes = form.cleaned_data['notes'] offline = form.cleaned_data['offline'] race = None if optionsform.is_valid(): - make_plot = optionsform.cleaned_data['make_plot'] - plottype = optionsform.cleaned_data['plottype'] - upload_to_c2 = optionsform.cleaned_data['upload_to_C2'] - upload_to_strava = optionsform.cleaned_data['upload_to_Strava'] - upload_to_st = optionsform.cleaned_data['upload_to_SportTracks'] - upload_to_rk = optionsform.cleaned_data['upload_to_RunKeeper'] - upload_to_ua = optionsform.cleaned_data['upload_to_MapMyFitness'] - upload_to_tp = optionsform.cleaned_data['upload_to_TrainingPeaks'] + make_plot = optionsform.cleaned_data['make_plot'] + plottype = optionsform.cleaned_data['plottype'] + upload_to_c2 = optionsform.cleaned_data['upload_to_C2'] + upload_to_strava = optionsform.cleaned_data['upload_to_Strava'] + upload_to_st = optionsform.cleaned_data['upload_to_SportTracks'] + upload_to_rk = optionsform.cleaned_data['upload_to_RunKeeper'] + upload_to_ua = optionsform.cleaned_data['upload_to_MapMyFitness'] + upload_to_tp = optionsform.cleaned_data['upload_to_TrainingPeaks'] makeprivate = optionsform.cleaned_data['makeprivate'] landingpage = optionsform.cleaned_data['landingpage'] @@ -3946,8 +3946,8 @@ def workout_upload_view(request, request.session['uploadoptions'] = uploadoptions - f1 = res[0] # file name - f2 = res[1] # file name incl media directory + f1 = res[0] # file name + f2 = res[1] # file name incl media directory if not offline: id,message,f2 = dataprep.new_workout_from_file( @@ -3989,11 +3989,11 @@ def workout_upload_view(request, if not id: messages.error(request,message) - url = reverse('workout_upload_view') + url = reverse('workout_upload_view') if is_ajax: return JSONResponse({'result':0,'url':url}) else: - response = HttpResponseRedirect(url) + response = HttpResponseRedirect(url) return response elif id == -1: message = 'The zip archive will be processed in the background. The files in the archive will only be uploaded without the extra actions. You will receive email when the workouts are ready.' @@ -4022,7 +4022,7 @@ def workout_upload_view(request, r = getrower(request.user) - if (make_plot): + if (make_plot): res,jobid = uploads.make_plot(r,w,f1,f2,plottype,t) if res == 0: messages.error(request,jobid) @@ -4032,8 +4032,8 @@ def workout_upload_view(request, except KeyError: request.session['async_tasks'] = [(jobid,'make_plot')] - # upload to C2 - if (upload_to_c2): + # upload to C2 + if (upload_to_c2): try: message,id = c2stuff.workout_c2_upload(request.user,w) except NoTokenError: @@ -4149,20 +4149,20 @@ def workout_upload_view(request, response = {'result':1,'url':url} else: response = HttpResponseRedirect(url) - else: + else: if not is_ajax: - response = render(request, - 'document_form.html', - {'form':form, + response = render(request, + 'document_form.html', + {'form':form, 'teams':get_my_teams(request.user), - 'optionsform': optionsform, + 'optionsform': optionsform, }) if is_ajax: return JSONResponse(response) else: - return response + return response else: if not is_ajax: if r.c2_auto_export and isprorower(r): @@ -4183,15 +4183,15 @@ def workout_upload_view(request, if r.mapmyfitness_auto_export and isprorower(r): uploadoptions['upload_to_MapMyFitness'] = True - form = DocumentsForm(initial=docformoptions) - optionsform = UploadOptionsForm(initial=uploadoptions, + form = DocumentsForm(initial=docformoptions) + optionsform = UploadOptionsForm(initial=uploadoptions, request=request) - return render(request, 'document_form.html', - {'form':form, + return render(request, 'document_form.html', + {'form':form, 'active':'nav-workouts', 'breadcrumbs':breadcrumbs, 'teams':get_my_teams(request.user), - 'optionsform': optionsform, + 'optionsform': optionsform, }) else: return {'result':0} @@ -4231,17 +4231,17 @@ def team_workout_upload_view(request,message="", r = getrower(request.user) if request.method == 'POST': - form = DocumentsForm(request.POST,request.FILES) - optionsform = TeamUploadOptionsForm(request.POST) + form = DocumentsForm(request.POST,request.FILES) + optionsform = TeamUploadOptionsForm(request.POST) rowerform = TeamInviteForm(request.POST) rowerform.fields.pop('email') rowers = Rower.objects.filter(coachinggroups__in=[r.mycoachgroup]).distinct() rowerform.fields['user'].queryset = User.objects.filter(rower__in=rowers).distinct() - if form.is_valid(): - f = request.FILES['file'] - res = handle_uploaded_file(f) - t = form.cleaned_data['title'] + if form.is_valid(): + f = request.FILES['file'] + res = handle_uploaded_file(f) + t = form.cleaned_data['title'] offline = form.cleaned_data['offline'] boattype = form.cleaned_data['boattype'] workouttype = form.cleaned_data['workouttype'] @@ -4254,22 +4254,22 @@ def team_workout_upload_view(request,message="", messages.error(request,message) messages.info(request,successmessage) response = render(request, - 'team_document_form.html', - {'form':form, + 'team_document_form.html', + {'form':form, 'teams':get_my_teams(request.user), - 'optionsform': optionsform, + 'optionsform': optionsform, 'rowerform': rowerform, }) - return response + return response workouttype = form.cleaned_data['workouttype'] - notes = form.cleaned_data['notes'] + notes = form.cleaned_data['notes'] if optionsform.is_valid(): - make_plot = optionsform.cleaned_data['make_plot'] - plottype = optionsform.cleaned_data['plottype'] + make_plot = optionsform.cleaned_data['make_plot'] + plottype = optionsform.cleaned_data['plottype'] uploadoptions = { 'makeprivate':False, @@ -4281,8 +4281,8 @@ def team_workout_upload_view(request,message="", request.session['uploadoptions'] = uploadoptions - f1 = res[0] # file name - f2 = res[1] # file name incl media directory + f1 = res[0] # file name + f2 = res[1] # file name incl media directory if not offline: @@ -4311,14 +4311,14 @@ def team_workout_upload_view(request,message="", url = reverse('team_workout_upload_view') - response = HttpResponseRedirect(url) + response = HttpResponseRedirect(url) return response if not id: messages.error(request,message) - url = reverse('team_workout_upload_view') - response = HttpResponseRedirect(url) + url = reverse('team_workout_upload_view') + response = HttpResponseRedirect(url) return response elif id == -1: message = 'The zip archive will be processed in the background. The files in the archive will only be uploaded without the extra actions. You will receive email when the workouts are ready.' @@ -4337,35 +4337,35 @@ def team_workout_upload_view(request,message="", w = Workout.objects.get(id=id) r = getrower(request.user) - if (make_plot): + if (make_plot): id,jobid = uploads.make_plot(r,w,f1,f2,plottype,t) - else: + else: response = render(request, - 'team_document_form.html', - {'form':form, + 'team_document_form.html', + {'form':form, 'teams':get_my_teams(request.user), 'active': 'nav-workouts', 'breadcrumbs':breadcrumbs, - 'optionsform': optionsform, + 'optionsform': optionsform, 'rowerform': rowerform, }) - return response + return response else: - form = DocumentsForm() - optionsform = TeamUploadOptionsForm(initial=uploadoptions) + form = DocumentsForm() + optionsform = TeamUploadOptionsForm(initial=uploadoptions) rowerform = TeamInviteForm() rowerform.fields.pop('email') rowerform.fields['user'].queryset = User.objects.filter(rower__isnull=False,rower__team__in=myteams).distinct() - return render(request, 'team_document_form.html', - {'form':form, + return render(request, 'team_document_form.html', + {'form':form, # 'teams':get_my_teams(request.user), - 'optionsform': optionsform, + 'optionsform': optionsform, 'active': 'nav-workouts', 'breadcrumbs':breadcrumbs, # 'rower':r, @@ -4381,8 +4381,8 @@ def team_workout_upload_view(request,message="", def graphs_view(request): request.session['referer'] = reverse('graphs_view') try: - r = getrower(request.user) - workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime") + r = getrower(request.user) + workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime") query = request.GET.get('q') if query: query_list = query.split() @@ -4396,7 +4396,7 @@ def graphs_view(request): else: searchform = SearchForm() - g = GraphImage.objects.filter(workout__in=workouts).order_by("-creationdatetime") + g = GraphImage.objects.filter(workout__in=workouts).order_by("-creationdatetime") paginator = Paginator(g,8) @@ -4409,20 +4409,20 @@ def graphs_view(request): except EmptyPage: g = paginator.page(paginator.num_pages) - return render(request, 'list_graphs.html', - {'graphs': g, + return render(request, 'list_graphs.html', + {'graphs': g, 'searchform':searchform, 'active':'nav-workouts', 'teams':get_my_teams(request.user), }) except Rower.DoesNotExist: - raise Http404("User has no rower instance") + raise Http404("User has no rower instance") # Show the chart (png image) def graph_show_view(request,id): try: - g = GraphImage.objects.get(id=id) + g = GraphImage.objects.get(id=id) try: width,height = Image.open(g.filename).size g.width = width @@ -4431,8 +4431,8 @@ def graph_show_view(request,id): except: pass - w = Workout.objects.get(id=g.workout.id) - r = Rower.objects.get(id=w.user.id) + w = Workout.objects.get(id=g.workout.id) + r = Rower.objects.get(id=w.user.id) breadcrumbs = [ { @@ -4451,16 +4451,16 @@ def graph_show_view(request,id): ] - return render(request,'show_graph.html', - {'graph':g, + return render(request,'show_graph.html', + {'graph':g, 'teams':get_my_teams(request.user), - 'workout':w, + 'workout':w, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', - 'rower':r,}) - + 'rower':r,}) + except GraphImage.DoesNotExist: - raise Http404("This graph doesn't exist") + raise Http404("This graph doesn't exist") except Workout.DoesNotExist: raise Http404("This workout doesn't exist") @@ -4484,12 +4484,12 @@ def workout_summary_restore_view(request,id,message="",successmessage=""): ftp = ftp*(100.-r.otwslack)/100. rr = rrower(hrmax=r.max,hrut2=r.ut2, - hrut1=r.ut1,hrat=r.at, - hrtr=r.tr,hran=r.an,ftp=ftp, + hrut1=r.ut1,hrat=r.at, + hrtr=r.tr,hran=r.an,ftp=ftp, powerperc=powerperc,powerzones=r.powerzones) rowdata = rdata(f1,rower=rr) if rowdata == 0: - raise Http404("Error: CSV Data File Not Found") + raise Http404("Error: CSV Data File Not Found") rowdata.restoreintervaldata() rowdata.write_csv(f1,gzip=True) dataprep.update_strokedata(encoder.decode_hex(id),rowdata.df) @@ -4499,18 +4499,18 @@ def workout_summary_restore_view(request,id,message="",successmessage=""): # create interactive plot try: - res = interactive_chart(encoder.decode_hex(id),promember=1) - script = res[0] - div = res[1] + res = interactive_chart(encoder.decode_hex(id),promember=1) + script = res[0] + div = res[1] except ValueError: - pass + pass messages.info(request,'Original Interval Data Restored') url = reverse('workout_summary_edit_view', kwargs={ - 'id':encoder.encode_hex(row.id), - } + 'id':encoder.encode_hex(row.id), + } ) return HttpResponseRedirect(url) @@ -4570,7 +4570,7 @@ def workout_split_view(request,id=0): url = reverse('workouts_view', kwargs={ - 'teamid':int(teamid), + 'teamid':int(teamid), } ) else: @@ -4591,14 +4591,14 @@ def workout_split_view(request,id=0): # create interactive plot try: - res = interactive_chart(encoder.decode_hex(id),promember=1) - script = res[0] - div = res[1] + res = interactive_chart(encoder.decode_hex(id),promember=1) + script = res[0] + div = res[1] except ValueError: - pass + pass return render(request, 'splitworkout.html', - {'form':form, + {'form':form, 'rower':r, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', @@ -4689,7 +4689,7 @@ def workout_fusion_view(request,id1=0,id2=1): ] return render(request, 'fusion.html', - {'form':form, + {'form':form, 'teams':get_my_teams(request.user), 'workout':w1, 'rower':r, @@ -4703,7 +4703,7 @@ def workout_fusion_view(request,id1=0,id2=1): # Edit the splits/summary @login_required() def workout_summary_edit_view(request,id,message="",successmessage="" - ): + ): row = get_workout_permitted(request.user,id) r = getrower(request.user) breadcrumbs = [ @@ -4737,12 +4737,12 @@ def workout_summary_edit_view(request,id,message="",successmessage="" ftp = ftp*(100.-r.otwslack)/100. rr = rrower(hrmax=r.max,hrut2=r.ut2, - hrut1=r.ut1,hrat=r.at, - hrtr=r.tr,hran=r.an,ftp=ftp, + hrut1=r.ut1,hrat=r.at, + hrtr=r.tr,hran=r.an,ftp=ftp, powerperc=powerperc,powerzones=r.powerzones) rowdata = rdata(f1,rower=rr) if rowdata == 0: - return HttpResponse("Error: CSV Data File Not Found") + return HttpResponse("Error: CSV Data File Not Found") intervalstats = rowdata.allstats() try: itime,idist,itype = rowdata.intervalstats_values() @@ -4790,18 +4790,18 @@ def workout_summary_edit_view(request,id,message="",successmessage="" # We have submitted the mini language interpreter if request.method == 'POST' and "intervalstring" in request.POST: - form = SummaryStringForm(request.POST) - if form.is_valid(): - cd = form.cleaned_data - s = cd["intervalstring"] + form = SummaryStringForm(request.POST) + if form.is_valid(): + cd = form.cleaned_data + s = cd["intervalstring"] try: - rowdata.updateinterval_string(s) - except ParseException,err: + rowdata.updateinterval_string(s) + except (ParseException,err): messages.error(request,'Parsing error in column '+str(err.col)) - intervalstats = rowdata.allstats() - itime,idist,itype = rowdata.intervalstats_values() - nrintervals = len(idist) - savebutton = 'savestringform' + intervalstats = rowdata.allstats() + itime,idist,itype = rowdata.intervalstats_values() + nrintervals = len(idist) + savebutton = 'savestringform' powerupdateform = PowerIntervalUpdateForm(initial=data) # we are saving the results obtained from the split by power/pace interpreter @@ -4874,39 +4874,39 @@ def workout_summary_edit_view(request,id,message="",successmessage="" # we are saving the results obtained from the mini language interpreter elif request.method == 'POST' and "savestringform" in request.POST: - s = request.POST["savestringform"] + s = request.POST["savestringform"] try: - rowdata.updateinterval_string(s) - except ParseException,err: + rowdata.updateinterval_string(s) + except (ParseException,err): messages.error(request,'Parsing error in column '+str(err.col)) - intervalstats = rowdata.allstats() - itime,idist,itype = rowdata.intervalstats_values() - nrintervals = len(idist) - row.summary = intervalstats - #intervalstats = rowdata.allstats() + intervalstats = rowdata.allstats() + itime,idist,itype = rowdata.intervalstats_values() + nrintervals = len(idist) + row.summary = intervalstats + #intervalstats = rowdata.allstats() if s: try: - row.notes = u'{n} \n {s}'.format( + row.notes = u'{n} \n {s}'.format( n = row.notes, s = s ) except TypeError: pass - row.save() - rowdata.write_csv(f1,gzip=True) + row.save() + rowdata.write_csv(f1,gzip=True) dataprep.update_strokedata(encoder.decode_hex(id),rowdata.df) - messages.info(request,"Updated interval data saved") - data = {'intervalstring':s} - form = SummaryStringForm(initial=data) + messages.info(request,"Updated interval data saved") + data = {'intervalstring':s} + form = SummaryStringForm(initial=data) powerupdateform = PowerIntervalUpdateForm(initial={ 'power': int(normp), 'pace': avpace, 'selector': 'power', 'work': int(normw) }) - savebutton = 'savestringform' + savebutton = 'savestringform' # we are saving the results obtained from the power update form elif request.method == 'POST' and 'selector' in request.POST: @@ -4955,66 +4955,66 @@ def workout_summary_edit_view(request,id,message="",successmessage="" 'value_work': work, } powerupdateform = PowerIntervalUpdateForm(initial=cd) - form = SummaryStringForm() + form = SummaryStringForm() form = SummaryStringForm() # we are saving the results obtained from the detailed form elif request.method == 'POST' and "savedetailform" in request.POST: - savebutton = 'savedetailform' - form = SummaryStringForm() - nrintervals = int(request.POST['nrintervals']) - detailform = IntervalUpdateForm(request.POST,aantal=nrintervals) - itime = [] - idist = [] - itype = [] - ivalues = [] - iunits = [] - itypes = [] - iresults = [] - for i in xrange(nrintervals): - try: - t = datetime.datetime.strptime(request.POST['intervalt_%s' % i],"%H:%M:%S.%f") - except ValueError: - t = datetime.datetime.strptime(request.POST['intervalt_%s' % i],"%H:%M:%S") - - timesecs = 3600*t.hour+60*t.minute+t.second+t.microsecond/1.e6 - itime += [timesecs] - idist += [int(request.POST['intervald_%s' % i])] - itype += [int(request.POST['type_%s' % i])] + savebutton = 'savedetailform' + form = SummaryStringForm() + nrintervals = int(request.POST['nrintervals']) + detailform = IntervalUpdateForm(request.POST,aantal=nrintervals) + itime = [] + idist = [] + itype = [] + ivalues = [] + iunits = [] + itypes = [] + iresults = [] + for i in xrange(nrintervals): + try: + t = datetime.datetime.strptime(request.POST['intervalt_%s' % i],"%H:%M:%S.%f") + except ValueError: + t = datetime.datetime.strptime(request.POST['intervalt_%s' % i],"%H:%M:%S") + + timesecs = 3600*t.hour+60*t.minute+t.second+t.microsecond/1.e6 + itime += [timesecs] + idist += [int(request.POST['intervald_%s' % i])] + itype += [int(request.POST['type_%s' % i])] - if itype[i] == 3: # rest - itypes += ['rest'] - ivalues += [timesecs] - iresults += [idist[i]] - iunits += ['seconds'] - if itype[i] == 5 or itype[i] == 2: # distance based work - itypes += ['work'] - ivalues += [idist[i]] - iresults += [timesecs] - iunits += ['meters'] - if itype[i] == 4 or itype[i] == 1: # time based work - itypes += ['work'] - ivalues += [timesecs] - iresults += [idist[i]] - iunits += ['seconds'] + if itype[i] == 3: # rest + itypes += ['rest'] + ivalues += [timesecs] + iresults += [idist[i]] + iunits += ['seconds'] + if itype[i] == 5 or itype[i] == 2: # distance based work + itypes += ['work'] + ivalues += [idist[i]] + iresults += [timesecs] + iunits += ['meters'] + if itype[i] == 4 or itype[i] == 1: # time based work + itypes += ['work'] + ivalues += [timesecs] + iresults += [idist[i]] + iunits += ['seconds'] - rowdata.updateintervaldata(ivalues,iunits,itypes,iresults=iresults) - intervalstats = rowdata.allstats() - row.summary = intervalstats - try: + rowdata.updateintervaldata(ivalues,iunits,itypes,iresults=iresults) + intervalstats = rowdata.allstats() + row.summary = intervalstats + try: row.notes += "\n"+s except TypeError: pass - row.save() - rowdata.write_csv(f1,gzip=True) + row.save() + rowdata.write_csv(f1,gzip=True) dataprep.update_strokedata(encoder.decode_hex(id),rowdata.df) - messages.info(request,"Updated interval data saved") + messages.info(request,"Updated interval data saved") - form = SummaryStringForm() + form = SummaryStringForm() powerupdateform = PowerIntervalUpdateForm(initial={ 'power': int(normp), 'pace': avpace, @@ -5025,57 +5025,57 @@ def workout_summary_edit_view(request,id,message="",successmessage="" # we are processing the details form elif request.method == 'POST' and "nrintervals" in request.POST: - savebutton = 'savedetailform' - nrintervals = int(request.POST['nrintervals']) - detailform = IntervalUpdateForm(request.POST,aantal=nrintervals) - if detailform.is_valid(): - cd = detailform.cleaned_data - itime = [] - idist = [] - itype = [] - ivalues = [] - iunits = [] - itypes = [] - iresults = [] - for i in xrange(nrintervals): - t = cd['intervalt_%s' % i] - timesecs = t.total_seconds() - itime += [timesecs] - idist += [cd['intervald_%s' % i]] - itype += [cd['type_%s' % i]] + savebutton = 'savedetailform' + nrintervals = int(request.POST['nrintervals']) + detailform = IntervalUpdateForm(request.POST,aantal=nrintervals) + if detailform.is_valid(): + cd = detailform.cleaned_data + itime = [] + idist = [] + itype = [] + ivalues = [] + iunits = [] + itypes = [] + iresults = [] + for i in xrange(nrintervals): + t = cd['intervalt_%s' % i] + timesecs = t.total_seconds() + itime += [timesecs] + idist += [cd['intervald_%s' % i]] + itype += [cd['type_%s' % i]] - if itype[i] == '3': # rest - itypes += ['rest'] - ivalues += [timesecs] - iresults += [idist[i]] - iunits += ['seconds'] - if itype[i] == '5' or itype[i] == '2': # distance based work - itypes += ['work'] - ivalues += [idist[i]] - iresults += [timesecs] - iunits += ['meters'] - if itype[i] == '4' or itype[i] == '1': # time based work - itypes += ['work'] - ivalues += [timesecs] - iresults += [idist[i]] - iunits += ['seconds'] + if itype[i] == '3': # rest + itypes += ['rest'] + ivalues += [timesecs] + iresults += [idist[i]] + iunits += ['seconds'] + if itype[i] == '5' or itype[i] == '2': # distance based work + itypes += ['work'] + ivalues += [idist[i]] + iresults += [timesecs] + iunits += ['meters'] + if itype[i] == '4' or itype[i] == '1': # time based work + itypes += ['work'] + ivalues += [timesecs] + iresults += [idist[i]] + iunits += ['seconds'] - rowdata.updateintervaldata(ivalues,iunits, - itypes,iresults=iresults) - intervalstats = rowdata.allstats() + rowdata.updateintervaldata(ivalues,iunits, + itypes,iresults=iresults) + intervalstats = rowdata.allstats() - form = SummaryStringForm() - powerupdateform = PowerIntervalUpdateForm() + form = SummaryStringForm() + powerupdateform = PowerIntervalUpdateForm() initial = {} for i in xrange(nrintervals): try: - initial['intervald_%s' % i] = idist[i] - initial['intervalt_%s' % i] = get_time(itime[i]) - initial['type_%s' % i] = itype[i] + initial['intervald_%s' % i] = idist[i] + initial['intervalt_%s' % i] = get_time(itime[i]) + initial['type_%s' % i] = itype[i] except IndexError: pass @@ -5092,9 +5092,9 @@ def workout_summary_edit_view(request,id,message="",successmessage="" 'normp': normp, 'normv': normv, } - res = interactive_chart(encoder.decode_hex(id),promember=1,intervaldata=intervaldata) - script = res[0] - div = res[1] + res = interactive_chart(encoder.decode_hex(id),promember=1,intervaldata=intervaldata) + script = res[0] + div = res[1] except ValueError: script = '' div = '' @@ -5102,22 +5102,22 @@ def workout_summary_edit_view(request,id,message="",successmessage="" # render page return render(request, 'summary_edit.html', - {'form':form, - 'detailform':detailform, + {'form':form, + 'detailform':detailform, 'powerupdateform':powerupdateform, - 'workout':row, + 'workout':row, 'rower':r, 'breadcrumbs':breadcrumbs, 'active':'nav-workouts', 'teams':get_my_teams(request.user), - 'intervalstats':intervalstats, - 'nrintervals':nrintervals, - 'interactiveplot':script, - 'the_div':div, - 'intervalstring':s, - 'savebutton':savebutton, + 'intervalstats':intervalstats, + 'nrintervals':nrintervals, + 'interactiveplot':script, + 'the_div':div, + 'intervalstring':s, + 'savebutton':savebutton, 'formvalues':formvalues, - }) + }) class GraphDelete(DeleteView): @@ -5200,12 +5200,12 @@ class WorkoutDelete(DeleteView): mayedit=0 promember=0 if not self.request.user.is_anonymous(): - r = getrower(self.request.user) - result = self.request.user.is_authenticated() and ispromember(self.request.user) - if result: - promember=1 - if self.request.user == self.object.user.user: - mayedit=1 + r = getrower(self.request.user) + result = self.request.user.is_authenticated() and ispromember(self.request.user) + if result: + promember=1 + if self.request.user == self.object.user.user: + mayedit=1 context['active'] = 'nav-workouts' context['rower'] = getrower(self.request.user) diff --git a/rowers/weather.py b/rowers/weather.py index 9e08627f..f6ece062 100644 --- a/rowers/weather.py +++ b/rowers/weather.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals, absolute_import import requests import json from lxml import objectify,etree @@ -30,9 +31,9 @@ def get_weather_data(long,lat,unixtime): s = requests.get(url) if s.ok: - return s.json() + return s.json() else: - return 0 + return 0 # Get Metar data def get_metar_data(airportcode,unixtime): @@ -78,7 +79,7 @@ def get_metar_data(airportcode,unixtime): message = 'Summary for your location at '+timestamp+': ' message += 'Temperature '+temp_c+'C/'+temp_f+'F' - message += '. Wind: '+str(wind_ms)+' m/s ('+str(wind_knots)+' kt)' + message += '. Wind: '+str(wind_ms)+' m/s ('+str(wind_knots)+' kt)' message +='. Wind Bearing: '+str(windbearing)+' degrees' # message +='\n'+rawtext @@ -93,36 +94,36 @@ def get_metar_data(airportcode,unixtime): def get_wind_data(lat,long,unixtime): data = get_weather_data(lat,long,unixtime) if data: - try: - # we are getting wind in mph - windspeed = data['currently']['windSpeed']*0.44704 - windbearing = data['currently']['windBearing'] - except KeyError: - windspeed = 0 - windbearing = 0 + try: + # we are getting wind in mph + windspeed = data['currently']['windSpeed']*0.44704 + windbearing = data['currently']['windBearing'] + except KeyError: + windspeed = 0 + windbearing = 0 - try: - airports = data['flags']['madis-stations'] - except KeyError: - airports = ['unknown'] + try: + airports = data['flags']['madis-stations'] + except KeyError: + airports = ['unknown'] - try: - temperature = data['currently']['temperature'] + try: + temperature = data['currently']['temperature'] # Temp is given in Fahrenheit, so convert to Celsius for Europeans - temperaturec = (temperature-32.)*(5./9.) - temperaturec = int(10*temperaturec)/10. - except KeyError: - temperature = 'unknown' - temperaturec = 'unknown' + temperaturec = (temperature-32.)*(5./9.) + temperaturec = int(10*temperaturec)/10. + except KeyError: + temperature = 'unknown' + temperaturec = 'unknown' - try: - summary = data['currently']['summary'] - except KeyError: - summary = 'unknown' + try: + summary = data['currently']['summary'] + except KeyError: + summary = 'unknown' else: - windspeed = 0 - windbearing = 0 - message = 'Not able to get weather data' + windspeed = 0 + windbearing = 0 + message = 'Not able to get weather data' # apply Hellman's coefficient for neutral air above human # inhabitated areas @@ -135,7 +136,7 @@ def get_wind_data(lat,long,unixtime): message += '. Temperature '+str(temperature)+'F/'+str(temperaturec)+'C' if data: - message += '. Wind: '+str(windspeed)+' m/s. Wind Bearing: '+str(windbearing)+' degrees' + message += '. Wind: '+str(windspeed)+' m/s. Wind Bearing: '+str(windbearing)+' degrees' return [windspeed,windbearing,message,airports,timestamp] diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index 145a972b..19d215d1 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -378,9 +378,11 @@ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', - 'oauth2_provider.ext.rest_framework.OAuth2Authentication', +# 'oauth2_provider.ext.rest_framework.OAuth2Authentication', + 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', ), 'PAGE_SIZE': 20, + 'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.LimitOffsetPagination', } SWAGGER_SETTINGS = { diff --git a/rowsandall_app/settings_dev.py b/rowsandall_app/settings_dev.py index b4953f19..6733c420 100644 --- a/rowsandall_app/settings_dev.py +++ b/rowsandall_app/settings_dev.py @@ -9,7 +9,7 @@ https://docs.djangoproject.com/en/1.9/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.9/ref/settings/ """ -from settings import * +from .settings import * DATABASES = { 'default': { diff --git a/rowsandall_app/settings_thinkpad.py b/rowsandall_app/settings_thinkpad.py index e5aef3c0..ea7fc6fc 100644 --- a/rowsandall_app/settings_thinkpad.py +++ b/rowsandall_app/settings_thinkpad.py @@ -12,7 +12,7 @@ https://docs.djangoproject.com/en/1.9/ref/settings/ import os -from settings import * +from .settings import * DATABASES = { 'default': { diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py index 7a5ab265..ce2714fa 100644 --- a/rowsandall_app/urls.py +++ b/rowsandall_app/urls.py @@ -35,19 +35,26 @@ handler500 = 'rowers.views.error500_view' urlpatterns = [ url('^', include('django.contrib.auth.urls')), url(r'^django-rq/',include('django_rq.urls')), - url(r'^password_change_done/$',auth_views.password_change_done,name='password_change_done'), - url(r'^password_change/$',auth_views.password_change), +# url(r'^password_change_done/$',auth_views.password_change_done,name='password_change_done'), + url(r'^password_change_done/$',auth_views.PasswordChangeDoneView,name='password_change_done'), +# url(r'^password_change/$',auth_views.password_change), + url(r'^password_change/$',auth_views.PasswordChangeView,name='password_change'), url(r'^password_reset/$', - auth_views.password_reset, +# auth_views.password_reset, + auth_views.PasswordResetView, {'template_name': 'rowers/templates/registration/password_reset.html'}, name='password_reset'), url(r'^password_reset/done/$', - auth_views.password_reset_done, +# auth_views.password_reset_done, + auth_views.PasswordResetDoneView, name='password_reset_done'), url(r'^reset/(?P[0-9A-Za-z_\-]+)/(?P.+)/$', - auth_views.password_reset_confirm, +# auth_views.password_reset_confirm, + auth_views.PasswordResetConfirmView, name='password_reset_confirm'), - url(r'^reset/done/$', auth_views.password_reset_complete, + url(r'^reset/done/$', +# auth_views.password_reset_complete, + auth_views.PasswordResetCompleteView, name='password_reset_complete'), ] @@ -55,16 +62,21 @@ urlpatterns += [ url(r'^robots\.txt$', TemplateView.as_view(template_name='robots.txt', content_type='text/plain')), url(r'^admin/', admin.site.urls), - url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), + url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework2')), url(r'^$',rootview), url(r'^getblogs/$',rowersviews.get_blog_posts), - url(r'^login/',auth_views.login, name='login'), - url(r'^logout/$',auth_views.logout, + url(r'^login/', +# auth_views.login, + auth_views.LoginView, + name='login'), + url(r'^logout/$', +# auth_views.logout, + auth_views.LogoutView, {'next_page': '/'}, name='logout',), url(r'^rowers/',include('rowers.urls')), # url(r'^cvkbrno/',include('cvkbrno.urls')), - url(r'^admin/rq/',include('django_rq_dashboard.urls')), +# url(r'^admin/rq/',include('django_rq_dashboard.urls')), url(r'^call\_back',rowersviews.rower_process_callback), url(r'^stravacall\_back',rowersviews.rower_process_stravacallback), url(r'^sporttracks\_callback',rowersviews.rower_process_sporttrackscallback), @@ -75,7 +87,7 @@ urlpatterns += [ url(r'^twitter\_callback',rowersviews.rower_process_twittercallback), url(r'^i18n/', include('django.conf.urls.i18n')), url(r'^tz_detect/', include('tz_detect.urls')), - url(r'^jsi18n/', 'django.views.i18n.javascript_catalog',name='jsi18n'), +# url(r'^jsi18n/', 'django.views.i18n.javascript_catalog',name='jsi18n'), ] @@ -83,7 +95,7 @@ if settings.DEBUG: import debug_toolbar import django urlpatterns += [ - url(r'^__debug__/',include(debug_toolbar.urls)), +# url(r'^__debug__/','debug_toolbar.urls'), url(r'^static/(?P.*)$', django.views.static.serve, kwargs={'document_root': settings.STATIC_ROOT,}