diff --git a/rowers/admin.py b/rowers/admin.py index 27453428..f89d9710 100644 --- a/rowers/admin.py +++ b/rowers/admin.py @@ -8,7 +8,7 @@ from .models import ( WorkoutComment, C2WorldClassAgePerformance, PlannedSession, GeoCourse, GeoPolygon, GeoPoint, VirtualRace, VirtualRaceResult, PaidPlan, IndoorVirtualRaceResult, ShareKey, - CourseStandard, StandardCollection, + CourseStandard, StandardCollection, InstantPlan, ) # Register your models here so you can use them in the Admin module @@ -165,6 +165,8 @@ class StandardCollectionAdmin(admin.ModelAdmin): class CourseStandardAdmin(admin.ModelAdmin): list_display = ('name', 'standardcollection') +class InstantPlanAdmin(admin.ModelAdmin): + list_display = ('name','duration','price') admin.site.unregister(User) admin.site.register(User, UserAdmin) @@ -187,3 +189,4 @@ admin.site.register(PaidPlan, PaidPlanAdmin) admin.site.register(ShareKey, ShareKeyAdmin) admin.site.register(CourseStandard, CourseStandardAdmin) admin.site.register(StandardCollection, StandardCollectionAdmin) +admin.site.register(InstantPlan, InstantPlanAdmin) diff --git a/rowers/alerts.py b/rowers/alerts.py index c2414e62..e88dbcdf 100644 --- a/rowers/alerts.py +++ b/rowers/alerts.py @@ -2,9 +2,7 @@ from rowers.models import Alert, Condition, User, Rower, Workout from rowers.teams import coach_getcoachees from rowers.dataprep import getsmallrowdata_db, getrowdata_db import datetime -# BASIC operations - -# create alert +import numpy as np def create_alert(manager, rower, measured, period=7, emailalert=True, @@ -65,7 +63,6 @@ def alert_add_filters(alert, filters): for f in filters: metric = f['metric'] value1 = f['value1'] - value2 = f['value2'] condition = f['condition'] if condition and metric and value1: diff --git a/rowers/braintreestuff.py b/rowers/braintreestuff.py index 2f38f0bc..a5624ca4 100644 --- a/rowers/braintreestuff.py +++ b/rowers/braintreestuff.py @@ -72,8 +72,7 @@ def process_webhook(notification): transactions = subscription.transactions if transactions: amount = int(transactions[0].amount) - eurocredits = credits.upgrade(amount, r) - eurocredits = credits.upgrade(amount, r) + _ = credits.upgrade(amount, r) return send_invoice(notification.subscription) if notification.kind == 'subscription_canceled': subscription = notification.subscription @@ -97,10 +96,7 @@ def process_webhook(notification): def send_invoice(subscription): - with open('braintreewebhooks.log', 'a') as f: - t = time.localtime() - timestamp = time.strftime('%b-%d-%Y_%H%M', t) - f.write('Subscription ID '+str(subscription.id)+'\n') + dologging('braintreewebhooks.log', 'Subscription ID '+str(subscription.id)) subscription_id = subscription.id rs = Rower.objects.filter(subscription_id=subscription_id) if rs.count() == 0: # pragma: no cover @@ -176,20 +172,6 @@ def get_client_token(rower): return client_token -def get_plans_costs(): # pragma: no cover - plans = gateway.plan.all() - - localplans = PaidPlan.object.filter(paymentprocessor='braintree') - - for plan in localplans: - for btplan in btplans: - if int(btplan.id) == plan.external_id: - plan.price = float(x) - plan.save() - - return plans - - def make_payment(rower, data): nonce_from_the_client = data['payment_method_nonce'] nonce = gateway.payment_method_nonce.find(nonce_from_the_client) @@ -226,17 +208,11 @@ def make_payment(rower, data): fakturoid_contact_id = fakturoid.get_contacts(rower) if not fakturoid_contact_id: fakturoid_contact_id = fakturoid.create_contact(rower) - id = fakturoid.create_invoice(rower, amount, transaction.id, dosend=True, contact_id=fakturoid_contact_id, - name=additional_text) - - try: - job = myqueue(queuehigh, handle_send_email_transaction, - name, rower.user.email, amount) - job = myqueue(queuehigh, handle_send_email_transation_notification, - name.rower.user.email, amount, additional_text) - except: # pragma: no cover - pass + _ = fakturoid.create_invoice(rower, amount, transaction.id, dosend=True, contact_id=fakturoid_contact_id, + name=additional_text) + _ = myqueue(queuehigh, handle_send_email_transaction, + name, rower.user.email, amount) return amount, True else: # pragma: no cover return 0, False @@ -280,7 +256,7 @@ def update_subscription(rower, data, method='up'): yesterday = (timezone.now()-datetime.timedelta(days=1)).date() rower.paidplan = plan amount_int = int(float(amount)) - eurocredits = credits.upgrade(amount_int, rower) + _ = credits.upgrade(amount_int, rower) rower.planexpires = result.subscription.billing_period_end_date rower.teamplanexpires = result.subscription.billing_period_end_date rower.clubsize = plan.clubsize @@ -319,16 +295,16 @@ def update_subscription(rower, data, method='up'): else: # pragma: no cover amount = 0 - job = myqueue(queuehigh, - handle_send_email_subscription_update, - name, rower.user.email, - plan.name, - plan.paymenttype, - plan.price, - amount, - result.subscription.billing_period_end_date.strftime( - '%Y-%m-%d'), - method) + _ = myqueue(queuehigh, + handle_send_email_subscription_update, + name, rower.user.email, + plan.name, + plan.paymenttype, + plan.price, + amount, + result.subscription.billing_period_end_date.strftime( + '%Y-%m-%d'), + method) return True, amount else: # pragma: no cover @@ -352,12 +328,12 @@ def create_subscription(rower, data): nonce_from_the_client = data['payment_method_nonce'] nonce = gateway.payment_method_nonce.find(nonce_from_the_client) info = nonce.three_d_secure_info - paymenttype = nonce.type + # paymenttype = nonce.type if nonce.type != 'PayPalAccount': # pragma: no cover if info is None or not info.liability_shifted: return False, 0 - amount = data['amount'] + # amount = data['amount'] planid = data['plan'] plan = PaidPlan.objects.get(id=planid) @@ -399,7 +375,7 @@ def create_subscription(rower, data): recurring = plan.paymenttype - job = myqueue( + _ = myqueue( queuehigh, handle_send_email_subscription_create, name, rower.user.email, @@ -420,18 +396,19 @@ def cancel_subscription(rower, id): themessages = [] errormessages = [] try: - result = gateway.subscription.cancel(id) + _ = gateway.subscription.cancel(id) themessages.append("Subscription canceled") except: # pragma: no cover errormessages.append( - "We could not find the subscription record in our customer database. We have notified the site owner, who will contact you.") + "We could not find the subscription record in our customer database." + " We have notified the site owner, who will contact you.") name = '{f} {l}'.format(f=rower.user.first_name, l=rower.user.last_name) - job = myqueue(queuehigh, - handle_send_email_failed_cancel, - name, rower.user.email, rower.user.username, id) + _ = myqueue(queuehigh, + handle_send_email_failed_cancel, + name, rower.user.email, rower.user.username, id) return False, themessages, errormessages @@ -510,15 +487,13 @@ def get_transactions(start_date, end_date): # pragma: no cover dates = [] currencies = [] statuses = [] - ids = [] + # ids = [] usernames = [] customerids = [] transactionids = [] subscriptionids = [] ownids = [] - countlines = [1 for transaction in results] - for transaction in results: r = None rs = Rower.objects.filter( diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 1e2316f4..bddc3bbe 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -74,11 +74,12 @@ def getagegrouprecord(age, sex='male', weightcategory='hwt', ages = df['age'] powers = df['power'] - #poly_coefficients = np.polyfit(ages,powers,6) - def fitfunc(pars, x): return np.abs(pars[0])*(1-x/max(120, pars[1]))-np.abs( - pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50, pars[5]))) + def fitfunc(pars, x): + return np.abs(pars[0])*(1-x/max(120, pars[1]))-np.abs( + pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50, pars[5]))) - def errfunc(pars, x, y): return fitfunc(pars, x)-y + def errfunc(pars, x, y): + return fitfunc(pars, x)-y p0 = [700, 120, 700, 10, 100, 100] @@ -92,8 +93,6 @@ def getagegrouprecord(age, sex='male', weightcategory='hwt', if success: power = fitfunc(p1, float(age)) - #power = np.polyval(poly_coefficients,age) - power = 0.5*(np.abs(power)+power) else: # pragma: no cover power = 0 @@ -123,14 +122,13 @@ 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") else: if (timezone.now() > r.tokenexpirydate): res = rower_c2_token_refresh(user) - if res == None: # pragma: no cover + if res is None: # pragma: no cover raise NoTokenError("User has no token") - if res[0] != None: + if res[0] is not None: thetoken = res[0] else: # pragma: no cover raise NoTokenError("User has no token") @@ -142,7 +140,7 @@ def c2_open(user): def get_c2_workouts(rower, page=1, do_async=True): try: - thetoken = c2_open(rower.user) + _ = c2_open(rower.user) except NoTokenError: # pragma: no cover return 0 @@ -175,7 +173,7 @@ def get_c2_workouts(rower, page=1, do_async=True): knownc2ids = uniqify(knownc2ids+tombstones+parkedids) - newids = [c2id for c2id in c2ids if not c2id in knownc2ids] + newids = [c2id for c2id in c2ids if c2id not in knownc2ids] if settings.TESTING: newids = c2ids @@ -188,20 +186,18 @@ def get_c2_workouts(rower, page=1, do_async=True): counter = 0 for c2id in newids: if do_async: # pragma: no cover - res = myqueue(queuehigh, - handle_c2_async_workout, - alldata, - rower.user.id, - rower.c2token, - c2id, - counter, - rower.defaulttimezone - ) - #res = handle_c2_async_workout(alldata,rower.user.id,rower.c2token,c2id,counter) + _ = myqueue(queuehigh, + handle_c2_async_workout, + alldata, + rower.user.id, + rower.c2token, + c2id, + counter, + rower.defaulttimezone) + counter = counter+1 else: - workoutid = create_async_workout(alldata, - rower.user, c2id) + _ = create_async_workout(alldata, rower.user, c2id) return 1 @@ -212,12 +208,9 @@ def create_async_workout(alldata, user, c2id): data = alldata[c2id] splitdata = None - distance = data['distance'] c2id = data['id'] workouttype = data['type'] - verified = data['verified'] startdatetime = iso8601.parse_date(data['date']) - weightclass = data['weight_class'] try: title = data['name'] @@ -229,43 +222,16 @@ def create_async_workout(alldata, user, c2id): except: title = '' - weightcategory = 'hwt' - if weightclass == "L": - weightcategory = 'lwt' - # Create CSV file name and save data to CSV file csvfilename = 'media/Import_'+str(c2id)+'.csv.gz' - totaltime = data['time']/10. - duration = dataprep.totaltime_sec_to_string(totaltime) - - try: - timezone_str = data['timezone'] - except: # pragma: no cover - timezone_str = 'UTC' - - workoutdate = startdatetime.astimezone( - pytz.timezone(timezone_str) - ).strftime('%Y-%m-%d') - starttime = startdatetime.astimezone( - pytz.timezone(timezone_str) - ).strftime('%H:%M:%S') - - try: - notes = data['comments'] - name = notes[:40] - except (KeyError, TypeError): - notes = 'C2 Import Workout from {startdatetime}'.format( - startdatetime=startdatetime) - name = notes - r = Rower.objects.get(user=user) authorizationstring = str('Bearer ' + r.c2token) headers = {'Authorization': authorizationstring, 'user-agent': 'sanderroosendaal', 'Content-Type': 'application/json'} - url2 = "https://log.concept2.com/api/users/me/results"+str(c2id) + # url2 = "https://log.concept2.com/api/users/me/results"+str(c2id) url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes" try: s = requests.get(url, headers=headers) @@ -638,7 +604,7 @@ def createc2workoutdata(w): spmav = int(row.df[' Cadence (stokes/min)'][mask].mean()) hrav = int(row.df[' HRCur (bpm)'][mask].mean()) except ValueError: - smpav = 0 + spmav = 0 try: hrav = int(row.df[' HRCur (bpm)'][mask].mean()) except ValuError: @@ -729,7 +695,6 @@ def createc2workoutdata(w): "time": int(10*makeseconds(durationstr)), "weight_class": c2wc(w.weightcategory), "comments": w.notes, - "stroke_count": int(row.stroke_count), 'stroke_rate': int(row.df[' Cadence (stokes/min)'].mean()), 'drag_factor': int(row.dragfactor), "heart_rate": { @@ -749,7 +714,7 @@ def createc2workoutdata(w): def do_refresh_token(refreshtoken): scope = "results:write,user:read" - client_auth = requests.auth.HTTPBasicAuth(C2_CLIENT_ID, C2_CLIENT_SECRET) + # 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, @@ -793,7 +758,7 @@ def do_refresh_token(refreshtoken): def get_token(code): messg = '' scope = "user:read,results:write" - client_auth = requests.auth.HTTPBasicAuth(C2_CLIENT_ID, C2_CLIENT_SECRET) + # client_auth = requests.auth.HTTPBasicAuth(C2_CLIENT_ID, C2_CLIENT_SECRET) post_data = {"grant_type": "authorization_code", "code": code, "redirect_uri": C2_REDIRECT_URI, @@ -840,7 +805,7 @@ def make_authorization_url(request): # pragma: no cover # Generate a random string for the state parameter # Save it for use later to prevent xsrf attacks from uuid import uuid4 - state = str(uuid4()) + # state = str(uuid4()) scope = "user:read,results:write" params = {"client_id": C2_CLIENT_ID, @@ -857,14 +822,14 @@ def make_authorization_url(request): # pragma: no cover def get_workout(user, c2id, do_async=True): r = Rower.objects.get(user=user) - thetoken = c2_open(user) + _ = c2_open(user) - job = myqueue(queuehigh, - handle_c2_getworkout, - user.id, - r.c2token, - c2id, - r.defaulttimezone) + _ = myqueue(queuehigh, + handle_c2_getworkout, + user.id, + r.c2token, + c2id, + r.defaulttimezone) return 1 @@ -909,7 +874,7 @@ def get_username(access_token): # pragma: no cover try: res = me_json['data']['username'] - id = me_json['data']['id'] + _ = me_json['data']['id'] except KeyError: res = None @@ -974,7 +939,7 @@ def workout_c2_upload(user, w, asynchron=False): except KeyError: # pragma: no cover return "This workout type cannot be uploaded to Concept2", 0 - thetoken = c2_open(user) + _ = c2_open(user) r = Rower.objects.get(user=user) @@ -1017,16 +982,17 @@ def workout_c2_upload(user, w, asynchron=False): w.save() message = "Upload to Concept2 was successful" else: # pragma: no cover - message = "Something went wrong in workout_c2_upload_view. Response code 200/201 but C2 sync failed: "+response.text + message = "Something went wrong in workout_c2_upload_view." \ + " Response code 200/201 but C2 sync failed: "+response.text c2id = 0 else: # pragma: no cover - job = myqueue(queue, - handle_c2_sync, - w.id, - url, - headers, - json.dumps(data, default=default)) + _ = myqueue(queue, + handle_c2_sync, + w.id, + url, + headers, + json.dumps(data, default=default)) c2id = 0 return message, c2id diff --git a/rowers/courses.py b/rowers/courses.py index 8b4661dd..7fa3d8f9 100644 --- a/rowers/courses.py +++ b/rowers/courses.py @@ -25,7 +25,7 @@ from django.conf import settings import geocoder -from matplotlib import path +# from matplotlib import path import xml.etree.ElementTree as et from xml.etree.ElementTree import Element, SubElement, Comment, tostring @@ -42,10 +42,6 @@ def howfaris(lat_lon, course): return distance -#whatisnear = 150 - -# get nearest races - def getnearestraces(lat_lon, races, whatisnear=150): newlist = [] @@ -55,7 +51,6 @@ def getnearestraces(lat_lon, races, whatisnear=150): newlist.append(race) else: c = race.course - coords = c.coord distance = howfaris(lat_lon, c) if distance < whatisnear: newlist.append(race) @@ -84,7 +79,6 @@ def getnearestcourses(lat_lon, courses, whatisnear=150, strict=False): newlist = [] counter = 0 for c in courses: - coords = c.coord distance = howfaris(lat_lon, c) if distance < whatisnear: @@ -199,8 +193,6 @@ def coursetokml(course): polygons = GeoPolygon.objects.filter( course=course).order_by("order_in_course") - polygonsxml = [] - for polygon in polygons: placemark = SubElement(folder2, 'Placemark') polygonname = SubElement(placemark, 'name') diff --git a/rowers/courseutils.py b/rowers/courseutils.py index b31d7750..04b34d25 100644 --- a/rowers/courseutils.py +++ b/rowers/courseutils.py @@ -20,10 +20,8 @@ def time_in_path(df, p, maxmin='max', getall=False, name='unknown', logfile=None if df.empty: # pragma: no cover return 0 - latitude = df.latitude - longitude = df.longitude - - def f(x): return coordinate_in_path(x['latitude'], x['longitude'], p) + def f(x): + return coordinate_in_path(x['latitude'], x['longitude'], p) df['inpolygon'] = df.apply(f, axis=1) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 3eb79f46..eb2e3c46 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -31,7 +31,6 @@ from zipfile import BadZipFile import zipfile import os from rowers.models import strokedatafields -from rowingdata.csvparsers import HumonParser from rowingdata import ( KinoMapParser, @@ -56,8 +55,7 @@ from rowingdata import ( ETHParser, NKLiNKLogbookParser, HeroParser, - SmartRowParser, - ) + SmartRowParser,) # All the data preparation, data cleaning and data mangling should # be defined here @@ -111,13 +109,8 @@ import arrow thetimezone = get_current_timezone() - -#allowedcolumns = [item[0] for item in rowingmetrics] allowedcolumns = [key for key, value in strokedatafields.items()] -#from async_messages import messages as a_messages - - queue = django_rq.get_queue('default') queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('default') @@ -169,8 +162,6 @@ def get_video_data(w, groups=['basic'], mode='water'): p = nicepaceformat(p) df2['pace'] = p - #mask = df2['time'] < delay - #df2 = df2.mask(mask).dropna() df2['time'] = (df2['time']-df2['time'].min()) df2 = df2.round(decimals=2) @@ -190,8 +181,6 @@ def get_video_data(w, groups=['basic'], mode='water'): coordinates.set_index(pd.to_timedelta( coordinates['time'], unit='s'), inplace=True) coordinates = coordinates.resample('1s').mean().interpolate() - #mask = coordinates['time'] < delay - #coordinates = coordinates.mask(mask).dropna() coordinates['time'] = coordinates['time']-coordinates['time'].min() latitude = coordinates['latitude'] longitude = coordinates['longitude'] @@ -295,11 +284,11 @@ def get_latlon_time(id): try: try: - latitude = rowdata.df.loc[:, ' latitude'] - longitude = rowdata.df.loc[:, ' longitude'] + _ = rowdata.df.loc[:, ' latitude'] + _ = rowdata.df.loc[:, ' longitude'] except KeyError: # pragma: no cover - latitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] - longitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] + rowdata.df['latitude'] = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] + rowdata.df['longitude'] = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] except AttributeError: # pragma: no cover return pd.DataFrame() @@ -438,7 +427,7 @@ def get_workouts(ids, userid): # pragma: no cover def filter_df(datadf, fieldname, value, largerthan=True): try: - x = datadf[fieldname] + _ = datadf[fieldname] except KeyError: return datadf @@ -486,9 +475,9 @@ def join_workouts(r, ids, title='Joined Workout', makeprivate = False startdatetime = timezone.now() - if setprivate == True and makeprivate == False: # pragma: no cover + if setprivate is True and makeprivate is False: # pragma: no cover makeprivate = True - elif setprivate == False and makeprivate == True: # pragma: no cover + elif setprivate is False and makeprivate is True: # pragma: no cover makeprivate = False # reorder in chronological order @@ -501,6 +490,11 @@ def join_workouts(r, ids, title='Joined Workout', workouttype = parent.workouttype notes = parent.notes summary = parent.summary + if parent.privacy == 'hidden': + makeprivate = True + else: + makeprivate = False + startdatetime = parent.startdatetime files = [w.csvfilename for w in ws] @@ -524,7 +518,9 @@ def join_workouts(r, ids, title='Joined Workout', notes=notes, oarlength=oarlength, inboard=inboard, + startdatetime=startdatetime, makeprivate=makeprivate, + summary=summary, dosmooth=False, consistencychecks=False) @@ -585,12 +581,12 @@ def resample(id, r, parent, overwrite='copy'): row.write_csv(parent.csvfilename, gzip=True) - res = dataprep(row.df, id=parent.id, bands=True, barchart=True, - otwpower=True, empower=True, inboard=parent.inboard) + _ = dataprep(row.df, id=parent.id, bands=True, barchart=True, + otwpower=True, empower=True, inboard=parent.inboard) isbreakthrough, ishard = checkbreakthrough(parent, r) - marker = check_marker(parent) - result = update_wps(r, mytypes.otwtypes) - result = update_wps(r, mytypes.otetypes) + _ = check_marker(parent) + _ = update_wps(r, mytypes.otwtypes) + _ = update_wps(r, mytypes.otetypes) tss, normp = workout_rscore(parent) goldmedalstandard, goldmedalseconds = workout_goldmedalstandard(parent) @@ -607,7 +603,7 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True, # clean data remove zeros and negative values try: - workoutids = datadf['workoutid'].unique() + _ = datadf['workoutid'].unique() except KeyError: datadf['workoutid'] = 0 @@ -638,13 +634,13 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True, # protect 0 spm values from being nulled try: datadf['spm'] = datadf['spm'] + 1.0 - except (KeyError, TypeError) as e: + except (KeyError, TypeError): pass # protect 0 workoutstate values from being nulled try: datadf['workoutstate'] = datadf['workoutstate'] + 1 - except (KeyError, TypeError) as e: + except (KeyError, TypeError): pass try: @@ -676,13 +672,13 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True, # bring spm back to real values try: datadf['spm'] = datadf['spm'] - 1 - except (TypeError, KeyError) as e: + except (TypeError, KeyError): pass # bring workoutstate back to real values try: datadf['workoutstate'] = datadf['workoutstate'] - 1 - except (TypeError, KeyError) as e: + except (TypeError, KeyError): pass # return from positive domain to negative @@ -840,11 +836,11 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True, except (KeyError, TypeError): pass - workoutstateswork = [1, 4, 5, 8, 9, 6, 7] + # workoutstateswork = [1, 4, 5, 8, 9, 6, 7] workoutstatesrest = [3] - workoutstatetransition = [0, 2, 10, 11, 12, 13] + # workoutstatetransition = [0, 2, 10, 11, 12, 13] - if workstrokesonly == 'True' or workstrokesonly == True: + if workstrokesonly == 'True' or workstrokesonly is True: try: datadf = datadf[~datadf['workoutstate'].isin(workoutstatesrest)] except: @@ -872,10 +868,10 @@ def getpartofday(row, r): timezone_str = tf.timezone_at(lng=lonavg, lat=latavg) except (ValueError, OverflowError): # pragma: no cover timezone_str = 'UTC' - if timezone_str == None: # pragma: no cover + if timezone_str is None: # pragma: no cover timezone_str = tf.closest_timezone_at(lng=lonavg, lat=latavg) - if timezone_str == None: + if timezone_str is None: timezone_str = r.defaulttimezone try: workoutstartdatetime = pytz.timezone(timezone_str).localize( @@ -1008,7 +1004,7 @@ def update_c2id_sql(id, c2id): table, c2id, id) with engine.connect() as conn, conn.begin(): - result = conn.execute(query) + _ = conn.execute(query) conn.close() engine.dispose() @@ -1022,7 +1018,8 @@ def getcpdata_sql(rower_id, table='cpdata'): rower_id=rower_id, table=table, )) - connection = engine.raw_connection() + + _ = engine.raw_connection() df = pd.read_sql_query(query, engine) return df @@ -1036,7 +1033,7 @@ def deletecpdata_sql(rower_id, table='cpdata'): # pragma: no cover )) with engine.connect() as conn, conn.begin(): try: - result = conn.execute(query) + _ = conn.execute(query) except: print("Database locked") conn.close() @@ -1064,11 +1061,10 @@ def updatecpdata_sql(rower_id, delta, cp, table='cpdata', distance=[]): # pragm def fetchcperg(rower, theworkouts): - theids = [int(w.id) for w in theworkouts] thefilenames = [w.csvfilename for w in theworkouts] cpdf = getcpdata_sql(rower.id, table='ergcpdata') - job = myqueue( + _ = myqueue( queuelow, handle_updateergcp, rower.id, @@ -1138,7 +1134,7 @@ def check_marker(workout): theid = df.loc[indexmax, 'id'] wmax = Workout.objects.get(id=theid) - gms_max = wmax.goldmedalstandard + # gms_max = wmax.goldmedalstandard # check if equal, bigger, or smaller than previous if not wmax.rankingpiece: @@ -1210,16 +1206,17 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True): ) ) jsondf = df2.to_json() - job = myqueue(queuelow, handle_getagegrouprecords, - jsondf, distances, durations, age, rower.sex, rower.weightcategory) + _ = myqueue(queuelow, handle_getagegrouprecords, + jsondf, distances, durations, age, rower.sex, rower.weightcategory) wcpower = pd.Series(wcpower, dtype='float') wcdurations = pd.Series(wcdurations, dtype='float') - def fitfunc(pars, x): return pars[0] / \ - (1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) + def fitfunc(pars, x): + return pars[0] / (1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) - def errfunc(pars, x, y): return fitfunc(pars, x)-y + def errfunc(pars, x, y): + return fitfunc(pars, x)-y if len(wcdurations) >= 4: # pragma: no cover p1wc, success = optimize.leastsq( @@ -1227,7 +1224,7 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True): else: factor = fitfunc(p0, wcdurations.mean()/wcpower.mean()) p1wc = [p0[0]/factor, p0[1]/factor, p0[2], p0[3]] - success = 0 + return 0, 0 times = df['delta'] @@ -1292,7 +1289,7 @@ def setcp(workout, background=False, recurrance=True): return pd.DataFrame(), pd.Series(dtype='float'), pd.Series(dtype='float') if background: # pragma: no cover - job = myqueue(queuelow, handle_setcp, strokesdf, filename, workout.id) + _ = myqueue(queuelow, handle_setcp, strokesdf, filename, workout.id) return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float') if not strokesdf.empty: @@ -1339,7 +1336,7 @@ def update_wps(r, types, mode='water', asynchron=True): ids = [w.id for w in workouts] if asynchron: - job = myqueue( + _ = myqueue( queue, handle_update_wps, r.id, @@ -1441,11 +1438,11 @@ def fetchcp(rower, theworkouts, table='cpdata'): # pragma: no cover if not cpdf.empty: return cpdf['delta'], cpdf['cp'], avgpower2 else: - job = myqueue(queuelow, - handle_updatecp, - rower.id, - theids, - table=table) + _ = myqueue(queuelow, + handle_updatecp, + rower.id, + theids, + table=table) return pd.Series([], dtype='float'), pd.Series([], dtype='float'), avgpower2 @@ -1489,11 +1486,11 @@ def create_row_df(r, distance, duration, startdatetime, workouttype='rower', else: spm = avgspm - step = totalseconds/float(nr_strokes) + # step = totalseconds/float(nr_strokes) elapsed = np.arange(nr_strokes)*totalseconds/(float(nr_strokes-1)) - dstep = distance/float(nr_strokes) + # dstep = distance/float(nr_strokes) d = np.arange(nr_strokes)*distance/(float(nr_strokes-1)) @@ -1564,12 +1561,12 @@ def checkbreakthrough(w, r): if workouttype in otwtypes: res, btvalues, res2 = utils.isbreakthrough( delta, cpvalues, r.p0, r.p1, r.p2, r.p3, r.cpratio) - success = update_rolling_cp(r, otwtypes, 'water') + _ = update_rolling_cp(r, otwtypes, 'water') elif workouttype in otetypes: res, btvalues, res2 = utils.isbreakthrough( delta, cpvalues, r.ep0, r.ep1, r.ep2, r.ep3, r.ecpratio) - success = update_rolling_cp(r, otetypes, 'erg') + _ = update_rolling_cp(r, otetypes, 'erg') else: # pragma: no cover res = 0 res2 = 0 @@ -1584,12 +1581,12 @@ def checkbreakthrough(w, r): w.rankingpiece = True w.save() if r.getemailnotifications and not r.emailbounced: # pragma: no cover - job = myqueue(queuehigh, handle_sendemail_breakthrough, - w.id, - r.user.email, - r.user.first_name, - r.user.last_name, - btvalues=btvalues.to_json()) + _ = myqueue(queuehigh, handle_sendemail_breakthrough, + w.id, + r.user.email, + r.user.first_name, + r.user.last_name, + btvalues=btvalues.to_json()) # submit email task to send email about breakthrough workout if ishard: # pragma: no cover @@ -1597,12 +1594,12 @@ def checkbreakthrough(w, r): w.rankingpiece = True w.save() if r.getemailnotifications and not r.emailbounced: - job = myqueue(queuehigh, handle_sendemail_hard, - w.id, - r.user.email, - r.user.first_name, - r.user.last_name, - btvalues=btvalues.to_json()) + _ = myqueue(queuehigh, handle_sendemail_hard, + w.id, + r.user.email, + r.user.first_name, + r.user.last_name, + btvalues=btvalues.to_json()) return isbreakthrough, ishard @@ -1624,7 +1621,6 @@ def checkduplicates(r, workoutdate, workoutstartdatetime, workoutenddatetime): ws2.append(ww) if (len(ws2) != 0): - message = "Warning: This workout overlaps with an existing one and was marked as a duplicate" duplicate = True return duplicate @@ -1724,7 +1720,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', windowsize = 2 * (int(10. / (f))) + 1 else: # pragma: no cover windowsize = 1 - if not 'originalvelo' in row.df: + if 'originalvelo' not in row.df: row.df['originalvelo'] = velo if windowsize > 3 and windowsize < len(velo): @@ -1861,16 +1857,16 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', w.team.add(t) # put stroke data in database - res = dataprep(row.df, id=w.id, bands=True, - barchart=True, otwpower=True, empower=True, inboard=inboard) + _ = dataprep(row.df, id=w.id, bands=True, + barchart=True, otwpower=True, empower=True, inboard=inboard) isbreakthrough, ishard = checkbreakthrough(w, r) - marker = check_marker(w) - result = update_wps(r, mytypes.otwtypes) - result = update_wps(r, mytypes.otetypes) + _ = check_marker(w) + _ = update_wps(r, mytypes.otwtypes) + _ = update_wps(r, mytypes.otetypes) - job = myqueue(queuehigh, handle_calctrimp, w.id, f2, - r.ftp, r.sex, r.hrftp, r.max, r.rest) + _ = myqueue(queuehigh, handle_calctrimp, w.id, f2, + r.ftp, r.sex, r.hrftp, r.max, r.rest) return (w.id, message) @@ -1914,7 +1910,7 @@ def get_startdate_time_zone(r, row, startdatetime=None): startdatetime = row.rowdatetime try: - tz = startdatetime.tzinfo + _ = startdatetime.tzinfo except AttributeError: # pragma: no cover startdatetime = row.rowdatetime @@ -1987,7 +1983,6 @@ def parsenonpainsled(fileformat, f2, summary, startdatetime='', empowerfirmware= s = 'Parsenonpainsled, start date time = {startdatetime}'.format( startdatetime=startdatetime, - #rowdatetime = row.rowdatetime ) dologging('debuglog.log', s) @@ -2130,6 +2125,7 @@ def new_workout_from_file(r, f2, uploadoptions={'boattype': '1x', 'workouttype': 'rower'}): message = "" + try: fileformat = get_file_type(f2) except (IOError, UnicodeDecodeError): # pragma: no cover @@ -2158,11 +2154,10 @@ def new_workout_from_file(r, f2, uploadoptions['file'] = datafile url = settings.UPLOAD_SERVICE_URL - job = myqueue(queuehigh, - handle_request_post, - url, - uploadoptions - ) + _ = myqueue(queuehigh, + handle_request_post, + url, + uploadoptions) except BadZipFile: # pragma: no cover pass @@ -2227,10 +2222,10 @@ def new_workout_from_file(r, f2, extension = extension2 f4 = filename+'a'+extension copyfile(f2, f4) - job = myqueue(queuehigh, - handle_sendemail_unrecognized, - f4, - r.user.email) + _ = myqueue(queuehigh, + handle_sendemail_unrecognized, + f4, + r.user.email) return (0, message, f2) @@ -2377,7 +2372,7 @@ def split_workout(r, parent, splitsecond, splitmode): messages.append(message) ids.append(encoder.encode_hex(id)) - if not 'keep original' in splitmode: # pragma: no cover + if 'keep original' not in splitmode: # pragma: no cover if 'keep second' in splitmode or 'keep first' in splitmode: parent.delete() messages.append('Deleted Workout: ' + parent.name) @@ -2448,7 +2443,6 @@ def new_workout_from_df(r, df, df.rename(columns=columndict, inplace=True) - #starttimeunix = mktime(startdatetime.utctimetuple()) starttimeunix = arrow.get(startdatetime).timestamp() df[' ElapsedTime (sec)'] = df['TimeStamp (sec)'] @@ -2458,15 +2452,13 @@ def new_workout_from_df(r, df, row.write_csv(csvfilename, gzip=True) - # res = df.to_csv(csvfilename+'.gz',index_label='index', - # compression='gzip') - id, message = save_workout_database(csvfilename, r, workouttype=workouttype, boattype=boattype, title=title, workoutsource=workoutsource, notes=notes, + summary=summary, oarlength=oarlength, inboard=inboard, makeprivate=makeprivate, @@ -2474,8 +2466,8 @@ def new_workout_from_df(r, df, rpe=rpe, consistencychecks=False) - job = myqueue(queuehigh, handle_calctrimp, id, csvfilename, - r.ftp, r.sex, r.hrftp, r.max, r.rest) + _ = myqueue(queuehigh, handle_calctrimp, id, csvfilename, + r.ftp, r.sex, r.hrftp, r.max, r.rest) return (id, message) @@ -2520,7 +2512,7 @@ def delete_strokedata(id): def update_strokedata(id, df): delete_strokedata(id) - rowdata = dataprep(df, id=id, bands=True, barchart=True, otwpower=True) + _ = dataprep(df, id=id, bands=True, barchart=True, otwpower=True) # Test that all data are of a numerical time @@ -2555,7 +2547,7 @@ def getrowdata_db(id=0, doclean=False, convertnewtons=True, else: row = Workout.objects.get(id=id) - if checkefficiency == True and not data.empty: + if checkefficiency is True and not data.empty: try: if data['efficiency'].mean() == 0 and data['power'].mean() != 0: # pragma: no cover data = add_efficiency(id=id) @@ -2586,15 +2578,13 @@ def getsmallrowdata_db(columns, ids=[], doclean=True, workstrokesonly=True, comp if len(ids) > 1: for id, f in zip(ids, csvfilenames): try: - #df = dd.read_parquet(f,columns=columns,engine='pyarrow') df = pd.read_parquet(f, columns=columns) data.append(df) except (OSError, ArrowInvalid, IndexError): # pragma: no cover rowdata, row = getrowdata(id=id) if rowdata and len(rowdata.df): - datadf = dataprep(rowdata.df, id=id, - bands=True, otwpower=True, barchart=True) - # df = dd.read_parquet(f,columns=columns,engine='pyarrow') + _ = dataprep(rowdata.df, id=id, + bands=True, otwpower=True, barchart=True) df = pd.read_parquet(f, columns=columns) data.append(df) @@ -2649,7 +2639,6 @@ def getrowdata(id=0): # get user r = row.user - u = r.user rr = rrower(hrmax=r.max, hrut2=r.ut2, hrut1=r.ut1, hrat=r.at, @@ -2677,8 +2666,8 @@ def prepmultipledata(ids, verbose=False): # pragma: no cover if verbose: print(id) if rowdata and len(rowdata.df): - data = dataprep(rowdata.df, id=id, bands=True, - barchart=True, otwpower=True) + _ = dataprep(rowdata.df, id=id, bands=True, + barchart=True, otwpower=True) return ids # Read a set of columns for a set of workout ids, returns data as a @@ -2707,8 +2696,8 @@ def read_cols_df_sql(ids, columns, convertnewtons=True): except OSError: rowdata, row = getrowdata(id=ids[0]) if rowdata and len(rowdata.df): - datadf = dataprep( - rowdata.df, id=ids[0], bands=True, otwpower=True, barchart=True) + _ = dataprep(rowdata.df, + id=ids[0], bands=True, otwpower=True, barchart=True) df = pd.read_parquet(filename, columns=columns) else: data = [] @@ -2721,8 +2710,8 @@ def read_cols_df_sql(ids, columns, convertnewtons=True): except (OSError, IndexError, ArrowInvalid): rowdata, row = getrowdata(id=id) if rowdata and len(rowdata.df): # pragma: no cover - datadf = dataprep(rowdata.df, id=id, - bands=True, otwpower=True, barchart=True) + _ = dataprep(rowdata.df, id=id, + bands=True, otwpower=True, barchart=True) df = pd.read_parquet(f, columns=columns) data.append(df) @@ -2753,8 +2742,8 @@ def read_cols_df_sql(ids, columns, convertnewtons=True): def initiate_cp(r): - success = update_rolling_cp(r, otwtypes, 'water') - success = update_rolling_cp(r, otetypes, 'erg') + _ = update_rolling_cp(r, otwtypes, 'water') + _ = update_rolling_cp(r, otetypes, 'erg') # Read stroke data from the DB for a Workout ID. Returns a pandas dataframe @@ -2784,9 +2773,6 @@ def read_df_sql(id): def datafusion(id1, id2, columns, offset): - workout1 = Workout.objects.get(id=id1) - workout2 = Workout.objects.get(id=id2) - df1, w1 = getrowdata_db(id=id1) df1 = df1.drop([ # 'cumdist', 'hr_ut2', @@ -2821,7 +2807,7 @@ def datafusion(id1, id2, columns, offset): keep1.pop(c) for c in df1.columns: - if not c in keep1: + if c not in keep1: df1 = df1.drop(c, 1, errors='ignore') df = pd.concat([df1, df2], ignore_index=True) @@ -2846,7 +2832,6 @@ def fix_newtons(id=0, limit=3000): # pragma: no cover # rowdata,row = getrowdata_db(id=id,doclean=False,convertnewtons=False) rowdata = getsmallrowdata_db(['peakforce'], ids=[id], doclean=False) try: - #avgforce = rowdata['averageforce'] peakforce = rowdata['peakforce'] if peakforce.mean() > limit: w = Workout.objects.get(id=id) @@ -2860,7 +2845,7 @@ def fix_newtons(id=0, limit=3000): # pragma: no cover def remove_invalid_columns(df): # pragma: no cover for c in df.columns: - if not c in allowedcolumns: + if c not in allowedcolumns: df.drop(labels=c, axis=1, inplace=True) return df @@ -2907,7 +2892,6 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, if rowdatadf.empty: return 0 - #rowdatadf.set_index([range(len(rowdatadf))], inplace=True) t = rowdatadf.loc[:, 'TimeStamp (sec)'] t = pd.Series(t - rowdatadf.loc[:, 'TimeStamp (sec)'].iloc[0]) @@ -2981,7 +2965,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, if forceunit == 'lbs': driveenergy = drivelength * averageforce * lbstoN else: - drivenergy = drivelength * averageforce + driveenergy = drivelength * averageforce if forceunit == 'lbs': averageforce *= lbstoN @@ -3034,7 +3018,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, data['hr_bottom'] = 0.0 * data['hr'] try: - tel = rowdatadf.loc[:, ' ElapsedTime (sec)'] + _ = rowdatadf.loc[:, ' ElapsedTime (sec)'] except KeyError: # pragma: no cover rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)'] @@ -3218,7 +3202,7 @@ def workout_trimp(w, reset=False): w.maxhr = maxhr w.save() - job = myqueue( + _ = myqueue( queuehigh, handle_calctrimp, w.id, @@ -3246,7 +3230,7 @@ def workout_rscore(w, reset=False): r.hrftp = int(hrftp) r.save() - job = myqueue( + _ = myqueue( queuehigh, handle_calctrimp, w.id, @@ -3274,7 +3258,7 @@ def workout_normv(w, pp=4.0): r.hrftp = int(hrftp) r.save() - job = myqueue( + _ = myqueue( queuehigh, handle_calctrimp, w.id, diff --git a/rowers/dataprepnodjango.py b/rowers/dataprepnodjango.py index 50a7a5b9..e3713b7a 100644 --- a/rowers/dataprepnodjango.py +++ b/rowers/dataprepnodjango.py @@ -2,6 +2,7 @@ from rowers.utils import totaltime_sec_to_string from rowers.metrics import dtypes import datetime from scipy.signal import savgol_filter +import os # This is Data prep used for testing purposes (no Django environment) # Uses the debug SQLite database for stroke data @@ -35,6 +36,12 @@ from rowers.utils import lbstoN import pytz from timezonefinder import TimezoneFinder +from rowingdata import ( + RowProParser, TCXParser, MysteryParser, RowPerfectParser, + ErgDataParser, CoxMateParser, BoatCoachAdvancedParser, BoatCoachOTWParser, + BoatCoachParser, painsledDesktopParser, SpeedCoach2Parser, speedcoachParser, + ErgStickParser, FITParser, fitsummarydata +) try: user = DATABASES['default']['USER'] @@ -171,14 +178,12 @@ def create_c2_stroke_data_db( spm = 20*np.zeros(nr_strokes) try: - step = totalseconds/float(nr_strokes) + _ = totalseconds/float(nr_strokes) except ZeroDivisionError: return 0 elapsed = np.arange(nr_strokes)*totalseconds/(float(nr_strokes-1)) - dstep = distance/float(nr_strokes) - d = np.arange(nr_strokes)*distance/(float(nr_strokes-1)) unixtime = starttimeunix + elapsed @@ -215,12 +220,9 @@ def create_c2_stroke_data_db( 'cum_dist': d }) - timestr = strftime("%Y%m%d-%H%M%S") - df[' ElapsedTime (sec)'] = df['TimeStamp (sec)'] - res = df.to_csv(csvfilename, index_label='index', - compression='gzip') + _ = df.to_csv(csvfilename, index_label='index', compression='gzip') data = dataprep(df, id=workoutid, bands=False, debug=debug) @@ -300,8 +302,6 @@ def add_c2_stroke_data_db(strokedata, workoutid, starttimeunix, csvfilename, df.sort_values(by='TimeStamp (sec)', ascending=True) - timestr = strftime("%Y%m%d-%H%M%S") - # Create CSV file name and save data to CSV file res = df.to_csv(csvfilename, index_label='index', @@ -447,8 +447,7 @@ def update_empower(id, inboard, oarlength, boattype, df, f1, debug=False): # pr if debug: # pragma: no cover print("not updated ", id) - rowdata = dataprep(df, id=id, bands=True, barchart=True, otwpower=True, - debug=debug) + _ = dataprep(df, id=id, bands=True, barchart=True, otwpower=True, debug=debug) row = rrdata(df=df) row.write_csv(f1, gzip=True) @@ -511,7 +510,7 @@ def update_workout_field_sql(workoutid, fieldname, value, debug=False): table, fieldname, value, workoutid) with engine.connect() as conn, conn.begin(): - result = conn.execute(query) + _ = conn.execute(query) conn.close() engine.dispose() @@ -527,7 +526,7 @@ def update_c2id_sql(id, c2id): # pragma: no cover table, c2id, id) with engine.connect() as conn, conn.begin(): - result = conn.execute(query) + _ = conn.execute(query) conn.close() engine.dispose() @@ -588,7 +587,7 @@ def getcpdata_sql(rower_id, table='cpdata', debug=False): # pragma: no cover rower_id=rower_id, table=table, )) - connection = engine.raw_connection() + _ = engine.raw_connection() df = pd.read_sql_query(query, engine) return df @@ -606,7 +605,7 @@ def deletecpdata_sql(rower_id, table='cpdata', debug=False): # pragma: no cover )) with engine.connect() as conn, conn.begin(): try: - result = conn.execute(query) + _ = conn.execute(query) except: # pragma: no cover print("Database locked") conn.close() @@ -627,7 +626,7 @@ def delete_agegroup_db(age, sex, weightcategory, debug=False): )) with engine.connect() as conn, conn.begin(): try: - result = conn.execute(query) + _ = conn.execute(query) except: # pragma: no cover print("Database locked") conn.close() @@ -687,7 +686,7 @@ def updatecpdata_sql(rower_id, delta, cp, table='cpdata', distance=pd.Series([], else: engine = create_engine(database_url, echo=False) - with engine.connect() as conn, conn.begin(): + with engine.connect() as conn, conn.begin(): df.to_sql(table, engine, if_exists='append', index=False) conn.close() engine.dispose() @@ -818,7 +817,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, if forceunit == 'lbs': driveenergy = drivelength*averageforce*lbstoN else: # pragma: no cover - drivenergy = drivelength*averageforce + driveenergy = drivelength*averageforce distance = rowdatadf.loc[:, 'cum_dist'] @@ -865,7 +864,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, data['hr_bottom'] = 0.0*data['hr'] try: - tel = rowdatadf.loc[:, ' ElapsedTime (sec)'] + _ = rowdatadf.loc[:, ' ElapsedTime (sec)'] except KeyError: # pragma: no cover rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)'] diff --git a/rowers/datautils.py b/rowers/datautils.py index b54b87a8..47581604 100644 --- a/rowers/datautils.py +++ b/rowers/datautils.py @@ -6,7 +6,6 @@ from scipy import optimize from rowers.mytypes import otwtypes, otetypes, rowtypes -#p0 = [500,350,10,8000] p0 = [190, 200, 33, 16000] # RPE to TSS @@ -73,10 +72,12 @@ def updatecp(delta, cpvalues, r, workouttype='water'): # pragma: no cover def cpfit(powerdf, fraclimit=0.0001, nmax=1000): # Fit the data to thee parameter CP model - def fitfunc(pars, x): return abs( - pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3]))) + def fitfunc(pars, x): + return abs( + pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3]))) - def errfunc(pars, x, y): return fitfunc(pars, x)-y + def errfunc(pars, x, y): + return fitfunc(pars, x)-y p1 = p0 @@ -235,8 +236,6 @@ def getcp_new(dfgrouped, logarr): # pragma: no cover restime = np.array(restime) power = np.array(power) - #power[0] = power[1] - cpvalues = griddata(restime, power, logarr, method='linear', fill_value=0) @@ -264,7 +263,6 @@ def getcp(dfgrouped, logarr): delta = [] cpvalue = [] avgpower = {} - #avgpower[0] = 0 for id, group in dfgrouped: tt = group['time'].copy() @@ -273,7 +271,7 @@ def getcp(dfgrouped, logarr): # Remove data where PM is repeating final power value # of an interval during the rest rolling_std = ww.rolling(window=4).std() - deltas = tt.diff() + # deltas = tt.diff() mask = rolling_std == 0 ww.loc[mask] = 0 @@ -281,7 +279,7 @@ def getcp(dfgrouped, logarr): mask = ww > 2000 ww.loc[mask] = 0 - tmax = tt.max() + # tmax = tt.max() try: avgpower[id] = int(ww.mean()) @@ -389,13 +387,13 @@ def getfastest(df, thevalue, mode='distance'): dd = pd.Series(dd, dtype='float') G = pd.concat([pd.Series([0]), dd]) - T = pd.concat([pd.Series([0]), dd]) - h = np.mgrid[0:len(tt)+1:1, 0:len(tt)+1:1] - distances = pd.DataFrame(h[1]-h[0]) + # T = pd.concat([pd.Series([0]), dd]) + # h = np.mgrid[0:len(tt)+1:1, 0:len(tt)+1:1] + # distances = pd.DataFrame(h[1]-h[0]) ones = 1+np.zeros(len(G)) Ghor = np.outer(ones, G) - Thor = np.outer(ones, T) - Tver = np.outer(T, ones) + # Thor = np.outer(ones, T) + # Tver = np.outer(T, ones) Gver = np.outer(G, ones) Gdif = Ghor-Gver Gdif = np.tril(Gdif.T).T @@ -428,8 +426,6 @@ def getfastest(df, thevalue, mode='distance'): # if restime[i]', - [fullemail], - subject, 'confirmemail.html', - d - ) + _ = send_template_email('Rowsandall ', + [fullemail], + subject, 'confirmemail.html', + d + ) return 1 diff --git a/rowers/fakturoid.py b/rowers/fakturoid.py index ff540092..f025a319 100644 --- a/rowers/fakturoid.py +++ b/rowers/fakturoid.py @@ -129,7 +129,7 @@ def create_invoice(rower, amount, braintreeid, dosend=True, if res.status_code not in [200, 201]: # pragma: no cover return 0 - url = res.json()['url'] + # url = res.json()['url'] id = res.json()['id'] urlpay = 'https://app.fakturoid.cz/api/v2/accounts/{slug}/invoices/{id}/fire.json?event=pay'.format( diff --git a/rowers/forms.py b/rowers/forms.py index d3bbc613..1b3793fb 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1,4 +1,3 @@ -from rowers.models import VirtualRace, GeoCourse from rowers.utils import rankingdistances, rankingdurations from rowers.utils import ( workflowleftpanel, workflowmiddlepanel, @@ -18,7 +17,7 @@ from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from django.contrib.admin.widgets import AdminDateWidget from django.forms.widgets import SelectDateWidget, HiddenInput -#from django.forms.extras.widgets import SelectDateWidget + from django.utils import timezone, translation from django.forms import ModelForm, Select import rowers.dataprep as dataprep @@ -573,11 +572,17 @@ class UploadOptionsForm(forms.Form): choices3 = [(0, '---')] noregistrations = [] - for ra in VirtualRace.objects.filter(registration_closure__gt=timezone.now(), sessiontype='race'): # pragma: no cover + for ra in VirtualRace.objects.filter( + registration_closure__gt=timezone.now(), + sessiontype='race' + ): # pragma: no cover rs = VirtualRaceResult.objects.filter(race=ra, userid=r.id) if rs.count() == 0: noregistrations.append((-ra.id, ra.name)) - for ra in VirtualRace.objects.filter(registration_closure__gt=timezone.now(), sessiontype='indoorrace'): # pragma: no cover + for ra in VirtualRace.objects.filter( + registration_closure__gt=timezone.now(), + sessiontype='indoorrace' + ): # pragma: no cover rs = IndoorVirtualRaceResult.objects.filter(race=ra, userid=r.id) if rs.count() == 0: noregistrations.append((-ra.id, ra.name)) @@ -1055,20 +1060,6 @@ class RegistrationFormSex(RegistrationFormUniqueEmail): adaptiveclass = forms.ChoiceField(label='Adaptive Classification', choices=adaptivecategories, initial='None', required=False) -# def __init__(self, *args, **kwargs): -# self.fields['sex'].initial = 'not specified' - -# Time field supporting microseconds. Not used, I believe. - - -class MyTimeField(forms.TimeField): - - def __init__(self, *args, **kwargs): # pragma: no cover - super(MyTimeField, self).__init__(*args, **kwargs) - supports_microseconds = True - -# Form used to automatically define intervals by pace or power - class PowerIntervalUpdateForm(forms.Form): selectorchoices = ( @@ -1847,14 +1838,13 @@ class StravaChartForm(forms.Form): choices=yaxchoices2, label='Fourth Chart', required=True) def __init__(self, request, *args, **kwargs): - extrametrics = kwargs.pop('extrametrics', []) super(StravaChartForm, self).__init__(*args, **kwargs) rower = Rower.objects.get(user=request.user) - axchoicespro = ( - ('', ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0], ax[1]) for ax in axes - ) +# axchoicespro = ( +# ('', ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0], ax[1]) for ax in axes +# ) axchoicesbasicx = [] axchoicesbasicy = [] @@ -1889,14 +1879,13 @@ class FlexAxesForm(forms.Form): choices=yaxchoices2, label='Right Axis', required=True) def __init__(self, request, *args, **kwargs): - extrametrics = kwargs.pop('extrametrics', []) super(FlexAxesForm, self).__init__(*args, **kwargs) rower = Rower.objects.get(user=request.user) - axchoicespro = ( - ('', ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0], ax[1]) for ax in axes - ) +# axchoicespro = ( +# ('', ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0], ax[1]) for ax in axes +# ) axchoicesbasicx = [] axchoicesbasicy = [] diff --git a/rowers/garmin_stuff.py b/rowers/garmin_stuff.py index 8bba69e1..33575778 100644 --- a/rowers/garmin_stuff.py +++ b/rowers/garmin_stuff.py @@ -11,7 +11,7 @@ import requests from requests import Session, Request from requests_oauthlib import OAuth1, OAuth1Session from requests_oauthlib.oauth1_session import TokenRequestDenied -from requests import Request, Session + import rowers.mytypes as mytypes from rowers.mytypes import otwtypes from rowers.rower_rules import is_workout_user, ispromember @@ -35,13 +35,6 @@ from rowsandall_app.settings import ( from pytz import timezone as tz, utc -# You must initialize logging, otherwise you'll not see debug output. -# logging.basicConfig() -# logging.getLogger().setLevel(logging.DEBUG) -#requests_log = logging.getLogger("requests.packages.urllib3") -# requests_log.setLevel(logging.DEBUG) -#requests_log.propagate = True - from rowers.tasks import handle_get_garmin_file import django_rq @@ -100,18 +93,15 @@ repeattypes = { "RepeatUntilDistance": "REPEAT_UNTIL_TIME", "RepeatUntilCalories": "REPEAT_UNTIL_CALORIES", "RepeatUntilHrLessThan": "REPEAT_UNTIL_HR_LESS_THAN", - "RepeatUntilHrGreaterThan": "REPEAT_UNTIL_HR_GREATER_THAN", - "RepeatUntilPowerLessThan": "REPEAT_UNTIL_POWER_LESS_THAN", + "RepeatUntilHrGreaterThan": "REPEAT_UNTIL_HR_GREATER_THAN", + "RepeatUntilPowerLessThan": "REPEAT_UNTIL_POWER_LESS_THAN", "RepeatUntilPowerGreaterThan": "REPEAT_UNTIL_POWER_GREATER_THAN", - "RepeatUntilPowerLapLessThan": "REPEAT_UNTIL_POWER_LAP_LESS_THAN", + "RepeatUntilPowerLapLessThan": "REPEAT_UNTIL_POWER_LAP_LESS_THAN", "RepeatUntilPowerLapGreaterThan": "REPEAT_UNTIL_POWER_LAP_GREATER_THAN", } def garmin_authorize(): # pragma: no cover - redirect_uri = oauth_data['redirect_uri'] - client_secret = oauth_data['client_secret'] - client_id = oauth_data['client_id'] base_uri = oauth_data['base_url'] garmin = OAuth1Session(oauth_data['client_id'], @@ -133,7 +123,7 @@ def garmin_processcallback(redirect_response, resource_owner_key, resource_owner oauth_response = garmin.parse_authorization_response(redirect_response) verifier = oauth_response.get('oauth_verifier') - token = oauth_response.get('oauth_token') + # token = oauth_response.get('oauth_token') access_token_url = 'https://connectapi.garmin.com/oauth-service/oauth/access_token' # Using OAuth1Session @@ -155,7 +145,7 @@ def garmin_processcallback(redirect_response, resource_owner_key, resource_owner def garmin_open(user): # pragma: no cover r = Rower.objects.get(user=user) - token = Rower.garmintoken + token = r.garmintoken if (token == '') or (token is None): raise NoTokenError("User has no garmin token") @@ -191,7 +181,8 @@ def get_garmin_workout_list(user): # pragma: no cover resource_owner_secret=r.garminrefreshtoken, ) - url = 'https://healthapi.garmin.com/wellness-api/rest/activities?uploadStartTimeInSeconds=1593113760&uploadEndTimeInSeconds=1593279360' + url = 'https://healthapi.garmin.com/wellness-api/rest/' \ + 'activities?uploadStartTimeInSeconds=1593113760&uploadEndTimeInSeconds=1593279360' result = garmin.get(url) @@ -218,7 +209,7 @@ def step_to_garmin(step, order=0): intensity = 'INTERVAL' except KeyError: intensity = None - #durationvaluetype = '' + # durationvaluetype = '' if durationtype == 'Time': durationtype = 'TIME' durationvalue = int(durationvalue/1000.) @@ -272,11 +263,11 @@ def step_to_garmin(step, order=0): if targetType is not None and targetType.lower() == "power": targetType = 'POWER' - if targetValue is not None and targetValue <= 1000: - targetValueType = 'PERCENT' # pragma: no cover - else: - targetValueType = None - targetValue -= 1000 +# if targetValue is not None and targetValue <= 1000: +# targetValueType = 'PERCENT' # pragma: no cover +# else: +# # targetValueType = None +# targetValue -= 1000 try: targetValueLow = step['dict']['targetValueLow'] @@ -285,8 +276,8 @@ def step_to_garmin(step, order=0): targetValue = None elif targetValueLow == 0: # pragma: no cover targetValueLow = None - elif targetValueLow <= 1000 and targetType == 'POWER': # pragma: no cover - targetValueType = 'PERCENT' + # elif targetValueLow <= 1000 and targetType == 'POWER': # pragma: no cover + # targetValueType = 'PERCENT' elif targetValueLow > 1000 and targetType == 'POWER': # pragma: no cover targetValueLow -= 1000 except KeyError: @@ -296,8 +287,8 @@ def step_to_garmin(step, order=0): if targetValue is not None and targetValue > 0 and targetValueHigh == 0: # pragma: no cover targetValueHigh = targetValue targetValue = 0 - elif targetValueHigh <= 1000 and targetType == 'POWER': # pragma: no cover - targetValueType = 'PERCENT' + # elif targetValueHigh <= 1000 and targetType == 'POWER': # pragma: no cover + # targetValueType = 'PERCENT' elif targetValueHigh > 1000 and targetType == 'POWER': # pragma: no cover targetValueHigh -= 1000 elif targetValueHigh == 0: # pragma: no cover @@ -477,12 +468,6 @@ def garmin_getworkout(garminid, r, activity): distance = activity['distanceInMeters'] except KeyError: distance = 0 - try: - averagehr = activity['averageHeartRateInBeatsPerMinute'] - maxhr = activity['maxHeartRateInBeatsPerMinute'] - except KeyError: # pragma: no cover - averagehr = 0 - maxhr = 0 try: w = Workout.objects.get(uploadedtogarmin=garminid) except Workout.DoesNotExist: @@ -494,8 +479,8 @@ def garmin_getworkout(garminid, r, activity): utc_offset = datetime.timedelta(seconds=offset) now = datetime.datetime.now(pytz.utc) - zones = [tz.zone for tz in map(pytz.timezone, pytz.all_timezones_set) - if now.astimezone(tz).utcoffset() == utc_offset] + zones = [ttz.zone for ttz in map( + pytz.timezone, pytz.all_timezones_set) if now.astimezone(ttz).utcoffset() == utc_offset] if r.defaulttimezone in zones: # pragma: no cover thetimezone = r.defaulttimezone elif len(zones): @@ -509,8 +494,7 @@ def garmin_getworkout(garminid, r, activity): day=startdatetime.day, hour=startdatetime.hour, minute=startdatetime.minute, - second=startdatetime.second, - ).astimezone(pytz.timezone(thetimezone)) + second=startdatetime.second,).astimezone(pytz.timezone(thetimezone)) w.startdatetime = startdatetime w.starttime = w.startdatetime.time() @@ -557,12 +541,12 @@ def garmin_workouts_from_details(data): df[' AverageBoatSpeed (m/s)'] = 0 df[' Stroke500mPace (sec/500m)'] = pace try: - spm = df[' Cadence (stokes/min)'] + _ = df[' Cadence (stokes/min)'] except KeyError: df[' Cadence (stokes/min)'] = 0 df['cum_dist'] = df[' Horizontal (meters)'] try: - power = df[' Power (watts)'] + _ = df[' Power (watts)'] except KeyError: df[' Power (watts)'] = 0 df[' AverageDriveForce (lbs)'] = 0 @@ -591,7 +575,7 @@ def garmin_workouts_from_summaries(activities): try: r = Rower.objects.get(garmintoken=garmintoken) id = activity['summaryId'] - w = garmin_getworkout(id, r, activity) + _ = garmin_getworkout(id, r, activity) except Rower.DoesNotExist: # pragma: no cover pass diff --git a/rowers/imports.py b/rowers/imports.py index 9877ddab..6e40e0b5 100644 --- a/rowers/imports.py +++ b/rowers/imports.py @@ -70,10 +70,6 @@ def splitstdata(lijst): def imports_open(user, oauth_data): r = Rower.objects.get(user=user) token = getattr(r, oauth_data['tokenname']) - try: - refreshtoken = getattr(r, oauth_data['refreshtokenname']) - except (TypeError, AttributeError, KeyError): # pragma: no cover - refreshtoken = None try: tokenexpirydate = getattr(r, oauth_data['expirydatename']) @@ -81,7 +77,6 @@ def imports_open(user, oauth_data): tokenexpirydate = None if (token == '') or (token is None): - s = "Token doesn't exist. Need to authorize" raise NoTokenError("User has no token") else: tokenname = oauth_data['tokenname'] @@ -109,10 +104,10 @@ def imports_open(user, oauth_data): # Refresh token using refresh token def imports_do_refresh_token(refreshtoken, oauth_data, access_token=''): - client_auth = requests.auth.HTTPBasicAuth( - oauth_data['client_id'], - oauth_data['client_secret'] - ) + # client_auth = requests.auth.HTTPBasicAuth( + # oauth_data['client_id'], + # oauth_data['client_secret'] + # ) post_data = {"grant_type": "refresh_token", "client_secret": oauth_data['client_secret'], @@ -127,8 +122,6 @@ def imports_do_refresh_token(refreshtoken, oauth_data, access_token=''): if 'grant_type' in oauth_data: if oauth_data['grant_type']: post_data['grant_type'] = oauth_data['grant_type'] - else: # pragma: no cover - grant_type = post_data.pop('grant_type', None) if oauth_data['bearer_auth']: headers['authorization'] = 'Bearer %s' % access_token @@ -192,9 +185,9 @@ def imports_get_token( client_id = oauth_data['client_id'] base_uri = oauth_data['base_url'] - client_auth = requests.auth.HTTPBasicAuth( - client_id, client_secret - ) + # client_auth = requests.auth.HTTPBasicAuth( + # client_id, client_secret + # ) post_data = {"grant_type": "authorization_code", "code": code, @@ -216,8 +209,6 @@ def imports_get_token( post_data['grant_type'] = oauth_data['grant_type'] if 'strava' in oauth_data['autorization_uri']: post_data['grant_type'] = "authorization_code" - else: # pragma: no cover - grant_type = post_data.pop('grant_type', None) if 'json' in oauth_data['content_type']: response = requests.post( @@ -268,7 +259,6 @@ def imports_make_authorization_url(oauth_data): # pragma: no cover "scope": oauth_data['scope'], "state": state} - import urllib url = oauth_data['authorizaton_uri']+urllib.parse.urlencode(params) return HttpResponseRedirect(url) diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index c37dac24..69ed2ff7 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -9,7 +9,6 @@ from rowers.models import course_spline, VirtualRaceResult from bokeh.palettes import Category20c, Category10 from bokeh.layouts import layout, widgetbox from bokeh.resources import CDN, INLINE -from math import pi from rowers.dataprep import timedeltaconv from pandas.core.groupby.groupby import DataError import rowers.datautils as datautils @@ -41,8 +40,7 @@ from bokeh.core.properties import value from rowers.opaque import encoder from bokeh.models import ( OpenURL, TapTool, CrosshairTool, Span, Label, SaveTool, - PanTool, BoxZoomTool, WheelZoomTool, ResetTool, - ) + PanTool, BoxZoomTool, WheelZoomTool, ResetTool,) from bokeh.models.glyphs import ImageURL from bokeh.transform import cumsum from bokeh.models import ( @@ -82,9 +80,6 @@ queue = django_rq.get_queue('default') queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low') -#from bokeh.io import output_file, show, vplot -#from bokeh.models.widgets import Slider, Select, TextInput - activate(settings.TIME_ZONE) thetimezone = get_current_timezone() @@ -132,7 +127,6 @@ def errorbar(fig, x, y, source=ColumnDataSource(), colorvalues = ["#%02x%02x%02x" % (255, 0, 0) for x in xvalues] try: - a = xvalues[0]+1 if xerr: x_err_x = [] x_err_y = [] @@ -155,7 +149,6 @@ def errorbar(fig, x, y, source=ColumnDataSource(), pass try: - a = yvalues[0]+1 if yerr: y_err_x = [] y_err_y = [] @@ -254,7 +247,6 @@ def interactive_hr_piechart(df, rower, title, totalseconds=0): data['totaltime'] = pd.Series([pretty_timedelta(v) for v in data['value']]) - size = 350 TOOLS = 'save,hover' z = figure(title="HR "+title, x_range=(-0.5, 1), plot_height=375, @@ -345,10 +337,10 @@ def interactive_boxchart(datadf, fieldname, extratitle='', columns = datadf.columns - if not fieldname in columns: # pragma: no cover + if fieldname not in columns: # pragma: no cover return '', 'It looks like there are no data matching your filter' - if not 'date' in columns: # pragma: no cover + if 'date' not in columns: # pragma: no cover return '', 'Not enough data' tooltips = [ @@ -411,8 +403,6 @@ def interactive_boxchart(datadf, fieldname, extratitle='', def interactive_planchart(data, startdate, enddate): - source = ColumnDataSource(data) - hv.extension('bokeh') yaxmaximum = data['executed'].max() @@ -565,14 +555,9 @@ def interactive_activitychart(workouts, startdate, enddate, stack='type', toolba 'link': links, } - dim_expr = hv.dim('type').categorize(mytypes.color_map) - df = pd.DataFrame(thedict) - source = ColumnDataSource(df) - df.sort_values('date_sorting', inplace=True) - #clrs = hv.Cycle(df['colors'].values) hv.extension('bokeh') @@ -608,7 +593,6 @@ def interactive_activitychart(workouts, startdate, enddate, stack='type', toolba p.toolbar_location = toolbar_location p.y_range.start = 0 p.sizing_mode = 'stretch_both' - url = "http://rowsandall.com/rowers/workout/@duration/" taptool = p.select(type=TapTool) callback = CustomJS(args={'links': df.link}, code=""" @@ -749,8 +733,6 @@ def interactive_activitychart2(workouts, startdate, enddate, stack='type', toolb 'link': links, } - dim_expr = hv.dim('type').categorize(mytypes.color_map) - df = pd.DataFrame(thedict) if totaldays > 30 and yaxis == 'duration': # pragma: no cover @@ -772,9 +754,6 @@ def interactive_activitychart2(workouts, startdate, enddate, stack='type', toolb df.sort_values('date_sorting', inplace=True) - #clrs = hv.Cycle(df['colors'].values) - source = ColumnDataSource(df) - hv.extension('bokeh') # table = hv.Table(df,[('date','Date'),('type','Workout Type')], @@ -815,7 +794,6 @@ def interactive_activitychart2(workouts, startdate, enddate, stack='type', toolb p.toolbar_location = toolbar_location p.sizing_mode = 'stretch_both' p.y_range.start = 0 - url = "http://rowsandall.com/rowers/workout/@duration/" taptool = p.select(type=TapTool) callback = CustomJS(args={'links': df['link']}, code=""" @@ -849,9 +827,7 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter' rowdata.dropna(axis=1, how='all', inplace=True) rowdata.dropna(axis=0, how='any', inplace=True) - workoutstateswork = [1, 4, 5, 8, 9, 6, 7] workoutstatesrest = [3] - workoutstatetransition = [0, 2, 10, 11, 12, 13] if workstrokesonly: try: @@ -862,15 +838,6 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter' if rowdata.empty: return "", "No Valid Data Available", "", "" - # quick linear regression - # peakforce = slope*peakforceangle + intercept - try: - slope, intercept, r, p, stderr = linregress( - rowdata['peakforceangle'], rowdata['peakforce']) - except KeyError: # pragma: no cover - slope = 0 - intercept = 0 - try: covariancematrix = np.cov( rowdata['peakforceangle'], y=rowdata['peakforce']) @@ -997,16 +964,8 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter' try: peakforceav = rowdata['peakforce'].median() - peakforce25 = rowdata['peakforce'].quantile(q=0.25) - peakforce75 = rowdata['peakforce'].quantile(q=0.75) - peakforce05 = rowdata['peakforce'].quantile(q=0.05) - peakforce95 = rowdata['peakforce'].quantile(q=0.95) except KeyError: # pragma: no cover peakforceav = 0 - peakforce25 = 0 - peakforce75 = 0 - peakforce05 = 0 - peakforce95 = 0 try: averageforceav = rowdata['averageforce'].median() @@ -1015,16 +974,8 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter' try: peakforceangleav = rowdata['peakforceangle'].median() - peakforceangle05 = rowdata['peakforceangle'].quantile(q=0.05) - peakforceangle25 = rowdata['peakforceangle'].quantile(q=0.25) - peakforceangle75 = rowdata['peakforceangle'].quantile(q=0.75) - peakforceangle95 = rowdata['peakforceangle'].quantile(q=0.95) except KeyError: # pragma: no cover peakforceangleav = 0 - peakforceangle25 = 0 - peakforceangle75 = 0 - peakforceangle05 = 0 - peakforceangle95 = 0 # thresholdforce /= 4.45 # N to lbs thresholdforce = 100 if 'x' in boattype else 200 @@ -1095,20 +1046,6 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter' ) ) - sourcetrend = ColumnDataSource( - data=dict( - x=[peakforceangle25, peakforceangle75], - y=[peakforce25, peakforce75] - ) - ) - - sourcefit = ColumnDataSource( - data=dict( - x=np.array([peakforceangle25, peakforceangle75]), - y=slope*np.array([peakforceangle25, peakforceangle75])+intercept - ) - ) - source2 = ColumnDataSource( rowdata ) @@ -1150,8 +1087,6 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter' # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 @@ -1524,14 +1459,6 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter' slider_dist_max.js_on_change('value', callback) callback.args["maxdist"] = slider_dist_max - #annotation.sizing_mode = 'fixed' - #slider_spm_min.sizing_mode = 'fixed' - #slider_spm_max.sizing_mode = 'fixed' - #slider_work_min.sizing_mode = 'fixed' - #slider_work_max.sizing_mode = 'fixed' - #slider_dist_min.sizing_mode = 'fixed' - #slider_dist_max.sizing_mode = 'fixed' - thesliders = layoutcolumn([annotation, slider_spm_min, slider_spm_max, @@ -1541,14 +1468,12 @@ def interactive_forcecurve(theworkouts, workstrokesonly=True, plottype='scatter' slider_work_max, ] ) - #thesliders.sizing_mode = 'fixed' - layout = layoutrow([thesliders, - plot]) + mylayout = layoutrow([thesliders, plot]) - layout.sizing_mode = 'stretch_both' + mylayout.sizing_mode = 'stretch_both' - script, div = components(layout) + script, div = components(mylayout) js_resources = INLINE.render_js() css_resources = INLINE.render_css() @@ -1658,12 +1583,9 @@ def goldmedalscorechart(user, startdate=None, enddate=None): duration = [] workoutid = [] - previous = 0 - for i in range(len(dates)): id = ids[i] w = Workout.objects.get(id=id) - dd = str(dates[i]) # td.append(arrow.get(dd).datetime) td.append(arrow.get(w.date).datetime) markerscore.append(testpower[i]) @@ -1729,9 +1651,6 @@ def goldmedalscorechart(user, startdate=None, enddate=None): # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 watermarkx = 0.99 @@ -1892,9 +1811,6 @@ def performance_chart(user, startdate=None, enddate=None, kfitness=42, kfatigue= # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 watermarkx = 0.99 @@ -1951,10 +1867,8 @@ def performance_chart(user, startdate=None, enddate=None, kfitness=42, kfatigue= # y1rangemin = df.loc[:,['testpower','fitness']].min().min() # y1rangemax = df.loc[:,['testpower','fitness']].max().max()*1.02 if dofatigue: # pragma: no cover - y1rangemin = df.loc[:, ['fitness', 'fatigue']].min().min() y1rangemax = df.loc[:, ['fitness', 'fatigue']].max().max()*1.02 else: - y1rangemin = df.loc[:, ['fitness']].min().min() y1rangemax = df.loc[:, ['fitness']].max().max()*1.02 if doform: # pragma: no cover @@ -1979,7 +1893,6 @@ def performance_chart(user, startdate=None, enddate=None, kfitness=42, kfatigue= plot.sizing_mode = 'scale_both' - #plot.y_range = Range1d(0,1.5*max(df['testpower'])) startdate = datetime.datetime.combine( startdate, datetime.datetime.min.time()) enddate = datetime.datetime.combine(enddate, datetime.datetime.min.time()) @@ -2036,11 +1949,11 @@ def performance_chart(user, startdate=None, enddate=None, kfitness=42, kfatigue= plot.add_tools(linked_crosshair) plot2.add_tools(linked_crosshair) - layout = layoutcolumn([plot, plot2]) - layout.sizing_mode = 'stretch_both' + mylayout = layoutcolumn([plot, plot2]) + mylayout.sizing_mode = 'stretch_both' try: - script, div = components(layout) + script, div = components(mylayout) except Exception as e: # pragma: no cover df.dropna(inplace=True, axis=0, how='any') return ( @@ -2102,9 +2015,6 @@ def interactive_histoall(theworkouts, histoparam, includereststrokes, # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 watermarkx = 0.99 @@ -2190,10 +2100,10 @@ def interactive_histoall(theworkouts, histoparam, includereststrokes, annotation.js_on_change('value', callback) callback.args["annotation"] = annotation - layout = layoutcolumn([annotation, plot]) + mylayout = layoutcolumn([annotation, plot]) try: - script, div = components(layout) + script, div = components(mylayout) except ValueError: # pragma: no cover script = '' div = '' @@ -2514,10 +2424,6 @@ def get_map_script_course( """.format( latmean=latmean, lonmean=lonmean, - latbegin=latbegin, - latend=latend, - longbegin=longbegin, - longend=longend, scoordinates=scoordinates, pcoordinates=pcoordinates, plabels=plabels @@ -2778,11 +2684,6 @@ def leaflet_chart_compare(course, workoutids, labeldict={}, startenddict={}): if lat.empty or lon.empty: # pragma: no cover return [0, "invalid coordinate data"] - latbegin = lat.values[0] - longbegin = lon.values[0] - latend = lat.values[-1] - longend = lon.values[-1] - colors = itertools.cycle(palette) try: items = itertools.izip(workoutids, colors) @@ -2869,10 +2770,6 @@ var navionics = new JNC.Leaflet.NavionicsOverlay({{ """.format( latmean=latmean, lonmean=lonmean, - latbegin=latbegin, - latend=latend, - longbegin=longbegin, - longend=longend, pcoordinates=pcoordinates, plabels=plabels, ) @@ -2926,7 +2823,6 @@ var navionics = new JNC.Leaflet.NavionicsOverlay({{ scoordinates=scoordinates, color=color, label=label, - id=id, ) script += """ @@ -3101,8 +2997,6 @@ def leaflet_chart_video(lat, lon, name=""): lonmean = lon.mean() latbegin = lat[lat.index[0]] longbegin = lon[lon.index[0]] - latend = lat[lat.index[-1]] - longend = lon[lon.index[-1]] coordinates = zip(lat, lon) @@ -3201,9 +3095,7 @@ def leaflet_chart_video(lat, lon, name=""): latmean=latmean, lonmean=lonmean, latbegin=latbegin, - latend=latend, longbegin=longbegin, - longend=longend, scoordinates=scoordinates, ) @@ -3350,10 +3242,11 @@ def interactive_agegroupcpchart(age, normalized=False): mhduration.append(60.*duration) mhpower.append(np.nan) - def fitfunc(pars, x): return pars[0] / \ - (1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) + def fitfunc(pars, x): + return pars[0] / (1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) - def errfunc(pars, x, y): return fitfunc(pars, x)-y + def errfunc(pars, x, y): + return fitfunc(pars, x)-y # p0 = [500,350,10,8000] @@ -3444,7 +3337,6 @@ def interactive_agegroupcpchart(age, normalized=False): ) x_axis_type = 'log' - y_axis_type = 'linear' TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' @@ -3500,7 +3392,6 @@ def interactive_otwcpchart(powerdf, promember=0, rowername="", r=None, cpfit='da TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' x_axis_type = 'log' - y_axis_type = 'linear' deltas = powerdf2['Delta'].apply(lambda x: timedeltaconv(x)) powerdf2['ftime'] = deltas.apply(lambda x: strfdelta(x)) @@ -3524,8 +3415,9 @@ def interactive_otwcpchart(powerdf, promember=0, rowername="", r=None, cpfit='da p1 = [r.ep0, r.ep1, r.ep2, r.ep3] ratio = r.ecpratio - def fitfunc(pars, x): return abs( - pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3]))) + def fitfunc(pars, x): + return abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3]))) + fitpower = fitfunc(p1, fitt) message = "" @@ -3534,8 +3426,6 @@ def interactive_otwcpchart(powerdf, promember=0, rowername="", r=None, cpfit='da deltas = fitt.apply(lambda x: timedeltaconv(x)) ftime = niceformat(deltas) - workouts = powerdf2['workout'] - urls = powerdf2['url'] # add world class wcpower = pd.Series(wcpower, dtype='float') @@ -3543,10 +3433,12 @@ def interactive_otwcpchart(powerdf, promember=0, rowername="", r=None, cpfit='da # fitting WC data to three parameter CP model if len(wcdurations) >= 4: # pragma: no cover - def fitfunc(pars, x): return pars[0] / \ - (1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) + def fitfunc(pars, x): + return pars[0] / (1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) + + def errfunc(pars, x, y): + return fitfunc(pars, x)-y - def errfunc(pars, x, y): return fitfunc(pars, x)-y p1wc, success = optimize.leastsq(errfunc, p0[:], args=(wcdurations, wcpower)) else: @@ -3582,13 +3474,6 @@ def interactive_otwcpchart(powerdf, promember=0, rowername="", r=None, cpfit='da ) ) - sourceannot = ColumnDataSource( - data=dict( - workout=workouts, - url=urls, - ) - ) - # making the plot plot = Figure(tools=TOOLS, x_axis_type=x_axis_type, plot_width=900, @@ -3597,12 +3482,8 @@ def interactive_otwcpchart(powerdf, promember=0, rowername="", r=None, cpfit='da # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 - watermarkx = 0.99 watermarky = 0.01 watermarkw = 184 watermarkh = 35 @@ -3705,10 +3586,12 @@ def interactive_agegroup_plot(df, distance=2000, duration=None, # poly_vals = np.polyval(poly_coefficients,age2) # poly_vals = 0.5*(np.abs(poly_vals)+poly_vals) - def fitfunc(pars, x): return np.abs(pars[0])*(1-x/max(120, pars[1]))-np.abs( - pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50, pars[5]))) + def fitfunc(pars, x): + return np.abs(pars[0])*(1-x/max(120, pars[1])) \ + - np.abs(pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50, pars[5]))) - def errfunc(pars, x, y): return fitfunc(pars, x)-y + def errfunc(pars, x, y): + return fitfunc(pars, x)-y p0age = [700, 120, 700, 10, 100, 100] @@ -3722,8 +3605,6 @@ def interactive_agegroup_plot(df, distance=2000, duration=None, data=dict( age=age, power=power, - #age2 = age2, - #expo_vals = expo_vals, season=season, name=name, ) @@ -3774,7 +3655,6 @@ def interactive_cpchart(rower, thedistances, thesecs, theavpower, TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' x_axis_type = 'log' - y_axis_type = 'linear' thesecs = pd.Series(thesecs) @@ -3828,10 +3708,11 @@ def interactive_cpchart(rower, thedistances, thesecs, theavpower, ) ) - def fitfunc(pars, x): return pars[0] / \ - (1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) + def fitfunc(pars, x): + return pars[0] / (1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) - def errfunc(pars, x, y): return fitfunc(pars, x)-y + def errfunc(pars, x, y): + return fitfunc(pars, x)-y # p0 = [500,350,10,8000] wcpower = pd.Series(wcpower, dtype='float') @@ -3863,28 +3744,19 @@ def interactive_cpchart(rower, thedistances, thesecs, theavpower, # Get stayer score if success == 1: # pragma: no cover - power1min = fitfunc(p1, 60.) power4min = fitfunc(p1, 240.) - power6min = fitfunc(p1, 360.) - power30min = fitfunc(p1, 1800.) power1h = fitfunc(p1, 3600.) power10sec = fitfunc(p1, 10.) r10sec4min = 100.*power10sec/power4min r1h4min = 100.*power1h/power4min - r1min6min = 100.*power1min/power6min - r30min6min = 100.*power30min/power6min combined = r1h4min-0.2*(r10sec4min-100) - combined2 = r30min6min-1.5*(r1min6min-100) dataset = pd.read_csv('static/stats/combined_set.csv') - dataset2 = pd.read_csv('static/stats/combined_set6min.csv') stayerscore = int(percentileofscore(dataset['combined'], combined)) - stayerscore2 = int(percentileofscore(dataset2['combined'], combined2)) else: stayerscore = None - stayerscore2 = None fitt = pd.Series(10**(4*np.arange(100)/100.)) @@ -3938,12 +3810,8 @@ def interactive_cpchart(rower, thedistances, thesecs, theavpower, # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 - watermarkx = 0.99 watermarky = 0.01 watermarkw = 184 watermarkh = 35 @@ -4069,7 +3937,6 @@ def interactive_windchart(id=0, promember=0): # get user # u = User.objects.get(id=row.user.id) r = row.user - u = r.user rr = rrower(hrmax=r.max, hrut2=r.ut2, hrut1=r.ut1, hrat=r.at, @@ -4158,7 +4025,6 @@ def interactive_streamchart(id=0, promember=0): # get user # u = User.objects.get(id=row.user.id) r = row.user - u = r.user rr = rrower(hrmax=r.max, hrut2=r.ut2, hrut1=r.ut1, hrat=r.at, @@ -4223,12 +4089,12 @@ def interactive_chart(id=0, promember=0, intervaldata={}): return "", "No Valid Data Available" try: - spm = datadf['spm'] + _ = datadf['spm'] except KeyError: # pragma: no cover datadf['spm'] = 0 try: - pace = datadf['pace'] + _ = datadf['pace'] except KeyError: # pragma: no cover datadf['pace'] = 0 @@ -4244,16 +4110,10 @@ def interactive_chart(id=0, promember=0, intervaldata={}): # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 - watermarkx = 0.99 - watermarky = 0.01 watermarkw = 184 watermarkh = 35 - watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} @@ -4476,7 +4336,7 @@ def interactive_multiflex(datadf, xparam, yparam, groupby, extratitle='', else: groupname = axlabels[groupby] - if title == None: + if title is None: title = '{y} vs {x} grouped by {gr}'.format( x=xparamname, y=yparamname, @@ -4555,9 +4415,6 @@ def interactive_multiflex(datadf, xparam, yparam, groupby, extratitle='', # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 watermarkx = 0.99 @@ -4683,12 +4540,12 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, workstrokesonly=workstrokesonly) try: - tests = datadf[yparam2] + _ = datadf[yparam2] except KeyError: # pragma: no cover yparam2 = 'None' try: - tests = datadf[yparam1] + _ = datadf[yparam1] except KeyError: yparam1 = 'None' @@ -4696,18 +4553,14 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, datadf.dropna(axis=0, how='any', inplace=True) # test if we have drive energy - nowork = 1 try: # pragma: no cover - test = datadf['driveenergy'].mean() - nowork = 0 + _ = datadf['driveenergy'].mean() except KeyError: # pragma: no cover datadf['driveenergy'] = 500. # test if we have power - nopower = 1 try: # pragma: no cover - test = datadf['power'].mean() - nopower = 0 + _ = datadf['power'].mean() except KeyError: # pragma: no cover datadf['power'] = 50. @@ -4745,21 +4598,12 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, else: # pragma: no cover datadf['y2'] = datadf['y1'] - if xparam == 'distance': # pragma: no cover - xaxmax = datadf['x1'].max() - xaxmin = datadf['x1'].min() - else: - xaxmax = yaxmaxima[xparam] - xaxmin = yaxminima[xparam] - # average values x1mean = datadf['x1'].mean() y1mean = datadf['y1'].mean() y2mean = datadf['y2'].mean() - xvals = pd.Series(xaxmin+np.arange(100)*(xaxmax-xaxmin)/100.) - x_axis_type = 'linear' y_axis_type = 'linear' if xparam == 'time': @@ -4797,9 +4641,6 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 watermarkx = 0.99 @@ -5041,13 +4882,6 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, slider_dist_max.js_on_change('value', callback) callback.args["maxdist"] = slider_dist_max - #slider_spm_min.sizing_mode = 'fixed' - #slider_spm_max.sizing_mode = 'fixed' - #slider_work_min.sizing_mode = 'fixed' - #slider_work_max.sizing_mode = 'fixed' - #slider_dist_min.sizing_mode = 'fixed' - #slider_dist_max.sizing_mode = 'fixed' - thesliders = layoutcolumn([slider_spm_min, slider_spm_max, slider_dist_min, @@ -5057,14 +4891,11 @@ def interactive_cum_flex_chart2(theworkouts, promember=0, ], ) - #thesliders.sizing_mode = 'fixed' + mylayout = layoutrow([thesliders, plot]) - layout = layoutrow([thesliders, - plot]) + mylayout.sizing_mode = 'stretch_both' - layout.sizing_mode = 'stretch_both' - - script, div = components(layout) + script, div = components(mylayout) js_resources = INLINE.render_js() css_resources = INLINE.render_css() @@ -5104,7 +4935,6 @@ def interactive_flexchart_stacked(id, r, xparam='time', doclean=False, workstrokesonly=False) - row = Workout.objects.get(id=id) if rowdata.empty: return "", "No valid data", '', '', comment @@ -5115,34 +4945,29 @@ def interactive_flexchart_stacked(id, r, xparam='time', try: rowdata['x1'] = rowdata.loc[:, xparam] - rowmin = rowdata[xparam].min() except KeyError: # pragma: no cover rowdata['x1'] = 0*rowdata.loc[:, 'time'] try: rowdata['y1'] = rowdata.loc[:, yparam1] - rowmin = rowdata[yparam1].min() except KeyError: # pragma: no cover rowdata['y1'] = 0*rowdata.loc[:, 'time'] rowdata[yparam1] = rowdata['y1'] try: # pragma: no cover rowdata['y2'] = rowdata.loc[:, yparam2] - rowmin = rowdata[yparam2].min() except KeyError: rowdata['y2'] = 0*rowdata.loc[:, 'time'] rowdata[yparam2] = rowdata['y2'] try: rowdata['y3'] = rowdata.loc[:, yparam3] - rowmin = rowdata[yparam3].min() except KeyError: # pragma: no cover rowdata['y3'] = 0*rowdata.loc[:, 'time'] rowdata[yparam3] = rowdata['y3'] try: rowdata['y4'] = rowdata.loc[:, yparam4] - rowmin = rowdata[yparam4].min() except KeyError: # pragma: no cover rowdata['y4'] = 0*rowdata.loc[:, 'time'] rowdata[yparam4] = rowdata['y4'] @@ -5418,16 +5243,16 @@ def interactive_flexchart_stacked(id, r, xparam='time', plot3.line('x1', 'y3', source=source, color=palette2[0]) plot4.line('x1', 'y4', source=source, color=palette2[2]) - layout = layoutcolumn([ + mylayout = layoutcolumn([ plot1, plot2, plot3, plot4, ]) - layout.sizing_mode = 'stretch_both' + mylayout.sizing_mode = 'stretch_both' - script, div = components(layout) + script, div = components(mylayout) js_resources = INLINE.render_js() css_resources = INLINE.render_css() @@ -5443,9 +5268,6 @@ def interactive_flex_chart2(id, r, promember=0, mode='rower'): watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 watermarkx = 0.99 @@ -5454,7 +5276,6 @@ def interactive_flex_chart2(id, r, promember=0, watermarkh = 35 watermarkanchor = 'bottom_right' - #rowdata,row = dataprep.getrowdata_db(id=id) columns = [xparam, yparam1, yparam2, 'ftime', 'distance', 'fpace', 'power', 'hr', 'spm', 'driveenergy', @@ -5484,28 +5305,24 @@ def interactive_flex_chart2(id, r, promember=0, workstrokesonly=False) workstrokesonly = False try: - tests = rowdata[yparam2] + _ = rowdata[yparam2] except KeyError: # pragma: no cover yparam2 = 'None' try: - tests = rowdata[yparam1] + _ = rowdata[yparam1] except KeyError: # pragma: no cover yparam1 = 'None' # test if we have drive energy - nowork = 1 try: - test = rowdata['driveenergy'].mean() - nowork = 0 + _ = rowdata['driveenergy'].mean() except KeyError: rowdata['driveenergy'] = 500. # test if we have power - nopower = 1 try: - test = rowdata['power'].mean() - nopower = 0 + _ = rowdata['power'].mean() except KeyError: rowdata['power'] = 50. @@ -5516,9 +5333,7 @@ def interactive_flex_chart2(id, r, promember=0, if rowdata.empty: return "", "No valid data", '', '', workstrokesonly - workoutstateswork = [1, 4, 5, 8, 9, 6, 7] workoutstatesrest = [3] - workoutstatetransition = [0, 2, 10, 11, 12, 13] if workstrokesonly: # pragma: no cover try: @@ -5533,13 +5348,11 @@ def interactive_flex_chart2(id, r, promember=0, try: rowdata['x1'] = rowdata.loc[:, xparam] - rowmin = rowdata[xparam].min() except KeyError: # pragma: no cover rowdata['x1'] = 0*rowdata.loc[:, 'time'] try: rowdata['y1'] = rowdata.loc[:, yparam1] - rowmin = rowdata[yparam1].min() except KeyError: # pragma: no cover rowdata['y1'] = 0*rowdata.loc[:, 'time'] rowdata[yparam1] = rowdata['y1'] @@ -5547,7 +5360,6 @@ def interactive_flex_chart2(id, r, promember=0, if yparam2 != 'None': try: rowdata['y2'] = rowdata.loc[:, yparam2] - rowmin = rowdata[yparam2].min() except KeyError: # pragma: no cover rowdata['y2'] = 0*rowdata.loc[:, 'time'] rowdata[yparam2] = rowdata['y2'] @@ -5639,13 +5451,9 @@ def interactive_flex_chart2(id, r, promember=0, toolbar_sticky=False, plot_width=800, plot_height=600, ) plot.sizing_mode = 'stretch_both' - #plot.width_policy = 'max' # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 watermarkx = 0.99 @@ -6005,14 +5813,6 @@ def interactive_flex_chart2(id, r, promember=0, slider_dist_max.js_on_change('value', callback) callback.args["maxdist"] = slider_dist_max - #annotation.sizing_mode = 'fixed' - #slider_spm_min.sizing_mode = 'fixed' - #slider_spm_max.sizing_mode = 'fixed' - #slider_work_min.sizing_mode = 'fixed' - #slider_work_max.sizing_mode = 'fixed' - #slider_dist_min.sizing_mode = 'fixed' - #slider_dist_max.sizing_mode = 'fixed' - thesliders = layoutcolumn([ annotation, slider_spm_min, @@ -6023,15 +5823,12 @@ def interactive_flex_chart2(id, r, promember=0, slider_work_max, ]) - #thesliders.sizing_mode = 'fixed' - - layout = layoutrow([thesliders, - plot]) + mylayout = layoutrow([thesliders, plot]) # layout.sizing_mode = 'stretch_both' - layout.sizing_mode = 'stretch_both' + mylayout.sizing_mode = 'stretch_both' - script, div = components(layout) + script, div = components(mylayout) js_resources = INLINE.render_js() css_resources = INLINE.render_css() @@ -6074,9 +5871,9 @@ def thumbnails_set(r, id, favorites): # except KeyError: # pass - l = len(rowdata) + lengte = len(rowdata) maxlength = 50 - if l > maxlength: + if lengte > maxlength: try: bins = np.linspace(rowdata['time'].min(), rowdata['time'].max(), maxlength) @@ -6086,7 +5883,6 @@ def thumbnails_set(r, id, favorites): pass for f in favorites: - workstrokesonly = not f.reststrokes script, div = thumbnail_flex_chart( rowdata, id=id, @@ -6112,12 +5908,12 @@ def thumbnail_flex_chart(rowdata, id=0, promember=0, workstrokesonly=False): try: - tests = rowdata[yparam2] + _ = rowdata[yparam2] except KeyError: yparam2 = 'None' try: - tests = rowdata[yparam1] + _ = rowdata[yparam1] except KeyError: yparam1 = 'None' @@ -6161,7 +5957,6 @@ def thumbnail_flex_chart(rowdata, id=0, promember=0, if yparam1 == 'pace': # pragma: no cover y_axis_type = 'datetime' - y1mean = rowdata.loc[:, 'pace'].mean() rowdata['xname'] = axlabels[xparam] try: @@ -6178,7 +5973,6 @@ def thumbnail_flex_chart(rowdata, id=0, promember=0, rowdata ) - sizing_mode = 'fixed' # 'stretch_both' 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, ) @@ -6188,7 +5982,6 @@ def thumbnail_flex_chart(rowdata, id=0, promember=0, plot.sizing_mode = 'fixed' plot.toolbar.logo = None plot.toolbar_location = None - #plot.yaxis.visible = False plot.xaxis.axis_label_text_font_size = "7pt" plot.yaxis.axis_label_text_font_size = "7pt" plot.xaxis.major_label_text_font_size = "7pt" @@ -6297,12 +6090,6 @@ def interactive_multiple_compare_chart(ids, xparam, yparam, plottype='line', except: return ['', '

A chart data error occurred

', '', 'A chart data error occurred'] - yparamname = axlabels[yparam] - - #datadf = datadf[datadf[yparam] > 0] - - #datadf = datadf[datadf[xparam] > 0] - # check if dataframe not empty if datadf.empty: # pragma: no cover return ['', '

No non-zero data in selection

', '', 'No non-zero data in selection'] @@ -6350,11 +6137,6 @@ def interactive_multiple_compare_chart(ids, xparam, yparam, plottype='line', if xparam == 'time': x_axis_type = 'datetime' - if xparam != 'time': - xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100. - else: - xvals = np.arange(100) - plot = Figure(x_axis_type=x_axis_type, y_axis_type=y_axis_type, tools=TOOLS, toolbar_location="above", @@ -6363,16 +6145,10 @@ def interactive_multiple_compare_chart(ids, xparam, yparam, plottype='line', # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 - watermarkx = 0.99 - watermarky = 0.01 watermarkw = 184 watermarkh = 35 - watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'stretch_both' @@ -6475,7 +6251,7 @@ def interactive_multiple_compare_chart(ids, xparam, yparam, plottype='line', try: legend_label = labeldict[id] except KeyError: # pragma: no cover - legend = str(id) + legend_label = str(id) else: # pragma: no cover legend_label = str(id) @@ -6549,9 +6325,6 @@ def interactive_otw_advanced_pace_chart(id=0, promember=0): # add watermark watermarkurl = "/static/img/logo7.png" - watermarksource = ColumnDataSource(dict( - url=[watermarkurl],)) - watermarkrange = Range1d(start=0, end=1) watermarkalpha = 0.6 watermarkx = 0.99 @@ -6625,10 +6398,6 @@ def interactive_otw_advanced_pace_chart(id=0, promember=0): def get_zones_report(rower, startdate, enddate, trainingzones='hr', date_agg='week', yaxis='time'): - duration = enddate-startdate - - totaldays = duration.total_seconds()/(24*3600) - dates = [] dates_sorting = [] minutes = [] @@ -6657,14 +6426,10 @@ def get_zones_report(rower, startdate, enddate, trainingzones='hr', date_agg='we df = dataprep.clean_df_stats(df, workstrokesonly=False, ignoreadvanced=True, ignorehr=False) - #totalmeters,totalhours, totalminutes, totalseconds = get_totals(workouts) - hrzones = rower.hrzones powerzones = rower.powerzones for w in workouts: - dd = w.date.strftime('%m/%d') - dd2 = w.date.strftime('%Y/%m/%d') dd3 = w.date.strftime('%Y/%m') dd4 = '{year}/{week:02d}'.format( week=arrow.get(w.date).isocalendar()[1], @@ -6798,7 +6563,6 @@ def get_zones_report(rower, startdate, enddate, trainingzones='hr', date_agg='we pass while d <= enddate: - dd = d.strftime('%d') if date_agg == 'week': dd4 = '{year}/{week:02d}'.format( week=arrow.get(d).isocalendar()[1], @@ -6842,12 +6606,6 @@ def interactive_zoneschart(rower, data, startdate, enddate, trainingzones='hr', startdate = enddate enddate = st - duration = enddate-startdate - - totaldays = duration.total_seconds()/(24*3600) - - colors = ['gray', 'yellow', 'lime', 'blue', 'purple', 'red'] - hrzones = rower.hrzones powerzones = rower.powerzones @@ -6893,10 +6651,6 @@ def interactive_zoneschart(rower, data, startdate, enddate, trainingzones='hr', df.drop('minutes', inplace=True, axis='columns') - # df.drop('hours',inplace=True,axis='columns') - - source = ColumnDataSource(df) - df.sort_values('date_sorting', inplace=True) df.drop('date_sorting', inplace=True, axis='columns') df['totaltime'] = 0 @@ -6927,7 +6681,6 @@ def interactive_zoneschart(rower, data, startdate, enddate, trainingzones='hr', bars = hv.Bars(df, kdims=['date', 'zones']).aggregate( function=np.sum).redim.values(zones=zones_order) - #bars = table.to.bars(['date','zones'],['minutes']) bars.opts( opts.Bars(cmap=color_map, show_legend=True, stacked=True, tools=['tap', 'hover'], width=550, padding=(0, (0, .1)), diff --git a/rowers/longtask.py b/rowers/longtask.py index f45cb9da..03e08a71 100644 --- a/rowers/longtask.py +++ b/rowers/longtask.py @@ -14,7 +14,6 @@ redis_connection = StrictRedis() def getvalue(data): # pragma: no cover - perc = 0 total = 1 done = 0 id = 0 @@ -43,8 +42,7 @@ def longtask(aantal, jobid=None, debug=False, if counter > 10: counter = 0 if debug: - progress = 100.*i/aantal - if jobid != None: + if jobid is not None: redis_connection.publish(channel, json.dumps( { 'done': i, @@ -60,7 +58,6 @@ def longtask(aantal, jobid=None, debug=False, def longtask2(aantal, jobid=None, debug=False, secret=''): # pragma: no cover counter = 0 - channel = 'tasks' for i in range(aantal): time.sleep(1) counter += 1 @@ -69,7 +66,7 @@ def longtask2(aantal, jobid=None, debug=False, secret=''): # pragma: no cover progress = int(100.*i/aantal) if debug: print(progress) - if jobid != None: + if jobid is not None: if debug: url = SITE_URL_DEV else: diff --git a/rowers/management/commands/autojoin.py b/rowers/management/commands/autojoin.py index 107e8305..7f5c224d 100644 --- a/rowers/management/commands/autojoin.py +++ b/rowers/management/commands/autojoin.py @@ -7,20 +7,22 @@ import arrow from django.utils import timezone from django.core.management.base import BaseCommand -from rowers.models import Rower,Workout +from rowers.models import Rower, Workout import re from django.db.models import Q from rowers.dataprep import join_workouts + def name_short(name): expr = '(.*)\s.*\(\d+\)' - match = re.findall(expr,name) + match = re.findall(expr, name) if match: return match[0] return name + def get_duplicates(a): seen = {} dupes = [] @@ -38,28 +40,25 @@ def get_duplicates(a): class Command(BaseCommand): def handle(self, *args, **options): - rs = (r for r in Rower.objects.all() if r.ispaid and r.autojoin) - now = timezone.now() + rs = (r for r in Rower.objects.all() if r.ispaid and r.autojoin) for r in rs: workouts = Workout.objects.filter(user=r, duplicate=False, startdatetime__gte=timezone.now()-datetime.timedelta(days=2)) - duplicates = get_duplicates(name_short(w.name) for w in workouts) for name, count in duplicates.items(): if count > 1: workouts2 = workouts.filter( - Q(name__contains=name) - ) + Q(name__contains=name)) duplicates2 = get_duplicates(w.date for w in workouts) for dd, count in duplicates2.items(): if count > 1: workouts3 = workouts2.filter(date=dd) ids = [w.id for w in workouts3] - id, message = join_workouts(r,ids,title=name, + id, message = join_workouts(r, ids, title=name, parent=workouts3[0], killparents=True) diff --git a/rowers/management/commands/getblogposts.py b/rowers/management/commands/getblogposts.py index b6cbf02b..be55701b 100644 --- a/rowers/management/commands/getblogposts.py +++ b/rowers/management/commands/getblogposts.py @@ -1,5 +1,3 @@ -#!/srv/venv/bin/python - import sys import os @@ -10,11 +8,12 @@ import json from simplejson.errors import JSONDecodeError -PY3K = sys.version_info >= (3,0) - from django.core.management.base import BaseCommand from rowers.models import BlogPost +PY3K = sys.version_info >= (3, 0) + + class Command(BaseCommand): def handle(self, *args, **options): blogs_json = [] @@ -24,7 +23,7 @@ class Command(BaseCommand): if response.status_code == 200: try: blogs_json = response.json() - except JSONDecodeError: + except JSONDecodeError: try: blogs_json = json.loads(response.text) except JSONDecodeError: @@ -35,16 +34,13 @@ class Command(BaseCommand): pass if blogs_json: - result = BlogPost.objects.all().delete() + _ = BlogPost.objects.all().delete() for postdata in blogs_json[0:3]: title = postdata['title']['rendered'] link = postdata['link'] - datetime = postdata['date'] - datetime = arrow.get(datetime).datetime date = datetime.date() - blogpost = BlogPost( link=link, date=date, diff --git a/rowers/management/commands/getemail_list.py b/rowers/management/commands/getemail_list.py index 8e538392..775d1b97 100644 --- a/rowers/management/commands/getemail_list.py +++ b/rowers/management/commands/getemail_list.py @@ -1,15 +1,9 @@ -#!/srv/venv/bin/python import sys import os -# If you find a solution that does not need the two paths, please comment! -sys.path.append('$path_to_root_of_project$') -sys.path.append('$path_to_root_of_project$/$project_name$') - -os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' from django.core.management.base import BaseCommand, CommandError from django.conf import settings -from django.core.mail import send_mail, BadHeaderError,EmailMessage +from django.core.mail import send_mail, BadHeaderError, EmailMessage import datetime from rowers.models import * @@ -17,6 +11,12 @@ from rowsandall_app.settings import BASE_DIR import pandas as pd +sys.path.append('$path_to_root_of_project$') +sys.path.append('$path_to_root_of_project$/$project_name$') + +os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' + + def getemails(): rs = Rower.objects.all() firstnames = [r.user.first_name for r in rs] @@ -24,33 +24,32 @@ def getemails(): emails = [r.user.email for r in rs] is_actives = [r.user.is_active for r in rs] df = pd.DataFrame({ - 'first_name':firstnames, - 'last_name':lastnames, - 'email':emails, - 'is_active':is_actives - }) + 'first_name': firstnames, + 'last_name': lastnames, + 'email': emails, + 'is_active': is_actives}) return df - class Command(BaseCommand): def handle(self, *args, **options): email_list = getemails() - email_list.to_csv('email_list.csv',encoding='utf-8') - + email_list.to_csv('email_list.csv', encoding='utf-8') + fullemail = 'roosendaalsander@gmail.com' subject = "Rowsandall users list" message = "Dear Sander,\n\n" message += "Best Regards, the Rowsandall Team" message += "Users list attached \n\n" - - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) - + + email = EmailMessage( + subject, message, + 'Rowsandall ', + [fullemail]) + email.attach_file('email_list.csv') - + os.remove('email_list.csv') - - res = email.send() + + _ = email.send() diff --git a/rowers/management/commands/getexpired.py b/rowers/management/commands/getexpired.py index 26ccd478..8aef0b9e 100644 --- a/rowers/management/commands/getexpired.py +++ b/rowers/management/commands/getexpired.py @@ -1,19 +1,19 @@ -#!/srv/venv/bin/python import sys import os -# If you find a solution that does not need the two paths, please comment! + +from django.core.management.base import BaseCommand, CommandError +from django.conf import settings +from django.core.mail import send_mail, BadHeaderError, EmailMessage + +import datetime +from rowers.models import Rower +from rowsandall_app.settings import BASE_DIR + sys.path.append('$path_to_root_of_project$') sys.path.append('$path_to_root_of_project$/$project_name$') os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' -from django.core.management.base import BaseCommand, CommandError -from django.conf import settings -from django.core.mail import send_mail, BadHeaderError,EmailMessage - -import datetime -from rowers.models import Rower -from rowsandall_app.settings import BASE_DIR def getexpired(): rs = Rower.objects.all() @@ -31,22 +31,21 @@ def getexpired(): class Command(BaseCommand): def handle(self, *args, **options): expiredrowers = getexpired() - + if len(expiredrowers) > 0: fullemail = 'roosendaalsander@gmail.com' subject = "Expired rowers report" message = "Dear Sander,\n\n" message += "Best Regards, the Rowsandall Team" message += "Expired rowers report\n\n" - + for r in expiredrowers: message += r.user.first_name+" "+r.user.last_name+" "+r.user.username message += "\n" - - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) - - - res = email.send() + email = EmailMessage( + subject, message, + 'Rowsandall ', + [fullemail]) + + _ = email.send() diff --git a/rowers/management/commands/processalerts.py b/rowers/management/commands/processalerts.py index 12937fcd..d910de93 100644 --- a/rowers/management/commands/processalerts.py +++ b/rowers/management/commands/processalerts.py @@ -3,8 +3,6 @@ import sys import os -PY3K = sys.version_info >= (3,0) - from django.core.management.base import BaseCommand from rowers.models import Alert, Condition, User from rowers.tasks import handle_send_email_alert @@ -13,15 +11,17 @@ from rowers import alerts from rowers.utils import myqueue +import datetime import django_rq + +PY3K = sys.version_info >= (3, 0) + queue = django_rq.get_queue('default') queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low') -import datetime - class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument( @@ -29,8 +29,7 @@ class Command(BaseCommand): action='store_true', dest='testing', default=False, - help="Run in testing mode, don't send emails", - ) + help="Run in testing mode, don't send emails", ) def handle(self, *args, **options): if 'testing' in options: @@ -38,7 +37,8 @@ class Command(BaseCommand): else: testing = False - todaysalerts = Alert.objects.filter(next_run__lt = datetime.date.today(),emailalert=True) + todaysalerts = Alert.objects.filter( + next_run__lt=datetime.date.today(), emailalert=True) for alert in todaysalerts: stats = alerts.alert_get_stats(alert) @@ -47,14 +47,14 @@ class Command(BaseCommand): othertexts = [alert.description()] # send email - job = myqueue(queue,handle_send_email_alert, - alert.manager.email, - alert.manager.first_name, - alert.manager.last_name, - alert.rower.user.first_name, - alert.name, - stats,debug=True, - othertexts=othertexts) + _ = myqueue(queue, handle_send_email_alert, + alert.manager.email, + alert.manager.first_name, + alert.manager.last_name, + alert.rower.user.first_name, + alert.name, + stats, debug=True, + othertexts=othertexts) # advance next_run if not testing: @@ -62,7 +62,7 @@ class Command(BaseCommand): alert.save() if testing: - print('{nr} alerts found'.format(nr = len(todaysalerts))) + print('{nr} alerts found'.format(nr=len(todaysalerts))) self.stdout.write(self.style.SUCCESS( 'Successfully processed alerts')) diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index 73ef5f40..f12a89ff 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -1,9 +1,6 @@ -#!/srv/venv/bin/python - """ Process emails """ import sys import os -PY3K = sys.version_info >= (3, 0) import zipfile from zipfile import BadZipFile @@ -18,12 +15,12 @@ import json import io from django.core.management.base import BaseCommand -#from django_mailbox.models import Message, MessageAttachment,Mailbox + from django.urls import reverse from django.conf import settings from django.utils import timezone -from rowers.models import Workout, Rower +from rowers.models import User, Workout, Rower from rowingdata import rower as rrower from rowingdata import rowingdata as rrdata @@ -37,7 +34,6 @@ import rowers.stravastuff as stravastuff import rowers.nkstuff as nkstuff from rowers.opaque import encoder -from rowers.models import User,Workout from rowers.rower_rules import user_is_not_basic from rowers.utils import dologging @@ -47,10 +43,14 @@ sys.path.append('$path_to_root_of_project$/$project_name$') os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' -if not getattr(__builtins__, "WindowsError", None): - class WindowsError(OSError): pass +PY3K = sys.version_info >= (3, 0) -def rdata(file_obj, rower=rrower()): # pragma: no cover +if not getattr(__builtins__, "WindowsError", None): + class WindowsError(OSError): + pass + + +def rdata(file_obj, rower=rrower()): # pragma: no cover """ Read rowing data file and return 0 if file doesn't exist""" try: result = rrdata(file_obj, rower=rower) @@ -60,7 +60,6 @@ def rdata(file_obj, rower=rrower()): # pragma: no cover return result - class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument( @@ -68,71 +67,57 @@ class Command(BaseCommand): action='store_true', dest='testing', default=False, - help="Run in testing mode, don't send emails", - ) + help="Run in testing mode, don't send emails", ) parser.add_argument( '--mailbox', action='store_true', dest='mailbox', default='workouts', - help="Changing mailbox name", - ) + help="Changing mailbox name", ) """Run the Email processing command """ def handle(self, *args, **options): - if 'testing' in options: - testing = options['testing'] - else: # pragma: no cover - testing = False - # Polar try: polar_available = polarstuff.get_polar_notifications() - res = polarstuff.get_all_new_workouts(polar_available) - except: # pragma: no cover + _ = polarstuff.get_all_new_workouts(polar_available) + except: # pragma: no cover exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) - dologging('processemail.log',''.join('!! ' + line for line in lines)) + dologging('processemail.log', ''.join('!! ' + line for line in lines)) # Concept2 try: rowers = Rower.objects.filter(c2_auto_import=True) - for r in rowers: # pragma: no cover + for r in rowers: # pragma: no cover if user_is_not_basic(r.user): c2stuff.get_c2_workouts(r) - except: # pragma: no cover + except: # pragma: no cover exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) - dologging('processemail.log',''.join('!! ' + line for line in lines)) - + dologging('processemail.log', ''.join('!! ' + line for line in lines)) try: rowers = Rower.objects.filter(rp3_auto_import=True) - for r in rowers: # pragma: no cover + for r in rowers: # pragma: no cover if user_is_not_basic(r.user): - res = rp3stuff.get_rp3_workouts(r) - except: # pragma: no cover + _ = rp3stuff.get_rp3_workouts(r) + except: # pragma: no cover exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) - dologging('processemail.log',''.join('!! ' + line for line in lines)) + dologging('processemail.log', ''.join('!! ' + line for line in lines)) try: rowers = Rower.objects.filter(nk_auto_import=True) - for r in rowers: # pragma: no cover + for r in rowers: # pragma: no cover if user_is_not_basic(r.user): s = 'Starting NK Auto Import for user {id}'.format(id=r.user.id) - dologging('nklog.log',s) - res = nkstuff.get_nk_workouts(r) - except: # pragma: no cover + dologging('nklog.log', s) + _ = nkstuff.get_nk_workouts(r) + except: # pragma: no cover exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) - dologging('processemail.log',''.join('!! ' + line for line in lines)) - - # Strava - #rowers = Rower.objects.filter(strava_auto_import=True) - #for r in rowers: - # if user_is_not_basic(r.user): # pragma: no cover - # stravastuff.get_strava_workouts(r) + dologging('processemail.log', ''.join('!! ' + line for line in lines)) self.stdout.write(self.style.SUCCESS( 'Successfully processed email attachments')) diff --git a/rowers/management/commands/repairstrokedata.py b/rowers/management/commands/repairstrokedata.py index c6400461..7a8133b1 100644 --- a/rowers/management/commands/repairstrokedata.py +++ b/rowers/management/commands/repairstrokedata.py @@ -1,24 +1,27 @@ #!/srv/venv/bin/python import sys import os -# If you find a solution that does not need the two paths, please comment! -sys.path.append('$path_to_root_of_project$') -sys.path.append('$path_to_root_of_project$/$project_name$') - -os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' - from django.core.management.base import BaseCommand, CommandError from django.conf import settings -#from rowers.mailprocessing import processattachments + import time -from django.conf import settings -from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage,AdvancedWorkoutForm + +from rowers.models import ( + Workout, User, Rower, WorkoutForm, + RowerForm, GraphImage, AdvancedWorkoutForm) from django.core.files.base import ContentFile from rowsandall_app.settings import BASE_DIR from rowers.dataprep import * +# If you find a solution that does not need the two paths, please comment! +sys.path.append('$path_to_root_of_project$') +sys.path.append('$path_to_root_of_project$/$project_name$') + +os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' + + class Command(BaseCommand): def handle(self, *args, **options): repair_data(verbose=True) diff --git a/rowers/middleware.py b/rowers/middleware.py index 7c59b0c3..7dc0d2d1 100644 --- a/rowers/middleware.py +++ b/rowers/middleware.py @@ -99,12 +99,12 @@ class RowerPlanMiddleWare(object): # remove from Free Coach groups # send email - job = myqueue(queue, - handle_sendemail_expired, - r.user.email, - r.user.first_name, - r.user.last_name, - str(r.planexpires)) + _ = myqueue(queue, + handle_sendemail_expired, + r.user.email, + r.user.first_name, + r.user.last_name, + str(r.planexpires)) response = self.get_response(request) diff --git a/rowers/models.py b/rowers/models.py index 6bb4d986..e1996516 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -3,7 +3,7 @@ from rowers.metrics import rowingmetrics from django.db.models.signals import m2m_changed from rowers.courseutils import coordinate_in_path from rowers.utils import ( - workflowleftpanel, workflowmiddlepanel, + # workflowleftpanel, workflowmiddlepanel, defaultleft, defaultmiddle, landingpages, landingpages2, steps_read_fit, steps_write_fit, ps_dict_order ) @@ -15,18 +15,15 @@ import uuid from django.db import models, IntegrityError from django.contrib.auth.models import User -from django.core.validators import validate_email 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, SelectDateWidget -#from django.forms.extras.widgets import SelectDateWidget from django.forms.formsets import BaseFormSet -#from datetimewidget.widgets import DateTimeWidget from django.contrib.admin.widgets import AdminDateWidget, AdminTimeWidget, AdminSplitDateTime -from django.core.validators import validate_email + import os import json import twitter @@ -55,8 +52,6 @@ import datetime from taggit.managers import TaggableManager -#from rules.contrib.models import RulesModel - from rowers.rower_rules import * from rowers.opaque import encoder @@ -322,7 +317,6 @@ def update_records(url=c2url, verbose=True): dfs = pd.read_html(url, attrs={'class': 'views-table'}) df = dfs[0] df.columns = df.columns.str.strip() - success = 1 except: # pragma: no cover df = pd.DataFrame() @@ -574,29 +568,16 @@ def course_spline(coordinates): latitudes = coordinates['latitude'].values longitudes = coordinates['longitude'].values - # spline parameters - s = 1.0 - k = min([5, len(latitudes)-1]) - nest = -1 - t = np.linspace(0, 1, len(latitudes)) tnew = np.linspace(0, 1, 100) try: - #latnew = CubicSpline(t,latitudes,bc_type='not-a-knot')(tnew) - #lonnew = CubicSpline(t,longitudes,bc_type='not-a-knot')(tnew) latnew = interp1d(t, latitudes)(tnew) lonnew = interp1d(t, longitudes)(tnew) except ValueError: # pragma: no cover latnew = latitudes lonnew = longitudes -# latnew = CubicSpline(t,latitudes,bc_type='natural')(tnew) -# lonnew = CubicSpline(t,longitudes,bc_type='natural')(tnew) - -# tckp,u = splprep([t,latitudes,longitudes],s=s,k=k,nest=nest) -# tnew,latnew,lonnew = splev(np.linspace(0,1,100),tckp) - newcoordinates = pd.DataFrame({ 'latitude': latnew, 'longitude': lonnew, @@ -673,7 +654,8 @@ def get_delta(vector, polygon): p = polygon_to_path(polygon) - def f(x): return coordinate_in_path(x['lat'], x['lon'], p) + def f(x): + return coordinate_in_path(x['lat'], x['lon'], p) df = pd.DataFrame({'x': x, 'lat': lat, @@ -795,7 +777,7 @@ class PaidPlan(models.Model): shortname=self.shortname, price=self.price, paymenttype=self.paymenttype, - paymentprocessor=self.paymentprocessor, + # paymentprocessor=self.paymentprocessor, ) @@ -1346,8 +1328,9 @@ class BaseFavoriteFormSet(BaseFormSet): xparam = form.cleaned_data['xparam'] yparam1 = form.cleaned_data['yparam1'] yparam2 = form.cleaned_data['yparam2'] - plottype = form.cleaned_data['plottype'] - reststrokes = form.cleaned_data['reststrokes'] + # plottype = form.cleaned_data['plottype'] + # reststrokes = form.cleaned_data['reststrokes'] + pass if not xparam: raise forms.ValidationError( @@ -1402,10 +1385,11 @@ class BaseConditionFormSet(BaseFormSet): for form in self.forms: if form.cleaned_data: - metric = form.cleaned_data['metric'] - condition = form.cleaned_data['condition'] - value1 = form.cleaned_data['value1'] - value2 = form.cleaned_data['value2'] + # metric = form.cleaned_data['metric'] + # condition = form.cleaned_data['condition'] + # value1 = form.cleaned_data['value1'] + # value2 = form.cleaned_data['value2'] + pass rowchoices = [] @@ -1475,7 +1459,7 @@ class Alert(models.Model): return description def shortdescription(self): # pragma: no cover - metricdict = {key: value for (key, value) in parchoicesy1} + # metricdict = {key: value for (key, value) in parchoicesy1} if self.measured.condition == 'between': description = '{value1} < {metric} < {value2}'.format( @@ -1526,7 +1510,7 @@ class GeoCourse(models.Model): def __str__(self): name = self.name - country = self.country + # country = self.country d = self.distance if d == 0: # pragma: no cover self.distance = course_length(self) @@ -1535,7 +1519,7 @@ class GeoCourse(models.Model): return u'{name} - {d}m'.format( name=name, - country=country, + # country=country, d=d, ) @@ -1821,6 +1805,26 @@ class TrainingPlan(models.Model): else: createmacrofillers(self) + def length(self): + startdate = self.startdate + enddate = self.enddate + return (enddate-startdate).days + + def overlap(self,startdate,enddate): + is_overlapped = max(self.startdate, startdate) < min(self.enddate, enddate) + if not is_overlapped: + return 0 + + if startdate >= self.startdate: + if self.enddate >= enddate: + return (enddate-startdate).days + else: + return (self.enddate-startdate).days + elif startdate < self.startdate: + if enddate >= self.enddate: + return (self.enddate-self.startdate).days + else: + return (enddate-self.startdate).days def check_trainingplan_on_change(sender, **kwargs): instance = kwargs.pop('instance', None) @@ -2407,6 +2411,111 @@ regularsessiontypechoices = ( ) # model for Planned Session (Workout, Challenge, Test) +class PlannedSessionStep(models.Model): + intensitytypes = ( + ("Active", "Active"), + ("Rest", "Rest"), + ("Warmup", "Warmup"), + ("Cooldown", "Cooldown") + ) + + durationtypes = ( + ("Distance", "Distance"), + ("Time", "Time"), + ('RepeatUntilStepsCmplt','Repeat previous blocks n times') + ) + + targettypes = ( + ("Speed", "Speed"), + ("HeartRate", "HeartRate"), + ("Cadence", "Cadence"), + ("Power", "Power") + ) + + manager = models.ForeignKey(User, null=True, on_delete=models.CASCADE) + name = models.TextField(default='',max_length=200, blank=True, null=True) + type = models.TextField(default='',max_length=200, blank=True, null=True) + durationvalue = models.FloatField(default=0, verbose_name="Duration Value") + durationtype = models.TextField(default='Time',max_length=200, + choices=durationtypes, + verbose_name='Duration Type') + targetvalue = models.IntegerField(default=0, verbose_name="Target Value") + targettype = models.TextField(default='',max_length=200, blank=True, null=True, + choices=targettypes, verbose_name="Target Type") + targetvaluelow = models.IntegerField(default=0, + verbose_name="Target Value Low") + targetvaluehigh = models.IntegerField(default=0, + verbose_name="Target Value High") + intensity = models.TextField(default='',max_length=200, blank=True, null=True, + choices=intensitytypes, + verbose_name = "Intensity") + description = models.TextField(default='',max_length=200, blank=True, null=True) + color = models.TextField(default='#ddd',max_length=200) + + def save(self, *args, **kwargs): + if self.intensity == "Warmup": + self.color = "#ffcccb" + elif self.intensity == "Cooldown": + self.color = '#90ee90' + elif self.intensity == "Rest": + self.color = 'add8e6' + if self.durationtype == 'RepeatUntilStepsCmplt': + self.color = 'ffffa7' + + self.durationvalue = int(self.durationvalue) + + super(PlannedSessionStep, self).save(*args, **kwargs) + + def asdict(self): + d = { + 'wkt_step_name': self.name, + 'durationType': self.durationtype, + 'durationValue': self.durationvalue, + 'targetType': self.targettype, + 'targetValue': self.targetvalue, + 'targetValueLow': self.targetvaluelow, + 'targetValueHigh': self.targetvaluehigh, + 'description': self.description, + 'stepId': self.pk, + 'intensity': self.intensity, + } + + return d + +class StepEditorForm(ModelForm): + class Meta: + model = PlannedSessionStep + fields = [ + 'name', + #'type', + 'durationtype', + 'durationvalue', + 'targettype', + 'targetvalue', + 'targetvaluelow', + 'targetvaluehigh', + 'intensity', + 'description', + ] + + widgets = { + 'name': forms.Textarea(attrs={'rows':1, 'cols':50}), + } + + def __init__(self, *args, **kwargs): + super(StepEditorForm, self).__init__(*args, **kwargs) + if self.instance.durationtype == 'Time': + self.initial['durationvalue'] = self.instance.durationvalue / 60000 + elif self.instance.durationtype == 'Distance': + self.initial['durationvalue'] = self.instance.durationvalue / 100 + + def save(self, *args, **kwargs): + # conversions + if self.instance.durationtype == 'Time': + self.instance.durationvalue *= 60000 + elif self.instance.durationtype == 'Distance': + self.instance.durationvalue *= 100 + return super(StepEditorForm, self).save(*args, **kwargs) class PlannedSession(models.Model): @@ -2530,7 +2639,6 @@ class PlannedSession(models.Model): can_be_shared = models.BooleanField(default=True) fitfile = models.FileField(upload_to=get_file_path, blank=True, null=True) - #steps_json = models.TextField(max_length=10000,default=None,blank=True,null=True) steps = PlannedSessionStepField(default={}, null=True, max_length=1000) interval_string = models.TextField(max_length=1000, default=None, blank=True, null=True, verbose_name='Interval String (optional)') @@ -2565,7 +2673,7 @@ class PlannedSession(models.Model): if self.sessionvalue <= 0: # pragma: no cover self.sessionvalue = 1 - manager = self.manager + # manager = self.manager if self.sessiontype not in ['race', 'indoorrace']: if not can_add_session(self.manager): raise ValidationError( @@ -2612,7 +2720,7 @@ class PlannedSession(models.Model): self.sessionmode = 'distance' self.sessionunit = 'm' self.criterium = 'none' - if self.course == None: # pragma: no cover + if self.course is None: # pragma: no cover self.course = GeoCourse.objects.all()[0] self.sessionvalue = self.course.distance elif self.sessiontype != 'coursetest' and self.sessiontype != 'race': @@ -2626,7 +2734,6 @@ class PlannedSession(models.Model): if self.preferreddate < self.startdate: # pragma: no cover self.preferreddate = self.startdate - #super(PlannedSession,self).save(*args, **kwargs) if self.steps: steps = self.steps elif self.fitfile: # pragma: no cover @@ -2640,7 +2747,7 @@ class PlannedSession(models.Model): steps = self.steps steps['filename'] = os.path.join(settings.MEDIA_ROOT, filename) - fitfile = steps_write_fit(steps) + _ = steps_write_fit(steps) self.fitfile.name = filename self.steps = steps @@ -2752,8 +2859,8 @@ class VirtualRace(PlannedSession): def __str__(self): name = self.name - startdate = self.startdate - enddate = self.enddate + # startdate = self.startdate + # enddate = self.enddate stri = u'Virtual challenge {n}'.format( n=name, @@ -4031,9 +4138,6 @@ class WorkoutForm(ModelForm): class AdvancedWorkoutForm(ModelForm): - #quick_calc = forms.BooleanField(initial=True,required=False) - #go_service = forms.BooleanField(initial=False,required=False,label='Experimental') - class Meta: model = Workout fields = ['boattype', 'weightvalue', 'boatbrand'] @@ -4332,8 +4436,8 @@ class RowerPowerZonesForm(ModelForm): try: ut3name = cleaned_data['ut3name'] except: - ut2name = 'UT3' - cleaned_data['ut3name'] = 'UT3' + ut3name = 'UT3' + cleaned_data['ut3name'] = ut3name try: ut2name = cleaned_data['ut2name'] except: @@ -4717,10 +4821,10 @@ class SiteAnnouncement(models.Model): self.modified = timezone.now() if self.dotweet: # pragma: no cover try: - status = tweetapi.PostUpdate(self.announcement) + _ = tweetapi.PostUpdate(self.announcement) except: try: - status = tweetapi.PostUpdate(self.announcement[:270]) + _ = tweetapi.PostUpdate(self.announcement[:270]) except: pass return super(SiteAnnouncement, self).save(*args, **kwargs) diff --git a/rowers/mytypes.py b/rowers/mytypes.py index 1950f14a..333c3a6a 100644 --- a/rowers/mytypes.py +++ b/rowers/mytypes.py @@ -358,7 +358,6 @@ rowtypes = ( checktypes = [i[0] for i in workouttypes_ordered.items()] -#colors = Category10[9] colors = list(set(Category10[9]))+list(set(Category20[19]+Category20c[19])) color_map = {checktypes[i]: colors[i] for i in range(len(checktypes))} @@ -557,7 +556,7 @@ polaraccesslink_sports = { 'DUATHLON_CYCLING': 'bike', 'DUATHLON_RUNNING': 'Run', 'FIELD_HOCKEY': 'other', - 'FINNISH_BASEBALL': 'other', + 'FINNISH_BASEBALL': 'other', 'FITNESS_DANCING': 'other', 'FITNESS_MARTIAL_ARTS': 'other', 'FITNESS_STEP': 'Workout', @@ -625,7 +624,7 @@ polaraccesslink_sports = { 'ROLLER_BLADING': 'InlineSkate', 'ROLLER_SKIING_CLASSIC': 'NordicSki', 'ROLLER_SKIING_FREESTYLE': 'NordicSki', - 'ROWING': 'water', + 'ROWING': 'water', 'RUGBY': 'other', 'RUNNING': 'Run', 'SHOW_DANCING': 'other', @@ -664,5 +663,5 @@ polaraccesslink_sports = { 'WATERSPORTS_WINDSURFING': 'other', 'XC_SKIING_CLASSIC': 'NordicSki', 'XC_SKIING_FREESTYLE': 'NordicSki', - 'YOGA': 'Yoga' + 'YOGA': 'Yoga' } diff --git a/rowers/nkimportutils.py b/rowers/nkimportutils.py index b0c62090..78c6df29 100644 --- a/rowers/nkimportutils.py +++ b/rowers/nkimportutils.py @@ -1,4 +1,5 @@ import pandas as pd +import numpy as np import datetime from datetime import timedelta from uuid import uuid4 @@ -52,14 +53,14 @@ def add_workout_from_data(userid, nkid, data, strokedata, source='nk', splitdata elapsedTime = data["elapsedTime"] totalDistanceGps = data["totalDistanceGps"] totalDistanceImp = data["totalDistanceImp"] - intervals = data["intervals"] # add intervals + # intervals = data["intervals"] # add intervals oarlockSessions = data["oarlockSessions"] - deviceId = data["deviceId"] # you could get the firmware version + # deviceId = data["deviceId"] # you could get the firmware version totalDistance = totalDistanceGps useImpeller = False if speedInput: # pragma: no cover - totdalDistance = totalDistanceImp + totalDistance = totalDistanceImp useImpeller = True summary = get_nk_allstats(data, strokedata) @@ -69,19 +70,19 @@ def add_workout_from_data(userid, nkid, data, strokedata, source='nk', splitdata # oarlock inboard, length, boat name if oarlockSessions: oarlocksession = oarlockSessions[0] # should take seatIndex - boatName = oarlocksession["boatName"] + # boatName = oarlocksession["boatName"] oarLength = oarlocksession["oarLength"] # cm oarInboardLength = oarlocksession["oarInboardLength"] # cm - seatNumber = oarlocksession["seatNumber"] + # seatNumber = oarlocksession["seatNumber"] try: oarlockfirmware = oarlocksession["firmwareVersion"] except KeyError: oarlockfirmware = '' else: # pragma: no cover - boatName = '' + # boatName = '' oarLength = 289 oarInboardLength = 88 - seatNumber = 1 + # seatNumber = 1 oarlockfirmware = '' workouttype = "water" @@ -139,7 +140,7 @@ def get_nk_intervalstats(workoutdata, strokedata): i = 0 for interval in intervals: - id = interval['id'] + # id = interval['id'] sdist = interval['totalDistanceGps'] avgpace = interval['avgPaceGps']/1000. avgpacetd = timedelta(seconds=avgpace) @@ -325,6 +326,6 @@ def readlogs_summaries(logfile, dosave=0): # pragma: no cover json.dump(strokeData, f2) with open(filename2, 'w') as f2: json.dump(summaryData, f2) - except Exception as e: + except Exception: print(traceback.format_exc()) print("error") diff --git a/rowers/nkstuff.py b/rowers/nkstuff.py index 7fad2cdf..e3e2b8b3 100644 --- a/rowers/nkstuff.py +++ b/rowers/nkstuff.py @@ -31,13 +31,6 @@ queue = django_rq.get_queue('default') queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low') - -try: - from json.decoder import JSONDecodeError -except ImportError: # pragma: no cover - JSONDecodeError = ValueError - - oauth_data = { 'client_id': NK_CLIENT_ID, 'client_secret': NK_CLIENT_SECRET, @@ -56,12 +49,6 @@ oauth_data = { def get_token(code): # pragma: no cover url = oauth_data['base_url'] - headers = {'Accept': 'application/json', - # 'Authorization': auth_header, - 'Content-Type': 'application/x-www-form-urlencoded', - # 'user-agent': 'sanderroosendaal' - } - post_data = {"client_id": oauth_data['client_id'], "grant_type": "authorization_code", "redirect_uri": oauth_data['redirect_uri'], @@ -88,13 +75,12 @@ def nk_open(user): r = Rower.objects.get(user=user) if (r.nktoken == '') or (r.nktoken is None): # pragma: no cover - s = "Token doesn't exist. Need to authorize" raise NoTokenError("User has no token") else: if (timezone.now() > r.nktokenexpirydate): thetoken = rower_nk_token_refresh(user) - if thetoken == None: # pragma: no cover + if thetoken is None: # pragma: no cover raise NoTokenError("User has no token") return thetoken else: @@ -105,7 +91,7 @@ def nk_open(user): def get_nk_workouts(rower, do_async=True, before=0, after=0): try: - thetoken = nk_open(rower.user) + _ = nk_open(rower.user) except NoTokenError: # pragma: no cover return 0 @@ -136,7 +122,7 @@ def get_nk_workouts(rower, do_async=True, before=0, after=0): pass knownnkids = uniqify(knownnkids+tombstones+parkedids) - newids = [nkid for nkid in nkids if not nkid in knownnkids] + newids = [nkid for nkid in nkids if nkid not in knownnkids] s = 'New NK IDs {newids}'.format(newids=newids) dologging('nklog.log', s) @@ -211,7 +197,8 @@ def get_nk_workout_list(user, fake=False, after=0, before=0): if (r.nktoken == '') or (r.nktoken is None): # pragma: no cover s = "Token doesn't exist. Need to authorize" return custom_exception_handler(401, s) - elif (r.nktokenexpirydate is None or timezone.now()+timedelta(seconds=10) > r.nktokenexpirydate): # pragma: no cover + elif (r.nktokenexpirydate is None or + timezone.now()+timedelta(seconds=10) > r.nktokenexpirydate): # pragma: no cover s = "Token expired. Needs to refresh." return custom_exception_handler(401, s) else: @@ -251,10 +238,6 @@ def get_workout(user, nkid, do_async=True, startdate='', enddate=''): s = "Token expired. Needs to refresh." return custom_exception_handler(401, s), 0 - params = { - 'sessionIds': nkid, - } - before = 0 after = 0 if startdate: # pragma: no cover diff --git a/rowers/opaque.py b/rowers/opaque.py index e108dcd0..bc8c8013 100644 --- a/rowers/opaque.py +++ b/rowers/opaque.py @@ -38,8 +38,8 @@ class OpaqueEncoder: def transcode(self, i): """Reversibly transcode a 32-bit integer to a scrambled form, returning a new 32-bit integer.""" r = i & 0xffff - l = i >> 16 & 0xffff ^ self.transform(r) - return ((r ^ self.transform(l)) << 16) + l + lla = i >> 16 & 0xffff ^ self.transform(r) + return ((r ^ self.transform(lla)) << 16) + lla def encode_hex(self, i): """Transcode an integer and return it as an 8-character hex string.""" diff --git a/rowers/ownapistuff.py b/rowers/ownapistuff.py index 82b2250a..d222986d 100644 --- a/rowers/ownapistuff.py +++ b/rowers/ownapistuff.py @@ -7,7 +7,7 @@ import requests import requests.auth import json from django.utils import timezone -from datetime import datetime +from datetime import datetime, timedelta import numpy as np from dateutil import parser import time @@ -30,7 +30,10 @@ from rowingdata import rowingdata import pandas as pd from rowers.models import Rower, Workout -from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, SPORTTRACKS_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI +from rowsandall_app.settings import ( + C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, + STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, + SPORTTRACKS_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI) TEST_CLIENT_ID = "1" TEST_CLIENT_SECRET = "aapnootmies" @@ -57,8 +60,8 @@ def custom_exception_handler(exc, message): # pragma: no cover def do_refresh_token(refreshtoken): # pragma: no cover - client_auth = requests.auth.HTTPBasicAuth( - TEST_CLIENT_ID, TEST_CLIENT_SECRET) + # 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, @@ -86,8 +89,8 @@ def do_refresh_token(refreshtoken): # pragma: no cover def get_token(code): # pragma: no cover - client_auth = requests.auth.HTTPBasicAuth( - TEST_CLIENT_ID, TEST_CLIENT_SECRET) + # client_auth = requests.auth.HTTPBasicAuth( + # TEST_CLIENT_ID, TEST_CLIENT_SECRET) post_data = {"grant_type": "authorization_code", "code": code, "redirect_uri": "http://localhost:8000/rowers/test_callback", @@ -123,7 +126,6 @@ def make_authorization_url(request): # pragma: no cover "scope": "write", "state": state} - import urllib url = "http://localhost:8000/rowers/o/authorize" + \ urllib.parse.urlencode(params) @@ -170,8 +172,8 @@ def get_ownapi_workout_list(user): # pragma: no cover def get_ownapi_workout(user, ownapiid): # pragma: no cover 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) elif (timezone.now() > r.ownapitokenexpirydate): s = "Token expired. Needs to refresh." return custom_exception_handler(401, s) diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index b9edb3a2..5f1c1a37 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -6,7 +6,6 @@ from rowers.models import ( get_course_timezone, IndoorVirtualRaceResult, VirtualRace, createmacrofillers, createmesofillers, createmicrofillers, CourseStandard, ) -from rowers.utils import totaltime_sec_to_string from rowers.tasks import ( handle_sendemail_raceregistration, handle_sendemail_racesubmission ) @@ -203,30 +202,21 @@ def get_execution_report(rower, startdate, enddate, plan=None): micros = micros.exclude(enddate__lte=startdate).exclude( startdate__gte=enddate) else: # pragma: no cover - plans = TrainingPlan.objects.filter( - startdate__lte=startdate, enddate__gte=startdate) - plans2 = TrainingPlan.objects.filter( - enddate__lte=enddate, startdate__lte=enddate) - plans = plans | plans2 + plans = TrainingPlan.objects.filter(rowers__in=[rower]) + #plans2 = TrainingPlan.objects.filter( + # enddate__lte=enddate, startdate__lte=enddate, rowers__in=[rower]) + #plans = plans | plans2 - plans = plans.exclude(status=False).order_by("-enddate") + #plans = plans.exclude(status=False).order_by("-enddate") if not plans: # make week cycles here # get monday before startdate - startdate += timedelta(days=1-startdate.isoweekday()) - startdate = startdate-timedelta(days=7) + micros = [] - while startdate <= enddate: - micro = type('micros', (object,), - { - 'startdate': startdate, - 'enddate': startdate+timedelta(days=7) - }) - micros.append(micro) - startdate += timedelta(days=7) else: - plan = plans[0] + sorted_plans = sorted(plans, key= lambda t: t.overlap(startdate,enddate)) + plan = plans.reverse()[0] macros = TrainingMacroCycle.objects.filter( plan=plan).order_by("startdate") checkscores(rower, macros) @@ -238,11 +228,26 @@ def get_execution_report(rower, startdate, enddate, plan=None): startdate__lte=enddate, ).order_by("startdate") + if len(micros)==0: + startdate += timedelta(days=1-startdate.isoweekday()) + startdate = startdate-timedelta(days=7) + micros = [] + while startdate <= enddate: + micro = type('micros', (object,), + { + 'startdate': startdate, + 'enddate': startdate+timedelta(days=7) + }) + micros.append(micro) + startdate += timedelta(days=7) + + # we've got micros, now get sessions startdates = [] planned = [] executed = [] + for mm in micros: plannedscore = 0 actualscore = 0 @@ -372,8 +377,6 @@ def get_todays_micro(plan, thedate=timezone.now()): if thismicro: thismicro = thismicro[0] else: # pragma: no cover - mms = TrainingMicroCycle.objects.all() - return None return thismicro @@ -421,17 +424,14 @@ def add_workouts_plannedsession(ws, ps, r): coursecompleted=False, ) record.save() - job = myqueue(queue, handle_check_race_course, w.csvfilename, - w.id, ps.course.id, record.id, - w.user.user.email, w.user.user.first_name, - mode='coursetest') + _ = myqueue(queue, handle_check_race_course, w.csvfilename, + w.id, ps.course.id, record.id, + w.user.user.email, w.user.user.first_name, + mode='coursetest') if ps.sessiontype == 'fastest_distance': # pragma: no cover records = CourseTestResult.objects.filter( userid=w.user.id, plannedsession=ps) for record in records: - #w1 = Workout.objects.get(id=record.workoutid) - #w1.plannedsession = None - # w1.save() record.delete() df = dataprep.getsmallrowdata_db( @@ -463,9 +463,6 @@ def add_workouts_plannedsession(ws, ps, r): records = CourseTestResult.objects.filter( userid=w.user.id, plannedsession=ps) for record in records: - #w1 = Workout.objects.get(id=record.workoutid) - #w1.plannedsession = None - # w1.save() record.delete() df = dataprep.getsmallrowdata_db( @@ -638,7 +635,7 @@ def is_session_complete_ws(ws, ps): value *= 1000. cratiomin = 1 - cratiomax = 1 + # cratiomax = 1 cratios = { 'better than nothing': 0, @@ -651,12 +648,12 @@ def is_session_complete_ws(ws, ps): if ps.criterium == 'none': if ps.sessiontype == 'session': cratiomin = 0.8 - cratiomax = 1.2 + # cratiomax = 1.2 else: cratios['on target'] = 0.9167 cratios['over target'] = 1.0833 cratiomin = 0.9167 - cratiomax = 1.0833 + # cratiomax = 1.0833 score = 0 completiondate = None @@ -790,10 +787,10 @@ def is_session_complete_ws(ws, ps): coursecompleted=False, ) record.save() - job = myqueue(queue, handle_check_race_course, ws[0].csvfilename, - ws[0].id, ps.course.id, record.id, - ws[0].user.user.email, ws[0].user.user.first_name, - mode='coursetest') + _ = myqueue(queue, handle_check_race_course, ws[0].csvfilename, + ws[0].id, ps.course.id, record.id, + ws[0].user.user.email, ws[0].user.user.first_name, + mode='coursetest') return (0, 'not done', None) @@ -804,8 +801,6 @@ def is_session_complete_ws(ws, ps): def is_session_complete(r, ps): - verdict = 'not done' - if r not in ps.rower.all(): # pragma: no cover return 0, 'not assigned', None @@ -1061,7 +1056,6 @@ def get_workouts_session(r, ps): return ws - def create_sessions_from_json(plansteps, rower, startdate, manager): trainingdays = plansteps['trainingDays'] planstartdate = startdate @@ -1290,7 +1284,7 @@ def race_can_submit(r, race): if timezone.now() > startdatetime and timezone.now() < evaluation_closure: is_complete, has_registered = race_rower_status(r, race) - if is_complete == False: + if is_complete is False: return True else: return True @@ -1311,7 +1305,7 @@ def race_can_editentry(r, race): if timezone.now() < evaluation_closure: is_complete, has_registered = race_rower_status(r, race) - if is_complete == False: + if is_complete is False: return True else: # pragma: no cover return False @@ -1594,7 +1588,6 @@ def add_workout_fastestrace(ws, race, r, recordid=0, doregister=False): errors.append('For tests, you can only attach one workout') return result, comments, errors, 0 - username = r.user.first_name+' '+r.user.last_name if r.birthdate: age = calculate_age(r.birthdate) else: # pragma: no cover @@ -1634,7 +1627,6 @@ def add_workout_fastestrace(ws, race, r, recordid=0, doregister=False): records = IndoorVirtualRaceResult.objects.filter( userid=r.id, race=race, - #workoutid = ws[0].id ) if ws[0].workouttype != record.boatclass: # pragma: no cover @@ -1767,7 +1759,6 @@ def add_workout_indoorrace(ws, race, r, recordid=0, doregister=False): errors.append('For tests, you can only attach one workout') return result, comments, errors, 0 - username = r.user.first_name+' '+r.user.last_name if r.birthdate: age = calculate_age(r.birthdate) else: # pragma: no cover @@ -1915,7 +1906,6 @@ def add_workout_race(ws, race, r, splitsecond=0, recordid=0, doregister=False): errors.append('For tests, you can only attach one workout') return result, comments, errors, 0 - username = r.user.first_name+' '+r.user.last_name if r.birthdate: age = calculate_age(r.birthdate) else: # pragma: no cover @@ -1971,8 +1961,6 @@ def add_workout_race(ws, race, r, splitsecond=0, recordid=0, doregister=False): if ws[0].workouttype != record.boatclass: # pragma: no cover ws[0].workouttype = record.boatclass ws[0].save() - #errors.append('Your workout boat class is different than on your race registration') - # return 0,comments,errors,0 if ws[0].boattype != record.boattype: # pragma: no cover errors.append( diff --git a/rowers/plots.py b/rowers/plots.py index 6d4934bc..ad002f55 100644 --- a/rowers/plots.py +++ b/rowers/plots.py @@ -76,8 +76,8 @@ def mkplot(row, title): ax1.set_title(title) plt.grid(True) majorFormatter = FuncFormatter(format_pace_tick) - majorLocator = (5) - timeTickFormatter = NullFormatter() + # majorLocator = (5) + # timeTickFormatter = NullFormatter() ax1.yaxis.set_major_formatter(majorFormatter) @@ -88,7 +88,7 @@ def mkplot(row, title): ax2.plot(t, hr, 'r-') ax2.set_ylabel('Heart Rate', color='r') majorTimeFormatter = FuncFormatter(format_time_tick) - majorLocator = (15*60) + # majorLocator = (15*60) ax2.xaxis.set_major_formatter(majorTimeFormatter) ax2.patch.set_alpha(0.0) for tl in ax2.get_yticklabels(): diff --git a/rowers/polarstuff.py b/rowers/polarstuff.py index 30a865fe..79073f93 100644 --- a/rowers/polarstuff.py +++ b/rowers/polarstuff.py @@ -57,8 +57,6 @@ queuehigh = django_rq.get_queue('high') # Project # from .models import Profile - -#baseurl = 'https://polaraccesslink.com/v3-example' baseurl = 'https://polaraccesslink.com/v3' @@ -125,7 +123,7 @@ def get_token(code): def make_authorization_url(): # pragma: no cover # Generate a random string for the state parameter # Save it for use later to prevent xsrf attacks - state = str(uuid4()) + # state = str(uuid4()) params = {"client_id": POLAR_CLIENT_ID, "response_type": "code", @@ -155,7 +153,7 @@ def revoke_access(user): # pragma: no cover def get_polar_notifications(): url = baseurl+'/notifications' - state = str(uuid4()) + # state = str(uuid4()) auth_string = '{id}:{secret}'.format( id=POLAR_CLIENT_ID, secret=POLAR_CLIENT_SECRET @@ -302,16 +300,12 @@ def get_polar_workouts(user): 'title': '', } - #session = requests.session() - #newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'} - # session.headers.update(newHeaders) - url = settings.UPLOAD_SERVICE_URL dologging('polar.log', uploadoptions) dologging('polar.log', url) - #response = session.post(url,json=uploadoptions) - job = myqueue( + + _ = myqueue( queuehigh, handle_request_post, url, @@ -381,9 +375,6 @@ def register_user(user, token): json=payload, headers=headers ) - #url = baseurl+'/users' - - #response = requests.post(url,params=params,headers=headers) if response.status_code not in [200, 201]: # pragma: no cover # dologging('polar.log',url) @@ -419,10 +410,6 @@ def get_polar_user_info(user, physical=False): # pragma: no cover 'Accept': 'application/json' } - params = { - 'user-id': r.polaruserid - } - if not physical: url = baseurl+'/users/{userid}'.format( userid=r.polaruserid @@ -478,11 +465,11 @@ def get_polar_workout(user, id, transactionid): exercise_dict = response.json() thisid = exercise_dict['id'] if thisid == id: - url = baseurl+'/users/{userid}/exercise-transactions/{transactionid}/exercises/{exerciseid}/tcx'.format( - userid=r.polaruserid, - transactionid=transactionid, - exerciseid=id - ) + url = baseurl+'/users/{userid}/exercise-transactions/{transactionid}' \ + '/exercises/{exerciseid}/tcx'.format( + userid=r.polaruserid, + transactionid=transactionid, + exerciseid=id) authorizationstring = str('Bearer ' + r.polartoken) headers2 = { 'Authorization': authorizationstring, diff --git a/rowers/rowing_workout_metrics_pb2.py b/rowers/rowing_workout_metrics_pb2.py index 93c47b37..d6422d38 100644 --- a/rowers/rowing_workout_metrics_pb2.py +++ b/rowers/rowing_workout_metrics_pb2.py @@ -19,7 +19,18 @@ DESCRIPTOR = _descriptor.FileDescriptor( package='rowing_workout_metrics', syntax='proto3', serialized_options=None, - serialized_pb=_b('\n\x1crowing-workout-metrics.proto\x12\x16rowing_workout_metrics\"p\n\x15WorkoutMetricsRequest\x12\x10\n\x08\x66ilename\x18\x01 \x01(\t\x12\x0b\n\x03sex\x18\x02 \x01(\t\x12\x0b\n\x03\x66tp\x18\x03 \x01(\x01\x12\r\n\x05hrftp\x18\x04 \x01(\x01\x12\r\n\x05hrmax\x18\x05 \x01(\x01\x12\r\n\x05hrmin\x18\x06 \x01(\x01\"p\n\x16WorkoutMetricsResponse\x12\x0b\n\x03tss\x18\x01 \x01(\x01\x12\r\n\x05normp\x18\x02 \x01(\x01\x12\r\n\x05trimp\x18\x03 \x01(\x01\x12\r\n\x05hrtss\x18\x04 \x01(\x01\x12\r\n\x05normv\x18\x05 \x01(\x01\x12\r\n\x05normw\x18\x06 \x01(\x01\x32w\n\x07Metrics\x12l\n\x0b\x43\x61lcMetrics\x12-.rowing_workout_metrics.WorkoutMetricsRequest\x1a..rowing_workout_metrics.WorkoutMetricsResponseb\x06proto3') + serialized_pb=_b('\n\x1crowing-workout-metrics.proto\x12\x16' + 'rowing_workout_metrics\"p\n\x15WorkoutMetricsRequest' + '\x12\x10\n\x08\x66ilename' + '\x18\x01 \x01(\t\x12\x0b\n\x03sex' + '\x18\x02 \x01(\t\x12\x0b\n\x03\x66tp\x18\x03 \x01' + '(\x01\x12\r\n\x05hrftp\x18\x04 \x01(\x01\x12\r\n\x05hrmax' + '\x18\x05 \x01(\x01\x12\r\n\x05hrmin\x18\x06 \x01(\x01\"p\n\x16WorkoutMetricsResponse' + '\x12\x0b\n\x03tss\x18\x01 \x01(\x01\x12\r\n\x05normp\x18\x02 \x01(\x01\x12\r\n\x05trimp' + '\x18\x03 \x01(\x01\x12\r\n\x05hrtss\x18\x04 \x01(\x01\x12\r\n\x05normv' + '\x18\x05 \x01(\x01\x12\r\n\x05normw\x18\x06 \x01(\x01\x32w\n\x07Metrics' + '\x12l\n\x0b\x43\x61lcMetrics\x12-.rowing_workout_metrics.WorkoutMetricsRequest' + '\x1a..rowing_workout_metrics.WorkoutMetricsResponseb\x06proto3') ) diff --git a/rowers/rows.py b/rowers/rows.py index b68ac1dc..623c926a 100644 --- a/rowers/rows.py +++ b/rowers/rows.py @@ -4,7 +4,7 @@ import gzip import shutil import hashlib - +from math import isinf, isnan import uuid @@ -60,7 +60,7 @@ def validate_image_extension(value): ext = os.path.splitext(value.name)[1].lower() valid_extension = ['.jpg', '.jpeg', '.png', '.gif'] - if not ext in valid_extension: # pragma: no cover + if ext not in valid_extension: # pragma: no cover raise ValidationError(u'File not supported') @@ -71,7 +71,7 @@ def validate_file_extension(value): '.CSV', '.fit', '.FIT', '.zip', '.ZIP', '.gz', '.GZ', '.xls', '.jpg', '.jpeg', '.tiff', '.png', '.gif', '.bmp'] - if not ext in valid_extensions: # pragma: no cover + if ext not in valid_extensions: # pragma: no cover raise ValidationError(u'File not supported!') @@ -79,7 +79,7 @@ def must_be_csv(value): import os ext = os.path.splitext(value.name)[1] valid_extensions = ['.csv', '.CSV'] - if not ext in valid_extensions: # pragma: no cover + if ext not in valid_extensions: # pragma: no cover raise ValidationError(u'File not supported!') @@ -87,7 +87,7 @@ def validate_kml(value): import os ext = os.path.splitext(value.name)[1] valid_extensions = ['.kml', '.KML'] - if not ext in valid_extensions: # pragma: no cover + if ext not in valid_extensions: # pragma: no cover raise ValidationError(u'File not supported!') @@ -144,8 +144,6 @@ def handle_uploaded_file(f): fname = f.name ext = fname.split('.')[-1] fname = '%s.%s' % (uuid.uuid4(), ext) - #timestr = uuid.uuid4().hex[:10]+'-'+time.strftime("%Y%m%d-%H%M%S") - #fname = timestr+'-'+fname fname2 = 'media/'+fname with open(fname2, 'wb+') as destination: for chunk in f.chunks(): diff --git a/rowers/rp3stuff.py b/rowers/rp3stuff.py index f4fffff1..9a50e0cd 100644 --- a/rowers/rp3stuff.py +++ b/rowers/rp3stuff.py @@ -6,8 +6,6 @@ from rowers.tasks import handle_rp3_async_workout from rowsandall_app.settings import ( C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, - RP3_CLIENT_ID, RP3_CLIENT_SECRET, - RP3_REDIRECT_URI, RP3_CLIENT_KEY, RP3_CLIENT_ID, RP3_CLIENT_KEY, RP3_REDIRECT_URI, RP3_CLIENT_SECRET, UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET ) @@ -29,8 +27,6 @@ queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('high') -#from async_messages import message_user,messages - oauth_data = { 'client_id': RP3_CLIENT_ID, 'client_secret': RP3_CLIENT_SECRET, @@ -64,8 +60,6 @@ def do_refresh_token(refreshtoken): # pragma: no cover def get_token(code): # pragma: no cover - client_auth = requests.auth.HTTPBasicAuth( - RP3_CLIENT_KEY, RP3_CLIENT_SECRET) post_data = { "client_id": RP3_CLIENT_KEY, "grant_type": "authorization_code", @@ -73,9 +67,6 @@ def get_token(code): # pragma: no cover "redirect_uri": RP3_REDIRECT_URI, "client_secret": RP3_CLIENT_SECRET, } - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - } response = requests.post( "https://rp3rowing-app.com/oauth/token", @@ -102,8 +93,6 @@ def make_authorization_url(request): # pragma: no cover def get_rp3_workout_list(user): - r = Rower.objects.get(user=user) - auth_token = rp3_open(user) headers = {'Authorization': 'Bearer ' + auth_token} @@ -148,13 +137,13 @@ def get_rp3_workouts(rower, do_async=True): # pragma: no cover w.uploadedtorp3 for w in Workout.objects.filter(user=rower) ]) - newids = [rp3id for rp3id in rp3ids if not rp3id in knownrp3ids] + newids = [rp3id for rp3id in rp3ids if rp3id not in knownrp3ids] for id in newids: startdatetime = workouts_list.loc[id, 'executed_at'] dologging('rp3_import.log', startdatetime) - job = myqueue( + _ = myqueue( queuehigh, handle_rp3_async_workout, rower.user.id, @@ -221,7 +210,6 @@ def get_rp3_workout_token(workout_id, auth_token, waittime=3, max_attempts=20): def get_rp3_workout_link(user, workout_id, waittime=3, max_attempts=20): # pragma: no cover - r = Rower.objects.get(user=user) auth_token = rp3_open(user) return get_rp3_workout_token(workout_id, auth_token, waittime=waittime, max_attempts=max_attempts) @@ -231,7 +219,6 @@ def get_rp3_workout(user, workout_id, startdatetime=None): # pragma: no cover url = get_rp3_workout_link(user, workout_id) filename = 'media/RP3Import_'+str(workout_id)+'.csv' - r = Rower.objects.get(user=user) auth_token = rp3_open(user) if not startdatetime: diff --git a/rowers/serializers.py b/rowers/serializers.py index 0bbd017e..cb9de92b 100644 --- a/rowers/serializers.py +++ b/rowers/serializers.py @@ -6,7 +6,7 @@ from rest_framework import serializers from rowers.models import ( Workout, Rower, FavoriteChart, VirtualRaceResult, VirtualRace, GeoCourse, StandardCollection, CourseStandard, - GeoCourse, GeoPolygon, GeoPoint, PlannedSession, + GeoPolygon, GeoPoint, PlannedSession, ) from django.core.exceptions import PermissionDenied diff --git a/rowers/sporttracksstuff.py b/rowers/sporttracksstuff.py index 71b2c460..4b4f2dd8 100644 --- a/rowers/sporttracksstuff.py +++ b/rowers/sporttracksstuff.py @@ -164,7 +164,7 @@ def createsporttracksworkoutdata(w): return 0 # adding diff, trying to see if this is valid - #t = row.df.loc[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)'] + # t = row.df.loc[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)'] t = row.df.loc[:, 'TimeStamp (sec)'].values - \ row.df.loc[:, 'TimeStamp (sec)'].iloc[0] try: @@ -293,7 +293,6 @@ def workout_sporttracks_upload(user, w, asynchron=False): # pragma: no cover message = "Uploading to SportTracks" stid = 0 # ready to upload. Hurray - r = w.user thetoken = sporttracks_open(user) @@ -311,8 +310,8 @@ def workout_sporttracks_upload(user, w, asynchron=False): # pragma: no cover url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" if asynchron: - job = myqueue(queue, handle_sporttracks_sync, - w.id, url, headers, json.dumps(data, default=default)) + _ = myqueue(queue, handle_sporttracks_sync, + w.id, url, headers, json.dumps(data, default=default)) return "Asynchronous sync", 0 response = requests.post(url, headers=headers, @@ -398,9 +397,9 @@ def add_workout_from_data(user, importid, data, strokedata, source='sporttracks' return (0, "No distance or heart rate data in the workout") try: - l = data['location'] + locs = data['location'] - res = splitstdata(l) + res = splitstdata(locs) times_location = res[0] latlong = res[1] latcoord = [] @@ -492,8 +491,6 @@ def add_workout_from_data(user, importid, data, strokedata, source='sporttracks' df.sort_values(by='TimeStamp (sec)', ascending=True) - timestr = strftime("%Y%m%d-%H%M%S") - # csvfilename ='media/Import_'+str(importid)+'.csv' csvfilename = 'media/{code}_{importid}.csv'.format( importid=importid, diff --git a/rowers/stravastuff.py b/rowers/stravastuff.py index e9312c9d..4eab0961 100644 --- a/rowers/stravastuff.py +++ b/rowers/stravastuff.py @@ -82,7 +82,7 @@ def strava_open(user): f.write('\n') token = imports_open(user, oauth_data) if user.rower.strava_owner_id == 0: # pragma: no cover - strava_owner_id = set_strava_athlete_id(user) + _ = set_strava_athlete_id(user) return token @@ -120,9 +120,6 @@ def strava_establish_push(): # pragma: no cover 'callback_url': webhooklink, 'verify_token': webhookverification, } - headers = {'user-agent': 'sanderroosendaal', - 'Accept': 'application/json', - 'Content-Type': oauth_data['content_type']} response = requests.post(url, data=post_data) @@ -160,7 +157,7 @@ def set_strava_athlete_id(user): 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): - token = imports_open(user, oauth_data) + _ = imports_open(user, oauth_data) authorizationstring = str('Bearer ' + r.stravatoken) headers = {'Authorization': authorizationstring, @@ -185,7 +182,9 @@ def get_strava_workout_list(user, limit_n=0): if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover 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): # pragma: no cover + elif ( + r.stravatokenexpirydate is None or timezone.now()+timedelta(seconds=3599) > r.stravatokenexpirydate + ): # pragma: no cover s = "Token expired. Needs to refresh." return custom_exception_handler(401, s) else: @@ -209,7 +208,7 @@ def get_strava_workout_list(user, limit_n=0): def async_get_workout(user, stravaid): try: - token = strava_open(user) + _ = strava_open(user) except NoTokenError: # pragma: no cover return 0 @@ -246,9 +245,9 @@ def createstravaworkoutdata(w, dozip=True): if datalength != 0: data.rename(columns=columndict, inplace=True) - res = data.to_csv(w.csvfilename+'.gz', - index_label='index', - compression='gzip') + _ = data.to_csv(w.csvfilename+'.gz', + index_label='index', + compression='gzip') try: row = rowingdata(csvfile=filename) except IOError: @@ -317,7 +316,7 @@ def handle_stravaexport(f2, workoutname, stravatoken, description='', def workout_strava_upload(user, w, quick=False, asynchron=True): try: - thetoken = strava_open(user) + _ = strava_open(user) except NoTokenError: # pragma: no cover return "Please connect to Strava first", 0 @@ -326,7 +325,6 @@ def workout_strava_upload(user, w, quick=False, asynchron=True): r = Rower.objects.get(user=user) res = -1 if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover - s = "Token doesn't exist. Need to authorize" raise NoTokenError("Your hovercraft is full of eels") if (is_workout_user(user, w)): @@ -340,13 +338,12 @@ def workout_strava_upload(user, w, quick=False, asynchron=True): activity_type = mytypes.stravamapping[w.workouttype] except KeyError: # pragma: no cover activity_type = 'Rowing' - job = myqueue(queue, - handle_strava_sync, - r.stravatoken, - w.id, - tcxfile, w.name, activity_type, - w.notes - ) + _ = myqueue(queue, + handle_strava_sync, + r.stravatoken, + w.id, + tcxfile, w.name, activity_type, + w.notes) dologging('strava_export_log.log', 'Exporting as {t} from {w}'.format( t=activity_type, w=w.workouttype)) return "Asynchronous sync", -1 diff --git a/rowers/tasks.py b/rowers/tasks.py index 171f2b66..7886c1e3 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -39,8 +39,6 @@ from rowingdata import rowingdata as rdata from datetime import timedelta from sqlalchemy import create_engine - -#from celery import app from rowers.celery import app from celery import shared_task @@ -53,7 +51,7 @@ from json.decoder import JSONDecodeError from pytz.exceptions import UnknownTimeZoneError from matplotlib.backends.backend_agg import FigureCanvas -#from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvas + import matplotlib.pyplot as plt from matplotlib import path @@ -86,10 +84,9 @@ from rowers import mytypes from rowers.dataprepnodjango import ( - update_strokedata, getsmallrowdata_db, updatecpdata_sql, update_c2id_sql, update_workout_field_sql, - update_agegroup_db, + update_agegroup_db, update_strokedata, add_c2_stroke_data_db, totaltime_sec_to_string, create_c2_stroke_data_db, update_empower, database_url_debug, database_url, dataprep, @@ -319,7 +316,7 @@ def handle_sporttracks_sync(workoutid, url, headers, data, debug=False, **kwargs id = int(m) - res = update_workout_field_sql( + _ = update_workout_field_sql( workoutid, 'uploadedtosporttracks', id, debug=debug) return 1 @@ -375,7 +372,7 @@ def handle_strava_sync(stravatoken, workoutid, filename, name, activity_type, de failed = True if not failed: - result = update_workout_field_sql( + _ = update_workout_field_sql( workoutid, 'uploadedtostrava', res.id, debug=debug) try: act = client.update_activity(res.id, activity_type=activity_type, @@ -426,7 +423,7 @@ def handle_c2_import_stroke_data(c2token, s = requests.get(url, headers=headers) if s.status_code == 200: strokedata = pd.DataFrame.from_dict(s.json()['data']) - result = add_c2_stroke_data_db( + _ = add_c2_stroke_data_db( strokedata, workoutid, starttimeunix, csvfilename, debug=debug, workouttype=workouttype ) @@ -443,30 +440,12 @@ def handle_c2_import_stroke_data(c2token, distance = workoutdata['distance'] c2id = workoutdata['id'] workouttype = workoutdata['type'] - verified = workoutdata['verified'] - startdatetime = iso8601.parse_date(workoutdata['date']) - weightclass = workoutdata['weight_class'] - weightcategory = 'hwt' - if weightclass == "L": - weightcategory = 'lwt' totaltime = workoutdata['time']/10. duration = totaltime_sec_to_string(totaltime) duration = datetime.datetime.strptime( duration, '%H:%M:%S.%f').time() - try: - timezone_str = workoutdata['timezone'] - except: - timezone_str = 'UTC' - - workoutdate = startdatetime.astimezone( - pytz.timezone(timezone_str) - ).strftime('%Y-%m-%d') - starttime = startdatetime.astimezone( - pytz.timezone(timezone_str) - ).strftime('%H:%M:%S') - - result = create_c2_stroke_data_db( + _ = create_c2_stroke_data_db( distance, duration, workouttype, workoutid, starttimeunix, csvfilename, debug=debug, @@ -499,11 +478,12 @@ def getagegrouprecord(age, sex='male', weightcategory='hwt', ages = df['age'] powers = df['power'] - #poly_coefficients = np.polyfit(ages,powers,6) - def fitfunc(pars, x): return np.abs(pars[0])*(1-x/max(120, pars[1]))-np.abs( - pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50, pars[5]))) + def fitfunc(pars, x): + return np.abs(pars[0])*(1-x/max(120, pars[1]))-np.abs( + pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50, pars[5]))) - def errfunc(pars, x, y): return fitfunc(pars, x)-y + def errfunc(pars, x, y): + return fitfunc(pars, x)-y p0 = [700, 120, 700, 10, 100, 100] @@ -512,15 +492,8 @@ def getagegrouprecord(age, sex='male', weightcategory='hwt', if success and age is not None: power = fitfunc(p1, float(age)) - - #power = np.polyval(poly_coefficients,age) - power = 0.5*(np.abs(power)+power) elif age is not None: # pragma: no cover - new_age = np.range([age]) - ww = griddata(ages.values, - powers.values, - new_age, method='linear', rescale=True) power = 0.5*(np.abs(power)+power) else: # pragma: no cover power = 0 @@ -530,9 +503,9 @@ def getagegrouprecord(age, sex='male', weightcategory='hwt', def polygon_to_path(polygon, debug=True): pid = polygon[0] - query = "SELECT id, latitude, longitude FROM rowers_geopoint WHERE polygon_id = {pid} ORDER BY order_in_poly ASC".format( - pid=pid - ) + query = "SELECT id, latitude, longitude FROM rowers_geopoint WHERE polygon_id = {pid}"\ + " ORDER BY order_in_poly ASC".format( + pid=pid) if debug: engine = create_engine(database_url_debug, echo=False) else: # pragma: no cover @@ -595,8 +568,6 @@ def handle_check_race_course(self, if 'successemail' in kwargs: successemail = kwargs['successemail'] - columns = ['time', ' latitude', ' longitude', 'cum_dist'] - try: row = rdata(csvfile=f1) except IOError: # pragma: no cover @@ -617,7 +588,7 @@ def handle_check_race_course(self, rowdata['cum_dist'] = rowdata['gps_dist_calculated'] try: - s = rowdata[' latitude'] + _ = rowdata[' latitude'] except KeyError: # pragma: no cover return 0 @@ -690,7 +661,6 @@ def handle_check_race_course(self, except InvalidTrajectoryError: # pragma: no cover entrytimes = [] - entrydistances = [] coursecompleted = False coursemeters = 0 coursetimeseconds = 0 @@ -742,19 +712,15 @@ def handle_check_race_course(self, 'endsecond': endseconds, }) - records = records[records['coursecompleted'] == True] + records = records[records['coursecompleted'] is True] if len(records): coursecompleted = True mintime = records['coursetimeseconds'].min() - coursetimeseconds = records[records['coursetimeseconds'] - == mintime]['coursetimeseconds'].min() - coursemeters = records[records['coursetimeseconds'] - == mintime]['coursemeters'].min() - startsecond = records[records['coursetimeseconds'] - == mintime]['startsecond'].min() - endsecond = records[records['coursetimeseconds'] - == mintime]['endsecond'].min() + coursetimeseconds = records[records['coursetimeseconds'] == mintime]['coursetimeseconds'].min() + coursemeters = records[records['coursetimeseconds'] == mintime]['coursemeters'].min() + startsecond = records[records['coursetimeseconds'] == mintime]['startsecond'].min() + endsecond = records[records['coursetimeseconds'] == mintime]['endsecond'].min() else: # pragma: no cover coursecompleted = False @@ -764,26 +730,30 @@ def handle_check_race_course(self, coursedistance = coursemeters velo = coursedistance/coursetimeseconds points = 100*(2.-referencespeed/velo) - query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( - recordid=recordid, - duration=totaltime_sec_to_string(coursetimeseconds), - distance=int(coursemeters), - points=points, - workoutid=workoutid, - startsecond=startsecond, - endsecond=endsecond, - ) + query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1,'\ + ' duration = "{duration}", distance = {distance},'\ + ' workoutid = {workoutid}, startsecond = {startsecond},'\ + ' endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( + recordid=recordid, + duration=totaltime_sec_to_string(coursetimeseconds), + distance=int(coursemeters), + points=points, + workoutid=workoutid, + startsecond=startsecond, + endsecond=endsecond,) if mode == 'coursetest': - query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( - recordid=recordid, - duration=totaltime_sec_to_string(coursetimeseconds), - distance=int(coursemeters), - points=points, - workoutid=workoutid, - startsecond=startsecond, - endsecond=endsecond, - ) + query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1,'\ + ' duration = "{duration}", distance = {distance},'\ + ' workoutid = {workoutid}, startsecond = {startsecond},'\ + ' endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( + recordid=recordid, + duration=totaltime_sec_to_string(coursetimeseconds), + distance=int(coursemeters), + points=points, + workoutid=workoutid, + startsecond=startsecond, + endsecond=endsecond,) with engine.connect() as conn, conn.begin(): result = conn.execute(query) @@ -828,26 +798,30 @@ def handle_check_race_course(self, return 1 else: # pragma: no cover - query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 0, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( - recordid=recordid, - duration=totaltime_sec_to_string(0), - distance=0, - points=0.0, - workoutid=workoutid, - startsecond=startsecond, - endsecond=endsecond, - ) + query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 0,'\ + ' duration = "{duration}", distance = {distance},'\ + ' workoutid = {workoutid}, startsecond = {startsecond},'\ + ' endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( + recordid=recordid, + duration=totaltime_sec_to_string(0), + distance=0, + points=0.0, + workoutid=workoutid, + startsecond=startsecond, + endsecond=endsecond,) if mode == 'coursetest': - query = 'UPDATE rowers_coursetestresult SET coursecompleted = 0, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( - recordid=recordid, - duration=totaltime_sec_to_string(0), - distance=0, - points=0, - workoutid=workoutid, - startsecond=startsecond, - endsecond=endsecond, - ) + query = 'UPDATE rowers_coursetestresult SET coursecompleted = 0,'\ + ' duration = "{duration}", distance = {distance}, workoutid = {workoutid}'\ + ', startsecond = {startsecond}, endsecond = {endsecond}'\ + ', points={points} WHERE id={recordid}'.format( + recordid=recordid, + duration=totaltime_sec_to_string(0), + distance=0, + points=0, + workoutid=workoutid, + startsecond=startsecond, + endsecond=endsecond,) with engine.connect() as conn, conn.begin(): result = conn.execute(query) @@ -986,24 +960,24 @@ def handle_get_garmin_file(client_id, session = requests.session() newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'} session.headers.update(newHeaders) - response = session.post(UPLOAD_SERVICE_URL, json=uploadoptions) + _ = session.post(UPLOAD_SERVICE_URL, json=uploadoptions) return 1 @app.task(bind=True) -def long_test_task(self, aantal, debug=False, job=None, session_key=None): # pragma: no cover - job = self.request +def long_test_task(self, aantal, debug=False, myjob=None, session_key=None): # pragma: no cover + myjob = self.request - return longtask.longtask(aantal, jobid=job.id, debug=debug, + return longtask.longtask(aantal, jobid=myjob.id, debug=debug, session_key=session_key) @app.task(bind=True) def long_test_task2(self, aantal, **kwargs): # pragma: no cover # debug=False,job=None,jobid='aap'): - job = self.request - job_id = job.id + myjob = self.request + job_id = myjob.id if 'jobkey' in kwargs: job_id = kwargs.pop('jobkey') @@ -1021,8 +995,8 @@ def handle_update_empower(self, workoutdicts, debug=False, **kwargs): # pragma: no cover - job = self.request - job_id = job.id + myjob = self.request + job_id = myjob.id if 'jobkey' in kwargs: job_id = kwargs.pop('jobkey') @@ -1052,10 +1026,10 @@ def handle_update_empower(self, havedata = 0 progressurl = SITE_URL - siteurl = SITE_URL + if debug: progressurl = SITE_URL_DEV - siteurl = SITE_URL_DEV + # siteurl = SITE_URL_DEV secret = PROGRESS_CACHE_SECRET kwargs['job_id'] = job_id @@ -1064,8 +1038,8 @@ def handle_update_empower(self, progressurl += job_id if havedata: - success = update_empower(wid, inboard, oarlength, boattype, - rowdata.df, f1, debug=debug) + _ = update_empower(wid, inboard, oarlength, boattype, + rowdata.df, f1, debug=debug) counter += 1 @@ -1076,8 +1050,7 @@ def handle_update_empower(self, "value": progress, } - s = requests.post(progressurl, data=post_data) - status_code = s.status_code + _ = requests.post(progressurl, data=post_data) subject = "Rowsandall.com Your Old Empower Oarlock data have been corrected" message = """ @@ -1094,7 +1067,7 @@ We have updated Power and Work per Stroke data according to the instructions by emailbounced = False if not emailbounced: - res = email.send() + _ = email.send() return 1 @@ -1199,18 +1172,19 @@ def handle_calctrimp(id, if hrtss > 1000: # pragma: no cover hrtss = 0 - query = 'UPDATE rowers_workout SET rscore = {tss}, normp = {normp}, trimp={trimp}, hrtss={hrtss}, normv={normv}, normw={normw} WHERE id={id}'.format( - tss=int(tss), - normp=int(normp), - trimp=int(trimp), - hrtss=int(hrtss), - normv=normv, - normw=normw, - id=id, - ) + query = 'UPDATE rowers_workout SET rscore = {tss},'\ + ' normp = {normp}, trimp={trimp}, hrtss={hrtss},'\ + ' normv={normv}, normw={normw} WHERE id={id}'.format( + tss=int(tss), + normp=int(normp), + trimp=int(trimp), + hrtss=int(hrtss), + normv=normv, + normw=normw, + id=id,) with engine.connect() as conn, conn.begin(): - result = conn.execute(query) + _ = conn.execute(query) conn.close() engine.dispose() @@ -1248,7 +1222,7 @@ def handle_updatedps(useremail, workoutids, debug=False, **kwargs): emailbounced = False if not emailbounced: - res = email.send() + _ = email.send() return 1 @@ -1275,11 +1249,6 @@ def sigdig(value, digits=3): def handle_send_email_alert( useremail, userfirstname, userlastname, rowerfirstname, alertname, stats, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = False - if 'othertexts' in kwargs: # pragma: no cover othertexts = kwargs['othertexts'] else: @@ -1334,9 +1303,9 @@ def handle_send_email_alert( 'othertexts': othertexts, } - res = send_template_email(from_email, [useremail], subject, - 'alertemail.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], subject, + 'alertemail.html', + d, **kwargs) return 1 @@ -1345,11 +1314,6 @@ def handle_send_email_alert( def handle_send_email_transaction( username, useremail, amount, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "Rowsandall Payment Confirmation" from_email = 'Rowsandall ' @@ -1360,10 +1324,10 @@ def handle_send_email_transaction( 'amount': amount, } - res = send_template_email(from_email, [useremail], - subject, - 'paymentconfirmationemail.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'paymentconfirmationemail.html', + d, **kwargs) return 1 @@ -1373,11 +1337,6 @@ def handle_send_email_instantplan_notification( username, useremail, amount, planname, startdate, enddate, **kwargs ): # pragma: no cover - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "Rowsandall Instant Plan Notification" from_email = 'Rowsandall ' @@ -1391,10 +1350,10 @@ def handle_send_email_instantplan_notification( 'enddate': enddate, } - res = send_template_email(from_email, ['roosendaalsander@gmail.com'], - subject, - 'instantplansold.html', - d, **kwargs) + _ = send_template_email(from_email, ['roosendaalsander@gmail.com'], + subject, + 'instantplansold.html', + d, **kwargs) return 1 @@ -1403,11 +1362,6 @@ def handle_send_email_instantplan_notification( def handle_send_email_failed_cancel( name, email, username, id, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "Rowsandall Subscription Cancellation Error" from_email = 'Rowsandall ' @@ -1420,10 +1374,10 @@ def handle_send_email_failed_cancel( 'id': id, } - res = send_template_email(from_email, ["support@rowsandall.com"], - subject, - 'cancel_subscription_fail_email.html', - d, **kwargs) + _ = send_template_email(from_email, ["support@rowsandall.com"], + subject, + 'cancel_subscription_fail_email.html', + d, **kwargs) return 1 @@ -1433,11 +1387,6 @@ def handle_send_email_subscription_update( username, useremail, planname, recurring, price, amount, end_of_billing_period, method, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - from_email = 'Rowsandall ' d = { @@ -1459,15 +1408,15 @@ def handle_send_email_subscription_update( notification_template_name = 'subscription_update_notification.html' subject = "Rowsandall Payment Confirmation" - res = send_template_email(from_email, [useremail], - subject, - template_name, - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + template_name, + d, **kwargs) - res = send_template_email(from_email, ['info@rowsandall.com'], - 'Subscription Update Notification', - notification_template_name, - d, **kwargs) + _ = send_template_email(from_email, ['info@rowsandall.com'], + 'Subscription Update Notification', + notification_template_name, + d, **kwargs) return 1 @@ -1477,11 +1426,6 @@ def handle_send_email_subscription_create( username, useremail, planname, recurring, price, amount, end_of_billing_period, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "Rowsandall Payment Confirmation" from_email = 'Rowsandall ' @@ -1496,15 +1440,15 @@ def handle_send_email_subscription_create( 'recurring': recurring, } - res = send_template_email(from_email, [useremail], - subject, - 'subscription_create_email.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'subscription_create_email.html', + d, **kwargs) - res = send_template_email(from_email, ['info@rowsandall.com'], - 'Subscription Update Notification', - 'subscription_create_notification.html', - d, **kwargs) + _ = send_template_email(from_email, ['info@rowsandall.com'], + 'Subscription Update Notification', + 'subscription_create_notification.html', + d, **kwargs) return 1 @@ -1512,11 +1456,6 @@ def handle_send_email_subscription_create( def handle_sendemail_raceregistration( useremail, username, registeredname, racename, raceid, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "A new competitor has registered for virtual challenge {n}".format( n=racename ) @@ -1531,21 +1470,15 @@ def handle_sendemail_raceregistration( 'raceid': raceid, } - res = send_template_email(from_email, [useremail], - subject, - 'raceregisteredemail.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'raceregisteredemail.html', + d, **kwargs) return 1 -def handle_sendemail_coursesucceed( - useremail, username, logfile, workoutid, **kwargs -): # pragma: no cover - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True +def handle_sendemail_coursesucceed(useremail, username, logfile, workoutid, **kwargs): # pragma: no cover subject = "The validation of your course has succeeded" @@ -1556,12 +1489,12 @@ def handle_sendemail_coursesucceed( 'workoutid': encoder.encode_hex(workoutid), } - res = send_template_email(from_email, [useremail], - subject, - 'trajectorysuccessemail.html', - d, - attach_file=logfile, - **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'trajectorysuccessemail.html', + d, + attach_file=logfile, + **kwargs) return 1 @@ -1569,11 +1502,6 @@ def handle_sendemail_coursesucceed( def handle_sendemail_coursefail( useremail, username, logfile, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "The validation of your course has failed" from_email = 'Rowsandall ' @@ -1582,13 +1510,13 @@ def handle_sendemail_coursefail( 'username': username, } - res = send_template_email(from_email, [useremail], - subject, - 'trajectoryfailemail.html', - d, - cc=['info@rowsandall.com'], - attach_file=logfile, - **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'trajectoryfailemail.html', + d, + cc=['info@rowsandall.com'], + attach_file=logfile, + **kwargs) return 1 @@ -1597,11 +1525,6 @@ def handle_sendemail_coursefail( def handle_sendemail_optout( useremail, username, registeredname, racename, raceid, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "{name} has opted out from social media posts around challenge {n}".format( n=racename, name=registeredname @@ -1617,10 +1540,10 @@ def handle_sendemail_optout( 'raceid': raceid, } - res = send_template_email(from_email, [useremail], - subject, - 'raceoptoutsocialmedia.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'raceoptoutsocialmedia.html', + d, **kwargs) return 1 @@ -1629,11 +1552,6 @@ def handle_sendemail_optout( def handle_sendemail_racesubmission( useremail, username, registeredname, racename, raceid, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "A new result has been submitted for virtual challenge {n}".format( n=racename ) @@ -1648,10 +1566,10 @@ def handle_sendemail_racesubmission( 'raceid': raceid, } - res = send_template_email(from_email, [useremail], - subject, - 'racesubmissionemail.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'racesubmissionemail.html', + d, **kwargs) return 1 @@ -1660,11 +1578,6 @@ def handle_sendemail_racesubmission( def handle_send_disqualification_email( useremail, username, reason, message, racename, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "Your result for {n} has been disqualified on rowsandall.com".format( n=racename ) @@ -1679,10 +1592,10 @@ def handle_send_disqualification_email( 'racename': racename, } - res = send_template_email(from_email, [useremail], - subject, - 'disqualificationemail.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'disqualificationemail.html', + d, **kwargs) return 1 @@ -1691,11 +1604,6 @@ def handle_send_disqualification_email( def handle_send_withdraw_email( useremail, username, reason, message, racename, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = True - subject = "Your result for {n} has been removed on rowsandall.com".format( n=racename ) @@ -1710,10 +1618,10 @@ def handle_send_withdraw_email( 'racename': racename, } - res = send_template_email(from_email, [useremail], - subject, - 'withdraw_email.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, + 'withdraw_email.html', + d, **kwargs) return 1 @@ -1721,11 +1629,6 @@ def handle_send_withdraw_email( @app.task def handle_sendemail_expired(useremail, userfirstname, userlastname, expireddate, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = False - subject = "Your rowsandall.com paid account has expired" from_email = 'Rowsandall ' @@ -1736,9 +1639,9 @@ def handle_sendemail_expired(useremail, userfirstname, userlastname, expireddate 'expireddate': expireddate, } - res = send_template_email(from_email, [useremail], - subject, 'accountexpiredemail.html', - d, cc=['support@rowsandall.com'], **kwargs) + _ = send_template_email(from_email, [useremail], + subject, 'accountexpiredemail.html', + d, cc=['support@rowsandall.com'], **kwargs) return 1 @@ -1748,11 +1651,6 @@ def handle_sendemail_breakthrough(workoutid, useremail, btvalues=pd.DataFrame().to_json(), **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = False - btvalues = pd.read_json(btvalues) btvalues.sort_values('delta', axis=0, inplace=True) @@ -1774,9 +1672,9 @@ def handle_sendemail_breakthrough(workoutid, useremail, 'btvalues': tablevalues, } - res = send_template_email(from_email, [useremail], - subject, 'breakthroughemail.html', - d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, 'breakthroughemail.html', + d, **kwargs) return 1 @@ -1789,11 +1687,6 @@ def handle_sendemail_hard(workoutid, useremail, btvalues=pd.DataFrame().to_json(), debug=False, **kwargs): - if 'debug' in kwargs: # pragma: no cover - debug = kwargs['debug'] - else: - debug = False - btvalues = pd.read_json(btvalues) btvalues.sort_values('delta', axis=0, inplace=True) @@ -1815,8 +1708,8 @@ def handle_sendemail_hard(workoutid, useremail, 'btvalues': tablevalues, } - res = send_template_email(from_email, [useremail], - subject, 'hardemail.html', d, **kwargs) + _ = send_template_email(from_email, [useremail], + subject, 'hardemail.html', d, **kwargs) return 1 @@ -1841,7 +1734,7 @@ def handle_sendemail_userdeleted(name, email, debug=False, **kwargs): emailbounced = False if not emailbounced: - res = email.send() + _ = email.send() return 1 @@ -1856,7 +1749,8 @@ def handle_sendemail_unrecognized(unrecognizedfile, useremail, fullemail = 'roosendaalsander@gmail.com' subject = "Unrecognized file from Rowsandall.com" message = "Dear Sander,\n\n" - message += "Please find attached a file that someone tried to upload to rowsandall.com. The file was not recognized as a valid file type.\n\n" + message += "Please find attached a file that someone tried to upload to rowsandall.com." + message += " The file was not recognized as a valid file type.\n\n" message += "User Email " + useremail + "\n\n" message += "Best Regards, the Rowsandall Team" @@ -1875,7 +1769,7 @@ def handle_sendemail_unrecognized(unrecognizedfile, useremail, emailbounced = False if not emailbounced: - res = email.send() + _ = email.send() # remove tcx file try: @@ -1902,9 +1796,9 @@ def handle_sendemail_unrecognizedowner(useremail, userfirstname, from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'unrecognizedemail.html', d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'unrecognizedemail.html', d, + **kwargs) return 1 @@ -1921,9 +1815,9 @@ def handle_sendemailics(first_name, last_name, email, icsfile, **kwargs): from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'icsemail.html', d, - attach_file=icsfile, **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'icsemail.html', d, + attach_file=icsfile, **kwargs) os.remove(icsfile) return 1 @@ -1942,9 +1836,9 @@ def handle_sendemailkml(first_name, last_name, email, kmlfile, **kwargs): from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'kmlemail.html', d, - attach_file=kmlfile, **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'kmlemail.html', d, + attach_file=kmlfile, **kwargs) os.remove(kmlfile) return 1 @@ -1965,9 +1859,9 @@ def handle_sendemailtcx(first_name, last_name, email, tcxfile, **kwargs): from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'tcxemail.html', d, - attach_file=tcxfile, **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'tcxemail.html', d, + attach_file=tcxfile, **kwargs) os.remove(tcxfile) return 1 @@ -1991,7 +1885,7 @@ def handle_zip_file(emailfrom, subject, file, **kwargs): # pragma: no cover if debug: print("attaching") - res = email.send() + _ = email.send() if debug: print("sent") @@ -2012,10 +1906,10 @@ def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs): from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'summarymail.html', d, - attach_file=csvfile, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'summarymail.html', d, + attach_file=csvfile, + **kwargs) try: os.remove(csvfile) @@ -2024,8 +1918,6 @@ def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs): return 1 -#from rowers.emails import sendemail - @app.task def handle_sendemailcsv(first_name, last_name, email, csvfile, **kwargs): @@ -2040,9 +1932,9 @@ def handle_sendemailcsv(first_name, last_name, email, csvfile, **kwargs): from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'csvemail.html', d, - attach_file=csvfile, **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'csvemail.html', d, + attach_file=csvfile, **kwargs) return 1 @@ -2060,7 +1952,7 @@ def handle_sendemail_ical(first_name, last_name, email, url, icsfile, **kwargs): siteurl = SITE_URL if debug: # pragma: no cover - progressurl = SITE_URL_DEV + # progressurl = SITE_URL_DEV siteurl = SITE_URL_DEV d = {'first_name': first_name, @@ -2070,12 +1962,12 @@ def handle_sendemail_ical(first_name, last_name, email, url, icsfile, **kwargs): from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'icsemail.html', d, - attach_file=icsfile, **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'icsemail.html', d, + attach_file=icsfile, **kwargs) try: - os.remove(csvfile) + os.remove(icsfile) except: pass @@ -2095,9 +1987,9 @@ def handle_sendemailfile(first_name, last_name, email, csvfile, **kwargs): from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'fileemail.html', d, - attach_file=csvfile, **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'fileemail.html', d, + attach_file=csvfile, **kwargs) if 'delete' in kwargs: # pragma: no cover dodelete = kwargs['delete'] @@ -2120,8 +2012,8 @@ def handle_otwsetpower(self, f1, boattype, boatclass, coastalbrand, weightvalue, first_name, last_name, email, workoutid, **kwargs): - job = self.request - job_id = job.id + myjob = self.request + job_id = myjob.id if 'jobkey' in kwargs: job_id = kwargs.pop('jobkey') @@ -2237,7 +2129,6 @@ def handle_otwsetpower(self, f1, boattype, boatclass, coastalbrand, weightvalue, dfgrouped = df.groupby(['workoutid']) delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr) - #delta,cpvalues,avgpower = datautils.getsinglecp(rowdata.df) res, btvalues, res2 = utils.isbreakthrough( delta, cpvalues, ps[0], ps[1], ps[2], ps[3], ratio) if res: # pragma: no cover @@ -2256,9 +2147,9 @@ def handle_otwsetpower(self, f1, boattype, boatclass, coastalbrand, weightvalue, 'workoutid': encoder.encode_hex(workoutid), } - res = send_template_email(from_email, [fullemail], - subject, 'otwpoweremail.html', d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'otwpoweremail.html', d, + **kwargs) return 1 @@ -2418,11 +2309,11 @@ def handle_sendemail_coachrequest(email, name, code, coachname, 'siteurl': siteurl } - form_email = 'Rowsandall ' + from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'coachrequestemail.html', d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'coachrequestemail.html', d, + **kwargs) return 1 @@ -2445,10 +2336,10 @@ def handle_sendemail_coachoffer_rejected(coachemail, coachname, name, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], - subject, 'coachofferrejectedemail.html', - d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'coachofferrejectedemail.html', + d, + **kwargs) return 1 @@ -2470,10 +2361,10 @@ def handle_sendemail_coachrequest_rejected(email, coachname, name, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], - subject, 'coachrequestrejectedemail.html', - d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'coachrequestrejectedemail.html', + d, + **kwargs) return 1 @@ -2495,10 +2386,10 @@ def handle_sendemail_coachrequest_accepted(email, coachname, name, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], - subject, 'coachrequestacceptedemail.html', - d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'coachrequestacceptedemail.html', + d, + **kwargs) return 1 @@ -2520,10 +2411,10 @@ def handle_sendemail_coachoffer_accepted(coachemail, coachname, name, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], - subject, 'coachofferacceptedemail.html', - d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'coachofferacceptedemail.html', + d, + **kwargs) return 1 @@ -2546,9 +2437,9 @@ def handle_sendemail_coacheerequest(email, name, code, coachname, 'siteurl': siteurl } - res = send_template_email(from_email, [fullemail], - subject, 'coacheerequestemail.html', d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'coacheerequestemail.html', d, + **kwargs) return 1 @@ -2573,9 +2464,9 @@ def handle_sendemail_invite(email, name, code, teamname, manager, from_email = 'Rowsandall ' - res = send_template_email(from_email, [fullemail], - subject, 'teaminviteemail.html', d, - **kwargs) + _ = send_template_email(from_email, [fullemail], + subject, 'teaminviteemail.html', d, + **kwargs) return 1 @@ -2620,9 +2511,9 @@ def handle_sendemailnewresponse(first_name, last_name, 'commentlink': commentlink, } - res = send_template_email(from_email, - [fullemail], - subject, 'teamresponseemail.html', d, **kwargs) + _ = send_template_email(from_email, + [fullemail], + subject, 'teamresponseemail.html', d, **kwargs) return 1 @@ -2668,8 +2559,8 @@ def handle_sendemailnewcomment(first_name, 'commentlink': commentlink, } - res = send_template_email(from_email, [fullemail], subject, - 'teamresponseemail.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teamresponseemail.html', d, **kwargs) return 1 @@ -2684,9 +2575,9 @@ def handle_send_template_email(template, email, fromemail, rowername, 'rowername': rowername, } - res = send_template_email('Rowsandall ', - ['info@rowsandall.com'], subject, - template, d, cc=[fromemail], bcc=fullemail, **kwargs) + _ = send_template_email('Rowsandall ', + ['info@rowsandall.com'], subject, + template, d, cc=[fromemail], bcc=fullemail, **kwargs) return 1 @@ -2706,8 +2597,8 @@ def handle_sendemail_message(email, fromemail, rowername, message, teamname, man 'message': message, } - res = send_template_email(from_email, [fullemail], subject, - 'teammessage.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teammessage.html', d, **kwargs) return 1 @@ -2732,8 +2623,8 @@ def handle_sendemail_request(email, name, code, teamname, requestor, id, 'first_name': name, } - res = send_template_email(from_email, [fullemail], subject, - 'teamrequestemail.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teamrequestemail.html', d, **kwargs) return 1 @@ -2755,8 +2646,8 @@ def handle_sendemail_request_accept(email, name, teamname, managername, 'teamname': teamname, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], subject, - 'teamwelcomeemail.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teamwelcomeemail.html', d, **kwargs) return 1 @@ -2778,8 +2669,8 @@ def handle_sendemail_request_reject(email, name, teamname, managername, 'teamname': teamname, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], subject, - 'teamrejectemail.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teamrejectemail.html', d, **kwargs) return 1 @@ -2801,8 +2692,8 @@ def handle_sendemail_member_dropped(email, name, teamname, managername, 'teamname': teamname, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], subject, - 'teamdropemail.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teamdropemail.html', d, **kwargs) return 1 @@ -2825,8 +2716,8 @@ def handle_sendemail_team_removed(email, name, teamname, managername, 'teamname': teamname, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], subject, - 'teamremoveemail.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teamremoveemail.html', d, **kwargs) return 1 @@ -2849,8 +2740,8 @@ def handle_sendemail_invite_reject(email, name, teamname, managername, 'teamname': teamname, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], subject, - 'teaminviterejectemail.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teaminviterejectemail.html', d, **kwargs) return 1 @@ -2911,8 +2802,8 @@ def handle_sendemail_invite_accept(email, name, teamname, managername, 'teamname': teamname, 'siteurl': siteurl, } - res = send_template_email(from_email, [fullemail], subject, - 'teaminviteacceptemail.html', d, **kwargs) + _ = send_template_email(from_email, [fullemail], subject, + 'teaminviteacceptemail.html', d, **kwargs) return 1 @@ -2950,7 +2841,7 @@ def handle_update_wps(rid, types, ids, mode, debug=False, **kwargs): engine = create_engine(database_url, echo=False) with engine.connect() as conn, conn.begin(): - result = conn.execute(query) + _ = conn.execute(query) conn.close() engine.dispose() @@ -2963,17 +2854,17 @@ def handle_rp3_async_workout(userid, rp3token, rp3id, startdatetime, max_attempt headers = {'Authorization': 'Bearer ' + rp3token} get_download_link = """{ - download(workout_id: """ + str(rp3id) + """, type:csv){ - id - status - link - } + download(workout_id: """ + str(rp3id) + """, type:csv){ + id + status + link + } }""" have_link = False download_url = '' counter = 0 - #max_attempts = 20 + waittime = 3 while not have_link: response = requests.post( @@ -3092,10 +2983,6 @@ def handle_nk_async_workout(alldata, userid, nktoken, nkid, delaysec, defaulttim df = strokeDataToDf(strokeData) - # get workout data - timestampbegin = df['timestamp'].min() - timestampend = df['timestamp'].max() - csvfilename = 'media/{code}_{nkid}.csv.gz'.format( nkid=nkid, code=uuid4().hex[:16] @@ -3158,17 +3045,16 @@ def handle_c2_getworkout(userid, c2token, c2id, defaulttimezone, debug=False, ** data = s.json()['data'] alldata = {c2id: data} - splitdata = None return handle_c2_async_workout(alldata, userid, c2token, c2id, 0, defaulttimezone) def df_from_summary(data): - distance = data['distance'] - c2id = data['id'] - workouttype = data['type'] - verified = data['verified'] - weightclass = data['weight_class'] + # distance = data['distance'] + # c2id = data['id'] + # workouttype = data['type'] + # verified = data['verified'] + # weightclass = data['weight_class'] try: title = data['name'] except KeyError: # pragma: no cover @@ -3179,10 +3065,6 @@ def df_from_summary(data): except: # pragma: no cover title = '' - weightcategory = 'hwt' - if weightclass == "L": - weightcategory = 'lwt' - startdatetime, starttime, workoutdate, duration, starttimeunix, timezone = utils.get_startdatetime_from_c2data( data) @@ -3238,25 +3120,23 @@ def df_from_summary(data): @app.task def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttimezone, debug=False, **kwargs): time.sleep(delaysec) - with open("c2_auto_import.log", "a") as errorlog: - timestr = time.strftime("%Y%m%d-%H%M%S") - errorlog.write(timestr+' '+str(c2id)+' for userid '+str(userid)+'\r\n') + dologging('c2_import.log',str(c2id)+' for userid '+str(userid)) data = alldata[c2id] splitdata = None distance = data['distance'] try: # pragma: no cover rest_distance = data['rest_distance'] - rest_time = data['rest_time']/10. + # rest_time = data['rest_time']/10. except KeyError: rest_distance = 0 - rest_time = 0 + # rest_time = 0 distance = distance+rest_distance c2id = data['id'] workouttype = data['type'] - verified = data['verified'] + # verified = data['verified'] - weightclass = data['weight_class'] + # weightclass = data['weight_class'] try: has_strokedata = data['stroke_data'] @@ -3264,8 +3144,8 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim has_strokedata = True s = 'User {userid}, C2 ID {c2id}'.format(userid=userid, c2id=c2id) - dologging('debuglog.log', s) - dologging('debuglog.log', json.dumps(data)) + dologging('c2_import.log', s) + dologging('c2_import.log', json.dumps(data)) try: title = data['name'] @@ -3277,29 +3157,17 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim except: # pragma: no cover title = '' - weightcategory = 'hwt' - if weightclass == "L": - weightcategory = 'lwt' - # Create CSV file name and save data to CSV file - csvfilename = 'media/{code}_{c2id}.csv'.format( + csvfilename = 'media/{code}_{c2id}.csv.gz'.format( code=uuid4().hex[:16], c2id=c2id) - + startdatetime, starttime, workoutdate, duration, starttimeunix, timezone = utils.get_startdatetime_from_c2data( data) s = 'Time zone {timezone}, startdatetime {startdatetime}, duration {duration}'.format( timezone=timezone, startdatetime=startdatetime, duration=duration) - dologging('debuglog.log', s) - - try: - notes = data['comments'] - name = notes[:40] - except (KeyError, TypeError): # pragma: no cover - notes = 'C2 Import Workout from {startdatetime}'.format( - startdatetime=startdatetime) - name = notes + dologging('c2_import.log', s) authorizationstring = str('Bearer ' + c2token) headers = {'Authorization': authorizationstring, @@ -3312,9 +3180,9 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim return 0 if s.status_code != 200: # pragma: no cover - dologging('debuglog.log', 'No Stroke Data. Status Code {code}'.format( + dologging('c2_import.log', 'No Stroke Data. Status Code {code}'.format( code=s.status_code)) - dologging('debuglog.log', s.text) + dologging('c2_import.log', s.text) has_strokedata = False if not has_strokedata: # pragma: no cover @@ -3324,7 +3192,7 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim try: strokedata = pd.DataFrame.from_dict(s.json()['data']) except AttributeError: # pragma: no cover - dologging('debuglog.log', 'No stroke data in stroke data') + dologging('c2_import.log', 'No stroke data in stroke data') return 0 try: @@ -3332,7 +3200,7 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim cum_time = res[0] lapidx = res[1] except KeyError: # pragma: no cover - dologging('debuglog.log', 'No time values in stroke data') + dologging('c2_import.log', 'No time values in stroke data') return 0 unixtime = cum_time+starttimeunix @@ -3374,7 +3242,7 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim if workouttype == 'bike': # pragma: no cover velo = 1000./pace - dologging('debuglog.log', 'Unix Time Stamp {s}'.format(s=unixtime[0])) + dologging('c2_import.log', 'Unix Time Stamp {s}'.format(s=unixtime[0])) # dologging('debuglog.log',json.dumps(s.json())) df = pd.DataFrame({'TimeStamp (sec)': unixtime, @@ -3400,9 +3268,8 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim df.sort_values(by='TimeStamp (sec)', ascending=True) - res = df.to_csv(csvfilename, index_label='index', - compression='gzip' - ) + _ = df.to_csv(csvfilename, index_label='index', compression='gzip') + uploadoptions = { 'secret': UPLOAD_SERVICE_SECRET, @@ -3423,6 +3290,9 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim response = session.post(UPLOAD_SERVICE_URL, json=uploadoptions) if response.status_code != 200: # pragma: no cover + dologging('c2_import.log', + 'Upload API returned status code {code}'.format( + code=response.status_code)) return 0 workoutid = response.json()['id'] @@ -3500,18 +3370,16 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim rowdata = rdata(csvfile=csvfilename) if rowdata: - rowdata.updateintervaldata(values, - units, types, results) + rowdata.updateintervaldata(values, units, types, results) rowdata.write_csv(csvfilename, gzip=True) - dataprepnodjango.update_strokedata(w.id, rowdata.df) + update_strokedata(workoutid, rowdata.df) return workoutid @app.task def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid, debug=False, **kwargs): - fetchresolution = 'high' authorizationstring = str('Bearer '+stravatoken) headers = {'Authorization': authorizationstring, 'user-agent': 'sanderroosendaal', @@ -3546,11 +3414,6 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid, except: # pragma: no cover return 0 - try: - startdatetime = workoutsummary['start_date'] - except KeyError: # pragma: no cover - startdatetime = timezone.now() - spm = get_strava_stream(None, 'cadence', stravaid, authorizationstring=authorizationstring) hr = get_strava_stream(None, 'heartrate', stravaid, @@ -3655,16 +3518,6 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid, except KeyError: # pragma: no cover pass - try: - comments = workoutsummary['comments'] - except: - comments = ' ' - - try: - thetimezone = workoutsummary['timezone'] - except: # pragma: no cover - thetimezone = 'UTC' - try: rowdatetime = iso8601.parse_date(workoutsummary['date_utc']) except KeyError: @@ -3672,18 +3525,12 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid, except ParseError: # pragma: no cover rowdatetime = iso8601.parse_date(workoutsummary['date']) - try: - intervaltype = workoutsummary['workout_type'] - - except KeyError: - intervaltype = '' - try: title = workoutsummary['name'] except KeyError: # pragma: no cover title = "" try: - t = data['comments'].split('\n', 1)[0] + t = workoutsummary['comments'].split('\n', 1)[0] title += t[:20] except: title = '' @@ -3767,8 +3614,8 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid, row = rowingdata.rowingdata(df=df) row.write_csv(csvfilename, gzip=False) - summary = row.allstats() - maxdist = df['cum_dist'].max() + # summary = row.allstats() + # maxdist = df['cum_dist'].max() duration = row.duration uploadoptions = { diff --git a/rowers/tasks_standalone.py b/rowers/tasks_standalone.py index f607e618..72234081 100644 --- a/rowers/tasks_standalone.py +++ b/rowers/tasks_standalone.py @@ -7,6 +7,8 @@ import time import os import sys import django +from django.contrib import messages + proj_path = "../" sys.path.append(proj_path) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rowsandall_app.settings") @@ -15,11 +17,7 @@ django.setup() @app.task def addcomment2(userid, id, debug=False): - time.sleep(5) -# w = Workout.objects.get(id=id) -# w.notes += '\n the task has run' -# w.save() u = User.objects.get(id=userid) messages.info(u, ' The task has run') messages.error(u, ' Het is veel te laat') diff --git a/rowers/teams.py b/rowers/teams.py index 78fe495e..83f214cf 100644 --- a/rowers/teams.py +++ b/rowers/teams.py @@ -88,7 +88,7 @@ def create_team(name, manager, private='open', notes='', viewing='allmembers'): private=private, viewing=viewing) t.save() r = Rower.objects.get(user=manager) - res = add_member(t.id, r) + _ = add_member(t.id, r) except IntegrityError: return (0, 'Team name duplication') return (t.id, 'Team created') @@ -131,13 +131,13 @@ def add_member(id, rower): # code to add all workouts ws = Workout.objects.filter(user=rower) - res = handle_add_workouts_team(ws, t) + _ = handle_add_workouts_team(ws, t) # code to add plannedsessions plannedsessions = PlannedSession.objects.filter( team=t, enddate__gte=timezone.now().date()) for ps in plannedsessions: # pragma: no cover - res = ps.rower.add(rower) + _ = ps.rower.add(rower) # set_teamplanexpires(rower) # code for Stuck At Home Team (temporary) @@ -154,7 +154,7 @@ def remove_member(id, rower): # remove the team from rower's workouts: ws = Workout.objects.filter(user=rower, team=t) - res = handle_remove_workouts_team(ws, t) + _ = handle_remove_workouts_team(ws, t) # set_teamplanexpires(rower) return (id, 'Member removed') @@ -270,9 +270,9 @@ def send_coachrequest_email(rekwest): coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name - res = myqueue(queuehigh, - handle_sendemail_coachrequest, - email, name, code, coachname) + _ = myqueue(queuehigh, + handle_sendemail_coachrequest, + email, name, code, coachname) def send_coacheerequest_email(rekwest): @@ -283,14 +283,13 @@ def send_coacheerequest_email(rekwest): coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name - res = myqueue(queuehigh, - handle_sendemail_coacheerequest, - email, name, code, coachname) + _ = myqueue(queuehigh, + handle_sendemail_coacheerequest, + email, name, code, coachname) def create_request(team, user): r2 = Rower.objects.get(user=user) - r = Rower.objects.get(user=team.manager) if r2 in Rower.objects.filter(team=team): # pragma: no cover return (0, 'Already a member of that team') @@ -323,8 +322,6 @@ def get_coach_club_size(coach): # request by coach to coach user def create_coaching_offer(coach, user): - r = user.rower - if coach in rower_get_coaches(user.rower): # pragma: no cover return (0, 'You are already coaching this person.') @@ -348,7 +345,6 @@ def create_coaching_offer(coach, user): def create_invite(team, manager, user=None, email=''): - r = Rower.objects.get(user=manager) if not is_team_manager(manager, team): return (0, 'Not the team manager') if user: @@ -359,7 +355,7 @@ def create_invite(team, manager, user=None, email=''): return (0, 'Rower does not exist') if r2 in Rower.objects.filter(team=team): return (0, 'Already member of that team') - elif email == None or email == '': # pragma: no cover + elif email is None or email == '': # pragma: no cover return (0, 'Invalid request - missing email or user') else: try: @@ -390,13 +386,11 @@ def revoke_request(user, id): except TeamRequest.DoesNotExist: # pragma: no cover return (0, 'The request is invalid') - t = rekwest.team - if rekwest.user == user: rekwest.delete() return (1, 'Request revoked') - else: # pragma: no cover - return (0, 'You are not the requestor') + + return (0, 'You are not the requestor') # pragma: no cover def reject_revoke_coach_offer(user, id): @@ -493,9 +487,9 @@ def send_invite_email(id): manager = invitation.team.manager.first_name + \ ' '+invitation.team.manager.last_name - res = myqueue(queuehigh, - handle_sendemail_invite, - email, name, code, teamname, manager) + _ = myqueue(queuehigh, + handle_sendemail_invite, + email, name, code, teamname, manager) return (1, 'Invitation email sent') @@ -506,9 +500,9 @@ def send_team_delete_mail(t, rower): email = u.email name = u.first_name+' '+u.last_name manager = t.manager.first_name+' '+t.manager.last_name - res = myqueue(queuehigh, - handle_sendemail_team_removed, - email, name, teamname, manager) + _ = myqueue(queuehigh, + handle_sendemail_team_removed, + email, name, teamname, manager) return (1, 'Team delete email sent') @@ -521,41 +515,38 @@ def send_email_member_dropped(teamid, rower): name = u.first_name+' '+u.last_name manager = t.manager.first_name+' '+t.manager.last_name - res = myqueue(queuehigh, handle_sendemail_member_dropped, - email, name, teamname, manager) + _ = myqueue(queuehigh, handle_sendemail_member_dropped, + email, name, teamname, manager) return (1, 'Member dropped email sent') def send_request_accept_email(rekwest): # pragma: no cover - id = rekwest.id email = rekwest.user.email teamname = rekwest.team.name name = rekwest.user.first_name+' '+rekwest.user.last_name manager = rekwest.team.manager.first_name+' '+rekwest.team.manager.last_name - res = myqueue(queuehigh, - handle_sendemail_request_accept, - email, name, teamname, manager) + _ = myqueue(queuehigh, + handle_sendemail_request_accept, + email, name, teamname, manager) return (1, 'Invitation email sent') def send_request_reject_email(rekwest): - id = rekwest.id teamname = rekwest.team.name email = rekwest.user.email name = rekwest.user.first_name+' '+rekwest.user.last_name manager = rekwest.team.manager.first_name+' '+rekwest.team.manager.last_name - res = myqueue(queuehigh, - handle_sendemail_request_reject, - email, name, teamname, manager) + _ = myqueue(queuehigh, + handle_sendemail_request_reject, + email, name, teamname, manager) return (1, 'Invitation email sent') def send_invite_reject_email(invitation): - id = invitation.id email = invitation.team.manager.email if invitation.user: name = invitation.user.first_name+' '+invitation.user.last_name @@ -566,15 +557,14 @@ def send_invite_reject_email(invitation): manager = invitation.team.manager.first_name + \ ' '+invitation.team.manager.last_name - res = myqueue(queuehigh, - handle_sendemail_invite_reject, - email, name, teamname, manager) + _ = myqueue(queuehigh, + handle_sendemail_invite_reject, + email, name, teamname, manager) return (1, 'Invitation email sent') def send_invite_accept_email(invitation): # pragma: no cover - id = invitation.id email = invitation.team.manager.email if invitation.user: name = invitation.user.first_name+' '+invitation.user.last_name @@ -585,9 +575,9 @@ def send_invite_accept_email(invitation): # pragma: no cover manager = invitation.team.manager.first_name + \ ' '+invitation.team.manager.last_name - res = myqueue(queuehigh, - handle_sendemail_invite_accept, - email, name, teamname, manager) + _ = myqueue(queuehigh, + handle_sendemail_invite_accept, + email, name, teamname, manager) return (1, 'Invitation email sent') @@ -598,9 +588,9 @@ def send_team_message(team, message): # pragma: no cover for rower in rowers: rowername = rower.user.first_name + " " + rower.user.last_name - res = myqueue(queuehigh, - handle_sendemail_message, - rower.user.email, team.manager.email, rowername, message, team.name, managername) + _ = myqueue(queuehigh, + handle_sendemail_message, + rower.user.email, team.manager.email, rowername, message, team.name, managername) return (1, 'message sent') @@ -613,9 +603,9 @@ def send_request_email(rekwest): teamname = rekwest.team.name requestor = rekwest.user.first_name+' '+rekwest.user.last_name - res = myqueue(queuehigh, - handle_sendemail_request, - email, name, code, teamname, requestor, id) + _ = myqueue(queuehigh, + handle_sendemail_request, + email, name, code, teamname, requestor, id) return (1, 'Invitation email sent') @@ -729,9 +719,9 @@ def send_coachoffer_rejected_email(rekwest): name = rekwest.user.first_name + " " + rekwest.user.last_name - res = myqueue(queuehigh, - handle_sendemail_coachoffer_rejected, - coachemail, coachname, name) + _ = myqueue(queuehigh, + handle_sendemail_coachoffer_rejected, + coachemail, coachname, name) def send_coachrequest_rejected_email(rekwest): @@ -740,9 +730,9 @@ def send_coachrequest_rejected_email(rekwest): name = rekwest.user.first_name + " " + rekwest.user.last_name - res = myqueue(queuehigh, - handle_sendemail_coachrequest_rejected, - email, coachname, name) + _ = myqueue(queuehigh, + handle_sendemail_coachrequest_rejected, + email, coachname, name) def send_coachrequest_accepted_email(rekwest): @@ -751,9 +741,9 @@ def send_coachrequest_accepted_email(rekwest): name = rekwest.user.first_name + " " + rekwest.user.last_name - res = myqueue(queuehigh, - handle_sendemail_coachrequest_accepted, - email, coachname, name) + _ = myqueue(queuehigh, + handle_sendemail_coachrequest_accepted, + email, coachname, name) def send_coachoffer_accepted_email(rekwest): @@ -762,6 +752,6 @@ def send_coachoffer_accepted_email(rekwest): name = rekwest.user.first_name + " " + rekwest.user.last_name - res = myqueue(queuehigh, - handle_sendemail_coachoffer_accepted, - coachemail, coachname, name) + _ = myqueue(queuehigh, + handle_sendemail_coachoffer_accepted, + coachemail, coachname, name) diff --git a/rowers/templates/plannedsessions.html b/rowers/templates/plannedsessions.html index 160abda7..67e57de8 100644 --- a/rowers/templates/plannedsessions.html +++ b/rowers/templates/plannedsessions.html @@ -154,6 +154,12 @@ href="/rowers/sessions/sendcalendar/user/{{ rower.user.id }}/?when={{ timeperiod }}"> Get Calendar File   + {% if user.is_authenticated and user.is_staff %} + + Save to YaML +   + {% endif %} Actual vs Plan chart diff --git a/rowers/templates/plannedsessiontemplatecreate.html b/rowers/templates/plannedsessiontemplatecreate.html index fbda21b5..c1d89a73 100644 --- a/rowers/templates/plannedsessiontemplatecreate.html +++ b/rowers/templates/plannedsessiontemplatecreate.html @@ -34,6 +34,8 @@ + + {% endblock %} {% block sidebar %} diff --git a/rowers/templates/plannedsessiontemplateedit.html b/rowers/templates/plannedsessiontemplateedit.html index d3c15a01..ea18075b 100644 --- a/rowers/templates/plannedsessiontemplateedit.html +++ b/rowers/templates/plannedsessiontemplateedit.html @@ -35,6 +35,17 @@ +
  • +

    Steps

    + {% if steps %} +

    {{ steps|safe }}

    + {% else %} + No Steps defined + {% endif %} +

    + Edit Steps (experimental) +

    +
  • {% endblock %} diff --git a/rowers/templates/stepedit.html b/rowers/templates/stepedit.html new file mode 100644 index 00000000..c53575dd --- /dev/null +++ b/rowers/templates/stepedit.html @@ -0,0 +1,97 @@ +{% extends "newbase.html" %} +{% load static %} +{% load rowerfilters %} + +{% block title %}Rowsandall Training Plans{% endblock %} + + +{% block main %} +

    Edit {{ step.name }}

    +
      +
    • +

      + WARNING: This is experimental functionality which may not behave as you + expect. Does not work on smartphones. +

      +
    • +
    • +

      Step Description

      + {{ stepdescription }} +
    • +
    • +

      Add new step

      +
      + + {{ form.as_table }} +
      + {% csrf_token %} + + +
      +
    • +
    • +

      Explanation

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      ParameterRegular StepRepeat Step
      Duration TypeTime or DistanceRepeat
      Duration ValueMinutes / MetersBlock number to start repeat from
      Target TypeSet a target to hold---
      Target Value +
      Power: Zone number (1-10), % of FTP (10-1000)
      +
      Speed: 1000x target speed in m/s
      +
      Heart Rate: Zone number (1-10), % of max (10-100);
      +
      Cadence: Strokes per Minute
      +
      + Number of repetitions +
      Target Value Low +
      Power: % of FTP (10-1000)
      +
      Speed: 1000x target speed in m/s
      +
      Heart Rate: % of max (10-100);
      +
      Cadence: Strokes per Minute
      +
      +
      Target Value High +
      Power: % of FTP (10-1000)
      +
      Speed: 1000x target speed in m/s
      +
      Heart Rate: % of max (10-100);
      +
      Cadence: Strokes per Minute
      +
      +
      IntensityWarming Up, Active, RestSet to Active
      DescriptionAny other text
      +
    • +
    +{% endblock %} + + +{% block sidebar %} +{% include 'menu_plan.html' %} +{% endblock %} diff --git a/rowers/templates/stepeditor.html b/rowers/templates/stepeditor.html new file mode 100644 index 00000000..efc9daf1 --- /dev/null +++ b/rowers/templates/stepeditor.html @@ -0,0 +1,403 @@ +{% extends "newbase.html" %} +{% load static %} +{% load rowerfilters %} + +{% block title %}Rowsandall Training Plans{% endblock %} + + +{% block main %} +

    Plan Training Steps

    +

    + WARNING: This is experimental functionality which may not behave as you + expect. Does not work on smartphones. +

    +

    + Drag from Library to Training to add a step to the end. + Drag on top of a training step to insert after it. + Drag out of Training to remove a step. +

    +
    +
    +

    Training Steps for {{ ps.name }}

    +

    +

    + + +
    +

    +{% for step in currentsteps %} +
    + + ({{ forloop.counter|add:-1 }}) + + + {{ step.name }} + {% if step.durationtype == "RepeatUntilStepsCmplt" %} + - repeat {{ step.targetvalue }}x from block {{ step.durationvalue|floatformat }} + {% endif %} + + + + + + + + + + + +
    +{% endfor %} +
    +
    +
    +

    +
    +
    +
    +

    Step Library

    + {% for step in steps %} +
    + + + + {{ step.name }} + {% if step.durationtype == "RepeatUntilStepsCmplt" %} + - repeat {{ step.targetvalue }}x from block {{ step.durationvalue|floatformat }} + {% endif %} + + + + + + + + + + + +
    + {% endfor %} +
    + +
      +
    • +

      Add new step

      +
      + + {{ form.as_table }} +
      + {% csrf_token %} + +
      +
    • +
    • +

      Step Information

      +
      +

      Step information

      +
      +
    • +
    • +

      Explanation

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      ParameterRegular StepRepeat Step
      Duration TypeTime or DistanceRepeat
      Duration ValueMinutes / MetersBlock number to start repeat from
      Target TypeSet a target to hold---
      Target Value +
      Power: Zone number (1-10), % of FTP (10-1000)
      +
      Speed: 1000x target speed in m/s
      +
      Heart Rate: Zone number (1-10), % of max (10-100);
      +
      Cadence: Strokes per Minute
      +
      + Number of repetitions +
      Target Value Low +
      Power: % of FTP (10-1000)
      +
      Speed: 1000x target speed in m/s
      +
      Heart Rate: % of max (10-100);
      +
      Cadence: Strokes per Minute
      +
      +
      Target Value High +
      Power: % of FTP (10-1000)
      +
      Speed: 1000x target speed in m/s
      +
      Heart Rate: % of max (10-100);
      +
      Cadence: Strokes per Minute
      +
      +
      IntensityWarming Up, Active, RestSet to Active
      DescriptionAny other text
      +
    • + +
    +{% endblock %} + +{% block scripts %} + + +{% endblock %} + +{% block sidebar %} +{% include 'menu_plan.html' %} +{% endblock %} diff --git a/rowers/templates/templatelibrary.html b/rowers/templates/templatelibrary.html index c8c72041..f845ce3e 100644 --- a/rowers/templates/templatelibrary.html +++ b/rowers/templates/templatelibrary.html @@ -39,6 +39,8 @@ Private/Shared Edit Copy to Calendar + Share + Lock Delete diff --git a/rowers/templates/trainingplan.html b/rowers/templates/trainingplan.html index f6a7c73d..156cdfbd 100644 --- a/rowers/templates/trainingplan.html +++ b/rowers/templates/trainingplan.html @@ -32,7 +32,10 @@ {% if plan|mayeditplan:request %}

    Edit the plan

    {% endif %} -

    Plan vs Actual chart

    +

    Plan vs Actual chart

    +

    + View all sessions +

    Plan Macro, Meso and Micro Cycles

    diff --git a/rowers/templates/trainingplan_create.html b/rowers/templates/trainingplan_create.html index 7f683aa4..2205f102 100644 --- a/rowers/templates/trainingplan_create.html +++ b/rowers/templates/trainingplan_create.html @@ -123,15 +123,20 @@ {% if plan.status %} active {% else %} inactive {% endif %} {% if request.user.rower == plan.manager %} - Edit + {% endif %} - Plan + {% if request.user.rower == plan.manager %} - Delete + {% endif %} + + + + + {% endfor %} diff --git a/rowers/tpstuff.py b/rowers/tpstuff.py index 81c3f0a4..4996bf9c 100644 --- a/rowers/tpstuff.py +++ b/rowers/tpstuff.py @@ -21,8 +21,6 @@ from rowsandall_app.settings import ( tpapilocation = "https://api.trainingpeaks.com" -#from async_messages import message_user,messages - oauth_data = { 'client_id': TP_CLIENT_ID, 'client_secret': TP_CLIENT_SECRET, @@ -53,7 +51,7 @@ def do_refresh_token(refreshtoken): def get_token(code): - client_auth = requests.auth.HTTPBasicAuth(TP_CLIENT_KEY, TP_CLIENT_SECRET) + # client_auth = requests.auth.HTTPBasicAuth(TP_CLIENT_KEY, TP_CLIENT_SECRET) post_data = { "client_id": TP_CLIENT_KEY, "grant_type": "authorization_code", @@ -61,9 +59,6 @@ def get_token(code): "redirect_uri": TP_REDIRECT_URI, "client_secret": TP_CLIENT_SECRET, } - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - } response = requests.post( "https://oauth.trainingpeaks.com/oauth/token", diff --git a/rowers/traverselinktest.py b/rowers/traverselinktest.py index d6563498..44fbd53a 100644 --- a/rowers/traverselinktest.py +++ b/rowers/traverselinktest.py @@ -151,8 +151,6 @@ class TraverseLinksTest(TestCase): if response.status_code == 200: soup = BeautifulSoup(response.content, 'html.parser') - text = soup.get_text() - for link in soup.find_all('a'): new_link = link.get('href') if VERBOSE: diff --git a/rowers/uploads.py b/rowers/uploads.py index 60b2a89a..2d08bfd1 100644 --- a/rowers/uploads.py +++ b/rowers/uploads.py @@ -87,7 +87,7 @@ def make_plot(r, w, f1, f2, plottype, title, imagename='', plotnr=0): } axis = r.staticgrids - if axis == None: # pragma: no cover + if axis is None: # pragma: no cover gridtrue = False axis = 'both' else: @@ -133,14 +133,14 @@ def do_sync(w, options, quick=False): do_strava_export = w.user.strava_auto_export try: - upload_to_strava = options['upload_to_Strava'] or do_strava_export + do_strava_export = options['upload_to_Strava'] or do_strava_export except KeyError: - upload_to_strava = False + pass try: if options['stravaid'] != 0 and options['stravaid'] != '': # pragma: no cover w.uploadedtostrava = options['stravaid'] - upload_to_strava = False + # upload_to_strava = False do_strava_export = False w.save() except KeyError: @@ -174,14 +174,14 @@ def do_sync(w, options, quick=False): do_c2_export = w.user.c2_auto_export try: - upload_to_c2 = options['upload_to_C2'] or do_c2_export + do_c2_export = options['upload_to_C2'] or do_c2_export except KeyError: - upload_to_c2 = False + pass try: if options['c2id'] != 0 and options['c2id'] != '': # pragma: no cover w.uploadedtoc2 = options['c2id'] - upload_to_c2 = False + # upload_to_c2 = False do_c2_export = False w.save() except KeyError: @@ -250,16 +250,15 @@ def do_sync(w, options, quick=False): with open('st_export.log', 'a') as logfile: logfile.write(str(timezone.now())+': ') logfile.write(str(w.user)+' NoTokenError\n') - message = "Please connect to SportTracks first" - id = 0 + + return 0 if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export): # pragma: no cover try: - message, id = tpstuff.workout_tp_upload( + _, id = tpstuff.workout_tp_upload( w.user.user, w ) except NoTokenError: - message = "Please connect to TrainingPeaks first" - id = 0 + return 0 return 1 diff --git a/rowers/urls.py b/rowers/urls.py index 57d3e9f5..49cfa865 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -17,7 +17,6 @@ from rest_framework.permissions import * from rowers import views from django.contrib.auth import views as auth_views from django.views.generic.base import TemplateView -from django.utils.decorators import method_decorator from rowers.permissions import ( IsOwnerOrNot, IsOwnerOrReadOnly, @@ -71,7 +70,7 @@ class PlannedSessionViewSet(viewsets.ModelViewSet): class WorkoutViewSet(viewsets.ModelViewSet): model = Workout - #queryset = Workout.objects.all().order_by("-date", "-starttime") + serializer_class = WorkoutSerializer def get_queryset(self): # pragma: no cover @@ -90,7 +89,6 @@ class WorkoutViewSet(viewsets.ModelViewSet): class RowerViewSet(viewsets.ModelViewSet): model = Rower serializer_class = RowerSerializer - #queryset = Rower.objects.all() def get_queryset(self): # pragma: no cover try: @@ -109,7 +107,6 @@ class RowerViewSet(viewsets.ModelViewSet): class FavoriteChartViewSet(viewsets.ModelViewSet): model = FavoriteChart serializer_class = FavoriteChartSerializer - #queryset = FavoriteChart.objects.all() def get_queryset(self): # pragma: no cover try: @@ -235,8 +232,6 @@ handler400 = views.error400_view handler500 = views.error500_view -#app_name = "rowers" - urlpatterns = [ re_path(r'^o/authorize/$', base.AuthorizationView.as_view(), name="authorize"), re_path(r'^o/token/$', base.TokenView.as_view(), name="token"), @@ -352,17 +347,21 @@ urlpatterns = [ re_path(r'^workouts-join-select/user/(?P\d+)/$', views.workouts_join_select, name='workouts_join_select'), re_path( - r'^user-analysis-select/(?P\w.*)/team/(?P\d+)/workout/(?P\b[0-9A-Fa-f]+\b)/$', views.analysis_new, name='analysis_new'), + r'^user-analysis-select/(?P\w.*)/team/(?P\d+)/workout/(?P\b[0-9A-Fa-f]+\b)/$', + views.analysis_new, name='analysis_new'), re_path( - r'^user-analysis-select/(?P\w.*)/session/(?P\d+)/workout/(?P\b[0-9A-Fa-f]+\b)/$', views.analysis_new, name='analysis_new'), + r'^user-analysis-select/(?P\w.*)/session/(?P\d+)/workout/(?P\b[0-9A-Fa-f]+\b)/$', + views.analysis_new, name='analysis_new'), re_path( - r'^user-analysis-select/(?P\w.*)/workout/(?P\b[0-9A-Fa-f]+\b)/$', views.analysis_new, name='analysis_new'), + r'^user-analysis-select/(?P\w.*)/workout/(?P\b[0-9A-Fa-f]+\b)/$', + views.analysis_new, name='analysis_new'), re_path(r'^user-analysis-select/(?P\w.*)/user/(?P\d+)/$', views.analysis_new, name='analysis_new'), re_path(r'^user-analysis-select/(?P\w.*)/team/(?P\d+)/$', views.analysis_new, name='analysis_new'), re_path( - r'^user-analysis-select/team/(?P\d+)/workout/(?P\b[0-9A-Fa-f]+\b)/$', views.analysis_new, name='analysis_new'), + r'^user-analysis-select/team/(?P\d+)/workout/(?P\b[0-9A-Fa-f]+\b)/$', + views.analysis_new, name='analysis_new'), re_path(r'^user-analysis-select/user/(?P\d+)/$', views.analysis_new, name='analysis_new'), re_path(r'^user-analysis-select/team/(?P\d+)/$', @@ -613,7 +612,8 @@ urlpatterns = [ views.workout_nkimport_view, name='workout_nkimport_view'), re_path(r'^workout/nkimport/all/$', views.workout_getnkworkout_all, name='workout_getnkworkout_all'), - re_path(r'^workout/nkimport/all/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$', views.workout_getnkworkout_all, + re_path(r'^workout/nkimport/all/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$', + views.workout_getnkworkout_all, name='workout_getnkworkout_all'), re_path(r'^workout/rp3import/(?P\d+)/$', views.workout_getrp3importview, name='workout_getrp3importview'), @@ -853,12 +853,16 @@ urlpatterns = [ name='workout_workflow_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/courses/$', views.workout_course_view, name='workout_course_view'), - re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/flexchart/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/(?P\w+)/$', + re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/flexchart/'\ + '(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/(?P\w+)/$', views.workout_flexchart3_view, name='workout_flexchart3_view'), - re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/flexchart/(?P\w+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/(?P\w+.*)/$', - views.workout_flexchart3_view, name='workout_flexchart3_view'), - re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/flexchart/(?P\w+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/$', + re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/flexchart/'\ + '(?P\w+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/(?P\w+.*)/$', views.workout_flexchart3_view, name='workout_flexchart3_view'), + re_path( + r'^workout/(?P\b[0-9A-Fa-f]+\b)/flexchart/'\ + '(?P\w+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/$', + views.workout_flexchart3_view, name='workout_flexchart3_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/flexchart/$', views.workout_flexchart3_view, name='workout_flexchart3_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/flexchartstacked/$', @@ -871,6 +875,18 @@ urlpatterns = [ views.rower_create_trainingplan, name='rower_create_trainingplan'), re_path(r'^plans/$', views.rower_select_instantplan, name='rower_select_instantplan'), + re_path(r'^plans/step/(?P\d+)/edit/$', + views.stepedit, name='stepedit'), + re_path(r'^plans/step/(?P\d+)/edit/(?P\d+)/$', + views.stepedit, name='stepedit'), + re_path(r'^plans/step/(?P\d+)/delete/$', + views.stepdelete, name='stepdelete'), + re_path(r'^plans/stepeditor/$', + views.stepeditor, name='stepeditor'), + re_path(r'^plans/stepeditor/(?P\d+)/$', + views.stepeditor, name='stepeditor'), + re_path(r'^plans/stepadder/(?P\d+)/$', + views.stepadder, name='stepadder'), re_path(r'^plans/(?P[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})/$', views.rower_view_instantplan, name='rower_view_instantplan'), re_path(r'^buyplan/(?P\d+)/$', views.buy_trainingplan_view, @@ -1002,7 +1018,8 @@ urlpatterns = [ name='plannedsession_teamclone_view'), re_path(r'^sessions/(?P\d+)/clone/$', views.plannedsession_clone_view), re_path( - r'^sessions/(?P\d+)/detach/(?P\b[0-9A-Fa-f]+\b)/user/(?P\d+)/$', views.plannedsession_detach_view), + r'^sessions/(?P\d+)/detach/(?P\b[0-9A-Fa-f]+\b)/user/(?P\d+)/$', + views.plannedsession_detach_view), re_path( r'^sessions/(?P\d+)/detach/(?P\b[0-9A-Fa-f]+\b)/$', views.plannedsession_detach_view), re_path(r'^sessions/(?P\d+)/$', views.plannedsession_view, @@ -1043,12 +1060,17 @@ urlpatterns = [ name='plannedsessions_print_view'), re_path(r'^sessions/(?P\d+)/message/$', views.plannedsession_message_view, name='plannedsession_message_view'), - re_path(r'^sessions/print/user/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$', views.plannedsessions_print_view, + re_path(r'^sessions/print/user/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$', + views.plannedsessions_print_view, name='plannedsessions_print_view'), re_path(r'^sessions/sendcalendar/$', views.plannedsessions_icsemail_view, name='plannedsessions_coach_icsemail_view'), re_path(r'^sessions/sendcalendar/user/(?P\d+)/$', views.plannedsessions_icsemail_view, name='plannedsessions_icsemail_view'), + re_path(r'^sessions/saveasplan/$', views.save_plan_yaml, + name='save_plan_yaml'), + re_path(r'^sessions/saveasplan/user/(?P\d+)/$', views.save_plan_yaml, + name='save_plan_yaml'), re_path(r'^sessions/$', views.plannedsessions_view, name='plannedsessions_view'), re_path(r'^sessions/user/(?P\d+)/$', views.plannedsessions_view, diff --git a/rowers/utils.py b/rowers/utils.py index 7f47f5b4..4f70f43b 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -16,14 +16,11 @@ import datetime import json import time from fitparse import FitFile -from django.conf import settings from django.http import HttpResponse import requests -from django.http import HttpResponse - import humanize from pytz.exceptions import UnknownTimeZoneError import pytz @@ -31,6 +28,8 @@ import iso8601 from iso8601 import ParseError import arrow +from django.conf import settings + lbstoN = 4.44822 landingpages = ( @@ -123,6 +122,11 @@ info_calls = [ def dologging(filename, s): + do_logging = settings.MYLOGGING.get(filename,True) + + if not do_logging: + return + tstamp = time.localtime() timestamp = time.strftime('%b-%d-%Y %H:%M:%S', tstamp) with open(filename, 'a') as f: @@ -189,7 +193,6 @@ palettes = { 'gold_sunset': (47, -31, .26, -0.12, 0.94, -0.5), 'blue_red': (207, -200, .85, 0, .74, -.24), 'blue_green': (207, -120, .85, 0, .75, .25), - 'cyan_green': (192, -50, .08, .65, .98, -.34), 'cyan_purple': trcolors(237, 248, 251, 136, 65, 157), 'green_blue': trcolors(240, 249, 232, 8, 104, 172), 'orange_red': trcolors(254, 240, 217, 179, 0, 0), @@ -237,7 +240,8 @@ def str2bool(v): # pragma: no cover def uniqify(seq, idfun=None): # order preserving if idfun is None: - def idfun(x): return x + def idfun(x): + return x seen = {} result = [] for item in seq: @@ -465,14 +469,14 @@ def totaltime_sec_to_string(totaltime, shorten=False): hours=hours, minutes=minutes, seconds=seconds, - tenths=tenths + # tenths=tenths ) else: duration = "{minutes}:{seconds:02d}".format( - hours=hours, + # hours=hours, minutes=minutes, seconds=seconds, - tenths=tenths + # tenths=tenths ) return duration @@ -559,12 +563,12 @@ def get_strava_stream(r, metric, stravaid, series_type='time', fetchresolution=' if metric == 'power': # pragma: no cover metric = 'watts' - url = "https://www.strava.com/api/v3/activities/{stravaid}/streams/{metric}?resolution={fetchresolution}&series_type={series_type}".format( - stravaid=stravaid, - fetchresolution=fetchresolution, - series_type=series_type, - metric=metric - ) + url = "https://www.strava.com/api/v3/activities/{stravaid}" \ + "/streams/{metric}?resolution={fetchresolution}&series_type={series_type}".format( + stravaid=stravaid, + fetchresolution=fetchresolution, + series_type=series_type, + metric=metric) s = requests.get(url, headers=headers) @@ -574,7 +578,6 @@ def get_strava_stream(r, metric, stravaid, series_type='time', fetchresolution=' try: for data in s.json(): - y = None try: if data['type'] == metric: return np.array(data['data']) @@ -790,14 +793,14 @@ def get_step_type(step): # pragma: no cover return t -def peel(l): - if len(l) == 0: # pragma: no cover +def peel(listToPeel): + if len(listToPeel) == 0: # pragma: no cover return None, None - if len(l) == 1: - return l[0], None + if len(listToPeel) == 1: + return listToPeel[0], None - first = l[0] - rest = l[1:] + first = listToPeel[0] + rest = listToPeel[1:] if first['type'] == 'Step': # pragma: no cover return first, rest @@ -944,7 +947,7 @@ def step_to_string(step, short=False): repeatValue = 1 nr = 0 - name = '' + intensity = '' duration = '' unit = '' @@ -954,7 +957,11 @@ def step_to_string(step, short=False): durationtype = step['durationType'] if step['durationValue'] == 0: - if durationtype not in ['RepeatUntilStepsCmplt', 'RepeatUntilHrLessThan', 'RepeatUntilHrGreaterThan']: # pragma: no cover + if durationtype not in [ + 'RepeatUntilStepsCmplt', + 'RepeatUntilHrLessThan', + 'RepeatUntilHrGreaterThan' + ]: # pragma: no cover return '', type, -1, -1, 1 if durationtype == 'Time': @@ -963,7 +970,6 @@ def step_to_string(step, short=False): if value/1000. >= 3600: # pragma: no cover unit = 'h' dd = timedelta(seconds=value/1000.) - #duration = humanize.naturaldelta(dd, minimum_unit="seconds") duration = '{v}'.format(v=str(dd)) elif durationtype == 'Distance': unit = 'm' @@ -1163,7 +1169,7 @@ def step_to_string(step, short=False): nr = step['stepId'] - name = step['wkt_step_name'] + # name = step['wkt_step_name'] notes = '' try: @@ -1178,10 +1184,10 @@ def step_to_string(step, short=False): intensity = 0 s = '{duration} {unit} {target} {repeat} {notes}'.format( - nr=nr, - name=name, + # nr=nr, + # name=name, unit=unit, - intensity=intensity, + # intensity=intensity, duration=duration, target=target, repeat=repeat, diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index 541e7041..b80126d5 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -1576,7 +1576,7 @@ def workout_c2import_view(request, page=1, userid=0, message=""): rower = getrequestrower(request, userid=userid) if rower.user != request.user: messages.error( - request, 'You can only access your own workouts on the NK Logbook, not those of your athletes') + request, 'You can only access your own workouts on the Concept2 Logbook, not those of your athletes') url = reverse('workout_c2import_view', kwargs={ 'userid': request.user.id}) return HttpResponseRedirect(url) diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py index b8dc1a75..fa5f1ac1 100644 --- a/rowers/views/planviews.py +++ b/rowers/views/planviews.py @@ -6,6 +6,8 @@ from rowers.views.statements import * import rowers.garmin_stuff as gs from rowers import credits +from json.decoder import JSONDecodeError +from rowers.utils import step_to_string @login_required @@ -1375,6 +1377,76 @@ def plannedsessions_coach_view(request, } ) +@login_required() +def save_plan_yaml(request, userid=0): + r = getrequestrower(request, userid=userid) + startdate, enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() + + duration = (enddate-startdate).days+1 + filename = 'myplan.yml' + + plan = { + 'filename': filename, + 'name': 'Training Plan', + 'duration': duration, + 'description': 'My Training Plan', + } + + sps = get_sessions(r, startdate=startdate, enddate=enddate) + + trainingdays = [] + + # add sessions to days + for i in range(duration): + dd = startdate+timedelta(days=i) + workouts = [] + for ps in sps: + if ps.preferreddate == dd: + sessionsport = mytypes.fitmapping[ps.sessionsport].capitalize() + if ps.steps: + steps = ps.steps + steps['filename'] = "" + workouts.append(steps) + else: + if ps.sessionmode == 'distance': + ps.interval_string = '{d}m'.format(d=ps.sessionvalue) + elif ps.sessionmode == 'time': + ps.interval_string = '{d}min'.format(d=ps.sessionvalue) + elif ps.sessionmode == 'rScore': + print('aap') + ps.approximate_duration = ps.sessionvalue + ps.interval_string = '{d}min'.format(d=ps.sessionvalue) + elif ps.sessionmode == 'TRIMP': + ps.approximate_duration = int(ps.sessionvalue/2.) + ps.interval_string = '{d}min'.format(d=int(ps.sessionvalue/2.)) + ps.fitfile = '' + ps.steps = None + ps.save() + ps_reload = PlannedSession.objects.get(id=ps.id) + steps = ps_reload.steps + steps['filename'] = "" + steps['workoutName'] = ps.name + workouts.append(steps) + + trainingdays.append({'order': i+1, 'workouts': workouts}) + + plan['trainingDays'] = trainingdays + + response = HttpResponse(yaml.dump(plan)) + + response['Content-Disposition'] = 'attachment; filename="training_plan_{u}_{d1}_{d2}.yml"'.format( + u=request.user.username, + d1=startdate.strftime("%Y%m%d"), + d2=enddate.strftime("%Y%m%d"), + ) + + response['Content-Type'] = 'application/octet-stream' + + return response + + @login_required() def plannedsessions_view(request, @@ -1954,6 +2026,12 @@ def plannedsession_templateedit_view(request, id=0): sessiontemplates = sessiontemplates | sessiontemplates2 + steps = '' + if ps.steps: # pragma: no cover + d = ps.steps + + steps = ps_dict_get_description_html(d, short=False) + return render(request, 'plannedsessiontemplateedit.html', { 'teams': get_my_teams(request.user), @@ -1964,6 +2042,7 @@ def plannedsession_templateedit_view(request, id=0): 'thesession': ps, 'sessiontemplates': sessiontemplates, 'rower': r, + 'steps': steps, }) @@ -2530,11 +2609,15 @@ def rower_view_instantplan(request, id='', userid=0): trainingdays = plansteps['trainingDays'] + + trainingdays2 = [] nextday = trainingdays.pop(0) + for i in range(plansteps['duration']): if nextday['order'] == i+1: nextday['week'] = (divmod(i, 7)[0])+1 + trainingdays2.append(nextday) try: nextday = trainingdays.pop(0) @@ -2549,6 +2632,7 @@ def rower_view_instantplan(request, id='', userid=0): } ) + targets = TrainingTarget.objects.filter( rowers=r, date__gte=timezone.now(), @@ -2905,6 +2989,286 @@ def rower_create_trainingplan(request, id=0): 'old_targets': old_targets, }) +@user_passes_test(can_plan, login_url="/rowers/paidplans", + message="This functionality requires a Coach or Self-Coach plan", + redirect_field_name=None) +def stepadder(request, id=0): + is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' + if not is_ajax: + return JSONResponse( + status=403, data={ + 'status': 'false', + 'message': 'this view cannot be accessed directly' + } + ) + ps = get_object_or_404(PlannedSession, pk=id) + + is_save = request.GET.get('save',0) + + if request.method != 'POST': + message = {'status': 'false', + 'message': 'this view cannot be accessed through GET'} + return JSONResponse(status=403, data=message) + + try: + json_data = json.loads(request.body) + post_data = json_data + except (KeyError, JSONDecodeError): + q = request.POST + post_data = {k: q.getlist(k) if len( + q.getlist(k)) > 1 else v for k, v in q.items()} + + # only allow local host + hostt = request.get_host().split(':') + if hostt[0] not in ['localhost', '127.0.0.1', 'dev.rowsandall.com', 'rowsandall.com']: + message = {'status': 'false', + 'message': 'permission denied for host '+hostt[0]} + return JSONResponse(status=403, data=message) + + if ps.steps: + filename = ps.steps.get('filename','') + sport = ps.steps.get('sport','rowing') + else: + filename = '' + sport = 'rowing' + + steps = { + "filename": filename, + "sport": sport, + "steps": [] + } + + for nr,id in enumerate(post_data): + try: + step = PlannedSessionStep.objects.get(id=int(id)) + # add JSON + d = step.asdict() + d['stepId'] = nr + steps['steps'].append(d) + except PlannedSessionStep.DoesNotExist: + pass + + if is_save: + # save the darn thing + ps.steps = steps + + ps.interval_string = '' + ps.fitfile = None + ps.save() + + return JSONResponse(status=200,data=post_data) + +@user_passes_test(can_plan, login_url="/rowers/paidplans", + message="This functionality requires a Coach or Self-Coach plan", + redirect_field_name=None) +def stepdelete(request, id=0): + step = get_object_or_404(PlannedSessionStep, pk=id) + + step.delete() + + backid = request.GET.get('id') + + url = reverse(stepeditor,kwargs={'id':backid}) + + return HttpResponseRedirect(url) + +@user_passes_test(can_plan, login_url="/rowers/paidplans", + message="This functionality requires a Coach or Self-Coach plan", + redirect_field_name=None) +def stepedit(request, id=0, psid=0): + step = get_object_or_404(PlannedSessionStep, pk=id) + try: + ps = PlannedSession.objects.get(id=psid) + except PlannedSession.DoesNotExist: + ps = None + + form = StepEditorForm(instance=step) + + if request.method == 'POST': + form = StepEditorForm(request.POST) + if form.is_valid(): + if ps: + dd = step.asdict() + dd.pop('stepId') + for id,ss in enumerate(ps.steps['steps']): + ee = ss.copy() + ee.pop('stepId') + + if (dd == ee): + ss['durationType'] = form.cleaned_data['durationtype'] + ss['durationValue'] = form.cleaned_data['durationvalue'] + ss['targetType'] = form.cleaned_data['targettype'] + ss['targetValue'] = form.cleaned_data['targetvalue'] + ss['targetValueLow']= form.cleaned_data['targetvaluelow'] + ss['targetValueHigh'] = form.cleaned_data['targetvaluehigh'] + ss['intensity'] = form.cleaned_data['intensity'] + ss['wkt_step_name'] = form.cleaned_data['name'] + ss['description'] = form.cleaned_data['description'] + + if form.cleaned_data['durationtype'] == 'Time': + ss['durationValue'] = form.cleaned_data['durationvalue']*60000 + elif form.cleaned_data['durationtype'] == 'Distance': + ss[durationValue] = form.cleaned_data['durationvalue']*100 + + ss['durationValue'] = int(ss['durationValue']) + ps.fitfile = None + ps.interval_string = "" + + ps.save() + + step.durationtype = form.cleaned_data['durationtype'] + step.durationvalue = form.cleaned_data['durationvalue'] + step.targettype = form.cleaned_data['targettype'] + step.targetvalue = form.cleaned_data['targetvalue'] + step.targetvaluelow = form.cleaned_data['targetvaluelow'] + step.targetvaluehigh = form.cleaned_data['targetvaluehigh'] + step.intensity = form.cleaned_data['intensity'] + step.name = form.cleaned_data['name'] + step.description = form.cleaned_data['description'] + + if step.durationtype == 'Time': + step.durationvalue *= 60000 + elif step.durationtype == 'Distance': + step.durationvalue *= 100 + + step.save() + + + if step.durationtype == 'Time': + form.fields['durationvalue'].initial = step.durationvalue / 60000 + elif step.durationtype == 'Distance': + form.fields['durationvalue'].initial = step.durationvalue / 100 + + + stepdescription = step_to_string(step.asdict(), short=False)[0] + + if request.method == 'POST': + if 'stepsave_and_return' in request.POST: + url = reverse('stepeditor',kwargs = {'id': ps.id}) + return HttpResponseRedirect(url) + + breadcrumbs = [ + { + 'url': reverse('template_library_view'), + 'name': 'Session Templates' + }, + { + 'url': reverse('plannedsession_templateedit_view', kwargs={'id': ps.id}), + 'name': ps.name + }, + { + 'url': reverse('stepeditor', kwargs={'id':ps.id}), + 'name': 'Edit Steps' + }, + { + 'url': reverse('stepedit', kwargs={'psid': ps.id, 'id': step.id}), + 'name': 'Edit Step' + } + ] + + return render(request,'stepedit.html', + { + 'step': step, + 'stepdescription': stepdescription, + 'form': form, + 'ps': ps, + 'breadcrumbs': breadcrumbs, + }) + + + +@user_passes_test(can_plan, login_url="/rowers/paidplans", + message="This functionality requires a Coach or Self-Coach plan", + redirect_field_name=None) +def stepeditor(request, id=0): + ps = get_object_or_404(PlannedSession, pk=id) + + currentsteps = [] + if ps.steps: + for step in ps.steps['steps']: + durationtype = step.get('durationType','') + durationvalue = step.get('durationValue',0) + targetvalue = step.get('targetValue',0) + targettype = step.get('targetType','') + targetvaluelow = step.get('targetValueLow',0) + targetvaluehigh = step.get('targetValueHigh',0) + intensity = step.get('intensity','Active') + + archived_steps = PlannedSessionStep.objects.filter( + manager = request.user, + durationtype = durationtype, + durationvalue = durationvalue, + targetvalue = targetvalue, + targettype = targettype, + targetvaluelow = targetvaluelow, + targetvaluehigh = targetvaluehigh, + intensity = intensity, + ) + if not archived_steps.count() and durationvalue != 0: + s = PlannedSessionStep( + manager = request.user, + durationtype = durationtype, + durationvalue = durationvalue, + targetvalue = targetvalue, + targettype = targettype, + targetvaluelow = targetvaluelow, + targetvaluehigh = targetvaluehigh, + intensity = intensity, + name = step.get('wkt_step_name','Step') + ) + s.save() + else: + s = archived_steps[0] + currentsteps.append(s) + + + form = StepEditorForm() + + if request.method == 'POST': + form = StepEditorForm(request.POST) + if form.is_valid(): + step = form.save(commit=False) + step.manager = request.user + step.save() + + + steps = PlannedSessionStep.objects.filter( + manager=request.user, + durationtype__in=['Time','Distance','RepeatUntilStepsCmplt'] + ).order_by( + 'intensity','-durationvalue','durationtype', + ) + + stepdescriptions = {} + + for step in steps: + stepdescriptions[step.id] = step_to_string(step.asdict(), short=False)[0] + + breadcrumbs = [ + { + 'url': reverse('template_library_view'), + 'name': 'Session Templates' + }, + { + 'url': reverse('plannedsession_templateedit_view', kwargs={'id': ps.id}), + 'name': ps.name + }, + { + 'url': reverse('stepeditor', kwargs={'id': ps.id}), + 'name': 'Edit Steps' + } + ] + + + return render(request, 'stepeditor.html', + { + 'steps':steps, + 'currentsteps': currentsteps, + 'stepdescriptions': stepdescriptions, + 'form':form, + 'ps':ps, + 'breadcrumbs': breadcrumbs, + }) @user_passes_test(can_plan, login_url="/rowers/paidplans", message="This functionality requires a Coach or Self-Coach plan", diff --git a/rowers/views/statements.py b/rowers/views/statements.py index 8232bfc6..257391fe 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -151,7 +151,8 @@ from rowers.models import ( PlannedSessionComment, CoachRequest, CoachOffer, VideoAnalysis, ShareKey, StandardCollection, CourseStandard, - VirtualRaceFollower, TombStone, InstantPlan + VirtualRaceFollower, TombStone, InstantPlan, + PlannedSessionStep, ) from rowers.models import ( RowerPowerForm, RowerHRZonesForm, RowerForm, RowerCPForm, GraphImage, AdvancedWorkoutForm, @@ -166,7 +167,8 @@ from rowers.models import ( IndoorVirtualRaceResultForm, IndoorVirtualRaceResult, IndoorVirtualRaceForm, PlannedSessionCommentForm, Alert, Condition, StaticChartRowerForm, - FollowerForm, VirtualRaceAthleteForm, InstantPlanForm, DataRowerForm + FollowerForm, VirtualRaceAthleteForm, InstantPlanForm, DataRowerForm, + StepEditorForm, ) from rowers.models import ( FavoriteForm, BaseFavoriteFormSet, SiteAnnouncement, BasePlannedSessionFormSet, diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index 3922a2fe..3da4b04f 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -3736,8 +3736,7 @@ def workout_flexchart3_view(request, *args, **kwargs): 'yaxis1': yparam1, 'yaxis2': yparam2, } - flexaxesform = FlexAxesForm(request, initial=initial, - extrametrics=extrametrics) + flexaxesform = FlexAxesForm(request, initial=initial) initial = { 'includereststrokes': not workstrokesonly, @@ -4594,6 +4593,7 @@ def workout_upload_api(request): message = {'status': 'false', 'message': 'invalid credentials'} return JSONResponse(status=403, data=message) + form = DocumentsForm(post_data) optionsform = TeamUploadOptionsForm(post_data) rowerform = TeamInviteForm(post_data) @@ -4614,6 +4614,7 @@ def workout_upload_api(request): message = {'status': 'false', 'message': 'could not find file'} return JSONResponse(status=400, data=message) + # sync related IDs c2id = post_data.get('c2id', '') @@ -4636,6 +4637,7 @@ def workout_upload_api(request): dologging('debuglog.log', s) + r = None if form.is_valid(): t = form.cleaned_data['title'] @@ -4769,6 +4771,7 @@ def workout_upload_api(request): message = form.errors return JSONResponse(status=400, data=message) + message = {'status': 'true', 'id': w.id} statuscode = 200 if fstr: diff --git a/rowers/weather.py b/rowers/weather.py index 6974c762..ad5fc227 100644 --- a/rowers/weather.py +++ b/rowers/weather.py @@ -70,7 +70,7 @@ def get_metar_data(airportcode, unixtime): lengte = len(doc.xpath('data/METAR/station_id')) idnr = int(lengte/2) try: - id = doc.xpath('data/METAR/station_id')[idnr].text + _ = doc.xpath('data/METAR/station_id')[idnr].text temp_c = doc.xpath('data/METAR/temp_c')[idnr].text wind_dir = doc.xpath('data/METAR/wind_dir_degrees')[idnr].text wind_speed = doc.xpath('data/METAR/wind_speed_kt')[idnr].text @@ -138,7 +138,7 @@ def get_wind_data(lat, long, unixtime): windbearing = 0 summary = 'unknown' airports = ['unknown'] - temparature = 'unknown' + temperature = 'unknown' temperaturec = 'unknown' message = 'Not able to get weather data' diff --git a/rowsandall_app/__init__.py b/rowsandall_app/__init__.py index 8b137891..e69de29b 100644 --- a/rowsandall_app/__init__.py +++ b/rowsandall_app/__init__.py @@ -1 +0,0 @@ - diff --git a/rowsandall_app/forms.py b/rowsandall_app/forms.py index 97f5d436..e79048bf 100644 --- a/rowsandall_app/forms.py +++ b/rowsandall_app/forms.py @@ -1,5 +1 @@ - from django import forms - - - diff --git a/rowsandall_app/models.py b/rowsandall_app/models.py index 9ae69826..4902b4fd 100644 --- a/rowsandall_app/models.py +++ b/rowsandall_app/models.py @@ -1,3 +1,2 @@ # -*- coding: utf-8 -*- from django.db import models - diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index 59150d59..80fbb290 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -12,7 +12,7 @@ https://docs.djangoproject.com/en/1.9/ref/settings/ # -*- coding: utf-8 -*- import os from YamJam import yamjam -#from django.utils.translation import ugettext_lazy as _ +# from django.utils.translation import ugettext_lazy as _ # Read configuration (passwords, keys, secrets) from YamJam configuration # You have to create your own config.yaml in the project directory @@ -20,8 +20,6 @@ CFG = yamjam()['rowsandallapp'] DEFAULT_CHARSET = 'UTF-8' - - # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -39,10 +37,10 @@ TESTING = False ALLOWED_HOSTS = CFG['allowed_hosts'] -#OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = 'oauth2_provider.AccessToken' -#OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application' -#OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = 'oauth2_provider.RefreshToken' -#OAUTH2_PROVIDER_ACCESS_TOKEN_EXPIRE_SECONDS = 3600 +# OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = 'oauth2_provider.AccessToken' +# OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application' +# OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = 'oauth2_provider.RefreshToken' +# OAUTH2_PROVIDER_ACCESS_TOKEN_EXPIRE_SECONDS = 3600 DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' @@ -51,20 +49,20 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' INSTALLED_APPS = [ 'rowers', 'survey', -# 'cvkbrno', + # 'cvkbrno', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', -# 'suit', -# 'suit_rq', + # 'suit', + # 'suit_rq', 'leaflet', 'django_rq', -# 'django_rq_dashboard', -# 'translation_manager', -# 'django_mailbox', + # 'django_rq_dashboard', + # 'translation_manager', + # 'django_mailbox', 'rest_framework', 'datetimewidget', 'rest_framework_swagger', @@ -91,12 +89,12 @@ MIDDLEWARE = [ 'django.middleware.common.CommonMiddleware', 'django.middleware.common.BrokenLinkEmailsMiddleware', 'django.middleware.gzip.GZipMiddleware', -# 'htmlmin.middleware.HtmlMinifyMiddleware', -# 'htmlmin.middleware.MarkRequestMiddleware', + # 'htmlmin.middleware.HtmlMinifyMiddleware', + # 'htmlmin.middleware.MarkRequestMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', -# 'django.middleware.locale.LocaleMiddleware', + # 'django.middleware.locale.LocaleMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', @@ -106,14 +104,14 @@ MIDDLEWARE = [ 'tz_detect.middleware.TimezoneMiddleware', 'rowers.middleware.SurveyMiddleWare', 'rowers.middleware.GDPRMiddleWare', -# 'rowers.middleware.PowerTimeFitnessMetricMiddleWare', + # 'rowers.middleware.PowerTimeFitnessMetricMiddleWare', 'rowers.middleware.RowerPlanMiddleWare', ] ROOT_URLCONF = 'rowsandall_app.urls' HTML_MINIFY = True -#EXCLUDE_FROM_MINIFYING = ('^rowers/flexall', +# EXCLUDE_FROM_MINIFYING = ('^rowers/flexall', # '^rowers/list-workouts', # '^rowers/list-graphs', # '^admin/', @@ -124,7 +122,7 @@ APPEND_SLASH = True TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR,'templates')], + 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -132,19 +130,18 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', - 'django.template.context_processors.i18n', -# 'context_processors.google_analytics', + 'django.template.context_processors.i18n', + # 'context_processors.google_analytics', 'context_processors.warning_message', 'rowers.context_processors.braintree_merchant', ], - 'libraries' : { + 'libraries': { 'staticfiles': 'django.templatetags.static', } -# 'loaders': [ -# 'django.template.loaders.app_directories.Loader', -# ], + # 'loaders': [ + # 'django.template.loaders.app_directories.Loader', + # ], }, - }, ] @@ -177,8 +174,8 @@ DATABASES = { 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), }, 'TEST': { - 'CHARSET': 'utf8', - 'COLLATION': 'utf8_general_ci', + 'CHARSET': 'utf8', + 'COLLATION': 'utf8_general_ci', }, } @@ -192,9 +189,9 @@ AUTH_PASSWORD_VALIDATORS = [ }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - 'OPTIONS': { - 'min_length': 9, - } + 'OPTIONS': { + 'min_length': 9, + } }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', @@ -203,7 +200,7 @@ AUTH_PASSWORD_VALIDATORS = [ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, { - 'NAME': 'rowers.validator.LettersAndDigitsValidator', + 'NAME': 'rowers.validator.LettersAndDigitsValidator', } ] @@ -217,11 +214,11 @@ USE_I18N = True USE_L10N = False DATE_INPUT_FORMATS = [ - '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' - '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' - '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' - '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' - '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' + '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' + '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' + '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' + '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' + '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' ] DATE_FORMAT = 'Y-m-d' @@ -229,12 +226,12 @@ DATE_FORMAT = 'Y-m-d' USE_TZ = True TIME_ZONE = 'UTC' -TZ_DETECT_COUNTRIES = ('US','DE','GB','CZ','FR','IT') +TZ_DETECT_COUNTRIES = ('US', 'DE', 'GB', 'CZ', 'FR', 'IT') LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale'), -# os.path.join(BASE_DIR, 'cvkbrno/locale'), - ) + # os.path.join(BASE_DIR, 'cvkbrno/locale'), +) LANGUAGE_CODE = 'en-us' @@ -244,19 +241,16 @@ LANGUAGE_COOKIE_NAME = 'wm_lang' # https://docs.djangoproject.com/en/1.9/howto/static-files/ STATIC_URL = '/static/' -#STATIC_ROOT = BASE_DIR +# STATIC_ROOT = BASE_DIR STATIC_ROOT = os.path.join(BASE_DIR, 'static') -STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static/plots'),] +STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static/plots'), ] # os.path.join(BASE_DIR, 'static'), MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') - -# user authentication - # user authentication LOGIN_REDIRECT_URL = '/rowers/list-workouts/' LOGIN_URL = '/login/' @@ -268,18 +262,18 @@ LOGOUT_REDIRECT_URL = '/' PROGRESS_CACHE_SECRET = CFG['progress_cache_secret'] try: UPLOAD_SERVICE_URL = CFG['upload_service_url'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover UPLOAD_SERVICE_URL = "http://localhost:8000/rowers/workout/api/upload/" try: UPLOAD_SERVICE_SECRET = CFG['upload_service_secret'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover UPLOAD_SERVICE_SECRET = "FoYezZWLSyfAVimumpHEeYsJjsNCerxV" # Concept 2 C2_CLIENT_ID = CFG['c2_client_id'] C2_CLIENT_SECRET = CFG['c2_client_secret'] C2_REDIRECT_URI = CFG['c2_callback'] -#C2_REDIRECT_URI = "http://localhost:8000/call_back" +# C2_REDIRECT_URI = "http://localhost:8000/call_back" # Strava @@ -322,8 +316,8 @@ UNDERARMOUR_CLIENT_ID = CFG['underarmour_client_name'] UNDERARMOUR_CLIENT_SECRET = CFG['underarmour_client_secret'] UNDERARMOUR_CLIENT_KEY = CFG['underarmour_client_key'] UNDERARMOUR_REDIRECT_URI = CFG['underarmour_callback'] -#UNDERARMOUR_REDIRECT_URI = "http://rowsandall.com/underarmour_callback" -#UNDERARMOUR_REDIRECT_URI = "http://localhost:8000/underarmour_callback" +# UNDERARMOUR_REDIRECT_URI = "http://rowsandall.com/underarmour_callback" +# UNDERARMOUR_REDIRECT_URI = "http://localhost:8000/underarmour_callback" # TrainingPeaks TP_CLIENT_ID = CFG["tp_client_id"] @@ -355,56 +349,56 @@ RQ_QUEUES = { 'HOST': 'localhost', 'PORT': 6379, 'DB': 0, -# 'PASSWORD': 'some-password', + # 'PASSWORD': 'some-password', 'DEFAULT_TIMEOUT': 360, }, 'low': { 'HOST': 'localhost', 'PORT': 6379, 'DB': 0, -# 'PASSWORD': 'some-password', + # 'PASSWORD': 'some-password', 'DEFAULT_TIMEOUT': 360, }, 'high': { 'HOST': 'localhost', 'PORT': 6379, 'DB': 0, -# 'PASSWORD': 'some-password', + # 'PASSWORD': 'some-password', 'DEFAULT_TIMEOUT': 360, }, } -#SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" -#SESSION_ENGINE = "django.contrib.sessions.backends.cached_db" +# SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" +# SESSION_ENGINE = "django.contrib.sessions.backends.cached_db" SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_SAVE_EVERY_REQUEST = True SESSION_EXPIRE_AT_BROWSER_CLOSE = True # admin stuff for error reporting -SERVER_EMAIL='admin@rowsandall.com' -ADMINS = [('Sander','roosendaalsander@gmail.com')] +SERVER_EMAIL = 'admin@rowsandall.com' +ADMINS = [('Sander', 'roosendaalsander@gmail.com')] CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': 'localhost:11211', 'TIMEOUT': 900, - } } +} CACHE_MIDDLEWARE_ALIAS = 'default' CACHE_MIDDLEWARE_SECONDS = 900 # email stuff -#EMAIL_BACKEND = CFG['email_backend'] -#EMAIL_HOST = CFG['email_host'] -#EMAIL_PORT = CFG['email_port'] -#EMAIL_HOST_USER = CFG['email_host_user'] -#EMAIL_HOST_PASSWORD = CFG['email_host_password'] -#EMAIL_USE_TLS = CFG['email_use_tls'] -#DEFAULT_FROM_EMAIL = 'admin@rowsandall.com' +# EMAIL_BACKEND = CFG['email_backend'] +# EMAIL_HOST = CFG['email_host'] +# EMAIL_PORT = CFG['email_port'] +# EMAIL_HOST_USER = CFG['email_host_user'] +# EMAIL_HOST_PASSWORD = CFG['email_host_password'] +# EMAIL_USE_TLS = CFG['email_use_tls'] +# DEFAULT_FROM_EMAIL = 'admin@rowsandall.com' EMAIL_BACKEND = 'django_ses.SESBackend' @@ -413,7 +407,7 @@ AWS_SES_REGION_ENDPOINT = CFG['aws_smtp'] AWS_SES_ACCESS_KEY_ID = CFG['aws_access_key_id'] AWS_SES_SECRET_ACCESS_KEY = CFG['aws_secret_access_key'] -AWS_ACCESS_KEY_ID = CFG['aws_access_key_id'] +AWS_ACCESS_KEY_ID = CFG['aws_access_key_id'] AWS_SECRET_ACCESS_KEY = CFG['aws_secret_access_key'] EMAIL_HOST = CFG['aws_smtp'] @@ -441,7 +435,7 @@ OAUTH2_PROVIDER = { 'APPLICATION_MODEL': 'oauth2_provider.Application', 'REFRESH_TOKEN_MODEL': 'oauth2_provider.RefreshToken', 'ACCESS_TOKEN_EXPIRE_SECONDS': 36000, - #'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore' + # 'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore' } @@ -452,38 +446,38 @@ REST_FRAMEWORK = { # or allow read-only access for unauthenticated users. 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated' -# 'rest_framework.permissions.DjangoModelPermissions' + # 'rest_framework.permissions.DjangoModelPermissions' ], 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', -# 'rest_framework.authentication.SessionAuthentication', -# 'rest_framework.authentication.TokenAuthentication', + # 'rest_framework.authentication.SessionAuthentication', + # 'rest_framework.authentication.TokenAuthentication', 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', ), 'PAGE_SIZE': 20, - 'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.LimitOffsetPagination', + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', } SWAGGER_SETTINGS = { 'SECURITY_DEFINITIONS': { 'basic': { - 'type':'basic' - }, + 'type': 'basic' + }, 'oauth2': { - 'type':'oauth2', - 'authorizationUrl':'/rowers/o/authorize', + 'type': 'oauth2', + 'authorizationUrl': '/rowers/o/authorize', 'flow': 'implicit', - }, - 'api_key': { + }, + 'api_key': { 'type': 'apiKey', 'in': 'header', 'name': 'Authorization' }, - }, + }, 'SHOW_REQUEST_HEADERS': True, 'USE_SESSION_AUTH': True, 'JSON_EDITOR': True, - } +} # Analytics @@ -517,75 +511,75 @@ except KeyError: try: BRAINTREE_MERCHANT_ID = CFG['braintree_merchant_id'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover BRAINTREE_MERCHANT_ID = '' try: BRAINTREE_MERCHANT_ACCOUNT_ID = CFG['braintree_merchant_account_id'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover BRAINTREE_MERCHANT_ACCOUNT_ID = 'rowsandallEUR' try: BRAINTREE_PUBLIC_KEY = CFG['braintree_public_key'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover BRAINTREE_PUBLIC_KEY = '' try: BRAINTREE_PRIVATE_KEY = CFG['braintree_private_key'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover BRAINTREE_PRIVATE_KEY = '' try: BRAINTREE_SANDBOX_MERCHANT_ID = CFG['braintree_sandbox_merchant_id'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover BRAINTREE_SANDBOX_MERCHANT_ID = '' try: BRAINTREE_SANDBOX_PUBLIC_KEY = CFG['braintree_sandbox_public_key'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover BRAINTREE_SANDBOX_PUBLIC_KEY = '' try: BRAINTREE_SANDBOX_PRIVATE_KEY = CFG['braintree_sandbox_private_key'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover BRAINTREE_SANDBOX_PRIVATE_KEY = '' try: PAYMENT_PROCESSING_ON = CFG['payment_processing_on'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover PAYMENT_PROCESSING_ON = False try: FAKTUROID_API_KEY = CFG['fakturoid_api_key'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover FAKTUROID_API_KEY = '' try: FAKTUROID_EMAIL = CFG['fakturoid_email'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover FAKTUROID_EMAIL = '' try: FAKTUROID_SLUG = CFG['fakturoid_slug'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover FAKTUROID_SLUG = '' # ID obfuscation try: OPAQUE_SECRET_KEY = CFG['opaque_secret_key'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover OPAQUE_SECRET_KEY = 0xa193443a # Celery or RQ try: CELERY = CFG['use_celery'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover CELERY = False try: WORKOUTS_FIT_TOKEN = CFG['workouts_fit_token'] WORKOUTS_FIT_URL = CFG['workouts_fit_url'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover WORKOUTS_FIT_TOKEN = 'aapnootmies' WORKOUTS_FIT_URL = 'http://localhost:50053/tojson' @@ -594,10 +588,15 @@ except KeyError: # pragma: no cover try: RECAPTCHA_SITE_KEY = CFG['recaptcha_site_key'] RECAPTCHA_SITE_SECRET = CFG['recaptcha_site_secret'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover RECAPTCHA_SITE_KEY = '' RECAPTCHA_SITE_SECRET = '' GEOIP_PATH = STATIC_ROOT TAGGIT_CASE_INSENSITIVE = True + +try: + MYLOGGING = CFG['logging'] +except KeyError: + MYLOGGING = {} diff --git a/rowsandall_app/settings_dev.py b/rowsandall_app/settings_dev.py index 685ec003..5bcfef4a 100644 --- a/rowsandall_app/settings_dev.py +++ b/rowsandall_app/settings_dev.py @@ -14,15 +14,13 @@ import sys try: use_sqlite = CFG['use_sqlite'] -except KeyError: # pragma: no cover +except KeyError: # pragma: no cover use_sqlite = False for element in sys.argv: if 'test' in element: TESTING = True - - if TESTING or use_sqlite: DATABASES = { 'default': { @@ -31,7 +29,8 @@ if TESTING or use_sqlite: 'HOST': 'localhost', 'USER': '', 'PASSWORD': 'roeidata', - 'PORT': '3306', }, + 'PORT': '3306', + }, # 'TEST': { # 'CHARSET': 'utf8', # 'COLLATION': 'utf8_general_ci', @@ -42,7 +41,7 @@ if TESTING or use_sqlite: # 'NAME': 'rowsanda_107501', # 'USER': 'rowsanda_107501', - # } + # } } @@ -63,10 +62,10 @@ DEBUG = True TEMPLATES[0]['OPTIONS']['debug'] = DEBUG -ALLOWED_HOSTS = ['localhost','127.0.0.1','dunav.ngrok.io'] +ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'dunav.ngrok.io'] # INSTALLED_APPS += ['debug_toolbar',] -#INSTALLED_APPS += ["sslserver"] +# INSTALLED_APPS += ["sslserver"] # MIDDLEWARE_CLASSES += ['debug_toolbar.middleware.DebugToolbarMiddleware',] @@ -74,18 +73,20 @@ CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': os.path.join(BASE_DIR, 'django_cache'), - } } +} # Application definition STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR -#STATIC_ROOT = os.path.join(BASE_DIR, 'static') +# STATIC_ROOT = os.path.join(BASE_DIR, 'static') -STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), - os.path.join(BASE_DIR, 'static/plots'),] +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'static'), + os.path.join(BASE_DIR, 'static/plots'), +] INTERNAL_IPS = ['127.0.0.1'] @@ -99,10 +100,10 @@ SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" SITE_URL = "http://localhost:8000" -#EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +# EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -#EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' -#EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +# EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' +# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_BACKEND = 'django_ses.SESBackend' diff --git a/rowsandall_app/settings_thinkpad.py b/rowsandall_app/settings_thinkpad.py deleted file mode 100644 index 04932380..00000000 --- a/rowsandall_app/settings_thinkpad.py +++ /dev/null @@ -1,104 +0,0 @@ -""" -Django settings for rowsandall_app project. - -Generated by 'django-admin startproject' using Django 1.9.5. - -For more information on this file, see -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/ -""" - -import os - -from .settings import * - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), -# 'HOST': 'localhost', - }, -# 'TEST': { -# 'CHARSET': 'utf8', -# 'COLLATION': 'utf8_general_ci', -# }, - -# 'slave': { -# 'ENGINE': 'django.db.backends.mysql', -# 'NAME': 'rowsanda_107501', -# 'USER': 'rowsanda_107501', -# 'PASSWORD': 'roeidata', -# 'HOST': 'store3.rosti.cz', -# 'PORT': '3306', -# } - } - -#BROKER_URL = 'redis://localhost:6379/0' -#CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' -#CELERY_IGNORE_RESULT = False - -#CELERY_ACCEPT_CONTENT = ['json'] -#CELERY_TASK_SERIALIZER = 'json' -#CELERY_RESULT_SERIALIZER = 'json' -#CELERY_TRACK_STARTED = True -#CELERY_SEND_TASK_SENT_EVENT = True - - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -TEMPLATES[0]['OPTIONS']['debug'] = DEBUG - -ALLOWED_HOSTS = [] - -INSTALLED_APPS += ['debug_toolbar',] - -MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware',] - -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', - 'LOCATION': os.path.join(BASE_DIR, 'django_cache'), - } - } - -# Application definition - - -STATIC_URL = '/static/' -STATIC_ROOT = BASE_DIR -STATICFILES_DIRS = [os.path.join(BASE_DIR,'static/plots'),os.path.join(BASE_DIR,'static'),] - -# INTERNAL_IPS = ['127.0.0.1'] - -MEDIA_URL = '/media/' -MEDIA_ROOT = os.path.join(BASE_DIR, 'media') - -LOGIN_REDIRECT_URL = '/rowers/list-workouts/' - -SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" - -SITE_URL = "http://localhost:8000" - -#EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' - -#EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' -#EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' - -#EMAIL_BACKEND = 'django_ses.SESBackend' - -AWS_SES_REGION_NAME = 'eu-west-1' -AWS_SES_REGION_ENDPOINT = 'email.eu-west-1.amazonaws.com' - -EMAIL_HOST = CFG['aws_smtp'] -EMAIL_PORT = CFG['aws_port'] -EMAIL_HOST_USER = CFG['aws_smtp_username'] -EMAIL_HOST_PASSWORD = CFG['aws_smtp_password'] -EMAIL_USE_TLS = CFG['email_use_tls'] -DEFAULT_FROM_EMAIL = 'info@rowsandall.com' - -SETTINGS_NAME = 'rowsandall_app.settings_thinkpad' - - diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py index 9fb16da9..5692ba76 100644 --- a/rowsandall_app/urls.py +++ b/rowsandall_app/urls.py @@ -25,69 +25,80 @@ from rowers import views as rowersviews from survey import views as surveyviews import django +import django.views.i18n + # admin look admin.site.enable_nav_sidebar = False -import django.views.i18n - urlpatterns = [ re_path('^', include('django.contrib.auth.urls')), - re_path(r'^password_change_done/$',auth_views.PasswordChangeDoneView.as_view(),name='password_change_done'), - re_path(r'^password_change/$',auth_views.PasswordChangeView.as_view(),name='password_change'), - re_path(r'^password_reset/$', + re_path( + r'^password_change_done/$', + auth_views.PasswordChangeDoneView.as_view(), + name='password_change_done'), + re_path( + r'^password_change/$', + auth_views.PasswordChangeView.as_view(), + name='password_change'), + re_path( + r'^password_reset/$', auth_views.PasswordResetView.as_view(), {'template_name': 'rowers/templates/registration/password_reset.html'}, name='password_reset'), - re_path(r'^password_reset/done/$', + re_path( + r'^password_reset/done/$', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'), - re_path(r'^reset/(?P[0-9A-Za-z_\-]+)/(?P.+)/$', + re_path( + r'^reset/(?P[0-9A-Za-z_\-]+)/(?P.+)/$', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'), - re_path(r'^reset/done/$', + re_path( + r'^reset/done/$', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'), - ] +] urlpatterns += [ - re_path(r'^robots\.txt$', TemplateView.as_view(template_name='robots.txt', - content_type='text/plain')), + re_path(r'^robots\.txt$', TemplateView.as_view( + template_name='robots.txt', + content_type='text/plain')), re_path(r'^admin/', admin.site.urls), re_path(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework2')), - re_path(r'^$',landingview), - re_path(r'^landing/$',landingview), - re_path(r'^getblogs/$',rowersviews.get_blog_posts), + re_path(r'^$', landingview), + re_path(r'^landing/$', landingview), + re_path(r'^getblogs/$', rowersviews.get_blog_posts), re_path(r'^login/', -# auth_views.LoginView, + # auth_views.LoginView, auth_views.LoginView.as_view(), name='login'), re_path(r'^logout/$', - auth_views.LogoutView.as_view(), - {'next_page': '/'}, - name='logout',), - re_path(r'^rowers/',include('rowers.urls')), -# re_path(r'^survey/',include('survey.urls')), -# re_path(r'^cvkbrno/',include('cvkbrno.urls')), -# re_path(r'^admin/rq/',include('django_rq_dashboard.urls')), - re_path(r'^call\_back',rowersviews.rower_process_callback), - re_path(r'^nk\_callback',rowersviews.rower_process_nkcallback), - re_path(r'^stravacall\_back',rowersviews.rower_process_stravacallback), - re_path(r'^garmin\_callback',rowersviews.rower_process_garmincallback), - re_path(r'^sporttracks\_callback',rowersviews.rower_process_sporttrackscallback), - re_path(r'^polarflowcallback',rowersviews.rower_process_polarcallback), - re_path(r'^tp\_callback',rowersviews.rower_process_tpcallback), - re_path(r'^rp3\_callback',rowersviews.rower_process_rp3callback), - re_path(r'^twitter\_callback',rowersviews.rower_process_twittercallback), + auth_views.LogoutView.as_view(), + {'next_page': '/'}, + name='logout',), + re_path(r'^rowers/', include('rowers.urls')), + # re_path(r'^survey/',include('survey.urls')), + # re_path(r'^cvkbrno/',include('cvkbrno.urls')), + # re_path(r'^admin/rq/',include('django_rq_dashboard.urls')), + re_path(r'^call\_back', rowersviews.rower_process_callback), + re_path(r'^nk\_callback', rowersviews.rower_process_nkcallback), + re_path(r'^stravacall\_back', rowersviews.rower_process_stravacallback), + re_path(r'^garmin\_callback', rowersviews.rower_process_garmincallback), + re_path(r'^sporttracks\_callback', rowersviews.rower_process_sporttrackscallback), + re_path(r'^polarflowcallback', rowersviews.rower_process_polarcallback), + re_path(r'^tp\_callback', rowersviews.rower_process_tpcallback), + re_path(r'^rp3\_callback', rowersviews.rower_process_rp3callback), + re_path(r'^twitter\_callback', rowersviews.rower_process_twittercallback), re_path(r'^i18n/', include('django.conf.urls.i18n')), re_path(r'^tz_detect/', include('tz_detect.urls')), - re_path(r'^logo/',logoview), - re_path(r'^media/(?P.*\.fit)$',rowersviews.download_fit), + re_path(r'^logo/', logoview), + re_path(r'^media/(?P.*\.fit)$', rowersviews.download_fit), path('django-rq/', include('django_rq.urls')), -# path('500/', rowersviews.error500_view), -# re_path(r'^jsi18n/', django.views.i18n.javascript_catalog,name='jsi18n'), - ] + # path('500/', rowersviews.error500_view), + # re_path(r'^jsi18n/', django.views.i18n.javascript_catalog,name='jsi18n'), +] js_info_dict = { 'packages': ('recurrence', ), @@ -100,7 +111,7 @@ urlpatterns += [ # monkey patch workaround for bug in recurrence library django.views.i18n.javascript_catalog = None -if settings.DEBUG: # pragma: no cover +if settings.DEBUG: # pragma: no cover import debug_toolbar import django urlpatterns += [ @@ -109,10 +120,13 @@ if settings.DEBUG: # pragma: no cover kwargs={'document_root': settings.STATIC_ROOT+'plots/'}) ] urlpatterns += [ -# re_path(r'^__debug__/','debug_toolbar.urls'), - re_path(r'^static/(?P.*)$', + # re_path(r'^__debug__/','debug_toolbar.urls'), + re_path( + r'^static/(?P.*)$', django.views.static.serve, - kwargs={'document_root': settings.STATIC_ROOT, - 'show_indexes': True} + kwargs={ + 'document_root': settings.STATIC_ROOT, + 'show_indexes': True + } ) ] diff --git a/rowsandall_app/views.py b/rowsandall_app/views.py index e92f2fd0..b18c6c8f 100644 --- a/rowsandall_app/views.py +++ b/rowsandall_app/views.py @@ -9,65 +9,64 @@ from rowingdata import main as rmain import random -def landingview(request): - loginform = LoginForm() - return render(request, - 'landingpage.html', +def landingview(request): + return render( + request, + 'landingpage.html', ) -def logoview(request): # pragma: no cover + +def logoview(request): # pragma: no cover image_data = open(settings.STATIC_ROOT+"/img/apple-icon-144x144.png", "rb").read() return HttpResponse(image_data, content_type="image/png") -def rootview(request): # pragma: no cover +def rootview(request): # pragma: no cover magicsentence = rmain() loginform = LoginForm() planoffering = { 'name': 'PLAN', - 'image':'/static/img/Plan.png', - 'text':'We offer a fully integrated way for you or your coach to set up a training plan. Compare plan vs execution based on time, distance, heart rate or power.' - } + 'image': '/static/img/Plan.png', + 'text': 'We offer a fully integrated way for you or your coach to set up a training plan. Compare plan vs execution based on time, distance, heart rate or power.' + } uploadoffering = { 'name': 'SYNC', - 'image':'/static/img/upload.png', - 'text':'Easily upload data from the most popular devices and apps' - } + 'image': '/static/img/upload.png', + 'text': 'Easily upload data from the most popular devices and apps' + } logoffering = { 'name': 'LOG', - 'image':'/static/img/log.png', - 'text':'Maintain a consistent log for all your rowing (indoor and on the water)' - } + 'image': '/static/img/log.png', + 'text': 'Maintain a consistent log for all your rowing (indoor and on the water)' + } analyzeoffering = { 'name': 'ANALYZE', - 'image':'/static/img/analyze.png', - 'text':'Analyze your workouts with a consistent set of tools' - } + 'image': '/static/img/analyze.png', + 'text': 'Analyze your workouts with a consistent set of tools' + } compareoffering = { 'name': 'COMPARE', - 'image':'/static/img/compare.png', - 'text':'Compare your results between workouts and with other rowers in your team' - } + 'image': '/static/img/compare.png', + 'text': 'Compare your results between workouts and with other rowers in your team' + } raceoffering = { 'name': 'RACE', - 'image':'/static/img/Race 01.png', - 'text':'Virtual regattas are an informal way to add a competitive element to your training and can be used as a quick way to set up small regattas' - } + 'image': '/static/img/Race 01.png', + 'text': 'Virtual regattas are an informal way to add a competitive element to your training and can be used as a quick way to set up small regattas' + } coachoffering = { 'name': 'COACHING', - 'image':'/static/img/Remote coaching.png', - 'text':'Rowsandall.com is the ideal platform for remote rowing coaching. As a coach, you can easily manage your athletes, set up plans and monitor execution and technique' - } - - + 'image': '/static/img/Remote coaching.png', + 'text': 'Rowsandall.com is the ideal platform for remote rowing coaching. As a coach, you can easily manage your athletes, set up plans and monitor execution and technique' + } allofferings = [ planoffering, @@ -77,7 +76,7 @@ def rootview(request): # pragma: no cover raceoffering, compareoffering, coachoffering, - ] + ] aux = list(allofferings) random.shuffle(aux) @@ -88,6 +87,6 @@ def rootview(request): # pragma: no cover 'frontpage.html', { 'versionstring': magicsentence, - 'form':loginform, - 'offerings':offerings, + 'form': loginform, + 'offerings': offerings, }) diff --git a/rowsandall_app/wsgi.py b/rowsandall_app/wsgi.py index 62686321..a6d5107e 100644 --- a/rowsandall_app/wsgi.py +++ b/rowsandall_app/wsgi.py @@ -13,4 +13,4 @@ from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rowsandall_app.settings") -application = get_wsgi_application() +application = get_wsgi_application() diff --git a/static/css/rowsandall2.css b/static/css/rowsandall2.css index c4d36853..a157f4ae 100644 --- a/static/css/rowsandall2.css +++ b/static/css/rowsandall2.css @@ -322,6 +322,61 @@ th.rotate > div > span { margin: 2px; } + +.stepcontainer { + display: grid; + grid-template-columns: 4fr 1fr 4fr; + gap: 10px; +} + +.trainingstep { + border: 3px solid #666; + background-color: #ddd; + border-radius: .5em; + padding: 10px; + cursor: move; +} + +.trainingstep.over { + border: 3px dotted #666; +} + +.trainingstep.Warmup { + background-color: #ffcccb; +} + +.trainingstep.Cooldown { + background-color: #90ee90; +} + +.trainingstep.Rest { + background-color: #add8e6; +} + +.RepeatUntilStepsCmplt { + background-color: #ffffa7; +} + +.drop-zone { + position: relative; + overflow: hidden; + background-color: #D7D7D7; + /* color: white; */ + padding: 10px; + padding-bottom: 40px; +} + +.allcentered { + /* Center vertically and horizontally */ + display: flex; + justify-content: center; + align-items: center; +} + +.allcenteredchild { + margin-top: 50%; +} + .divlines { display: block; overflow-x: hidden; diff --git a/tox.ini b/tox.ini index 3fb438ed..763b93d2 100644 --- a/tox.ini +++ b/tox.ini @@ -1,4 +1,4 @@ [flake8] -ignore = F405, F403, E722, E226, W504, F401, W605 +ignore = F405, F403, E722, E226, W504, F401, W605, E501 max-line-length = 120 -exclude = .git, rowers/migrations +exclude = .git, rowers/migrations, rowers/tests, rowers/admin.py