Private
Public Access
1
0

Merge branch 'feature/autopep' into develop

This commit is contained in:
Sander Roosendaal
2022-03-15 10:22:21 +01:00
59 changed files with 1136 additions and 1886 deletions
+1 -4
View File
@@ -2,9 +2,7 @@ from rowers.models import Alert, Condition, User, Rower, Workout
from rowers.teams import coach_getcoachees from rowers.teams import coach_getcoachees
from rowers.dataprep import getsmallrowdata_db, getrowdata_db from rowers.dataprep import getsmallrowdata_db, getrowdata_db
import datetime import datetime
# BASIC operations import numpy as np
# create alert
def create_alert(manager, rower, measured, period=7, emailalert=True, def create_alert(manager, rower, measured, period=7, emailalert=True,
@@ -65,7 +63,6 @@ def alert_add_filters(alert, filters):
for f in filters: for f in filters:
metric = f['metric'] metric = f['metric']
value1 = f['value1'] value1 = f['value1']
value2 = f['value2']
condition = f['condition'] condition = f['condition']
if condition and metric and value1: if condition and metric and value1:
+14 -39
View File
@@ -72,8 +72,7 @@ def process_webhook(notification):
transactions = subscription.transactions transactions = subscription.transactions
if transactions: if transactions:
amount = int(transactions[0].amount) amount = int(transactions[0].amount)
eurocredits = credits.upgrade(amount, r) _ = credits.upgrade(amount, r)
eurocredits = credits.upgrade(amount, r)
return send_invoice(notification.subscription) return send_invoice(notification.subscription)
if notification.kind == 'subscription_canceled': if notification.kind == 'subscription_canceled':
subscription = notification.subscription subscription = notification.subscription
@@ -97,10 +96,7 @@ def process_webhook(notification):
def send_invoice(subscription): def send_invoice(subscription):
with open('braintreewebhooks.log', 'a') as f: dologging('braintreewebhooks.log', 'Subscription ID '+str(subscription.id))
t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
f.write('Subscription ID '+str(subscription.id)+'\n')
subscription_id = subscription.id subscription_id = subscription.id
rs = Rower.objects.filter(subscription_id=subscription_id) rs = Rower.objects.filter(subscription_id=subscription_id)
if rs.count() == 0: # pragma: no cover if rs.count() == 0: # pragma: no cover
@@ -176,20 +172,6 @@ def get_client_token(rower):
return client_token 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): def make_payment(rower, data):
nonce_from_the_client = data['payment_method_nonce'] nonce_from_the_client = data['payment_method_nonce']
nonce = gateway.payment_method_nonce.find(nonce_from_the_client) 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) fakturoid_contact_id = fakturoid.get_contacts(rower)
if not fakturoid_contact_id: if not fakturoid_contact_id:
fakturoid_contact_id = fakturoid.create_contact(rower) fakturoid_contact_id = fakturoid.create_contact(rower)
id = fakturoid.create_invoice(rower, amount, transaction.id, dosend=True, contact_id=fakturoid_contact_id, _ = fakturoid.create_invoice(rower, amount, transaction.id, dosend=True, contact_id=fakturoid_contact_id,
name=additional_text) name=additional_text)
try: _ = myqueue(queuehigh, handle_send_email_transaction,
job = myqueue(queuehigh, handle_send_email_transaction,
name, rower.user.email, amount) 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
return amount, True return amount, True
else: # pragma: no cover else: # pragma: no cover
return 0, False return 0, False
@@ -280,7 +256,7 @@ def update_subscription(rower, data, method='up'):
yesterday = (timezone.now()-datetime.timedelta(days=1)).date() yesterday = (timezone.now()-datetime.timedelta(days=1)).date()
rower.paidplan = plan rower.paidplan = plan
amount_int = int(float(amount)) 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.planexpires = result.subscription.billing_period_end_date
rower.teamplanexpires = result.subscription.billing_period_end_date rower.teamplanexpires = result.subscription.billing_period_end_date
rower.clubsize = plan.clubsize rower.clubsize = plan.clubsize
@@ -319,7 +295,7 @@ def update_subscription(rower, data, method='up'):
else: # pragma: no cover else: # pragma: no cover
amount = 0 amount = 0
job = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_send_email_subscription_update, handle_send_email_subscription_update,
name, rower.user.email, name, rower.user.email,
plan.name, plan.name,
@@ -352,12 +328,12 @@ def create_subscription(rower, data):
nonce_from_the_client = data['payment_method_nonce'] nonce_from_the_client = data['payment_method_nonce']
nonce = gateway.payment_method_nonce.find(nonce_from_the_client) nonce = gateway.payment_method_nonce.find(nonce_from_the_client)
info = nonce.three_d_secure_info info = nonce.three_d_secure_info
paymenttype = nonce.type # paymenttype = nonce.type
if nonce.type != 'PayPalAccount': # pragma: no cover if nonce.type != 'PayPalAccount': # pragma: no cover
if info is None or not info.liability_shifted: if info is None or not info.liability_shifted:
return False, 0 return False, 0
amount = data['amount'] # amount = data['amount']
planid = data['plan'] planid = data['plan']
plan = PaidPlan.objects.get(id=planid) plan = PaidPlan.objects.get(id=planid)
@@ -399,7 +375,7 @@ def create_subscription(rower, data):
recurring = plan.paymenttype recurring = plan.paymenttype
job = myqueue( _ = myqueue(
queuehigh, queuehigh,
handle_send_email_subscription_create, handle_send_email_subscription_create,
name, rower.user.email, name, rower.user.email,
@@ -420,16 +396,17 @@ def cancel_subscription(rower, id):
themessages = [] themessages = []
errormessages = [] errormessages = []
try: try:
result = gateway.subscription.cancel(id) _ = gateway.subscription.cancel(id)
themessages.append("Subscription canceled") themessages.append("Subscription canceled")
except: # pragma: no cover except: # pragma: no cover
errormessages.append( 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, name = '{f} {l}'.format(f=rower.user.first_name,
l=rower.user.last_name) l=rower.user.last_name)
job = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_send_email_failed_cancel, handle_send_email_failed_cancel,
name, rower.user.email, rower.user.username, id) name, rower.user.email, rower.user.username, id)
@@ -510,15 +487,13 @@ def get_transactions(start_date, end_date): # pragma: no cover
dates = [] dates = []
currencies = [] currencies = []
statuses = [] statuses = []
ids = [] # ids = []
usernames = [] usernames = []
customerids = [] customerids = []
transactionids = [] transactionids = []
subscriptionids = [] subscriptionids = []
ownids = [] ownids = []
countlines = [1 for transaction in results]
for transaction in results: for transaction in results:
r = None r = None
rs = Rower.objects.filter( rs = Rower.objects.filter(
+24 -58
View File
@@ -74,11 +74,12 @@ def getagegrouprecord(age, sex='male', weightcategory='hwt',
ages = df['age'] ages = df['age']
powers = df['power'] powers = df['power']
#poly_coefficients = np.polyfit(ages,powers,6) def fitfunc(pars, x):
def fitfunc(pars, x): return np.abs(pars[0])*(1-x/max(120, pars[1]))-np.abs( 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]))) 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] p0 = [700, 120, 700, 10, 100, 100]
@@ -92,8 +93,6 @@ def getagegrouprecord(age, sex='male', weightcategory='hwt',
if success: if success:
power = fitfunc(p1, float(age)) power = fitfunc(p1, float(age))
#power = np.polyval(poly_coefficients,age)
power = 0.5*(np.abs(power)+power) power = 0.5*(np.abs(power)+power)
else: # pragma: no cover else: # pragma: no cover
power = 0 power = 0
@@ -123,14 +122,13 @@ oauth_data = {
def c2_open(user): def c2_open(user):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None): if (r.c2token == '') or (r.c2token is None):
s = "Token doesn't exist. Need to authorize"
raise NoTokenError("User has no token") raise NoTokenError("User has no token")
else: else:
if (timezone.now() > r.tokenexpirydate): if (timezone.now() > r.tokenexpirydate):
res = rower_c2_token_refresh(user) 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") raise NoTokenError("User has no token")
if res[0] != None: if res[0] is not None:
thetoken = res[0] thetoken = res[0]
else: # pragma: no cover else: # pragma: no cover
raise NoTokenError("User has no token") raise NoTokenError("User has no token")
@@ -142,7 +140,7 @@ def c2_open(user):
def get_c2_workouts(rower, page=1, do_async=True): def get_c2_workouts(rower, page=1, do_async=True):
try: try:
thetoken = c2_open(rower.user) _ = c2_open(rower.user)
except NoTokenError: # pragma: no cover except NoTokenError: # pragma: no cover
return 0 return 0
@@ -175,7 +173,7 @@ def get_c2_workouts(rower, page=1, do_async=True):
knownc2ids = uniqify(knownc2ids+tombstones+parkedids) 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: if settings.TESTING:
newids = c2ids newids = c2ids
@@ -188,20 +186,18 @@ def get_c2_workouts(rower, page=1, do_async=True):
counter = 0 counter = 0
for c2id in newids: for c2id in newids:
if do_async: # pragma: no cover if do_async: # pragma: no cover
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_c2_async_workout, handle_c2_async_workout,
alldata, alldata,
rower.user.id, rower.user.id,
rower.c2token, rower.c2token,
c2id, c2id,
counter, counter,
rower.defaulttimezone rower.defaulttimezone)
)
#res = handle_c2_async_workout(alldata,rower.user.id,rower.c2token,c2id,counter)
counter = counter+1 counter = counter+1
else: else:
workoutid = create_async_workout(alldata, _ = create_async_workout(alldata, rower.user, c2id)
rower.user, c2id)
return 1 return 1
@@ -212,12 +208,9 @@ def create_async_workout(alldata, user, c2id):
data = alldata[c2id] data = alldata[c2id]
splitdata = None splitdata = None
distance = data['distance']
c2id = data['id'] c2id = data['id']
workouttype = data['type'] workouttype = data['type']
verified = data['verified']
startdatetime = iso8601.parse_date(data['date']) startdatetime = iso8601.parse_date(data['date'])
weightclass = data['weight_class']
try: try:
title = data['name'] title = data['name']
@@ -229,43 +222,16 @@ def create_async_workout(alldata, user, c2id):
except: except:
title = '' title = ''
weightcategory = 'hwt'
if weightclass == "L":
weightcategory = 'lwt'
# Create CSV file name and save data to CSV file # Create CSV file name and save data to CSV file
csvfilename = 'media/Import_'+str(c2id)+'.csv.gz' 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) r = Rower.objects.get(user=user)
authorizationstring = str('Bearer ' + r.c2token) authorizationstring = str('Bearer ' + r.c2token)
headers = {'Authorization': authorizationstring, headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal', 'user-agent': 'sanderroosendaal',
'Content-Type': 'application/json'} '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" url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes"
try: try:
s = requests.get(url, headers=headers) s = requests.get(url, headers=headers)
@@ -638,7 +604,7 @@ def createc2workoutdata(w):
spmav = int(row.df[' Cadence (stokes/min)'][mask].mean()) spmav = int(row.df[' Cadence (stokes/min)'][mask].mean())
hrav = int(row.df[' HRCur (bpm)'][mask].mean()) hrav = int(row.df[' HRCur (bpm)'][mask].mean())
except ValueError: except ValueError:
smpav = 0 spmav = 0
try: try:
hrav = int(row.df[' HRCur (bpm)'][mask].mean()) hrav = int(row.df[' HRCur (bpm)'][mask].mean())
except ValuError: except ValuError:
@@ -729,7 +695,6 @@ def createc2workoutdata(w):
"time": int(10*makeseconds(durationstr)), "time": int(10*makeseconds(durationstr)),
"weight_class": c2wc(w.weightcategory), "weight_class": c2wc(w.weightcategory),
"comments": w.notes, "comments": w.notes,
"stroke_count": int(row.stroke_count),
'stroke_rate': int(row.df[' Cadence (stokes/min)'].mean()), 'stroke_rate': int(row.df[' Cadence (stokes/min)'].mean()),
'drag_factor': int(row.dragfactor), 'drag_factor': int(row.dragfactor),
"heart_rate": { "heart_rate": {
@@ -749,7 +714,7 @@ def createc2workoutdata(w):
def do_refresh_token(refreshtoken): def do_refresh_token(refreshtoken):
scope = "results:write,user:read" 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", post_data = {"grant_type": "refresh_token",
"client_secret": C2_CLIENT_SECRET, "client_secret": C2_CLIENT_SECRET,
"client_id": C2_CLIENT_ID, "client_id": C2_CLIENT_ID,
@@ -793,7 +758,7 @@ def do_refresh_token(refreshtoken):
def get_token(code): def get_token(code):
messg = '' messg = ''
scope = "user:read,results:write" 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", post_data = {"grant_type": "authorization_code",
"code": code, "code": code,
"redirect_uri": C2_REDIRECT_URI, "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 # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
from uuid import uuid4 from uuid import uuid4
state = str(uuid4()) # state = str(uuid4())
scope = "user:read,results:write" scope = "user:read,results:write"
params = {"client_id": C2_CLIENT_ID, params = {"client_id": C2_CLIENT_ID,
@@ -857,9 +822,9 @@ def make_authorization_url(request): # pragma: no cover
def get_workout(user, c2id, do_async=True): def get_workout(user, c2id, do_async=True):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
thetoken = c2_open(user) _ = c2_open(user)
job = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_c2_getworkout, handle_c2_getworkout,
user.id, user.id,
r.c2token, r.c2token,
@@ -909,7 +874,7 @@ def get_username(access_token): # pragma: no cover
try: try:
res = me_json['data']['username'] res = me_json['data']['username']
id = me_json['data']['id'] _ = me_json['data']['id']
except KeyError: except KeyError:
res = None res = None
@@ -974,7 +939,7 @@ def workout_c2_upload(user, w, asynchron=False):
except KeyError: # pragma: no cover except KeyError: # pragma: no cover
return "This workout type cannot be uploaded to Concept2", 0 return "This workout type cannot be uploaded to Concept2", 0
thetoken = c2_open(user) _ = c2_open(user)
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
@@ -1017,11 +982,12 @@ def workout_c2_upload(user, w, asynchron=False):
w.save() w.save()
message = "Upload to Concept2 was successful" message = "Upload to Concept2 was successful"
else: # pragma: no cover 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 c2id = 0
else: # pragma: no cover else: # pragma: no cover
job = myqueue(queue, _ = myqueue(queue,
handle_c2_sync, handle_c2_sync,
w.id, w.id,
url, url,
+1 -9
View File
@@ -25,7 +25,7 @@ from django.conf import settings
import geocoder import geocoder
from matplotlib import path # from matplotlib import path
import xml.etree.ElementTree as et import xml.etree.ElementTree as et
from xml.etree.ElementTree import Element, SubElement, Comment, tostring from xml.etree.ElementTree import Element, SubElement, Comment, tostring
@@ -42,10 +42,6 @@ def howfaris(lat_lon, course):
return distance return distance
#whatisnear = 150
# get nearest races
def getnearestraces(lat_lon, races, whatisnear=150): def getnearestraces(lat_lon, races, whatisnear=150):
newlist = [] newlist = []
@@ -55,7 +51,6 @@ def getnearestraces(lat_lon, races, whatisnear=150):
newlist.append(race) newlist.append(race)
else: else:
c = race.course c = race.course
coords = c.coord
distance = howfaris(lat_lon, c) distance = howfaris(lat_lon, c)
if distance < whatisnear: if distance < whatisnear:
newlist.append(race) newlist.append(race)
@@ -84,7 +79,6 @@ def getnearestcourses(lat_lon, courses, whatisnear=150, strict=False):
newlist = [] newlist = []
counter = 0 counter = 0
for c in courses: for c in courses:
coords = c.coord
distance = howfaris(lat_lon, c) distance = howfaris(lat_lon, c)
if distance < whatisnear: if distance < whatisnear:
@@ -199,8 +193,6 @@ def coursetokml(course):
polygons = GeoPolygon.objects.filter( polygons = GeoPolygon.objects.filter(
course=course).order_by("order_in_course") course=course).order_by("order_in_course")
polygonsxml = []
for polygon in polygons: for polygon in polygons:
placemark = SubElement(folder2, 'Placemark') placemark = SubElement(folder2, 'Placemark')
polygonname = SubElement(placemark, 'name') polygonname = SubElement(placemark, 'name')
+2 -4
View File
@@ -20,10 +20,8 @@ def time_in_path(df, p, maxmin='max', getall=False, name='unknown', logfile=None
if df.empty: # pragma: no cover if df.empty: # pragma: no cover
return 0 return 0
latitude = df.latitude def f(x):
longitude = df.longitude 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) df['inpolygon'] = df.apply(f, axis=1)
+79 -96
View File
@@ -31,7 +31,6 @@ from zipfile import BadZipFile
import zipfile import zipfile
import os import os
from rowers.models import strokedatafields from rowers.models import strokedatafields
from rowingdata.csvparsers import HumonParser
from rowingdata import ( from rowingdata import (
KinoMapParser, KinoMapParser,
@@ -56,8 +55,7 @@ from rowingdata import (
ETHParser, ETHParser,
NKLiNKLogbookParser, NKLiNKLogbookParser,
HeroParser, HeroParser,
SmartRowParser, SmartRowParser,)
)
# All the data preparation, data cleaning and data mangling should # All the data preparation, data cleaning and data mangling should
# be defined here # be defined here
@@ -111,13 +109,8 @@ import arrow
thetimezone = get_current_timezone() thetimezone = get_current_timezone()
#allowedcolumns = [item[0] for item in rowingmetrics]
allowedcolumns = [key for key, value in strokedatafields.items()] allowedcolumns = [key for key, value in strokedatafields.items()]
#from async_messages import messages as a_messages
queue = django_rq.get_queue('default') queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low') queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('default') queuehigh = django_rq.get_queue('default')
@@ -169,8 +162,6 @@ def get_video_data(w, groups=['basic'], mode='water'):
p = nicepaceformat(p) p = nicepaceformat(p)
df2['pace'] = p df2['pace'] = p
#mask = df2['time'] < delay
#df2 = df2.mask(mask).dropna()
df2['time'] = (df2['time']-df2['time'].min()) df2['time'] = (df2['time']-df2['time'].min())
df2 = df2.round(decimals=2) 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.set_index(pd.to_timedelta(
coordinates['time'], unit='s'), inplace=True) coordinates['time'], unit='s'), inplace=True)
coordinates = coordinates.resample('1s').mean().interpolate() coordinates = coordinates.resample('1s').mean().interpolate()
#mask = coordinates['time'] < delay
#coordinates = coordinates.mask(mask).dropna()
coordinates['time'] = coordinates['time']-coordinates['time'].min() coordinates['time'] = coordinates['time']-coordinates['time'].min()
latitude = coordinates['latitude'] latitude = coordinates['latitude']
longitude = coordinates['longitude'] longitude = coordinates['longitude']
@@ -295,11 +284,11 @@ def get_latlon_time(id):
try: try:
try: try:
latitude = rowdata.df.loc[:, ' latitude'] _ = rowdata.df.loc[:, ' latitude']
longitude = rowdata.df.loc[:, ' longitude'] _ = rowdata.df.loc[:, ' longitude']
except KeyError: # pragma: no cover except KeyError: # pragma: no cover
latitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] rowdata.df['latitude'] = 0 * rowdata.df.loc[:, 'TimeStamp (sec)']
longitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] rowdata.df['longitude'] = 0 * rowdata.df.loc[:, 'TimeStamp (sec)']
except AttributeError: # pragma: no cover except AttributeError: # pragma: no cover
return pd.DataFrame() return pd.DataFrame()
@@ -438,7 +427,7 @@ def get_workouts(ids, userid): # pragma: no cover
def filter_df(datadf, fieldname, value, largerthan=True): def filter_df(datadf, fieldname, value, largerthan=True):
try: try:
x = datadf[fieldname] _ = datadf[fieldname]
except KeyError: except KeyError:
return datadf return datadf
@@ -486,9 +475,9 @@ def join_workouts(r, ids, title='Joined Workout',
makeprivate = False makeprivate = False
startdatetime = timezone.now() 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 makeprivate = True
elif setprivate == False and makeprivate == True: # pragma: no cover elif setprivate is False and makeprivate is True: # pragma: no cover
makeprivate = False makeprivate = False
# reorder in chronological order # reorder in chronological order
@@ -501,6 +490,11 @@ def join_workouts(r, ids, title='Joined Workout',
workouttype = parent.workouttype workouttype = parent.workouttype
notes = parent.notes notes = parent.notes
summary = parent.summary summary = parent.summary
if parent.privacy == 'hidden':
makeprivate = True
else:
makeprivate = False
startdatetime = parent.startdatetime
files = [w.csvfilename for w in ws] files = [w.csvfilename for w in ws]
@@ -524,7 +518,9 @@ def join_workouts(r, ids, title='Joined Workout',
notes=notes, notes=notes,
oarlength=oarlength, oarlength=oarlength,
inboard=inboard, inboard=inboard,
startdatetime=startdatetime,
makeprivate=makeprivate, makeprivate=makeprivate,
summary=summary,
dosmooth=False, dosmooth=False,
consistencychecks=False) consistencychecks=False)
@@ -585,12 +581,12 @@ def resample(id, r, parent, overwrite='copy'):
row.write_csv(parent.csvfilename, gzip=True) row.write_csv(parent.csvfilename, gzip=True)
res = dataprep(row.df, id=parent.id, bands=True, barchart=True, _ = dataprep(row.df, id=parent.id, bands=True, barchart=True,
otwpower=True, empower=True, inboard=parent.inboard) otwpower=True, empower=True, inboard=parent.inboard)
isbreakthrough, ishard = checkbreakthrough(parent, r) isbreakthrough, ishard = checkbreakthrough(parent, r)
marker = check_marker(parent) _ = check_marker(parent)
result = update_wps(r, mytypes.otwtypes) _ = update_wps(r, mytypes.otwtypes)
result = update_wps(r, mytypes.otetypes) _ = update_wps(r, mytypes.otetypes)
tss, normp = workout_rscore(parent) tss, normp = workout_rscore(parent)
goldmedalstandard, goldmedalseconds = workout_goldmedalstandard(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 # clean data remove zeros and negative values
try: try:
workoutids = datadf['workoutid'].unique() _ = datadf['workoutid'].unique()
except KeyError: except KeyError:
datadf['workoutid'] = 0 datadf['workoutid'] = 0
@@ -638,13 +634,13 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True,
# protect 0 spm values from being nulled # protect 0 spm values from being nulled
try: try:
datadf['spm'] = datadf['spm'] + 1.0 datadf['spm'] = datadf['spm'] + 1.0
except (KeyError, TypeError) as e: except (KeyError, TypeError):
pass pass
# protect 0 workoutstate values from being nulled # protect 0 workoutstate values from being nulled
try: try:
datadf['workoutstate'] = datadf['workoutstate'] + 1 datadf['workoutstate'] = datadf['workoutstate'] + 1
except (KeyError, TypeError) as e: except (KeyError, TypeError):
pass pass
try: try:
@@ -676,13 +672,13 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True,
# bring spm back to real values # bring spm back to real values
try: try:
datadf['spm'] = datadf['spm'] - 1 datadf['spm'] = datadf['spm'] - 1
except (TypeError, KeyError) as e: except (TypeError, KeyError):
pass pass
# bring workoutstate back to real values # bring workoutstate back to real values
try: try:
datadf['workoutstate'] = datadf['workoutstate'] - 1 datadf['workoutstate'] = datadf['workoutstate'] - 1
except (TypeError, KeyError) as e: except (TypeError, KeyError):
pass pass
# return from positive domain to negative # return from positive domain to negative
@@ -840,11 +836,11 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True,
except (KeyError, TypeError): except (KeyError, TypeError):
pass pass
workoutstateswork = [1, 4, 5, 8, 9, 6, 7] # workoutstateswork = [1, 4, 5, 8, 9, 6, 7]
workoutstatesrest = [3] 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: try:
datadf = datadf[~datadf['workoutstate'].isin(workoutstatesrest)] datadf = datadf[~datadf['workoutstate'].isin(workoutstatesrest)]
except: except:
@@ -872,10 +868,10 @@ def getpartofday(row, r):
timezone_str = tf.timezone_at(lng=lonavg, lat=latavg) timezone_str = tf.timezone_at(lng=lonavg, lat=latavg)
except (ValueError, OverflowError): # pragma: no cover except (ValueError, OverflowError): # pragma: no cover
timezone_str = 'UTC' 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, timezone_str = tf.closest_timezone_at(lng=lonavg,
lat=latavg) lat=latavg)
if timezone_str == None: if timezone_str is None:
timezone_str = r.defaulttimezone timezone_str = r.defaulttimezone
try: try:
workoutstartdatetime = pytz.timezone(timezone_str).localize( workoutstartdatetime = pytz.timezone(timezone_str).localize(
@@ -1008,7 +1004,7 @@ def update_c2id_sql(id, c2id):
table, c2id, id) table, c2id, id)
with engine.connect() as conn, conn.begin(): with engine.connect() as conn, conn.begin():
result = conn.execute(query) _ = conn.execute(query)
conn.close() conn.close()
engine.dispose() engine.dispose()
@@ -1022,7 +1018,8 @@ def getcpdata_sql(rower_id, table='cpdata'):
rower_id=rower_id, rower_id=rower_id,
table=table, table=table,
)) ))
connection = engine.raw_connection()
_ = engine.raw_connection()
df = pd.read_sql_query(query, engine) df = pd.read_sql_query(query, engine)
return df return df
@@ -1036,7 +1033,7 @@ def deletecpdata_sql(rower_id, table='cpdata'): # pragma: no cover
)) ))
with engine.connect() as conn, conn.begin(): with engine.connect() as conn, conn.begin():
try: try:
result = conn.execute(query) _ = conn.execute(query)
except: except:
print("Database locked") print("Database locked")
conn.close() conn.close()
@@ -1064,11 +1061,10 @@ def updatecpdata_sql(rower_id, delta, cp, table='cpdata', distance=[]): # pragm
def fetchcperg(rower, theworkouts): def fetchcperg(rower, theworkouts):
theids = [int(w.id) for w in theworkouts]
thefilenames = [w.csvfilename for w in theworkouts] thefilenames = [w.csvfilename for w in theworkouts]
cpdf = getcpdata_sql(rower.id, table='ergcpdata') cpdf = getcpdata_sql(rower.id, table='ergcpdata')
job = myqueue( _ = myqueue(
queuelow, queuelow,
handle_updateergcp, handle_updateergcp,
rower.id, rower.id,
@@ -1138,7 +1134,7 @@ def check_marker(workout):
theid = df.loc[indexmax, 'id'] theid = df.loc[indexmax, 'id']
wmax = Workout.objects.get(id=theid) wmax = Workout.objects.get(id=theid)
gms_max = wmax.goldmedalstandard # gms_max = wmax.goldmedalstandard
# check if equal, bigger, or smaller than previous # check if equal, bigger, or smaller than previous
if not wmax.rankingpiece: if not wmax.rankingpiece:
@@ -1210,16 +1206,17 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True):
) )
) )
jsondf = df2.to_json() jsondf = df2.to_json()
job = myqueue(queuelow, handle_getagegrouprecords, _ = myqueue(queuelow, handle_getagegrouprecords,
jsondf, distances, durations, age, rower.sex, rower.weightcategory) jsondf, distances, durations, age, rower.sex, rower.weightcategory)
wcpower = pd.Series(wcpower, dtype='float') wcpower = pd.Series(wcpower, dtype='float')
wcdurations = pd.Series(wcdurations, dtype='float') wcdurations = pd.Series(wcdurations, dtype='float')
def fitfunc(pars, x): return pars[0] / \ def fitfunc(pars, x):
(1+(x/pars[2])) + pars[1]/(1+(x/pars[3])) 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 if len(wcdurations) >= 4: # pragma: no cover
p1wc, success = optimize.leastsq( p1wc, success = optimize.leastsq(
@@ -1227,7 +1224,7 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True):
else: else:
factor = fitfunc(p0, wcdurations.mean()/wcpower.mean()) factor = fitfunc(p0, wcdurations.mean()/wcpower.mean())
p1wc = [p0[0]/factor, p0[1]/factor, p0[2], p0[3]] p1wc = [p0[0]/factor, p0[1]/factor, p0[2], p0[3]]
success = 0
return 0, 0 return 0, 0
times = df['delta'] 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') return pd.DataFrame(), pd.Series(dtype='float'), pd.Series(dtype='float')
if background: # pragma: no cover 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') return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
if not strokesdf.empty: if not strokesdf.empty:
@@ -1339,7 +1336,7 @@ def update_wps(r, types, mode='water', asynchron=True):
ids = [w.id for w in workouts] ids = [w.id for w in workouts]
if asynchron: if asynchron:
job = myqueue( _ = myqueue(
queue, queue,
handle_update_wps, handle_update_wps,
r.id, r.id,
@@ -1441,7 +1438,7 @@ def fetchcp(rower, theworkouts, table='cpdata'): # pragma: no cover
if not cpdf.empty: if not cpdf.empty:
return cpdf['delta'], cpdf['cp'], avgpower2 return cpdf['delta'], cpdf['cp'], avgpower2
else: else:
job = myqueue(queuelow, _ = myqueue(queuelow,
handle_updatecp, handle_updatecp,
rower.id, rower.id,
theids, theids,
@@ -1489,11 +1486,11 @@ def create_row_df(r, distance, duration, startdatetime, workouttype='rower',
else: else:
spm = avgspm spm = avgspm
step = totalseconds/float(nr_strokes) # step = totalseconds/float(nr_strokes)
elapsed = np.arange(nr_strokes)*totalseconds/(float(nr_strokes-1)) 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)) d = np.arange(nr_strokes)*distance/(float(nr_strokes-1))
@@ -1564,12 +1561,12 @@ def checkbreakthrough(w, r):
if workouttype in otwtypes: if workouttype in otwtypes:
res, btvalues, res2 = utils.isbreakthrough( res, btvalues, res2 = utils.isbreakthrough(
delta, cpvalues, r.p0, r.p1, r.p2, r.p3, r.cpratio) 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: elif workouttype in otetypes:
res, btvalues, res2 = utils.isbreakthrough( res, btvalues, res2 = utils.isbreakthrough(
delta, cpvalues, r.ep0, r.ep1, r.ep2, r.ep3, r.ecpratio) 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 else: # pragma: no cover
res = 0 res = 0
res2 = 0 res2 = 0
@@ -1584,7 +1581,7 @@ def checkbreakthrough(w, r):
w.rankingpiece = True w.rankingpiece = True
w.save() w.save()
if r.getemailnotifications and not r.emailbounced: # pragma: no cover if r.getemailnotifications and not r.emailbounced: # pragma: no cover
job = myqueue(queuehigh, handle_sendemail_breakthrough, _ = myqueue(queuehigh, handle_sendemail_breakthrough,
w.id, w.id,
r.user.email, r.user.email,
r.user.first_name, r.user.first_name,
@@ -1597,7 +1594,7 @@ def checkbreakthrough(w, r):
w.rankingpiece = True w.rankingpiece = True
w.save() w.save()
if r.getemailnotifications and not r.emailbounced: if r.getemailnotifications and not r.emailbounced:
job = myqueue(queuehigh, handle_sendemail_hard, _ = myqueue(queuehigh, handle_sendemail_hard,
w.id, w.id,
r.user.email, r.user.email,
r.user.first_name, r.user.first_name,
@@ -1624,7 +1621,6 @@ def checkduplicates(r, workoutdate, workoutstartdatetime, workoutenddatetime):
ws2.append(ww) ws2.append(ww)
if (len(ws2) != 0): if (len(ws2) != 0):
message = "Warning: This workout overlaps with an existing one and was marked as a duplicate"
duplicate = True duplicate = True
return duplicate return duplicate
@@ -1724,7 +1720,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
windowsize = 2 * (int(10. / (f))) + 1 windowsize = 2 * (int(10. / (f))) + 1
else: # pragma: no cover else: # pragma: no cover
windowsize = 1 windowsize = 1
if not 'originalvelo' in row.df: if 'originalvelo' not in row.df:
row.df['originalvelo'] = velo row.df['originalvelo'] = velo
if windowsize > 3 and windowsize < len(velo): if windowsize > 3 and windowsize < len(velo):
@@ -1861,15 +1857,15 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
w.team.add(t) w.team.add(t)
# put stroke data in database # put stroke data in database
res = dataprep(row.df, id=w.id, bands=True, _ = dataprep(row.df, id=w.id, bands=True,
barchart=True, otwpower=True, empower=True, inboard=inboard) barchart=True, otwpower=True, empower=True, inboard=inboard)
isbreakthrough, ishard = checkbreakthrough(w, r) isbreakthrough, ishard = checkbreakthrough(w, r)
marker = check_marker(w) _ = check_marker(w)
result = update_wps(r, mytypes.otwtypes) _ = update_wps(r, mytypes.otwtypes)
result = update_wps(r, mytypes.otetypes) _ = update_wps(r, mytypes.otetypes)
job = myqueue(queuehigh, handle_calctrimp, w.id, f2, _ = myqueue(queuehigh, handle_calctrimp, w.id, f2,
r.ftp, r.sex, r.hrftp, r.max, r.rest) r.ftp, r.sex, r.hrftp, r.max, r.rest)
return (w.id, message) return (w.id, message)
@@ -1914,7 +1910,7 @@ def get_startdate_time_zone(r, row, startdatetime=None):
startdatetime = row.rowdatetime startdatetime = row.rowdatetime
try: try:
tz = startdatetime.tzinfo _ = startdatetime.tzinfo
except AttributeError: # pragma: no cover except AttributeError: # pragma: no cover
startdatetime = row.rowdatetime startdatetime = row.rowdatetime
@@ -1987,7 +1983,6 @@ def parsenonpainsled(fileformat, f2, summary, startdatetime='', empowerfirmware=
s = 'Parsenonpainsled, start date time = {startdatetime}'.format( s = 'Parsenonpainsled, start date time = {startdatetime}'.format(
startdatetime=startdatetime, startdatetime=startdatetime,
#rowdatetime = row.rowdatetime
) )
dologging('debuglog.log', s) dologging('debuglog.log', s)
@@ -2158,11 +2153,10 @@ def new_workout_from_file(r, f2,
uploadoptions['file'] = datafile uploadoptions['file'] = datafile
url = settings.UPLOAD_SERVICE_URL url = settings.UPLOAD_SERVICE_URL
job = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_request_post, handle_request_post,
url, url,
uploadoptions uploadoptions)
)
except BadZipFile: # pragma: no cover except BadZipFile: # pragma: no cover
pass pass
@@ -2227,7 +2221,7 @@ def new_workout_from_file(r, f2,
extension = extension2 extension = extension2
f4 = filename+'a'+extension f4 = filename+'a'+extension
copyfile(f2, f4) copyfile(f2, f4)
job = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_unrecognized, handle_sendemail_unrecognized,
f4, f4,
r.user.email) r.user.email)
@@ -2377,7 +2371,7 @@ def split_workout(r, parent, splitsecond, splitmode):
messages.append(message) messages.append(message)
ids.append(encoder.encode_hex(id)) 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: if 'keep second' in splitmode or 'keep first' in splitmode:
parent.delete() parent.delete()
messages.append('Deleted Workout: ' + parent.name) messages.append('Deleted Workout: ' + parent.name)
@@ -2448,7 +2442,6 @@ def new_workout_from_df(r, df,
df.rename(columns=columndict, inplace=True) df.rename(columns=columndict, inplace=True)
#starttimeunix = mktime(startdatetime.utctimetuple())
starttimeunix = arrow.get(startdatetime).timestamp() starttimeunix = arrow.get(startdatetime).timestamp()
df[' ElapsedTime (sec)'] = df['TimeStamp (sec)'] df[' ElapsedTime (sec)'] = df['TimeStamp (sec)']
@@ -2458,15 +2451,13 @@ def new_workout_from_df(r, df,
row.write_csv(csvfilename, gzip=True) row.write_csv(csvfilename, gzip=True)
# res = df.to_csv(csvfilename+'.gz',index_label='index',
# compression='gzip')
id, message = save_workout_database(csvfilename, r, id, message = save_workout_database(csvfilename, r,
workouttype=workouttype, workouttype=workouttype,
boattype=boattype, boattype=boattype,
title=title, title=title,
workoutsource=workoutsource, workoutsource=workoutsource,
notes=notes, notes=notes,
summary=summary,
oarlength=oarlength, oarlength=oarlength,
inboard=inboard, inboard=inboard,
makeprivate=makeprivate, makeprivate=makeprivate,
@@ -2474,7 +2465,7 @@ def new_workout_from_df(r, df,
rpe=rpe, rpe=rpe,
consistencychecks=False) consistencychecks=False)
job = myqueue(queuehigh, handle_calctrimp, id, csvfilename, _ = myqueue(queuehigh, handle_calctrimp, id, csvfilename,
r.ftp, r.sex, r.hrftp, r.max, r.rest) r.ftp, r.sex, r.hrftp, r.max, r.rest)
return (id, message) return (id, message)
@@ -2520,7 +2511,7 @@ def delete_strokedata(id):
def update_strokedata(id, df): def update_strokedata(id, df):
delete_strokedata(id) 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 # Test that all data are of a numerical time
@@ -2555,7 +2546,7 @@ def getrowdata_db(id=0, doclean=False, convertnewtons=True,
else: else:
row = Workout.objects.get(id=id) row = Workout.objects.get(id=id)
if checkefficiency == True and not data.empty: if checkefficiency is True and not data.empty:
try: try:
if data['efficiency'].mean() == 0 and data['power'].mean() != 0: # pragma: no cover if data['efficiency'].mean() == 0 and data['power'].mean() != 0: # pragma: no cover
data = add_efficiency(id=id) data = add_efficiency(id=id)
@@ -2586,15 +2577,13 @@ def getsmallrowdata_db(columns, ids=[], doclean=True, workstrokesonly=True, comp
if len(ids) > 1: if len(ids) > 1:
for id, f in zip(ids, csvfilenames): for id, f in zip(ids, csvfilenames):
try: try:
#df = dd.read_parquet(f,columns=columns,engine='pyarrow')
df = pd.read_parquet(f, columns=columns) df = pd.read_parquet(f, columns=columns)
data.append(df) data.append(df)
except (OSError, ArrowInvalid, IndexError): # pragma: no cover except (OSError, ArrowInvalid, IndexError): # pragma: no cover
rowdata, row = getrowdata(id=id) rowdata, row = getrowdata(id=id)
if rowdata and len(rowdata.df): if rowdata and len(rowdata.df):
datadf = dataprep(rowdata.df, id=id, _ = dataprep(rowdata.df, id=id,
bands=True, otwpower=True, barchart=True) bands=True, otwpower=True, barchart=True)
# df = dd.read_parquet(f,columns=columns,engine='pyarrow')
df = pd.read_parquet(f, columns=columns) df = pd.read_parquet(f, columns=columns)
data.append(df) data.append(df)
@@ -2649,7 +2638,6 @@ def getrowdata(id=0):
# get user # get user
r = row.user r = row.user
u = r.user
rr = rrower(hrmax=r.max, hrut2=r.ut2, rr = rrower(hrmax=r.max, hrut2=r.ut2,
hrut1=r.ut1, hrat=r.at, hrut1=r.ut1, hrat=r.at,
@@ -2677,7 +2665,7 @@ def prepmultipledata(ids, verbose=False): # pragma: no cover
if verbose: if verbose:
print(id) print(id)
if rowdata and len(rowdata.df): if rowdata and len(rowdata.df):
data = dataprep(rowdata.df, id=id, bands=True, _ = dataprep(rowdata.df, id=id, bands=True,
barchart=True, otwpower=True) barchart=True, otwpower=True)
return ids return ids
@@ -2707,8 +2695,8 @@ def read_cols_df_sql(ids, columns, convertnewtons=True):
except OSError: except OSError:
rowdata, row = getrowdata(id=ids[0]) rowdata, row = getrowdata(id=ids[0])
if rowdata and len(rowdata.df): if rowdata and len(rowdata.df):
datadf = dataprep( _ = dataprep(rowdata.df,
rowdata.df, id=ids[0], bands=True, otwpower=True, barchart=True) id=ids[0], bands=True, otwpower=True, barchart=True)
df = pd.read_parquet(filename, columns=columns) df = pd.read_parquet(filename, columns=columns)
else: else:
data = [] data = []
@@ -2721,7 +2709,7 @@ def read_cols_df_sql(ids, columns, convertnewtons=True):
except (OSError, IndexError, ArrowInvalid): except (OSError, IndexError, ArrowInvalid):
rowdata, row = getrowdata(id=id) rowdata, row = getrowdata(id=id)
if rowdata and len(rowdata.df): # pragma: no cover if rowdata and len(rowdata.df): # pragma: no cover
datadf = dataprep(rowdata.df, id=id, _ = dataprep(rowdata.df, id=id,
bands=True, otwpower=True, barchart=True) bands=True, otwpower=True, barchart=True)
df = pd.read_parquet(f, columns=columns) df = pd.read_parquet(f, columns=columns)
data.append(df) data.append(df)
@@ -2753,8 +2741,8 @@ def read_cols_df_sql(ids, columns, convertnewtons=True):
def initiate_cp(r): def initiate_cp(r):
success = update_rolling_cp(r, otwtypes, 'water') _ = update_rolling_cp(r, otwtypes, 'water')
success = update_rolling_cp(r, otetypes, 'erg') _ = update_rolling_cp(r, otetypes, 'erg')
# Read stroke data from the DB for a Workout ID. Returns a pandas dataframe # Read stroke data from the DB for a Workout ID. Returns a pandas dataframe
@@ -2784,9 +2772,6 @@ def read_df_sql(id):
def datafusion(id1, id2, columns, offset): 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, w1 = getrowdata_db(id=id1)
df1 = df1.drop([ # 'cumdist', df1 = df1.drop([ # 'cumdist',
'hr_ut2', 'hr_ut2',
@@ -2821,7 +2806,7 @@ def datafusion(id1, id2, columns, offset):
keep1.pop(c) keep1.pop(c)
for c in df1.columns: for c in df1.columns:
if not c in keep1: if c not in keep1:
df1 = df1.drop(c, 1, errors='ignore') df1 = df1.drop(c, 1, errors='ignore')
df = pd.concat([df1, df2], ignore_index=True) df = pd.concat([df1, df2], ignore_index=True)
@@ -2846,7 +2831,6 @@ def fix_newtons(id=0, limit=3000): # pragma: no cover
# rowdata,row = getrowdata_db(id=id,doclean=False,convertnewtons=False) # rowdata,row = getrowdata_db(id=id,doclean=False,convertnewtons=False)
rowdata = getsmallrowdata_db(['peakforce'], ids=[id], doclean=False) rowdata = getsmallrowdata_db(['peakforce'], ids=[id], doclean=False)
try: try:
#avgforce = rowdata['averageforce']
peakforce = rowdata['peakforce'] peakforce = rowdata['peakforce']
if peakforce.mean() > limit: if peakforce.mean() > limit:
w = Workout.objects.get(id=id) w = Workout.objects.get(id=id)
@@ -2860,7 +2844,7 @@ def fix_newtons(id=0, limit=3000): # pragma: no cover
def remove_invalid_columns(df): # pragma: no cover def remove_invalid_columns(df): # pragma: no cover
for c in df.columns: for c in df.columns:
if not c in allowedcolumns: if c not in allowedcolumns:
df.drop(labels=c, axis=1, inplace=True) df.drop(labels=c, axis=1, inplace=True)
return df return df
@@ -2907,7 +2891,6 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True,
if rowdatadf.empty: if rowdatadf.empty:
return 0 return 0
#rowdatadf.set_index([range(len(rowdatadf))], inplace=True)
t = rowdatadf.loc[:, 'TimeStamp (sec)'] t = rowdatadf.loc[:, 'TimeStamp (sec)']
t = pd.Series(t - rowdatadf.loc[:, 'TimeStamp (sec)'].iloc[0]) t = pd.Series(t - rowdatadf.loc[:, 'TimeStamp (sec)'].iloc[0])
@@ -2981,7 +2964,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True,
if forceunit == 'lbs': if forceunit == 'lbs':
driveenergy = drivelength * averageforce * lbstoN driveenergy = drivelength * averageforce * lbstoN
else: else:
drivenergy = drivelength * averageforce driveenergy = drivelength * averageforce
if forceunit == 'lbs': if forceunit == 'lbs':
averageforce *= lbstoN averageforce *= lbstoN
@@ -3034,7 +3017,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True,
data['hr_bottom'] = 0.0 * data['hr'] data['hr_bottom'] = 0.0 * data['hr']
try: try:
tel = rowdatadf.loc[:, ' ElapsedTime (sec)'] _ = rowdatadf.loc[:, ' ElapsedTime (sec)']
except KeyError: # pragma: no cover except KeyError: # pragma: no cover
rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)'] rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)']
@@ -3218,7 +3201,7 @@ def workout_trimp(w, reset=False):
w.maxhr = maxhr w.maxhr = maxhr
w.save() w.save()
job = myqueue( _ = myqueue(
queuehigh, queuehigh,
handle_calctrimp, handle_calctrimp,
w.id, w.id,
@@ -3246,7 +3229,7 @@ def workout_rscore(w, reset=False):
r.hrftp = int(hrftp) r.hrftp = int(hrftp)
r.save() r.save()
job = myqueue( _ = myqueue(
queuehigh, queuehigh,
handle_calctrimp, handle_calctrimp,
w.id, w.id,
@@ -3274,7 +3257,7 @@ def workout_normv(w, pp=4.0):
r.hrftp = int(hrftp) r.hrftp = int(hrftp)
r.save() r.save()
job = myqueue( _ = myqueue(
queuehigh, queuehigh,
handle_calctrimp, handle_calctrimp,
w.id, w.id,
+17 -18
View File
@@ -2,6 +2,7 @@ from rowers.utils import totaltime_sec_to_string
from rowers.metrics import dtypes from rowers.metrics import dtypes
import datetime import datetime
from scipy.signal import savgol_filter from scipy.signal import savgol_filter
import os
# This is Data prep used for testing purposes (no Django environment) # This is Data prep used for testing purposes (no Django environment)
# Uses the debug SQLite database for stroke data # Uses the debug SQLite database for stroke data
@@ -35,6 +36,12 @@ from rowers.utils import lbstoN
import pytz import pytz
from timezonefinder import TimezoneFinder from timezonefinder import TimezoneFinder
from rowingdata import (
RowProParser, TCXParser, MysteryParser, RowPerfectParser,
ErgDataParser, CoxMateParser, BoatCoachAdvancedParser, BoatCoachOTWParser,
BoatCoachParser, painsledDesktopParser, SpeedCoach2Parser, speedcoachParser,
ErgStickParser, FITParser, fitsummarydata
)
try: try:
user = DATABASES['default']['USER'] user = DATABASES['default']['USER']
@@ -171,14 +178,12 @@ def create_c2_stroke_data_db(
spm = 20*np.zeros(nr_strokes) spm = 20*np.zeros(nr_strokes)
try: try:
step = totalseconds/float(nr_strokes) _ = totalseconds/float(nr_strokes)
except ZeroDivisionError: except ZeroDivisionError:
return 0 return 0
elapsed = np.arange(nr_strokes)*totalseconds/(float(nr_strokes-1)) 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)) d = np.arange(nr_strokes)*distance/(float(nr_strokes-1))
unixtime = starttimeunix + elapsed unixtime = starttimeunix + elapsed
@@ -215,12 +220,9 @@ def create_c2_stroke_data_db(
'cum_dist': d 'cum_dist': d
}) })
timestr = strftime("%Y%m%d-%H%M%S")
df[' ElapsedTime (sec)'] = df['TimeStamp (sec)'] df[' ElapsedTime (sec)'] = df['TimeStamp (sec)']
res = df.to_csv(csvfilename, index_label='index', _ = df.to_csv(csvfilename, index_label='index', compression='gzip')
compression='gzip')
data = dataprep(df, id=workoutid, bands=False, debug=debug) 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) 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 # Create CSV file name and save data to CSV file
res = df.to_csv(csvfilename, index_label='index', 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 if debug: # pragma: no cover
print("not updated ", id) print("not updated ", id)
rowdata = dataprep(df, id=id, bands=True, barchart=True, otwpower=True, _ = dataprep(df, id=id, bands=True, barchart=True, otwpower=True, debug=debug)
debug=debug)
row = rrdata(df=df) row = rrdata(df=df)
row.write_csv(f1, gzip=True) row.write_csv(f1, gzip=True)
@@ -511,7 +510,7 @@ def update_workout_field_sql(workoutid, fieldname, value, debug=False):
table, fieldname, value, workoutid) table, fieldname, value, workoutid)
with engine.connect() as conn, conn.begin(): with engine.connect() as conn, conn.begin():
result = conn.execute(query) _ = conn.execute(query)
conn.close() conn.close()
engine.dispose() engine.dispose()
@@ -527,7 +526,7 @@ def update_c2id_sql(id, c2id): # pragma: no cover
table, c2id, id) table, c2id, id)
with engine.connect() as conn, conn.begin(): with engine.connect() as conn, conn.begin():
result = conn.execute(query) _ = conn.execute(query)
conn.close() conn.close()
engine.dispose() engine.dispose()
@@ -588,7 +587,7 @@ def getcpdata_sql(rower_id, table='cpdata', debug=False): # pragma: no cover
rower_id=rower_id, rower_id=rower_id,
table=table, table=table,
)) ))
connection = engine.raw_connection() _ = engine.raw_connection()
df = pd.read_sql_query(query, engine) df = pd.read_sql_query(query, engine)
return df 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(): with engine.connect() as conn, conn.begin():
try: try:
result = conn.execute(query) _ = conn.execute(query)
except: # pragma: no cover except: # pragma: no cover
print("Database locked") print("Database locked")
conn.close() conn.close()
@@ -627,7 +626,7 @@ def delete_agegroup_db(age, sex, weightcategory, debug=False):
)) ))
with engine.connect() as conn, conn.begin(): with engine.connect() as conn, conn.begin():
try: try:
result = conn.execute(query) _ = conn.execute(query)
except: # pragma: no cover except: # pragma: no cover
print("Database locked") print("Database locked")
conn.close() conn.close()
@@ -818,7 +817,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True,
if forceunit == 'lbs': if forceunit == 'lbs':
driveenergy = drivelength*averageforce*lbstoN driveenergy = drivelength*averageforce*lbstoN
else: # pragma: no cover else: # pragma: no cover
drivenergy = drivelength*averageforce driveenergy = drivelength*averageforce
distance = rowdatadf.loc[:, 'cum_dist'] 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'] data['hr_bottom'] = 0.0*data['hr']
try: try:
tel = rowdatadf.loc[:, ' ElapsedTime (sec)'] _ = rowdatadf.loc[:, ' ElapsedTime (sec)']
except KeyError: # pragma: no cover except KeyError: # pragma: no cover
rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)'] rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)']
+11 -15
View File
@@ -6,7 +6,6 @@ from scipy import optimize
from rowers.mytypes import otwtypes, otetypes, rowtypes from rowers.mytypes import otwtypes, otetypes, rowtypes
#p0 = [500,350,10,8000]
p0 = [190, 200, 33, 16000] p0 = [190, 200, 33, 16000]
# RPE to TSS # 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): def cpfit(powerdf, fraclimit=0.0001, nmax=1000):
# Fit the data to thee parameter CP model # Fit the data to thee parameter CP model
def fitfunc(pars, x): return abs( def fitfunc(pars, x):
return abs(
pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3]))) 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 p1 = p0
@@ -235,8 +236,6 @@ def getcp_new(dfgrouped, logarr): # pragma: no cover
restime = np.array(restime) restime = np.array(restime)
power = np.array(power) power = np.array(power)
#power[0] = power[1]
cpvalues = griddata(restime, power, cpvalues = griddata(restime, power,
logarr, method='linear', fill_value=0) logarr, method='linear', fill_value=0)
@@ -264,7 +263,6 @@ def getcp(dfgrouped, logarr):
delta = [] delta = []
cpvalue = [] cpvalue = []
avgpower = {} avgpower = {}
#avgpower[0] = 0
for id, group in dfgrouped: for id, group in dfgrouped:
tt = group['time'].copy() tt = group['time'].copy()
@@ -273,7 +271,7 @@ def getcp(dfgrouped, logarr):
# Remove data where PM is repeating final power value # Remove data where PM is repeating final power value
# of an interval during the rest # of an interval during the rest
rolling_std = ww.rolling(window=4).std() rolling_std = ww.rolling(window=4).std()
deltas = tt.diff() # deltas = tt.diff()
mask = rolling_std == 0 mask = rolling_std == 0
ww.loc[mask] = 0 ww.loc[mask] = 0
@@ -281,7 +279,7 @@ def getcp(dfgrouped, logarr):
mask = ww > 2000 mask = ww > 2000
ww.loc[mask] = 0 ww.loc[mask] = 0
tmax = tt.max() # tmax = tt.max()
try: try:
avgpower[id] = int(ww.mean()) avgpower[id] = int(ww.mean())
@@ -389,13 +387,13 @@ def getfastest(df, thevalue, mode='distance'):
dd = pd.Series(dd, dtype='float') dd = pd.Series(dd, dtype='float')
G = pd.concat([pd.Series([0]), dd]) G = pd.concat([pd.Series([0]), dd])
T = 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] # h = np.mgrid[0:len(tt)+1:1, 0:len(tt)+1:1]
distances = pd.DataFrame(h[1]-h[0]) # distances = pd.DataFrame(h[1]-h[0])
ones = 1+np.zeros(len(G)) ones = 1+np.zeros(len(G))
Ghor = np.outer(ones, G) Ghor = np.outer(ones, G)
Thor = np.outer(ones, T) # Thor = np.outer(ones, T)
Tver = np.outer(T, ones) # Tver = np.outer(T, ones)
Gver = np.outer(G, ones) Gver = np.outer(G, ones)
Gdif = Ghor-Gver Gdif = Ghor-Gver
Gdif = np.tril(Gdif.T).T Gdif = np.tril(Gdif.T).T
@@ -428,8 +426,6 @@ def getfastest(df, thevalue, mode='distance'):
# if restime[i]<thevalue*60*1000: # if restime[i]<thevalue*60*1000:
# print(i,restime[i],distance[i],60*1000*thevalue) # print(i,restime[i],distance[i],60*1000*thevalue)
d2 = 0
if mode == 'distance': if mode == 'distance':
duration = griddata(distance, restime, [ duration = griddata(distance, restime, [
thevalue], method='linear', rescale=True) thevalue], method='linear', rescale=True)
+1 -2
View File
@@ -1,5 +1,4 @@
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import login_required, user_passes_test
from django.urls import reverse from django.urls import reverse
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
+2 -2
View File
@@ -20,7 +20,7 @@ import pytz
import iso8601 import iso8601
from matplotlib.backends.backend_agg import FigureCanvas from matplotlib.backends.backend_agg import FigureCanvas
#from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvas
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from rowsandall_app.settings import SITE_URL from rowsandall_app.settings import SITE_URL
@@ -130,7 +130,7 @@ def send_confirm(user, name, link, options): # pragma: no cover
fullemail = user.email fullemail = user.email
subject = 'New Workout Added: '+name subject = 'New Workout Added: '+name
res = send_template_email('Rowsandall <info@rowsandall.com>', _ = send_template_email('Rowsandall <info@rowsandall.com>',
[fullemail], [fullemail],
subject, 'confirmemail.html', subject, 'confirmemail.html',
d d
+1 -1
View File
@@ -129,7 +129,7 @@ def create_invoice(rower, amount, braintreeid, dosend=True,
if res.status_code not in [200, 201]: # pragma: no cover if res.status_code not in [200, 201]: # pragma: no cover
return 0 return 0
url = res.json()['url'] # url = res.json()['url']
id = res.json()['id'] id = res.json()['id']
urlpay = 'https://app.fakturoid.cz/api/v2/accounts/{slug}/invoices/{id}/fire.json?event=pay'.format( urlpay = 'https://app.fakturoid.cz/api/v2/accounts/{slug}/invoices/{id}/fire.json?event=pay'.format(
+15 -26
View File
@@ -1,4 +1,3 @@
from rowers.models import VirtualRace, GeoCourse
from rowers.utils import rankingdistances, rankingdurations from rowers.utils import rankingdistances, rankingdurations
from rowers.utils import ( from rowers.utils import (
workflowleftpanel, workflowmiddlepanel, workflowleftpanel, workflowmiddlepanel,
@@ -18,7 +17,7 @@ from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.admin.widgets import AdminDateWidget from django.contrib.admin.widgets import AdminDateWidget
from django.forms.widgets import SelectDateWidget, HiddenInput from django.forms.widgets import SelectDateWidget, HiddenInput
#from django.forms.extras.widgets import SelectDateWidget
from django.utils import timezone, translation from django.utils import timezone, translation
from django.forms import ModelForm, Select from django.forms import ModelForm, Select
import rowers.dataprep as dataprep import rowers.dataprep as dataprep
@@ -573,11 +572,17 @@ class UploadOptionsForm(forms.Form):
choices3 = [(0, '---')] choices3 = [(0, '---')]
noregistrations = [] 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) rs = VirtualRaceResult.objects.filter(race=ra, userid=r.id)
if rs.count() == 0: if rs.count() == 0:
noregistrations.append((-ra.id, ra.name)) 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) rs = IndoorVirtualRaceResult.objects.filter(race=ra, userid=r.id)
if rs.count() == 0: if rs.count() == 0:
noregistrations.append((-ra.id, ra.name)) noregistrations.append((-ra.id, ra.name))
@@ -1055,20 +1060,6 @@ class RegistrationFormSex(RegistrationFormUniqueEmail):
adaptiveclass = forms.ChoiceField(label='Adaptive Classification', adaptiveclass = forms.ChoiceField(label='Adaptive Classification',
choices=adaptivecategories, initial='None', required=False) 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): class PowerIntervalUpdateForm(forms.Form):
selectorchoices = ( selectorchoices = (
@@ -1847,14 +1838,13 @@ class StravaChartForm(forms.Form):
choices=yaxchoices2, label='Fourth Chart', required=True) choices=yaxchoices2, label='Fourth Chart', required=True)
def __init__(self, request, *args, **kwargs): def __init__(self, request, *args, **kwargs):
extrametrics = kwargs.pop('extrametrics', [])
super(StravaChartForm, self).__init__(*args, **kwargs) super(StravaChartForm, self).__init__(*args, **kwargs)
rower = Rower.objects.get(user=request.user) rower = Rower.objects.get(user=request.user)
axchoicespro = ( # axchoicespro = (
('', ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0], ax[1]) for ax in axes # ('', ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0], ax[1]) for ax in axes
) # )
axchoicesbasicx = [] axchoicesbasicx = []
axchoicesbasicy = [] axchoicesbasicy = []
@@ -1889,14 +1879,13 @@ class FlexAxesForm(forms.Form):
choices=yaxchoices2, label='Right Axis', required=True) choices=yaxchoices2, label='Right Axis', required=True)
def __init__(self, request, *args, **kwargs): def __init__(self, request, *args, **kwargs):
extrametrics = kwargs.pop('extrametrics', [])
super(FlexAxesForm, self).__init__(*args, **kwargs) super(FlexAxesForm, self).__init__(*args, **kwargs)
rower = Rower.objects.get(user=request.user) rower = Rower.objects.get(user=request.user)
axchoicespro = ( # axchoicespro = (
('', ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0], ax[1]) for ax in axes # ('', ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0], ax[1]) for ax in axes
) # )
axchoicesbasicx = [] axchoicesbasicx = []
axchoicesbasicy = [] axchoicesbasicy = []
+21 -37
View File
@@ -11,7 +11,7 @@ import requests
from requests import Session, Request from requests import Session, Request
from requests_oauthlib import OAuth1, OAuth1Session from requests_oauthlib import OAuth1, OAuth1Session
from requests_oauthlib.oauth1_session import TokenRequestDenied from requests_oauthlib.oauth1_session import TokenRequestDenied
from requests import Request, Session
import rowers.mytypes as mytypes import rowers.mytypes as mytypes
from rowers.mytypes import otwtypes from rowers.mytypes import otwtypes
from rowers.rower_rules import is_workout_user, ispromember 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 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 from rowers.tasks import handle_get_garmin_file
import django_rq import django_rq
@@ -109,9 +102,6 @@ repeattypes = {
def garmin_authorize(): # pragma: no cover 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'] base_uri = oauth_data['base_url']
garmin = OAuth1Session(oauth_data['client_id'], 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) oauth_response = garmin.parse_authorization_response(redirect_response)
verifier = oauth_response.get('oauth_verifier') 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' access_token_url = 'https://connectapi.garmin.com/oauth-service/oauth/access_token'
# Using OAuth1Session # Using OAuth1Session
@@ -155,7 +145,7 @@ def garmin_processcallback(redirect_response, resource_owner_key, resource_owner
def garmin_open(user): # pragma: no cover def garmin_open(user): # pragma: no cover
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
token = Rower.garmintoken token = r.garmintoken
if (token == '') or (token is None): if (token == '') or (token is None):
raise NoTokenError("User has no garmin token") 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, 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) result = garmin.get(url)
@@ -218,7 +209,7 @@ def step_to_garmin(step, order=0):
intensity = 'INTERVAL' intensity = 'INTERVAL'
except KeyError: except KeyError:
intensity = None intensity = None
#durationvaluetype = '' # durationvaluetype = ''
if durationtype == 'Time': if durationtype == 'Time':
durationtype = 'TIME' durationtype = 'TIME'
durationvalue = int(durationvalue/1000.) durationvalue = int(durationvalue/1000.)
@@ -272,11 +263,11 @@ def step_to_garmin(step, order=0):
if targetType is not None and targetType.lower() == "power": if targetType is not None and targetType.lower() == "power":
targetType = 'POWER' targetType = 'POWER'
if targetValue is not None and targetValue <= 1000: # if targetValue is not None and targetValue <= 1000:
targetValueType = 'PERCENT' # pragma: no cover # targetValueType = 'PERCENT' # pragma: no cover
else: # else:
targetValueType = None # # targetValueType = None
targetValue -= 1000 # targetValue -= 1000
try: try:
targetValueLow = step['dict']['targetValueLow'] targetValueLow = step['dict']['targetValueLow']
@@ -285,8 +276,8 @@ def step_to_garmin(step, order=0):
targetValue = None targetValue = None
elif targetValueLow == 0: # pragma: no cover elif targetValueLow == 0: # pragma: no cover
targetValueLow = None targetValueLow = None
elif targetValueLow <= 1000 and targetType == 'POWER': # pragma: no cover # elif targetValueLow <= 1000 and targetType == 'POWER': # pragma: no cover
targetValueType = 'PERCENT' # targetValueType = 'PERCENT'
elif targetValueLow > 1000 and targetType == 'POWER': # pragma: no cover elif targetValueLow > 1000 and targetType == 'POWER': # pragma: no cover
targetValueLow -= 1000 targetValueLow -= 1000
except KeyError: 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 if targetValue is not None and targetValue > 0 and targetValueHigh == 0: # pragma: no cover
targetValueHigh = targetValue targetValueHigh = targetValue
targetValue = 0 targetValue = 0
elif targetValueHigh <= 1000 and targetType == 'POWER': # pragma: no cover # elif targetValueHigh <= 1000 and targetType == 'POWER': # pragma: no cover
targetValueType = 'PERCENT' # targetValueType = 'PERCENT'
elif targetValueHigh > 1000 and targetType == 'POWER': # pragma: no cover elif targetValueHigh > 1000 and targetType == 'POWER': # pragma: no cover
targetValueHigh -= 1000 targetValueHigh -= 1000
elif targetValueHigh == 0: # pragma: no cover elif targetValueHigh == 0: # pragma: no cover
@@ -477,12 +468,6 @@ def garmin_getworkout(garminid, r, activity):
distance = activity['distanceInMeters'] distance = activity['distanceInMeters']
except KeyError: except KeyError:
distance = 0 distance = 0
try:
averagehr = activity['averageHeartRateInBeatsPerMinute']
maxhr = activity['maxHeartRateInBeatsPerMinute']
except KeyError: # pragma: no cover
averagehr = 0
maxhr = 0
try: try:
w = Workout.objects.get(uploadedtogarmin=garminid) w = Workout.objects.get(uploadedtogarmin=garminid)
except Workout.DoesNotExist: except Workout.DoesNotExist:
@@ -494,8 +479,8 @@ def garmin_getworkout(garminid, r, activity):
utc_offset = datetime.timedelta(seconds=offset) utc_offset = datetime.timedelta(seconds=offset)
now = datetime.datetime.now(pytz.utc) now = datetime.datetime.now(pytz.utc)
zones = [tz.zone for tz in map(pytz.timezone, pytz.all_timezones_set) zones = [ttz.zone for ttz in map(
if now.astimezone(tz).utcoffset() == utc_offset] pytz.timezone, pytz.all_timezones_set) if now.astimezone(ttz).utcoffset() == utc_offset]
if r.defaulttimezone in zones: # pragma: no cover if r.defaulttimezone in zones: # pragma: no cover
thetimezone = r.defaulttimezone thetimezone = r.defaulttimezone
elif len(zones): elif len(zones):
@@ -509,8 +494,7 @@ def garmin_getworkout(garminid, r, activity):
day=startdatetime.day, day=startdatetime.day,
hour=startdatetime.hour, hour=startdatetime.hour,
minute=startdatetime.minute, minute=startdatetime.minute,
second=startdatetime.second, second=startdatetime.second,).astimezone(pytz.timezone(thetimezone))
).astimezone(pytz.timezone(thetimezone))
w.startdatetime = startdatetime w.startdatetime = startdatetime
w.starttime = w.startdatetime.time() w.starttime = w.startdatetime.time()
@@ -557,12 +541,12 @@ def garmin_workouts_from_details(data):
df[' AverageBoatSpeed (m/s)'] = 0 df[' AverageBoatSpeed (m/s)'] = 0
df[' Stroke500mPace (sec/500m)'] = pace df[' Stroke500mPace (sec/500m)'] = pace
try: try:
spm = df[' Cadence (stokes/min)'] _ = df[' Cadence (stokes/min)']
except KeyError: except KeyError:
df[' Cadence (stokes/min)'] = 0 df[' Cadence (stokes/min)'] = 0
df['cum_dist'] = df[' Horizontal (meters)'] df['cum_dist'] = df[' Horizontal (meters)']
try: try:
power = df[' Power (watts)'] _ = df[' Power (watts)']
except KeyError: except KeyError:
df[' Power (watts)'] = 0 df[' Power (watts)'] = 0
df[' AverageDriveForce (lbs)'] = 0 df[' AverageDriveForce (lbs)'] = 0
@@ -591,7 +575,7 @@ def garmin_workouts_from_summaries(activities):
try: try:
r = Rower.objects.get(garmintoken=garmintoken) r = Rower.objects.get(garmintoken=garmintoken)
id = activity['summaryId'] id = activity['summaryId']
w = garmin_getworkout(id, r, activity) _ = garmin_getworkout(id, r, activity)
except Rower.DoesNotExist: # pragma: no cover except Rower.DoesNotExist: # pragma: no cover
pass pass
+7 -17
View File
@@ -70,10 +70,6 @@ def splitstdata(lijst):
def imports_open(user, oauth_data): def imports_open(user, oauth_data):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
token = getattr(r, oauth_data['tokenname']) token = getattr(r, oauth_data['tokenname'])
try:
refreshtoken = getattr(r, oauth_data['refreshtokenname'])
except (TypeError, AttributeError, KeyError): # pragma: no cover
refreshtoken = None
try: try:
tokenexpirydate = getattr(r, oauth_data['expirydatename']) tokenexpirydate = getattr(r, oauth_data['expirydatename'])
@@ -81,7 +77,6 @@ def imports_open(user, oauth_data):
tokenexpirydate = None tokenexpirydate = None
if (token == '') or (token is None): if (token == '') or (token is None):
s = "Token doesn't exist. Need to authorize"
raise NoTokenError("User has no token") raise NoTokenError("User has no token")
else: else:
tokenname = oauth_data['tokenname'] tokenname = oauth_data['tokenname']
@@ -109,10 +104,10 @@ def imports_open(user, oauth_data):
# Refresh token using refresh token # Refresh token using refresh token
def imports_do_refresh_token(refreshtoken, oauth_data, access_token=''): def imports_do_refresh_token(refreshtoken, oauth_data, access_token=''):
client_auth = requests.auth.HTTPBasicAuth( # client_auth = requests.auth.HTTPBasicAuth(
oauth_data['client_id'], # oauth_data['client_id'],
oauth_data['client_secret'] # oauth_data['client_secret']
) # )
post_data = {"grant_type": "refresh_token", post_data = {"grant_type": "refresh_token",
"client_secret": oauth_data['client_secret'], "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 'grant_type' in oauth_data:
if oauth_data['grant_type']: if oauth_data['grant_type']:
post_data['grant_type'] = 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']: if oauth_data['bearer_auth']:
headers['authorization'] = 'Bearer %s' % access_token headers['authorization'] = 'Bearer %s' % access_token
@@ -192,9 +185,9 @@ def imports_get_token(
client_id = oauth_data['client_id'] client_id = oauth_data['client_id']
base_uri = oauth_data['base_url'] base_uri = oauth_data['base_url']
client_auth = requests.auth.HTTPBasicAuth( # client_auth = requests.auth.HTTPBasicAuth(
client_id, client_secret # client_id, client_secret
) # )
post_data = {"grant_type": "authorization_code", post_data = {"grant_type": "authorization_code",
"code": code, "code": code,
@@ -216,8 +209,6 @@ def imports_get_token(
post_data['grant_type'] = oauth_data['grant_type'] post_data['grant_type'] = oauth_data['grant_type']
if 'strava' in oauth_data['autorization_uri']: if 'strava' in oauth_data['autorization_uri']:
post_data['grant_type'] = "authorization_code" 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']: if 'json' in oauth_data['content_type']:
response = requests.post( response = requests.post(
@@ -268,7 +259,6 @@ def imports_make_authorization_url(oauth_data): # pragma: no cover
"scope": oauth_data['scope'], "scope": oauth_data['scope'],
"state": state} "state": state}
import urllib
url = oauth_data['authorizaton_uri']+urllib.parse.urlencode(params) url = oauth_data['authorizaton_uri']+urllib.parse.urlencode(params)
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
File diff suppressed because it is too large Load Diff
+2 -5
View File
@@ -14,7 +14,6 @@ redis_connection = StrictRedis()
def getvalue(data): # pragma: no cover def getvalue(data): # pragma: no cover
perc = 0
total = 1 total = 1
done = 0 done = 0
id = 0 id = 0
@@ -43,8 +42,7 @@ def longtask(aantal, jobid=None, debug=False,
if counter > 10: if counter > 10:
counter = 0 counter = 0
if debug: if debug:
progress = 100.*i/aantal if jobid is not None:
if jobid != None:
redis_connection.publish(channel, json.dumps( redis_connection.publish(channel, json.dumps(
{ {
'done': i, 'done': i,
@@ -60,7 +58,6 @@ def longtask(aantal, jobid=None, debug=False,
def longtask2(aantal, jobid=None, debug=False, secret=''): # pragma: no cover def longtask2(aantal, jobid=None, debug=False, secret=''): # pragma: no cover
counter = 0 counter = 0
channel = 'tasks'
for i in range(aantal): for i in range(aantal):
time.sleep(1) time.sleep(1)
counter += 1 counter += 1
@@ -69,7 +66,7 @@ def longtask2(aantal, jobid=None, debug=False, secret=''): # pragma: no cover
progress = int(100.*i/aantal) progress = int(100.*i/aantal)
if debug: if debug:
print(progress) print(progress)
if jobid != None: if jobid is not None:
if debug: if debug:
url = SITE_URL_DEV url = SITE_URL_DEV
else: else:
+6 -7
View File
@@ -7,20 +7,22 @@ import arrow
from django.utils import timezone from django.utils import timezone
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from rowers.models import Rower,Workout from rowers.models import Rower, Workout
import re import re
from django.db.models import Q from django.db.models import Q
from rowers.dataprep import join_workouts from rowers.dataprep import join_workouts
def name_short(name): def name_short(name):
expr = '(.*)\s.*\(\d+\)' expr = '(.*)\s.*\(\d+\)'
match = re.findall(expr,name) match = re.findall(expr, name)
if match: if match:
return match[0] return match[0]
return name return name
def get_duplicates(a): def get_duplicates(a):
seen = {} seen = {}
dupes = [] dupes = []
@@ -39,27 +41,24 @@ def get_duplicates(a):
class Command(BaseCommand): class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
rs = (r for r in Rower.objects.all() if r.ispaid and r.autojoin) rs = (r for r in Rower.objects.all() if r.ispaid and r.autojoin)
now = timezone.now()
for r in rs: for r in rs:
workouts = Workout.objects.filter(user=r, workouts = Workout.objects.filter(user=r,
duplicate=False, duplicate=False,
startdatetime__gte=timezone.now()-datetime.timedelta(days=2)) startdatetime__gte=timezone.now()-datetime.timedelta(days=2))
duplicates = get_duplicates(name_short(w.name) for w in workouts) duplicates = get_duplicates(name_short(w.name) for w in workouts)
for name, count in duplicates.items(): for name, count in duplicates.items():
if count > 1: if count > 1:
workouts2 = workouts.filter( workouts2 = workouts.filter(
Q(name__contains=name) Q(name__contains=name))
)
duplicates2 = get_duplicates(w.date for w in workouts) duplicates2 = get_duplicates(w.date for w in workouts)
for dd, count in duplicates2.items(): for dd, count in duplicates2.items():
if count > 1: if count > 1:
workouts3 = workouts2.filter(date=dd) workouts3 = workouts2.filter(date=dd)
ids = [w.id for w in workouts3] 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], parent=workouts3[0],
killparents=True) killparents=True)
+4 -8
View File
@@ -1,5 +1,3 @@
#!/srv/venv/bin/python
import sys import sys
import os import os
@@ -10,11 +8,12 @@ import json
from simplejson.errors import JSONDecodeError from simplejson.errors import JSONDecodeError
PY3K = sys.version_info >= (3,0)
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from rowers.models import BlogPost from rowers.models import BlogPost
PY3K = sys.version_info >= (3, 0)
class Command(BaseCommand): class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
blogs_json = [] blogs_json = []
@@ -35,16 +34,13 @@ class Command(BaseCommand):
pass pass
if blogs_json: if blogs_json:
result = BlogPost.objects.all().delete() _ = BlogPost.objects.all().delete()
for postdata in blogs_json[0:3]: for postdata in blogs_json[0:3]:
title = postdata['title']['rendered'] title = postdata['title']['rendered']
link = postdata['link'] link = postdata['link']
datetime = postdata['date']
datetime = arrow.get(datetime).datetime
date = datetime.date() date = datetime.date()
blogpost = BlogPost( blogpost = BlogPost(
link=link, link=link,
date=date, date=date,
+15 -16
View File
@@ -1,15 +1,9 @@
#!/srv/venv/bin/python
import sys import sys
import os 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.core.management.base import BaseCommand, CommandError
from django.conf import settings 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 import datetime
from rowers.models import * from rowers.models import *
@@ -17,6 +11,12 @@ from rowsandall_app.settings import BASE_DIR
import pandas as pd 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(): def getemails():
rs = Rower.objects.all() rs = Rower.objects.all()
firstnames = [r.user.first_name for r in rs] firstnames = [r.user.first_name for r in rs]
@@ -24,20 +24,18 @@ def getemails():
emails = [r.user.email for r in rs] emails = [r.user.email for r in rs]
is_actives = [r.user.is_active for r in rs] is_actives = [r.user.is_active for r in rs]
df = pd.DataFrame({ df = pd.DataFrame({
'first_name':firstnames, 'first_name': firstnames,
'last_name':lastnames, 'last_name': lastnames,
'email':emails, 'email': emails,
'is_active':is_actives 'is_active': is_actives})
})
return df return df
class Command(BaseCommand): class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
email_list = getemails() 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' fullemail = 'roosendaalsander@gmail.com'
subject = "Rowsandall users list" subject = "Rowsandall users list"
@@ -45,7 +43,8 @@ class Command(BaseCommand):
message += "Best Regards, the Rowsandall Team" message += "Best Regards, the Rowsandall Team"
message += "Users list attached \n\n" message += "Users list attached \n\n"
email = EmailMessage(subject, message, email = EmailMessage(
subject, message,
'Rowsandall <info@rowsandall.com>', 'Rowsandall <info@rowsandall.com>',
[fullemail]) [fullemail])
@@ -53,4 +52,4 @@ class Command(BaseCommand):
os.remove('email_list.csv') os.remove('email_list.csv')
res = email.send() _ = email.send()
+12 -13
View File
@@ -1,19 +1,19 @@
#!/srv/venv/bin/python
import sys import sys
import os 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$')
sys.path.append('$path_to_root_of_project$/$project_name$') sys.path.append('$path_to_root_of_project$/$project_name$')
os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' 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(): def getexpired():
rs = Rower.objects.all() rs = Rower.objects.all()
@@ -43,10 +43,9 @@ class Command(BaseCommand):
message += r.user.first_name+" "+r.user.last_name+" "+r.user.username message += r.user.first_name+" "+r.user.last_name+" "+r.user.username
message += "\n" message += "\n"
email = EmailMessage(subject, message, email = EmailMessage(
subject, message,
'Rowsandall <info@rowsandall.com>', 'Rowsandall <info@rowsandall.com>',
[fullemail]) [fullemail])
_ = email.send()
res = email.send()
+10 -10
View File
@@ -3,8 +3,6 @@
import sys import sys
import os import os
PY3K = sys.version_info >= (3,0)
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from rowers.models import Alert, Condition, User from rowers.models import Alert, Condition, User
from rowers.tasks import handle_send_email_alert from rowers.tasks import handle_send_email_alert
@@ -13,15 +11,17 @@ from rowers import alerts
from rowers.utils import myqueue from rowers.utils import myqueue
import datetime
import django_rq import django_rq
PY3K = sys.version_info >= (3, 0)
queue = django_rq.get_queue('default') queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low') queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low')
import datetime
class Command(BaseCommand): class Command(BaseCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument( parser.add_argument(
@@ -29,8 +29,7 @@ class Command(BaseCommand):
action='store_true', action='store_true',
dest='testing', dest='testing',
default=False, 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): def handle(self, *args, **options):
if 'testing' in options: if 'testing' in options:
@@ -38,7 +37,8 @@ class Command(BaseCommand):
else: else:
testing = False 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: for alert in todaysalerts:
stats = alerts.alert_get_stats(alert) stats = alerts.alert_get_stats(alert)
@@ -47,13 +47,13 @@ class Command(BaseCommand):
othertexts = [alert.description()] othertexts = [alert.description()]
# send email # send email
job = myqueue(queue,handle_send_email_alert, _ = myqueue(queue, handle_send_email_alert,
alert.manager.email, alert.manager.email,
alert.manager.first_name, alert.manager.first_name,
alert.manager.last_name, alert.manager.last_name,
alert.rower.user.first_name, alert.rower.user.first_name,
alert.name, alert.name,
stats,debug=True, stats, debug=True,
othertexts=othertexts) othertexts=othertexts)
# advance next_run # advance next_run
@@ -62,7 +62,7 @@ class Command(BaseCommand):
alert.save() alert.save()
if testing: if testing:
print('{nr} alerts found'.format(nr = len(todaysalerts))) print('{nr} alerts found'.format(nr=len(todaysalerts)))
self.stdout.write(self.style.SUCCESS( self.stdout.write(self.style.SUCCESS(
'Successfully processed alerts')) 'Successfully processed alerts'))
+17 -32
View File
@@ -1,9 +1,6 @@
#!/srv/venv/bin/python
""" Process emails """ """ Process emails """
import sys import sys
import os import os
PY3K = sys.version_info >= (3, 0)
import zipfile import zipfile
from zipfile import BadZipFile from zipfile import BadZipFile
@@ -18,12 +15,12 @@ import json
import io import io
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
#from django_mailbox.models import Message, MessageAttachment,Mailbox
from django.urls import reverse from django.urls import reverse
from django.conf import settings from django.conf import settings
from django.utils import timezone 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 rower as rrower
from rowingdata import rowingdata as rrdata from rowingdata import rowingdata as rrdata
@@ -37,7 +34,6 @@ import rowers.stravastuff as stravastuff
import rowers.nkstuff as nkstuff import rowers.nkstuff as nkstuff
from rowers.opaque import encoder from rowers.opaque import encoder
from rowers.models import User,Workout
from rowers.rower_rules import user_is_not_basic from rowers.rower_rules import user_is_not_basic
from rowers.utils import dologging from rowers.utils import dologging
@@ -47,8 +43,12 @@ sys.path.append('$path_to_root_of_project$/$project_name$')
os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings' os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings'
PY3K = sys.version_info >= (3, 0)
if not getattr(__builtins__, "WindowsError", None): if not getattr(__builtins__, "WindowsError", None):
class WindowsError(OSError): pass class WindowsError(OSError):
pass
def rdata(file_obj, rower=rrower()): # pragma: no cover def rdata(file_obj, rower=rrower()): # pragma: no cover
""" Read rowing data file and return 0 if file doesn't exist""" """ Read rowing data file and return 0 if file doesn't exist"""
@@ -60,7 +60,6 @@ def rdata(file_obj, rower=rrower()): # pragma: no cover
return result return result
class Command(BaseCommand): class Command(BaseCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument( parser.add_argument(
@@ -68,31 +67,24 @@ class Command(BaseCommand):
action='store_true', action='store_true',
dest='testing', dest='testing',
default=False, default=False,
help="Run in testing mode, don't send emails", help="Run in testing mode, don't send emails", )
)
parser.add_argument( parser.add_argument(
'--mailbox', '--mailbox',
action='store_true', action='store_true',
dest='mailbox', dest='mailbox',
default='workouts', default='workouts',
help="Changing mailbox name", help="Changing mailbox name", )
)
"""Run the Email processing command """ """Run the Email processing command """
def handle(self, *args, **options): def handle(self, *args, **options):
if 'testing' in options:
testing = options['testing']
else: # pragma: no cover
testing = False
# Polar # Polar
try: try:
polar_available = polarstuff.get_polar_notifications() polar_available = polarstuff.get_polar_notifications()
res = polarstuff.get_all_new_workouts(polar_available) _ = polarstuff.get_all_new_workouts(polar_available)
except: # pragma: no cover except: # pragma: no cover
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback) 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 # Concept2
try: try:
@@ -103,36 +95,29 @@ class Command(BaseCommand):
except: # pragma: no cover except: # pragma: no cover
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback) 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: try:
rowers = Rower.objects.filter(rp3_auto_import=True) 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): if user_is_not_basic(r.user):
res = rp3stuff.get_rp3_workouts(r) _ = rp3stuff.get_rp3_workouts(r)
except: # pragma: no cover except: # pragma: no cover
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback) 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: try:
rowers = Rower.objects.filter(nk_auto_import=True) 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): if user_is_not_basic(r.user):
s = 'Starting NK Auto Import for user {id}'.format(id=r.user.id) s = 'Starting NK Auto Import for user {id}'.format(id=r.user.id)
dologging('nklog.log',s) dologging('nklog.log', s)
res = nkstuff.get_nk_workouts(r) _ = nkstuff.get_nk_workouts(r)
except: # pragma: no cover except: # pragma: no cover
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback) 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))
# 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)
self.stdout.write(self.style.SUCCESS( self.stdout.write(self.style.SUCCESS(
'Successfully processed email attachments')) 'Successfully processed email attachments'))
+12 -9
View File
@@ -1,24 +1,27 @@
#!/srv/venv/bin/python #!/srv/venv/bin/python
import sys import sys
import os 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.core.management.base import BaseCommand, CommandError
from django.conf import settings from django.conf import settings
#from rowers.mailprocessing import processattachments
import time 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 django.core.files.base import ContentFile
from rowsandall_app.settings import BASE_DIR from rowsandall_app.settings import BASE_DIR
from rowers.dataprep import * 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): class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
repair_data(verbose=True) repair_data(verbose=True)
+1 -1
View File
@@ -99,7 +99,7 @@ class RowerPlanMiddleWare(object):
# remove from Free Coach groups # remove from Free Coach groups
# send email # send email
job = myqueue(queue, _ = myqueue(queue,
handle_sendemail_expired, handle_sendemail_expired,
r.user.email, r.user.email,
r.user.first_name, r.user.first_name,
+25 -46
View File
@@ -3,7 +3,7 @@ from rowers.metrics import rowingmetrics
from django.db.models.signals import m2m_changed from django.db.models.signals import m2m_changed
from rowers.courseutils import coordinate_in_path from rowers.courseutils import coordinate_in_path
from rowers.utils import ( from rowers.utils import (
workflowleftpanel, workflowmiddlepanel, # workflowleftpanel, workflowmiddlepanel,
defaultleft, defaultmiddle, landingpages, landingpages2, defaultleft, defaultmiddle, landingpages, landingpages2,
steps_read_fit, steps_write_fit, ps_dict_order steps_read_fit, steps_write_fit, ps_dict_order
) )
@@ -15,18 +15,15 @@ import uuid
from django.db import models, IntegrityError from django.db import models, IntegrityError
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.validators import validate_email
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django import forms from django import forms
from django.forms import ModelForm from django.forms import ModelForm
from django.dispatch import receiver from django.dispatch import receiver
from django.forms.widgets import SplitDateTimeWidget, SelectDateWidget from django.forms.widgets import SplitDateTimeWidget, SelectDateWidget
#from django.forms.extras.widgets import SelectDateWidget
from django.forms.formsets import BaseFormSet from django.forms.formsets import BaseFormSet
#from datetimewidget.widgets import DateTimeWidget
from django.contrib.admin.widgets import AdminDateWidget, AdminTimeWidget, AdminSplitDateTime from django.contrib.admin.widgets import AdminDateWidget, AdminTimeWidget, AdminSplitDateTime
from django.core.validators import validate_email
import os import os
import json import json
import twitter import twitter
@@ -55,8 +52,6 @@ import datetime
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
#from rules.contrib.models import RulesModel
from rowers.rower_rules import * from rowers.rower_rules import *
from rowers.opaque import encoder 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'}) dfs = pd.read_html(url, attrs={'class': 'views-table'})
df = dfs[0] df = dfs[0]
df.columns = df.columns.str.strip() df.columns = df.columns.str.strip()
success = 1
except: # pragma: no cover except: # pragma: no cover
df = pd.DataFrame() df = pd.DataFrame()
@@ -574,29 +568,16 @@ def course_spline(coordinates):
latitudes = coordinates['latitude'].values latitudes = coordinates['latitude'].values
longitudes = coordinates['longitude'].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)) t = np.linspace(0, 1, len(latitudes))
tnew = np.linspace(0, 1, 100) tnew = np.linspace(0, 1, 100)
try: 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) latnew = interp1d(t, latitudes)(tnew)
lonnew = interp1d(t, longitudes)(tnew) lonnew = interp1d(t, longitudes)(tnew)
except ValueError: # pragma: no cover except ValueError: # pragma: no cover
latnew = latitudes latnew = latitudes
lonnew = longitudes 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({ newcoordinates = pd.DataFrame({
'latitude': latnew, 'latitude': latnew,
'longitude': lonnew, 'longitude': lonnew,
@@ -673,7 +654,8 @@ def get_delta(vector, polygon):
p = polygon_to_path(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, df = pd.DataFrame({'x': x,
'lat': lat, 'lat': lat,
@@ -795,7 +777,7 @@ class PaidPlan(models.Model):
shortname=self.shortname, shortname=self.shortname,
price=self.price, price=self.price,
paymenttype=self.paymenttype, paymenttype=self.paymenttype,
paymentprocessor=self.paymentprocessor, # paymentprocessor=self.paymentprocessor,
) )
@@ -1346,8 +1328,9 @@ class BaseFavoriteFormSet(BaseFormSet):
xparam = form.cleaned_data['xparam'] xparam = form.cleaned_data['xparam']
yparam1 = form.cleaned_data['yparam1'] yparam1 = form.cleaned_data['yparam1']
yparam2 = form.cleaned_data['yparam2'] yparam2 = form.cleaned_data['yparam2']
plottype = form.cleaned_data['plottype'] # plottype = form.cleaned_data['plottype']
reststrokes = form.cleaned_data['reststrokes'] # reststrokes = form.cleaned_data['reststrokes']
pass
if not xparam: if not xparam:
raise forms.ValidationError( raise forms.ValidationError(
@@ -1402,10 +1385,11 @@ class BaseConditionFormSet(BaseFormSet):
for form in self.forms: for form in self.forms:
if form.cleaned_data: if form.cleaned_data:
metric = form.cleaned_data['metric'] # metric = form.cleaned_data['metric']
condition = form.cleaned_data['condition'] # condition = form.cleaned_data['condition']
value1 = form.cleaned_data['value1'] # value1 = form.cleaned_data['value1']
value2 = form.cleaned_data['value2'] # value2 = form.cleaned_data['value2']
pass
rowchoices = [] rowchoices = []
@@ -1475,7 +1459,7 @@ class Alert(models.Model):
return description return description
def shortdescription(self): # pragma: no cover 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': if self.measured.condition == 'between':
description = '{value1} < {metric} < {value2}'.format( description = '{value1} < {metric} < {value2}'.format(
@@ -1526,7 +1510,7 @@ class GeoCourse(models.Model):
def __str__(self): def __str__(self):
name = self.name name = self.name
country = self.country # country = self.country
d = self.distance d = self.distance
if d == 0: # pragma: no cover if d == 0: # pragma: no cover
self.distance = course_length(self) self.distance = course_length(self)
@@ -1535,7 +1519,7 @@ class GeoCourse(models.Model):
return u'{name} - {d}m'.format( return u'{name} - {d}m'.format(
name=name, name=name,
country=country, # country=country,
d=d, d=d,
) )
@@ -2530,7 +2514,6 @@ class PlannedSession(models.Model):
can_be_shared = models.BooleanField(default=True) can_be_shared = models.BooleanField(default=True)
fitfile = models.FileField(upload_to=get_file_path, blank=True, null=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) steps = PlannedSessionStepField(default={}, null=True, max_length=1000)
interval_string = models.TextField(max_length=1000, default=None, blank=True, null=True, interval_string = models.TextField(max_length=1000, default=None, blank=True, null=True,
verbose_name='Interval String (optional)') verbose_name='Interval String (optional)')
@@ -2565,7 +2548,7 @@ class PlannedSession(models.Model):
if self.sessionvalue <= 0: # pragma: no cover if self.sessionvalue <= 0: # pragma: no cover
self.sessionvalue = 1 self.sessionvalue = 1
manager = self.manager # manager = self.manager
if self.sessiontype not in ['race', 'indoorrace']: if self.sessiontype not in ['race', 'indoorrace']:
if not can_add_session(self.manager): if not can_add_session(self.manager):
raise ValidationError( raise ValidationError(
@@ -2612,7 +2595,7 @@ class PlannedSession(models.Model):
self.sessionmode = 'distance' self.sessionmode = 'distance'
self.sessionunit = 'm' self.sessionunit = 'm'
self.criterium = 'none' 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.course = GeoCourse.objects.all()[0]
self.sessionvalue = self.course.distance self.sessionvalue = self.course.distance
elif self.sessiontype != 'coursetest' and self.sessiontype != 'race': elif self.sessiontype != 'coursetest' and self.sessiontype != 'race':
@@ -2626,7 +2609,6 @@ class PlannedSession(models.Model):
if self.preferreddate < self.startdate: # pragma: no cover if self.preferreddate < self.startdate: # pragma: no cover
self.preferreddate = self.startdate self.preferreddate = self.startdate
#super(PlannedSession,self).save(*args, **kwargs)
if self.steps: if self.steps:
steps = self.steps steps = self.steps
elif self.fitfile: # pragma: no cover elif self.fitfile: # pragma: no cover
@@ -2640,7 +2622,7 @@ class PlannedSession(models.Model):
steps = self.steps steps = self.steps
steps['filename'] = os.path.join(settings.MEDIA_ROOT, filename) steps['filename'] = os.path.join(settings.MEDIA_ROOT, filename)
fitfile = steps_write_fit(steps) _ = steps_write_fit(steps)
self.fitfile.name = filename self.fitfile.name = filename
self.steps = steps self.steps = steps
@@ -2752,8 +2734,8 @@ class VirtualRace(PlannedSession):
def __str__(self): def __str__(self):
name = self.name name = self.name
startdate = self.startdate # startdate = self.startdate
enddate = self.enddate # enddate = self.enddate
stri = u'Virtual challenge {n}'.format( stri = u'Virtual challenge {n}'.format(
n=name, n=name,
@@ -4031,9 +4013,6 @@ class WorkoutForm(ModelForm):
class AdvancedWorkoutForm(ModelForm): class AdvancedWorkoutForm(ModelForm):
#quick_calc = forms.BooleanField(initial=True,required=False)
#go_service = forms.BooleanField(initial=False,required=False,label='Experimental')
class Meta: class Meta:
model = Workout model = Workout
fields = ['boattype', 'weightvalue', 'boatbrand'] fields = ['boattype', 'weightvalue', 'boatbrand']
@@ -4332,8 +4311,8 @@ class RowerPowerZonesForm(ModelForm):
try: try:
ut3name = cleaned_data['ut3name'] ut3name = cleaned_data['ut3name']
except: except:
ut2name = 'UT3' ut3name = 'UT3'
cleaned_data['ut3name'] = 'UT3' cleaned_data['ut3name'] = ut3name
try: try:
ut2name = cleaned_data['ut2name'] ut2name = cleaned_data['ut2name']
except: except:
@@ -4717,10 +4696,10 @@ class SiteAnnouncement(models.Model):
self.modified = timezone.now() self.modified = timezone.now()
if self.dotweet: # pragma: no cover if self.dotweet: # pragma: no cover
try: try:
status = tweetapi.PostUpdate(self.announcement) _ = tweetapi.PostUpdate(self.announcement)
except: except:
try: try:
status = tweetapi.PostUpdate(self.announcement[:270]) _ = tweetapi.PostUpdate(self.announcement[:270])
except: except:
pass pass
return super(SiteAnnouncement, self).save(*args, **kwargs) return super(SiteAnnouncement, self).save(*args, **kwargs)
-1
View File
@@ -358,7 +358,6 @@ rowtypes = (
checktypes = [i[0] for i in workouttypes_ordered.items()] checktypes = [i[0] for i in workouttypes_ordered.items()]
#colors = Category10[9]
colors = list(set(Category10[9]))+list(set(Category20[19]+Category20c[19])) colors = list(set(Category10[9]))+list(set(Category20[19]+Category20c[19]))
color_map = {checktypes[i]: colors[i] for i in range(len(checktypes))} color_map = {checktypes[i]: colors[i] for i in range(len(checktypes))}
+10 -9
View File
@@ -1,4 +1,5 @@
import pandas as pd import pandas as pd
import numpy as np
import datetime import datetime
from datetime import timedelta from datetime import timedelta
from uuid import uuid4 from uuid import uuid4
@@ -52,14 +53,14 @@ def add_workout_from_data(userid, nkid, data, strokedata, source='nk', splitdata
elapsedTime = data["elapsedTime"] elapsedTime = data["elapsedTime"]
totalDistanceGps = data["totalDistanceGps"] totalDistanceGps = data["totalDistanceGps"]
totalDistanceImp = data["totalDistanceImp"] totalDistanceImp = data["totalDistanceImp"]
intervals = data["intervals"] # add intervals # intervals = data["intervals"] # add intervals
oarlockSessions = data["oarlockSessions"] oarlockSessions = data["oarlockSessions"]
deviceId = data["deviceId"] # you could get the firmware version # deviceId = data["deviceId"] # you could get the firmware version
totalDistance = totalDistanceGps totalDistance = totalDistanceGps
useImpeller = False useImpeller = False
if speedInput: # pragma: no cover if speedInput: # pragma: no cover
totdalDistance = totalDistanceImp totalDistance = totalDistanceImp
useImpeller = True useImpeller = True
summary = get_nk_allstats(data, strokedata) 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 # oarlock inboard, length, boat name
if oarlockSessions: if oarlockSessions:
oarlocksession = oarlockSessions[0] # should take seatIndex oarlocksession = oarlockSessions[0] # should take seatIndex
boatName = oarlocksession["boatName"] # boatName = oarlocksession["boatName"]
oarLength = oarlocksession["oarLength"] # cm oarLength = oarlocksession["oarLength"] # cm
oarInboardLength = oarlocksession["oarInboardLength"] # cm oarInboardLength = oarlocksession["oarInboardLength"] # cm
seatNumber = oarlocksession["seatNumber"] # seatNumber = oarlocksession["seatNumber"]
try: try:
oarlockfirmware = oarlocksession["firmwareVersion"] oarlockfirmware = oarlocksession["firmwareVersion"]
except KeyError: except KeyError:
oarlockfirmware = '' oarlockfirmware = ''
else: # pragma: no cover else: # pragma: no cover
boatName = '' # boatName = ''
oarLength = 289 oarLength = 289
oarInboardLength = 88 oarInboardLength = 88
seatNumber = 1 # seatNumber = 1
oarlockfirmware = '' oarlockfirmware = ''
workouttype = "water" workouttype = "water"
@@ -139,7 +140,7 @@ def get_nk_intervalstats(workoutdata, strokedata):
i = 0 i = 0
for interval in intervals: for interval in intervals:
id = interval['id'] # id = interval['id']
sdist = interval['totalDistanceGps'] sdist = interval['totalDistanceGps']
avgpace = interval['avgPaceGps']/1000. avgpace = interval['avgPaceGps']/1000.
avgpacetd = timedelta(seconds=avgpace) avgpacetd = timedelta(seconds=avgpace)
@@ -325,6 +326,6 @@ def readlogs_summaries(logfile, dosave=0): # pragma: no cover
json.dump(strokeData, f2) json.dump(strokeData, f2)
with open(filename2, 'w') as f2: with open(filename2, 'w') as f2:
json.dump(summaryData, f2) json.dump(summaryData, f2)
except Exception as e: except Exception:
print(traceback.format_exc()) print(traceback.format_exc())
print("error") print("error")
+5 -22
View File
@@ -31,13 +31,6 @@ queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low') queuelow = django_rq.get_queue('low')
queuehigh = 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 = { oauth_data = {
'client_id': NK_CLIENT_ID, 'client_id': NK_CLIENT_ID,
'client_secret': NK_CLIENT_SECRET, 'client_secret': NK_CLIENT_SECRET,
@@ -56,12 +49,6 @@ oauth_data = {
def get_token(code): # pragma: no cover def get_token(code): # pragma: no cover
url = oauth_data['base_url'] 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'], post_data = {"client_id": oauth_data['client_id'],
"grant_type": "authorization_code", "grant_type": "authorization_code",
"redirect_uri": oauth_data['redirect_uri'], "redirect_uri": oauth_data['redirect_uri'],
@@ -88,13 +75,12 @@ def nk_open(user):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.nktoken == '') or (r.nktoken is None): # pragma: no cover 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") raise NoTokenError("User has no token")
else: else:
if (timezone.now() > r.nktokenexpirydate): if (timezone.now() > r.nktokenexpirydate):
thetoken = rower_nk_token_refresh(user) 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") raise NoTokenError("User has no token")
return thetoken return thetoken
else: else:
@@ -105,7 +91,7 @@ def nk_open(user):
def get_nk_workouts(rower, do_async=True, before=0, after=0): def get_nk_workouts(rower, do_async=True, before=0, after=0):
try: try:
thetoken = nk_open(rower.user) _ = nk_open(rower.user)
except NoTokenError: # pragma: no cover except NoTokenError: # pragma: no cover
return 0 return 0
@@ -136,7 +122,7 @@ def get_nk_workouts(rower, do_async=True, before=0, after=0):
pass pass
knownnkids = uniqify(knownnkids+tombstones+parkedids) 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) s = 'New NK IDs {newids}'.format(newids=newids)
dologging('nklog.log', s) 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 if (r.nktoken == '') or (r.nktoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401, s) 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." s = "Token expired. Needs to refresh."
return custom_exception_handler(401, s) return custom_exception_handler(401, s)
else: else:
@@ -251,10 +238,6 @@ def get_workout(user, nkid, do_async=True, startdate='', enddate=''):
s = "Token expired. Needs to refresh." s = "Token expired. Needs to refresh."
return custom_exception_handler(401, s), 0 return custom_exception_handler(401, s), 0
params = {
'sessionIds': nkid,
}
before = 0 before = 0
after = 0 after = 0
if startdate: # pragma: no cover if startdate: # pragma: no cover
+2 -2
View File
@@ -38,8 +38,8 @@ class OpaqueEncoder:
def transcode(self, i): def transcode(self, i):
"""Reversibly transcode a 32-bit integer to a scrambled form, returning a new 32-bit integer.""" """Reversibly transcode a 32-bit integer to a scrambled form, returning a new 32-bit integer."""
r = i & 0xffff r = i & 0xffff
l = i >> 16 & 0xffff ^ self.transform(r) lla = i >> 16 & 0xffff ^ self.transform(r)
return ((r ^ self.transform(l)) << 16) + l return ((r ^ self.transform(lla)) << 16) + lla
def encode_hex(self, i): def encode_hex(self, i):
"""Transcode an integer and return it as an 8-character hex string.""" """Transcode an integer and return it as an 8-character hex string."""
+10 -8
View File
@@ -7,7 +7,7 @@ import requests
import requests.auth import requests.auth
import json import json
from django.utils import timezone from django.utils import timezone
from datetime import datetime from datetime import datetime, timedelta
import numpy as np import numpy as np
from dateutil import parser from dateutil import parser
import time import time
@@ -30,7 +30,10 @@ from rowingdata import rowingdata
import pandas as pd import pandas as pd
from rowers.models import Rower, Workout 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_ID = "1"
TEST_CLIENT_SECRET = "aapnootmies" 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 def do_refresh_token(refreshtoken): # pragma: no cover
client_auth = requests.auth.HTTPBasicAuth( # client_auth = requests.auth.HTTPBasicAuth(
TEST_CLIENT_ID, TEST_CLIENT_SECRET) # TEST_CLIENT_ID, TEST_CLIENT_SECRET)
post_data = {"grant_type": "refresh_token", post_data = {"grant_type": "refresh_token",
"client_secret": TEST_CLIENT_SECRET, "client_secret": TEST_CLIENT_SECRET,
"client_id": TEST_CLIENT_ID, "client_id": TEST_CLIENT_ID,
@@ -86,8 +89,8 @@ def do_refresh_token(refreshtoken): # pragma: no cover
def get_token(code): # pragma: no cover def get_token(code): # pragma: no cover
client_auth = requests.auth.HTTPBasicAuth( # client_auth = requests.auth.HTTPBasicAuth(
TEST_CLIENT_ID, TEST_CLIENT_SECRET) # TEST_CLIENT_ID, TEST_CLIENT_SECRET)
post_data = {"grant_type": "authorization_code", post_data = {"grant_type": "authorization_code",
"code": code, "code": code,
"redirect_uri": "http://localhost:8000/rowers/test_callback", "redirect_uri": "http://localhost:8000/rowers/test_callback",
@@ -123,7 +126,6 @@ def make_authorization_url(request): # pragma: no cover
"scope": "write", "scope": "write",
"state": state} "state": state}
import urllib
url = "http://localhost:8000/rowers/o/authorize" + \ url = "http://localhost:8000/rowers/o/authorize" + \
urllib.parse.urlencode(params) 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 def get_ownapi_workout(user, ownapiid): # pragma: no cover
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.ownapitoken == '') or (r.ownapitoken is None): if (r.ownapitoken == '') or (r.ownapitoken is None):
return custom_exception_handler(401, s)
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401, s)
elif (timezone.now() > r.ownapitokenexpirydate): elif (timezone.now() > r.ownapitokenexpirydate):
s = "Token expired. Needs to refresh." s = "Token expired. Needs to refresh."
return custom_exception_handler(401, s) return custom_exception_handler(401, s)
+7 -24
View File
@@ -6,7 +6,6 @@ from rowers.models import (
get_course_timezone, IndoorVirtualRaceResult, VirtualRace, createmacrofillers, get_course_timezone, IndoorVirtualRaceResult, VirtualRace, createmacrofillers,
createmesofillers, createmicrofillers, CourseStandard, createmesofillers, createmicrofillers, CourseStandard,
) )
from rowers.utils import totaltime_sec_to_string
from rowers.tasks import ( from rowers.tasks import (
handle_sendemail_raceregistration, handle_sendemail_racesubmission handle_sendemail_raceregistration, handle_sendemail_racesubmission
) )
@@ -372,8 +371,6 @@ def get_todays_micro(plan, thedate=timezone.now()):
if thismicro: if thismicro:
thismicro = thismicro[0] thismicro = thismicro[0]
else: # pragma: no cover else: # pragma: no cover
mms = TrainingMicroCycle.objects.all()
return None return None
return thismicro return thismicro
@@ -421,7 +418,7 @@ def add_workouts_plannedsession(ws, ps, r):
coursecompleted=False, coursecompleted=False,
) )
record.save() record.save()
job = myqueue(queue, handle_check_race_course, w.csvfilename, _ = myqueue(queue, handle_check_race_course, w.csvfilename,
w.id, ps.course.id, record.id, w.id, ps.course.id, record.id,
w.user.user.email, w.user.user.first_name, w.user.user.email, w.user.user.first_name,
mode='coursetest') mode='coursetest')
@@ -429,9 +426,6 @@ def add_workouts_plannedsession(ws, ps, r):
records = CourseTestResult.objects.filter( records = CourseTestResult.objects.filter(
userid=w.user.id, plannedsession=ps) userid=w.user.id, plannedsession=ps)
for record in records: for record in records:
#w1 = Workout.objects.get(id=record.workoutid)
#w1.plannedsession = None
# w1.save()
record.delete() record.delete()
df = dataprep.getsmallrowdata_db( df = dataprep.getsmallrowdata_db(
@@ -463,9 +457,6 @@ def add_workouts_plannedsession(ws, ps, r):
records = CourseTestResult.objects.filter( records = CourseTestResult.objects.filter(
userid=w.user.id, plannedsession=ps) userid=w.user.id, plannedsession=ps)
for record in records: for record in records:
#w1 = Workout.objects.get(id=record.workoutid)
#w1.plannedsession = None
# w1.save()
record.delete() record.delete()
df = dataprep.getsmallrowdata_db( df = dataprep.getsmallrowdata_db(
@@ -638,7 +629,7 @@ def is_session_complete_ws(ws, ps):
value *= 1000. value *= 1000.
cratiomin = 1 cratiomin = 1
cratiomax = 1 # cratiomax = 1
cratios = { cratios = {
'better than nothing': 0, 'better than nothing': 0,
@@ -651,12 +642,12 @@ def is_session_complete_ws(ws, ps):
if ps.criterium == 'none': if ps.criterium == 'none':
if ps.sessiontype == 'session': if ps.sessiontype == 'session':
cratiomin = 0.8 cratiomin = 0.8
cratiomax = 1.2 # cratiomax = 1.2
else: else:
cratios['on target'] = 0.9167 cratios['on target'] = 0.9167
cratios['over target'] = 1.0833 cratios['over target'] = 1.0833
cratiomin = 0.9167 cratiomin = 0.9167
cratiomax = 1.0833 # cratiomax = 1.0833
score = 0 score = 0
completiondate = None completiondate = None
@@ -790,7 +781,7 @@ def is_session_complete_ws(ws, ps):
coursecompleted=False, coursecompleted=False,
) )
record.save() record.save()
job = myqueue(queue, handle_check_race_course, ws[0].csvfilename, _ = myqueue(queue, handle_check_race_course, ws[0].csvfilename,
ws[0].id, ps.course.id, record.id, ws[0].id, ps.course.id, record.id,
ws[0].user.user.email, ws[0].user.user.first_name, ws[0].user.user.email, ws[0].user.user.first_name,
mode='coursetest') mode='coursetest')
@@ -804,8 +795,6 @@ def is_session_complete_ws(ws, ps):
def is_session_complete(r, ps): def is_session_complete(r, ps):
verdict = 'not done'
if r not in ps.rower.all(): # pragma: no cover if r not in ps.rower.all(): # pragma: no cover
return 0, 'not assigned', None return 0, 'not assigned', None
@@ -1290,7 +1279,7 @@ def race_can_submit(r, race):
if timezone.now() > startdatetime and timezone.now() < evaluation_closure: if timezone.now() > startdatetime and timezone.now() < evaluation_closure:
is_complete, has_registered = race_rower_status(r, race) is_complete, has_registered = race_rower_status(r, race)
if is_complete == False: if is_complete is False:
return True return True
else: else:
return True return True
@@ -1311,7 +1300,7 @@ def race_can_editentry(r, race):
if timezone.now() < evaluation_closure: if timezone.now() < evaluation_closure:
is_complete, has_registered = race_rower_status(r, race) is_complete, has_registered = race_rower_status(r, race)
if is_complete == False: if is_complete is False:
return True return True
else: # pragma: no cover else: # pragma: no cover
return False return False
@@ -1594,7 +1583,6 @@ def add_workout_fastestrace(ws, race, r, recordid=0, doregister=False):
errors.append('For tests, you can only attach one workout') errors.append('For tests, you can only attach one workout')
return result, comments, errors, 0 return result, comments, errors, 0
username = r.user.first_name+' '+r.user.last_name
if r.birthdate: if r.birthdate:
age = calculate_age(r.birthdate) age = calculate_age(r.birthdate)
else: # pragma: no cover else: # pragma: no cover
@@ -1634,7 +1622,6 @@ def add_workout_fastestrace(ws, race, r, recordid=0, doregister=False):
records = IndoorVirtualRaceResult.objects.filter( records = IndoorVirtualRaceResult.objects.filter(
userid=r.id, userid=r.id,
race=race, race=race,
#workoutid = ws[0].id
) )
if ws[0].workouttype != record.boatclass: # pragma: no cover if ws[0].workouttype != record.boatclass: # pragma: no cover
@@ -1767,7 +1754,6 @@ def add_workout_indoorrace(ws, race, r, recordid=0, doregister=False):
errors.append('For tests, you can only attach one workout') errors.append('For tests, you can only attach one workout')
return result, comments, errors, 0 return result, comments, errors, 0
username = r.user.first_name+' '+r.user.last_name
if r.birthdate: if r.birthdate:
age = calculate_age(r.birthdate) age = calculate_age(r.birthdate)
else: # pragma: no cover else: # pragma: no cover
@@ -1915,7 +1901,6 @@ def add_workout_race(ws, race, r, splitsecond=0, recordid=0, doregister=False):
errors.append('For tests, you can only attach one workout') errors.append('For tests, you can only attach one workout')
return result, comments, errors, 0 return result, comments, errors, 0
username = r.user.first_name+' '+r.user.last_name
if r.birthdate: if r.birthdate:
age = calculate_age(r.birthdate) age = calculate_age(r.birthdate)
else: # pragma: no cover else: # pragma: no cover
@@ -1971,8 +1956,6 @@ def add_workout_race(ws, race, r, splitsecond=0, recordid=0, doregister=False):
if ws[0].workouttype != record.boatclass: # pragma: no cover if ws[0].workouttype != record.boatclass: # pragma: no cover
ws[0].workouttype = record.boatclass ws[0].workouttype = record.boatclass
ws[0].save() 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 if ws[0].boattype != record.boattype: # pragma: no cover
errors.append( errors.append(
+3 -3
View File
@@ -76,8 +76,8 @@ def mkplot(row, title):
ax1.set_title(title) ax1.set_title(title)
plt.grid(True) plt.grid(True)
majorFormatter = FuncFormatter(format_pace_tick) majorFormatter = FuncFormatter(format_pace_tick)
majorLocator = (5) # majorLocator = (5)
timeTickFormatter = NullFormatter() # timeTickFormatter = NullFormatter()
ax1.yaxis.set_major_formatter(majorFormatter) ax1.yaxis.set_major_formatter(majorFormatter)
@@ -88,7 +88,7 @@ def mkplot(row, title):
ax2.plot(t, hr, 'r-') ax2.plot(t, hr, 'r-')
ax2.set_ylabel('Heart Rate', color='r') ax2.set_ylabel('Heart Rate', color='r')
majorTimeFormatter = FuncFormatter(format_time_tick) majorTimeFormatter = FuncFormatter(format_time_tick)
majorLocator = (15*60) # majorLocator = (15*60)
ax2.xaxis.set_major_formatter(majorTimeFormatter) ax2.xaxis.set_major_formatter(majorTimeFormatter)
ax2.patch.set_alpha(0.0) ax2.patch.set_alpha(0.0)
for tl in ax2.get_yticklabels(): for tl in ax2.get_yticklabels():
+7 -20
View File
@@ -57,8 +57,6 @@ queuehigh = django_rq.get_queue('high')
# Project # Project
# from .models import Profile # from .models import Profile
#baseurl = 'https://polaraccesslink.com/v3-example'
baseurl = 'https://polaraccesslink.com/v3' baseurl = 'https://polaraccesslink.com/v3'
@@ -125,7 +123,7 @@ def get_token(code):
def make_authorization_url(): # pragma: no cover def make_authorization_url(): # pragma: no cover
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
state = str(uuid4()) # state = str(uuid4())
params = {"client_id": POLAR_CLIENT_ID, params = {"client_id": POLAR_CLIENT_ID,
"response_type": "code", "response_type": "code",
@@ -155,7 +153,7 @@ def revoke_access(user): # pragma: no cover
def get_polar_notifications(): def get_polar_notifications():
url = baseurl+'/notifications' url = baseurl+'/notifications'
state = str(uuid4()) # state = str(uuid4())
auth_string = '{id}:{secret}'.format( auth_string = '{id}:{secret}'.format(
id=POLAR_CLIENT_ID, id=POLAR_CLIENT_ID,
secret=POLAR_CLIENT_SECRET secret=POLAR_CLIENT_SECRET
@@ -302,16 +300,12 @@ def get_polar_workouts(user):
'title': '', 'title': '',
} }
#session = requests.session()
#newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
# session.headers.update(newHeaders)
url = settings.UPLOAD_SERVICE_URL url = settings.UPLOAD_SERVICE_URL
dologging('polar.log', uploadoptions) dologging('polar.log', uploadoptions)
dologging('polar.log', url) dologging('polar.log', url)
#response = session.post(url,json=uploadoptions)
job = myqueue( _ = myqueue(
queuehigh, queuehigh,
handle_request_post, handle_request_post,
url, url,
@@ -381,9 +375,6 @@ def register_user(user, token):
json=payload, json=payload,
headers=headers headers=headers
) )
#url = baseurl+'/users'
#response = requests.post(url,params=params,headers=headers)
if response.status_code not in [200, 201]: # pragma: no cover if response.status_code not in [200, 201]: # pragma: no cover
# dologging('polar.log',url) # dologging('polar.log',url)
@@ -419,10 +410,6 @@ def get_polar_user_info(user, physical=False): # pragma: no cover
'Accept': 'application/json' 'Accept': 'application/json'
} }
params = {
'user-id': r.polaruserid
}
if not physical: if not physical:
url = baseurl+'/users/{userid}'.format( url = baseurl+'/users/{userid}'.format(
userid=r.polaruserid userid=r.polaruserid
@@ -478,11 +465,11 @@ def get_polar_workout(user, id, transactionid):
exercise_dict = response.json() exercise_dict = response.json()
thisid = exercise_dict['id'] thisid = exercise_dict['id']
if thisid == id: if thisid == id:
url = baseurl+'/users/{userid}/exercise-transactions/{transactionid}/exercises/{exerciseid}/tcx'.format( url = baseurl+'/users/{userid}/exercise-transactions/{transactionid}' \
'/exercises/{exerciseid}/tcx'.format(
userid=r.polaruserid, userid=r.polaruserid,
transactionid=transactionid, transactionid=transactionid,
exerciseid=id exerciseid=id)
)
authorizationstring = str('Bearer ' + r.polartoken) authorizationstring = str('Bearer ' + r.polartoken)
headers2 = { headers2 = {
'Authorization': authorizationstring, 'Authorization': authorizationstring,
+12 -1
View File
@@ -19,7 +19,18 @@ DESCRIPTOR = _descriptor.FileDescriptor(
package='rowing_workout_metrics', package='rowing_workout_metrics',
syntax='proto3', syntax='proto3',
serialized_options=None, 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')
) )
+5 -7
View File
@@ -4,7 +4,7 @@ import gzip
import shutil import shutil
import hashlib import hashlib
from math import isinf, isnan
import uuid import uuid
@@ -60,7 +60,7 @@ def validate_image_extension(value):
ext = os.path.splitext(value.name)[1].lower() ext = os.path.splitext(value.name)[1].lower()
valid_extension = ['.jpg', '.jpeg', '.png', '.gif'] 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') raise ValidationError(u'File not supported')
@@ -71,7 +71,7 @@ def validate_file_extension(value):
'.CSV', '.fit', '.FIT', '.zip', '.ZIP', '.CSV', '.fit', '.FIT', '.zip', '.ZIP',
'.gz', '.GZ', '.xls', '.gz', '.GZ', '.xls',
'.jpg', '.jpeg', '.tiff', '.png', '.gif', '.bmp'] '.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!') raise ValidationError(u'File not supported!')
@@ -79,7 +79,7 @@ def must_be_csv(value):
import os import os
ext = os.path.splitext(value.name)[1] ext = os.path.splitext(value.name)[1]
valid_extensions = ['.csv', '.CSV'] 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!') raise ValidationError(u'File not supported!')
@@ -87,7 +87,7 @@ def validate_kml(value):
import os import os
ext = os.path.splitext(value.name)[1] ext = os.path.splitext(value.name)[1]
valid_extensions = ['.kml', '.KML'] 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!') raise ValidationError(u'File not supported!')
@@ -144,8 +144,6 @@ def handle_uploaded_file(f):
fname = f.name fname = f.name
ext = fname.split('.')[-1] ext = fname.split('.')[-1]
fname = '%s.%s' % (uuid.uuid4(), ext) 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 fname2 = 'media/'+fname
with open(fname2, 'wb+') as destination: with open(fname2, 'wb+') as destination:
for chunk in f.chunks(): for chunk in f.chunks():
+2 -15
View File
@@ -6,8 +6,6 @@ from rowers.tasks import handle_rp3_async_workout
from rowsandall_app.settings import ( from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_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, RP3_CLIENT_ID, RP3_CLIENT_KEY, RP3_REDIRECT_URI, RP3_CLIENT_SECRET,
UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET
) )
@@ -29,8 +27,6 @@ queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('high') queuehigh = django_rq.get_queue('high')
#from async_messages import message_user,messages
oauth_data = { oauth_data = {
'client_id': RP3_CLIENT_ID, 'client_id': RP3_CLIENT_ID,
'client_secret': RP3_CLIENT_SECRET, 'client_secret': RP3_CLIENT_SECRET,
@@ -64,8 +60,6 @@ def do_refresh_token(refreshtoken): # pragma: no cover
def get_token(code): # pragma: no cover def get_token(code): # pragma: no cover
client_auth = requests.auth.HTTPBasicAuth(
RP3_CLIENT_KEY, RP3_CLIENT_SECRET)
post_data = { post_data = {
"client_id": RP3_CLIENT_KEY, "client_id": RP3_CLIENT_KEY,
"grant_type": "authorization_code", "grant_type": "authorization_code",
@@ -73,9 +67,6 @@ def get_token(code): # pragma: no cover
"redirect_uri": RP3_REDIRECT_URI, "redirect_uri": RP3_REDIRECT_URI,
"client_secret": RP3_CLIENT_SECRET, "client_secret": RP3_CLIENT_SECRET,
} }
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
response = requests.post( response = requests.post(
"https://rp3rowing-app.com/oauth/token", "https://rp3rowing-app.com/oauth/token",
@@ -102,8 +93,6 @@ def make_authorization_url(request): # pragma: no cover
def get_rp3_workout_list(user): def get_rp3_workout_list(user):
r = Rower.objects.get(user=user)
auth_token = rp3_open(user) auth_token = rp3_open(user)
headers = {'Authorization': 'Bearer ' + auth_token} 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) 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: for id in newids:
startdatetime = workouts_list.loc[id, 'executed_at'] startdatetime = workouts_list.loc[id, 'executed_at']
dologging('rp3_import.log', startdatetime) dologging('rp3_import.log', startdatetime)
job = myqueue( _ = myqueue(
queuehigh, queuehigh,
handle_rp3_async_workout, handle_rp3_async_workout,
rower.user.id, 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 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) auth_token = rp3_open(user)
return get_rp3_workout_token(workout_id, auth_token, waittime=waittime, max_attempts=max_attempts) 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) url = get_rp3_workout_link(user, workout_id)
filename = 'media/RP3Import_'+str(workout_id)+'.csv' filename = 'media/RP3Import_'+str(workout_id)+'.csv'
r = Rower.objects.get(user=user)
auth_token = rp3_open(user) auth_token = rp3_open(user)
if not startdatetime: if not startdatetime:
+1 -1
View File
@@ -6,7 +6,7 @@ from rest_framework import serializers
from rowers.models import ( from rowers.models import (
Workout, Rower, FavoriteChart, VirtualRaceResult, Workout, Rower, FavoriteChart, VirtualRaceResult,
VirtualRace, GeoCourse, StandardCollection, CourseStandard, VirtualRace, GeoCourse, StandardCollection, CourseStandard,
GeoCourse, GeoPolygon, GeoPoint, PlannedSession, GeoPolygon, GeoPoint, PlannedSession,
) )
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
+4 -7
View File
@@ -164,7 +164,7 @@ def createsporttracksworkoutdata(w):
return 0 return 0
# adding diff, trying to see if this is valid # 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 - \ t = row.df.loc[:, 'TimeStamp (sec)'].values - \
row.df.loc[:, 'TimeStamp (sec)'].iloc[0] row.df.loc[:, 'TimeStamp (sec)'].iloc[0]
try: try:
@@ -293,7 +293,6 @@ def workout_sporttracks_upload(user, w, asynchron=False): # pragma: no cover
message = "Uploading to SportTracks" message = "Uploading to SportTracks"
stid = 0 stid = 0
# ready to upload. Hurray # ready to upload. Hurray
r = w.user
thetoken = sporttracks_open(user) thetoken = sporttracks_open(user)
@@ -311,7 +310,7 @@ def workout_sporttracks_upload(user, w, asynchron=False): # pragma: no cover
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json" url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
if asynchron: if asynchron:
job = myqueue(queue, handle_sporttracks_sync, _ = myqueue(queue, handle_sporttracks_sync,
w.id, url, headers, json.dumps(data, default=default)) w.id, url, headers, json.dumps(data, default=default))
return "Asynchronous sync", 0 return "Asynchronous sync", 0
@@ -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") return (0, "No distance or heart rate data in the workout")
try: try:
l = data['location'] locs = data['location']
res = splitstdata(l) res = splitstdata(locs)
times_location = res[0] times_location = res[0]
latlong = res[1] latlong = res[1]
latcoord = [] latcoord = []
@@ -492,8 +491,6 @@ def add_workout_from_data(user, importid, data, strokedata, source='sporttracks'
df.sort_values(by='TimeStamp (sec)', ascending=True) df.sort_values(by='TimeStamp (sec)', ascending=True)
timestr = strftime("%Y%m%d-%H%M%S")
# csvfilename ='media/Import_'+str(importid)+'.csv' # csvfilename ='media/Import_'+str(importid)+'.csv'
csvfilename = 'media/{code}_{importid}.csv'.format( csvfilename = 'media/{code}_{importid}.csv'.format(
importid=importid, importid=importid,
+10 -13
View File
@@ -82,7 +82,7 @@ def strava_open(user):
f.write('\n') f.write('\n')
token = imports_open(user, oauth_data) token = imports_open(user, oauth_data)
if user.rower.strava_owner_id == 0: # pragma: no cover 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 return token
@@ -120,9 +120,6 @@ def strava_establish_push(): # pragma: no cover
'callback_url': webhooklink, 'callback_url': webhooklink,
'verify_token': webhookverification, 'verify_token': webhookverification,
} }
headers = {'user-agent': 'sanderroosendaal',
'Accept': 'application/json',
'Content-Type': oauth_data['content_type']}
response = requests.post(url, data=post_data) 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" s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401, s) return custom_exception_handler(401, s)
elif (r.stravatokenexpirydate is None or timezone.now()+timedelta(seconds=3599) > r.stravatokenexpirydate): 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) authorizationstring = str('Bearer ' + r.stravatoken)
headers = {'Authorization': authorizationstring, 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 if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401, s) 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." s = "Token expired. Needs to refresh."
return custom_exception_handler(401, s) return custom_exception_handler(401, s)
else: else:
@@ -209,7 +208,7 @@ def get_strava_workout_list(user, limit_n=0):
def async_get_workout(user, stravaid): def async_get_workout(user, stravaid):
try: try:
token = strava_open(user) _ = strava_open(user)
except NoTokenError: # pragma: no cover except NoTokenError: # pragma: no cover
return 0 return 0
@@ -246,7 +245,7 @@ def createstravaworkoutdata(w, dozip=True):
if datalength != 0: if datalength != 0:
data.rename(columns=columndict, inplace=True) data.rename(columns=columndict, inplace=True)
res = data.to_csv(w.csvfilename+'.gz', _ = data.to_csv(w.csvfilename+'.gz',
index_label='index', index_label='index',
compression='gzip') compression='gzip')
try: try:
@@ -317,7 +316,7 @@ def handle_stravaexport(f2, workoutname, stravatoken, description='',
def workout_strava_upload(user, w, quick=False, asynchron=True): def workout_strava_upload(user, w, quick=False, asynchron=True):
try: try:
thetoken = strava_open(user) _ = strava_open(user)
except NoTokenError: # pragma: no cover except NoTokenError: # pragma: no cover
return "Please connect to Strava first", 0 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) r = Rower.objects.get(user=user)
res = -1 res = -1
if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover 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") raise NoTokenError("Your hovercraft is full of eels")
if (is_workout_user(user, w)): 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] activity_type = mytypes.stravamapping[w.workouttype]
except KeyError: # pragma: no cover except KeyError: # pragma: no cover
activity_type = 'Rowing' activity_type = 'Rowing'
job = myqueue(queue, _ = myqueue(queue,
handle_strava_sync, handle_strava_sync,
r.stravatoken, r.stravatoken,
w.id, w.id,
tcxfile, w.name, activity_type, tcxfile, w.name, activity_type,
w.notes w.notes)
)
dologging('strava_export_log.log', 'Exporting as {t} from {w}'.format( dologging('strava_export_log.log', 'Exporting as {t} from {w}'.format(
t=activity_type, w=w.workouttype)) t=activity_type, w=w.workouttype))
return "Asynchronous sync", -1 return "Asynchronous sync", -1
+131 -286
View File
File diff suppressed because it is too large Load Diff
+2 -4
View File
@@ -7,6 +7,8 @@ import time
import os import os
import sys import sys
import django import django
from django.contrib import messages
proj_path = "../" proj_path = "../"
sys.path.append(proj_path) sys.path.append(proj_path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rowsandall_app.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rowsandall_app.settings")
@@ -15,11 +17,7 @@ django.setup()
@app.task @app.task
def addcomment2(userid, id, debug=False): def addcomment2(userid, id, debug=False):
time.sleep(5) time.sleep(5)
# w = Workout.objects.get(id=id)
# w.notes += '\n the task has run'
# w.save()
u = User.objects.get(id=userid) u = User.objects.get(id=userid)
messages.info(u, ' The task has run') messages.info(u, ' The task has run')
messages.error(u, ' Het is veel te laat') messages.error(u, ' Het is veel te laat')
+22 -32
View File
@@ -88,7 +88,7 @@ def create_team(name, manager, private='open', notes='', viewing='allmembers'):
private=private, viewing=viewing) private=private, viewing=viewing)
t.save() t.save()
r = Rower.objects.get(user=manager) r = Rower.objects.get(user=manager)
res = add_member(t.id, r) _ = add_member(t.id, r)
except IntegrityError: except IntegrityError:
return (0, 'Team name duplication') return (0, 'Team name duplication')
return (t.id, 'Team created') return (t.id, 'Team created')
@@ -131,13 +131,13 @@ def add_member(id, rower):
# code to add all workouts # code to add all workouts
ws = Workout.objects.filter(user=rower) ws = Workout.objects.filter(user=rower)
res = handle_add_workouts_team(ws, t) _ = handle_add_workouts_team(ws, t)
# code to add plannedsessions # code to add plannedsessions
plannedsessions = PlannedSession.objects.filter( plannedsessions = PlannedSession.objects.filter(
team=t, enddate__gte=timezone.now().date()) team=t, enddate__gte=timezone.now().date())
for ps in plannedsessions: # pragma: no cover for ps in plannedsessions: # pragma: no cover
res = ps.rower.add(rower) _ = ps.rower.add(rower)
# set_teamplanexpires(rower) # set_teamplanexpires(rower)
# code for Stuck At Home Team (temporary) # code for Stuck At Home Team (temporary)
@@ -154,7 +154,7 @@ def remove_member(id, rower):
# remove the team from rower's workouts: # remove the team from rower's workouts:
ws = Workout.objects.filter(user=rower, team=t) ws = Workout.objects.filter(user=rower, team=t)
res = handle_remove_workouts_team(ws, t) _ = handle_remove_workouts_team(ws, t)
# set_teamplanexpires(rower) # set_teamplanexpires(rower)
return (id, 'Member removed') return (id, 'Member removed')
@@ -270,7 +270,7 @@ def send_coachrequest_email(rekwest):
coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_coachrequest, handle_sendemail_coachrequest,
email, name, code, coachname) email, name, code, coachname)
@@ -283,14 +283,13 @@ def send_coacheerequest_email(rekwest):
coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name coachname = rekwest.coach.user.first_name + " " + rekwest.coach.user.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_coacheerequest, handle_sendemail_coacheerequest,
email, name, code, coachname) email, name, code, coachname)
def create_request(team, user): def create_request(team, user):
r2 = Rower.objects.get(user=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 if r2 in Rower.objects.filter(team=team): # pragma: no cover
return (0, 'Already a member of that team') return (0, 'Already a member of that team')
@@ -323,8 +322,6 @@ def get_coach_club_size(coach):
# request by coach to coach user # request by coach to coach user
def create_coaching_offer(coach, user): def create_coaching_offer(coach, user):
r = user.rower
if coach in rower_get_coaches(user.rower): # pragma: no cover if coach in rower_get_coaches(user.rower): # pragma: no cover
return (0, 'You are already coaching this person.') 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=''): def create_invite(team, manager, user=None, email=''):
r = Rower.objects.get(user=manager)
if not is_team_manager(manager, team): if not is_team_manager(manager, team):
return (0, 'Not the team manager') return (0, 'Not the team manager')
if user: if user:
@@ -359,7 +355,7 @@ def create_invite(team, manager, user=None, email=''):
return (0, 'Rower does not exist') return (0, 'Rower does not exist')
if r2 in Rower.objects.filter(team=team): if r2 in Rower.objects.filter(team=team):
return (0, 'Already member of that 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') return (0, 'Invalid request - missing email or user')
else: else:
try: try:
@@ -390,13 +386,11 @@ def revoke_request(user, id):
except TeamRequest.DoesNotExist: # pragma: no cover except TeamRequest.DoesNotExist: # pragma: no cover
return (0, 'The request is invalid') return (0, 'The request is invalid')
t = rekwest.team
if rekwest.user == user: if rekwest.user == user:
rekwest.delete() rekwest.delete()
return (1, 'Request revoked') 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): def reject_revoke_coach_offer(user, id):
@@ -493,7 +487,7 @@ def send_invite_email(id):
manager = invitation.team.manager.first_name + \ manager = invitation.team.manager.first_name + \
' '+invitation.team.manager.last_name ' '+invitation.team.manager.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_invite, handle_sendemail_invite,
email, name, code, teamname, manager) email, name, code, teamname, manager)
@@ -506,7 +500,7 @@ def send_team_delete_mail(t, rower):
email = u.email email = u.email
name = u.first_name+' '+u.last_name name = u.first_name+' '+u.last_name
manager = t.manager.first_name+' '+t.manager.last_name manager = t.manager.first_name+' '+t.manager.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_team_removed, handle_sendemail_team_removed,
email, name, teamname, manager) email, name, teamname, manager)
@@ -521,19 +515,18 @@ def send_email_member_dropped(teamid, rower):
name = u.first_name+' '+u.last_name name = u.first_name+' '+u.last_name
manager = t.manager.first_name+' '+t.manager.last_name manager = t.manager.first_name+' '+t.manager.last_name
res = myqueue(queuehigh, handle_sendemail_member_dropped, _ = myqueue(queuehigh, handle_sendemail_member_dropped,
email, name, teamname, manager) email, name, teamname, manager)
return (1, 'Member dropped email sent') return (1, 'Member dropped email sent')
def send_request_accept_email(rekwest): # pragma: no cover def send_request_accept_email(rekwest): # pragma: no cover
id = rekwest.id
email = rekwest.user.email email = rekwest.user.email
teamname = rekwest.team.name teamname = rekwest.team.name
name = rekwest.user.first_name+' '+rekwest.user.last_name name = rekwest.user.first_name+' '+rekwest.user.last_name
manager = rekwest.team.manager.first_name+' '+rekwest.team.manager.last_name manager = rekwest.team.manager.first_name+' '+rekwest.team.manager.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_request_accept, handle_sendemail_request_accept,
email, name, teamname, manager) email, name, teamname, manager)
@@ -541,13 +534,12 @@ def send_request_accept_email(rekwest): # pragma: no cover
def send_request_reject_email(rekwest): def send_request_reject_email(rekwest):
id = rekwest.id
teamname = rekwest.team.name teamname = rekwest.team.name
email = rekwest.user.email email = rekwest.user.email
name = rekwest.user.first_name+' '+rekwest.user.last_name name = rekwest.user.first_name+' '+rekwest.user.last_name
manager = rekwest.team.manager.first_name+' '+rekwest.team.manager.last_name manager = rekwest.team.manager.first_name+' '+rekwest.team.manager.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_request_reject, handle_sendemail_request_reject,
email, name, teamname, manager) email, name, teamname, manager)
@@ -555,7 +547,6 @@ def send_request_reject_email(rekwest):
def send_invite_reject_email(invitation): def send_invite_reject_email(invitation):
id = invitation.id
email = invitation.team.manager.email email = invitation.team.manager.email
if invitation.user: if invitation.user:
name = invitation.user.first_name+' '+invitation.user.last_name name = invitation.user.first_name+' '+invitation.user.last_name
@@ -566,7 +557,7 @@ def send_invite_reject_email(invitation):
manager = invitation.team.manager.first_name + \ manager = invitation.team.manager.first_name + \
' '+invitation.team.manager.last_name ' '+invitation.team.manager.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_invite_reject, handle_sendemail_invite_reject,
email, name, teamname, manager) email, name, teamname, manager)
@@ -574,7 +565,6 @@ def send_invite_reject_email(invitation):
def send_invite_accept_email(invitation): # pragma: no cover def send_invite_accept_email(invitation): # pragma: no cover
id = invitation.id
email = invitation.team.manager.email email = invitation.team.manager.email
if invitation.user: if invitation.user:
name = invitation.user.first_name+' '+invitation.user.last_name name = invitation.user.first_name+' '+invitation.user.last_name
@@ -585,7 +575,7 @@ def send_invite_accept_email(invitation): # pragma: no cover
manager = invitation.team.manager.first_name + \ manager = invitation.team.manager.first_name + \
' '+invitation.team.manager.last_name ' '+invitation.team.manager.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_invite_accept, handle_sendemail_invite_accept,
email, name, teamname, manager) email, name, teamname, manager)
@@ -598,7 +588,7 @@ def send_team_message(team, message): # pragma: no cover
for rower in rowers: for rower in rowers:
rowername = rower.user.first_name + " " + rower.user.last_name rowername = rower.user.first_name + " " + rower.user.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_message, handle_sendemail_message,
rower.user.email, team.manager.email, rowername, message, team.name, managername) rower.user.email, team.manager.email, rowername, message, team.name, managername)
@@ -613,7 +603,7 @@ def send_request_email(rekwest):
teamname = rekwest.team.name teamname = rekwest.team.name
requestor = rekwest.user.first_name+' '+rekwest.user.last_name requestor = rekwest.user.first_name+' '+rekwest.user.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_request, handle_sendemail_request,
email, name, code, teamname, requestor, id) email, name, code, teamname, requestor, id)
@@ -729,7 +719,7 @@ def send_coachoffer_rejected_email(rekwest):
name = rekwest.user.first_name + " " + rekwest.user.last_name name = rekwest.user.first_name + " " + rekwest.user.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_coachoffer_rejected, handle_sendemail_coachoffer_rejected,
coachemail, coachname, name) coachemail, coachname, name)
@@ -740,7 +730,7 @@ def send_coachrequest_rejected_email(rekwest):
name = rekwest.user.first_name + " " + rekwest.user.last_name name = rekwest.user.first_name + " " + rekwest.user.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_coachrequest_rejected, handle_sendemail_coachrequest_rejected,
email, coachname, name) email, coachname, name)
@@ -751,7 +741,7 @@ def send_coachrequest_accepted_email(rekwest):
name = rekwest.user.first_name + " " + rekwest.user.last_name name = rekwest.user.first_name + " " + rekwest.user.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_coachrequest_accepted, handle_sendemail_coachrequest_accepted,
email, coachname, name) email, coachname, name)
@@ -762,6 +752,6 @@ def send_coachoffer_accepted_email(rekwest):
name = rekwest.user.first_name + " " + rekwest.user.last_name name = rekwest.user.first_name + " " + rekwest.user.last_name
res = myqueue(queuehigh, _ = myqueue(queuehigh,
handle_sendemail_coachoffer_accepted, handle_sendemail_coachoffer_accepted,
coachemail, coachname, name) coachemail, coachname, name)
+1 -6
View File
@@ -21,8 +21,6 @@ from rowsandall_app.settings import (
tpapilocation = "https://api.trainingpeaks.com" tpapilocation = "https://api.trainingpeaks.com"
#from async_messages import message_user,messages
oauth_data = { oauth_data = {
'client_id': TP_CLIENT_ID, 'client_id': TP_CLIENT_ID,
'client_secret': TP_CLIENT_SECRET, 'client_secret': TP_CLIENT_SECRET,
@@ -53,7 +51,7 @@ def do_refresh_token(refreshtoken):
def get_token(code): 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 = { post_data = {
"client_id": TP_CLIENT_KEY, "client_id": TP_CLIENT_KEY,
"grant_type": "authorization_code", "grant_type": "authorization_code",
@@ -61,9 +59,6 @@ def get_token(code):
"redirect_uri": TP_REDIRECT_URI, "redirect_uri": TP_REDIRECT_URI,
"client_secret": TP_CLIENT_SECRET, "client_secret": TP_CLIENT_SECRET,
} }
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
response = requests.post( response = requests.post(
"https://oauth.trainingpeaks.com/oauth/token", "https://oauth.trainingpeaks.com/oauth/token",
-2
View File
@@ -151,8 +151,6 @@ class TraverseLinksTest(TestCase):
if response.status_code == 200: if response.status_code == 200:
soup = BeautifulSoup(response.content, 'html.parser') soup = BeautifulSoup(response.content, 'html.parser')
text = soup.get_text()
for link in soup.find_all('a'): for link in soup.find_all('a'):
new_link = link.get('href') new_link = link.get('href')
if VERBOSE: if VERBOSE:
+11 -12
View File
@@ -87,7 +87,7 @@ def make_plot(r, w, f1, f2, plottype, title, imagename='', plotnr=0):
} }
axis = r.staticgrids axis = r.staticgrids
if axis == None: # pragma: no cover if axis is None: # pragma: no cover
gridtrue = False gridtrue = False
axis = 'both' axis = 'both'
else: else:
@@ -133,14 +133,14 @@ def do_sync(w, options, quick=False):
do_strava_export = w.user.strava_auto_export do_strava_export = w.user.strava_auto_export
try: 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: except KeyError:
upload_to_strava = False pass
try: try:
if options['stravaid'] != 0 and options['stravaid'] != '': # pragma: no cover if options['stravaid'] != 0 and options['stravaid'] != '': # pragma: no cover
w.uploadedtostrava = options['stravaid'] w.uploadedtostrava = options['stravaid']
upload_to_strava = False # upload_to_strava = False
do_strava_export = False do_strava_export = False
w.save() w.save()
except KeyError: except KeyError:
@@ -174,14 +174,14 @@ def do_sync(w, options, quick=False):
do_c2_export = w.user.c2_auto_export do_c2_export = w.user.c2_auto_export
try: 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: except KeyError:
upload_to_c2 = False pass
try: try:
if options['c2id'] != 0 and options['c2id'] != '': # pragma: no cover if options['c2id'] != 0 and options['c2id'] != '': # pragma: no cover
w.uploadedtoc2 = options['c2id'] w.uploadedtoc2 = options['c2id']
upload_to_c2 = False # upload_to_c2 = False
do_c2_export = False do_c2_export = False
w.save() w.save()
except KeyError: except KeyError:
@@ -250,16 +250,15 @@ def do_sync(w, options, quick=False):
with open('st_export.log', 'a') as logfile: with open('st_export.log', 'a') as logfile:
logfile.write(str(timezone.now())+': ') logfile.write(str(timezone.now())+': ')
logfile.write(str(w.user)+' NoTokenError\n') 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 if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export): # pragma: no cover
try: try:
message, id = tpstuff.workout_tp_upload( _, id = tpstuff.workout_tp_upload(
w.user.user, w w.user.user, w
) )
except NoTokenError: except NoTokenError:
message = "Please connect to TrainingPeaks first" return 0
id = 0
return 1 return 1
+22 -16
View File
@@ -17,7 +17,6 @@ from rest_framework.permissions import *
from rowers import views from rowers import views
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.utils.decorators import method_decorator
from rowers.permissions import ( from rowers.permissions import (
IsOwnerOrNot, IsOwnerOrReadOnly, IsOwnerOrNot, IsOwnerOrReadOnly,
@@ -71,7 +70,7 @@ class PlannedSessionViewSet(viewsets.ModelViewSet):
class WorkoutViewSet(viewsets.ModelViewSet): class WorkoutViewSet(viewsets.ModelViewSet):
model = Workout model = Workout
#queryset = Workout.objects.all().order_by("-date", "-starttime")
serializer_class = WorkoutSerializer serializer_class = WorkoutSerializer
def get_queryset(self): # pragma: no cover def get_queryset(self): # pragma: no cover
@@ -90,7 +89,6 @@ class WorkoutViewSet(viewsets.ModelViewSet):
class RowerViewSet(viewsets.ModelViewSet): class RowerViewSet(viewsets.ModelViewSet):
model = Rower model = Rower
serializer_class = RowerSerializer serializer_class = RowerSerializer
#queryset = Rower.objects.all()
def get_queryset(self): # pragma: no cover def get_queryset(self): # pragma: no cover
try: try:
@@ -109,7 +107,6 @@ class RowerViewSet(viewsets.ModelViewSet):
class FavoriteChartViewSet(viewsets.ModelViewSet): class FavoriteChartViewSet(viewsets.ModelViewSet):
model = FavoriteChart model = FavoriteChart
serializer_class = FavoriteChartSerializer serializer_class = FavoriteChartSerializer
#queryset = FavoriteChart.objects.all()
def get_queryset(self): # pragma: no cover def get_queryset(self): # pragma: no cover
try: try:
@@ -235,8 +232,6 @@ handler400 = views.error400_view
handler500 = views.error500_view handler500 = views.error500_view
#app_name = "rowers"
urlpatterns = [ urlpatterns = [
re_path(r'^o/authorize/$', base.AuthorizationView.as_view(), name="authorize"), re_path(r'^o/authorize/$', base.AuthorizationView.as_view(), name="authorize"),
re_path(r'^o/token/$', base.TokenView.as_view(), name="token"), re_path(r'^o/token/$', base.TokenView.as_view(), name="token"),
@@ -352,17 +347,21 @@ urlpatterns = [
re_path(r'^workouts-join-select/user/(?P<userid>\d+)/$', re_path(r'^workouts-join-select/user/(?P<userid>\d+)/$',
views.workouts_join_select, name='workouts_join_select'), views.workouts_join_select, name='workouts_join_select'),
re_path( re_path(
r'^user-analysis-select/(?P<function>\w.*)/team/(?P<teamid>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$', views.analysis_new, name='analysis_new'), r'^user-analysis-select/(?P<function>\w.*)/team/(?P<teamid>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',
views.analysis_new, name='analysis_new'),
re_path( re_path(
r'^user-analysis-select/(?P<function>\w.*)/session/(?P<session>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$', views.analysis_new, name='analysis_new'), r'^user-analysis-select/(?P<function>\w.*)/session/(?P<session>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',
views.analysis_new, name='analysis_new'),
re_path( re_path(
r'^user-analysis-select/(?P<function>\w.*)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$', views.analysis_new, name='analysis_new'), r'^user-analysis-select/(?P<function>\w.*)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',
views.analysis_new, name='analysis_new'),
re_path(r'^user-analysis-select/(?P<function>\w.*)/user/(?P<userid>\d+)/$', re_path(r'^user-analysis-select/(?P<function>\w.*)/user/(?P<userid>\d+)/$',
views.analysis_new, name='analysis_new'), views.analysis_new, name='analysis_new'),
re_path(r'^user-analysis-select/(?P<function>\w.*)/team/(?P<teamid>\d+)/$', re_path(r'^user-analysis-select/(?P<function>\w.*)/team/(?P<teamid>\d+)/$',
views.analysis_new, name='analysis_new'), views.analysis_new, name='analysis_new'),
re_path( re_path(
r'^user-analysis-select/team/(?P<teamid>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$', views.analysis_new, name='analysis_new'), r'^user-analysis-select/team/(?P<teamid>\d+)/workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',
views.analysis_new, name='analysis_new'),
re_path(r'^user-analysis-select/user/(?P<userid>\d+)/$', re_path(r'^user-analysis-select/user/(?P<userid>\d+)/$',
views.analysis_new, name='analysis_new'), views.analysis_new, name='analysis_new'),
re_path(r'^user-analysis-select/team/(?P<teamid>\d+)/$', re_path(r'^user-analysis-select/team/(?P<teamid>\d+)/$',
@@ -613,7 +612,8 @@ urlpatterns = [
views.workout_nkimport_view, name='workout_nkimport_view'), views.workout_nkimport_view, name='workout_nkimport_view'),
re_path(r'^workout/nkimport/all/$', views.workout_getnkworkout_all, re_path(r'^workout/nkimport/all/$', views.workout_getnkworkout_all,
name='workout_getnkworkout_all'), name='workout_getnkworkout_all'),
re_path(r'^workout/nkimport/all/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\d+-\d+-\d+)/$', views.workout_getnkworkout_all, re_path(r'^workout/nkimport/all/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\d+-\d+-\d+)/$',
views.workout_getnkworkout_all,
name='workout_getnkworkout_all'), name='workout_getnkworkout_all'),
re_path(r'^workout/rp3import/(?P<externalid>\d+)/$', views.workout_getrp3importview, re_path(r'^workout/rp3import/(?P<externalid>\d+)/$', views.workout_getrp3importview,
name='workout_getrp3importview'), name='workout_getrp3importview'),
@@ -853,11 +853,15 @@ urlpatterns = [
name='workout_workflow_view'), name='workout_workflow_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/courses/$', views.workout_course_view, re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/courses/$', views.workout_course_view,
name='workout_course_view'), name='workout_course_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/flexchart/(?P<xparam>[\w\ ]+.*)/(?P<yparam1>[\w\ ]+.*)/(?P<yparam2>[\w\ ]+.*)/(?P<plottype>\w+)/$', re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/flexchart/'\
'(?P<xparam>[\w\ ]+.*)/(?P<yparam1>[\w\ ]+.*)/(?P<yparam2>[\w\ ]+.*)/(?P<plottype>\w+)/$',
views.workout_flexchart3_view, name='workout_flexchart3_view'), views.workout_flexchart3_view, name='workout_flexchart3_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/flexchart/(?P<xparam>\w+.*)/(?P<yparam1>[\w\ ]+.*)/(?P<yparam2>[\w\ ]+.*)/(?P<plottype>\w+.*)/$', re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/flexchart/'\
'(?P<xparam>\w+.*)/(?P<yparam1>[\w\ ]+.*)/(?P<yparam2>[\w\ ]+.*)/(?P<plottype>\w+.*)/$',
views.workout_flexchart3_view, name='workout_flexchart3_view'), views.workout_flexchart3_view, name='workout_flexchart3_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/flexchart/(?P<xparam>\w+.*)/(?P<yparam1>[\w\ ]+.*)/(?P<yparam2>[\w\ ]+.*)/$', re_path(
r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/flexchart/'\
'(?P<xparam>\w+.*)/(?P<yparam1>[\w\ ]+.*)/(?P<yparam2>[\w\ ]+.*)/$',
views.workout_flexchart3_view, name='workout_flexchart3_view'), views.workout_flexchart3_view, name='workout_flexchart3_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/flexchart/$', re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/flexchart/$',
views.workout_flexchart3_view, name='workout_flexchart3_view'), views.workout_flexchart3_view, name='workout_flexchart3_view'),
@@ -1002,7 +1006,8 @@ urlpatterns = [
name='plannedsession_teamclone_view'), name='plannedsession_teamclone_view'),
re_path(r'^sessions/(?P<id>\d+)/clone/$', views.plannedsession_clone_view), re_path(r'^sessions/(?P<id>\d+)/clone/$', views.plannedsession_clone_view),
re_path( re_path(
r'^sessions/(?P<psid>\d+)/detach/(?P<id>\b[0-9A-Fa-f]+\b)/user/(?P<userid>\d+)/$', views.plannedsession_detach_view), r'^sessions/(?P<psid>\d+)/detach/(?P<id>\b[0-9A-Fa-f]+\b)/user/(?P<userid>\d+)/$',
views.plannedsession_detach_view),
re_path( re_path(
r'^sessions/(?P<psid>\d+)/detach/(?P<id>\b[0-9A-Fa-f]+\b)/$', views.plannedsession_detach_view), r'^sessions/(?P<psid>\d+)/detach/(?P<id>\b[0-9A-Fa-f]+\b)/$', views.plannedsession_detach_view),
re_path(r'^sessions/(?P<id>\d+)/$', views.plannedsession_view, re_path(r'^sessions/(?P<id>\d+)/$', views.plannedsession_view,
@@ -1043,7 +1048,8 @@ urlpatterns = [
name='plannedsessions_print_view'), name='plannedsessions_print_view'),
re_path(r'^sessions/(?P<id>\d+)/message/$', views.plannedsession_message_view, re_path(r'^sessions/(?P<id>\d+)/message/$', views.plannedsession_message_view,
name='plannedsession_message_view'), name='plannedsession_message_view'),
re_path(r'^sessions/print/user/(?P<userid>\d+)/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\d+-\d+-\d+)/$', views.plannedsessions_print_view, re_path(r'^sessions/print/user/(?P<userid>\d+)/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\d+-\d+-\d+)/$',
views.plannedsessions_print_view,
name='plannedsessions_print_view'), name='plannedsessions_print_view'),
re_path(r'^sessions/sendcalendar/$', views.plannedsessions_icsemail_view, re_path(r'^sessions/sendcalendar/$', views.plannedsessions_icsemail_view,
name='plannedsessions_coach_icsemail_view'), name='plannedsessions_coach_icsemail_view'),
+24 -25
View File
@@ -16,14 +16,11 @@ import datetime
import json import json
import time import time
from fitparse import FitFile from fitparse import FitFile
from django.conf import settings
from django.http import HttpResponse from django.http import HttpResponse
import requests import requests
from django.http import HttpResponse
import humanize import humanize
from pytz.exceptions import UnknownTimeZoneError from pytz.exceptions import UnknownTimeZoneError
import pytz import pytz
@@ -189,7 +186,6 @@ palettes = {
'gold_sunset': (47, -31, .26, -0.12, 0.94, -0.5), 'gold_sunset': (47, -31, .26, -0.12, 0.94, -0.5),
'blue_red': (207, -200, .85, 0, .74, -.24), 'blue_red': (207, -200, .85, 0, .74, -.24),
'blue_green': (207, -120, .85, 0, .75, .25), '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), 'cyan_purple': trcolors(237, 248, 251, 136, 65, 157),
'green_blue': trcolors(240, 249, 232, 8, 104, 172), 'green_blue': trcolors(240, 249, 232, 8, 104, 172),
'orange_red': trcolors(254, 240, 217, 179, 0, 0), 'orange_red': trcolors(254, 240, 217, 179, 0, 0),
@@ -237,7 +233,8 @@ def str2bool(v): # pragma: no cover
def uniqify(seq, idfun=None): def uniqify(seq, idfun=None):
# order preserving # order preserving
if idfun is None: if idfun is None:
def idfun(x): return x def idfun(x):
return x
seen = {} seen = {}
result = [] result = []
for item in seq: for item in seq:
@@ -465,14 +462,14 @@ def totaltime_sec_to_string(totaltime, shorten=False):
hours=hours, hours=hours,
minutes=minutes, minutes=minutes,
seconds=seconds, seconds=seconds,
tenths=tenths # tenths=tenths
) )
else: else:
duration = "{minutes}:{seconds:02d}".format( duration = "{minutes}:{seconds:02d}".format(
hours=hours, # hours=hours,
minutes=minutes, minutes=minutes,
seconds=seconds, seconds=seconds,
tenths=tenths # tenths=tenths
) )
return duration return duration
@@ -559,12 +556,12 @@ def get_strava_stream(r, metric, stravaid, series_type='time', fetchresolution='
if metric == 'power': # pragma: no cover if metric == 'power': # pragma: no cover
metric = 'watts' metric = 'watts'
url = "https://www.strava.com/api/v3/activities/{stravaid}/streams/{metric}?resolution={fetchresolution}&series_type={series_type}".format( url = "https://www.strava.com/api/v3/activities/{stravaid}" \
"/streams/{metric}?resolution={fetchresolution}&series_type={series_type}".format(
stravaid=stravaid, stravaid=stravaid,
fetchresolution=fetchresolution, fetchresolution=fetchresolution,
series_type=series_type, series_type=series_type,
metric=metric metric=metric)
)
s = requests.get(url, headers=headers) s = requests.get(url, headers=headers)
@@ -574,7 +571,6 @@ def get_strava_stream(r, metric, stravaid, series_type='time', fetchresolution='
try: try:
for data in s.json(): for data in s.json():
y = None
try: try:
if data['type'] == metric: if data['type'] == metric:
return np.array(data['data']) return np.array(data['data'])
@@ -790,14 +786,14 @@ def get_step_type(step): # pragma: no cover
return t return t
def peel(l): def peel(listToPeel):
if len(l) == 0: # pragma: no cover if len(listToPeel) == 0: # pragma: no cover
return None, None return None, None
if len(l) == 1: if len(listToPeel) == 1:
return l[0], None return listToPeel[0], None
first = l[0] first = listToPeel[0]
rest = l[1:] rest = listToPeel[1:]
if first['type'] == 'Step': # pragma: no cover if first['type'] == 'Step': # pragma: no cover
return first, rest return first, rest
@@ -944,7 +940,7 @@ def step_to_string(step, short=False):
repeatValue = 1 repeatValue = 1
nr = 0 nr = 0
name = ''
intensity = '' intensity = ''
duration = '' duration = ''
unit = '' unit = ''
@@ -954,7 +950,11 @@ def step_to_string(step, short=False):
durationtype = step['durationType'] durationtype = step['durationType']
if step['durationValue'] == 0: 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 return '', type, -1, -1, 1
if durationtype == 'Time': if durationtype == 'Time':
@@ -963,7 +963,6 @@ def step_to_string(step, short=False):
if value/1000. >= 3600: # pragma: no cover if value/1000. >= 3600: # pragma: no cover
unit = 'h' unit = 'h'
dd = timedelta(seconds=value/1000.) dd = timedelta(seconds=value/1000.)
#duration = humanize.naturaldelta(dd, minimum_unit="seconds")
duration = '{v}'.format(v=str(dd)) duration = '{v}'.format(v=str(dd))
elif durationtype == 'Distance': elif durationtype == 'Distance':
unit = 'm' unit = 'm'
@@ -1163,7 +1162,7 @@ def step_to_string(step, short=False):
nr = step['stepId'] nr = step['stepId']
name = step['wkt_step_name'] # name = step['wkt_step_name']
notes = '' notes = ''
try: try:
@@ -1178,10 +1177,10 @@ def step_to_string(step, short=False):
intensity = 0 intensity = 0
s = '{duration} {unit} {target} {repeat} {notes}'.format( s = '{duration} {unit} {target} {repeat} {notes}'.format(
nr=nr, # nr=nr,
name=name, # name=name,
unit=unit, unit=unit,
intensity=intensity, # intensity=intensity,
duration=duration, duration=duration,
target=target, target=target,
repeat=repeat, repeat=repeat,
+1 -2
View File
@@ -3736,8 +3736,7 @@ def workout_flexchart3_view(request, *args, **kwargs):
'yaxis1': yparam1, 'yaxis1': yparam1,
'yaxis2': yparam2, 'yaxis2': yparam2,
} }
flexaxesform = FlexAxesForm(request, initial=initial, flexaxesform = FlexAxesForm(request, initial=initial)
extrametrics=extrametrics)
initial = { initial = {
'includereststrokes': not workstrokesonly, 'includereststrokes': not workstrokesonly,
+2 -2
View File
@@ -70,7 +70,7 @@ def get_metar_data(airportcode, unixtime):
lengte = len(doc.xpath('data/METAR/station_id')) lengte = len(doc.xpath('data/METAR/station_id'))
idnr = int(lengte/2) idnr = int(lengte/2)
try: 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 temp_c = doc.xpath('data/METAR/temp_c')[idnr].text
wind_dir = doc.xpath('data/METAR/wind_dir_degrees')[idnr].text wind_dir = doc.xpath('data/METAR/wind_dir_degrees')[idnr].text
wind_speed = doc.xpath('data/METAR/wind_speed_kt')[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 windbearing = 0
summary = 'unknown' summary = 'unknown'
airports = ['unknown'] airports = ['unknown']
temparature = 'unknown' temperature = 'unknown'
temperaturec = 'unknown' temperaturec = 'unknown'
message = 'Not able to get weather data' message = 'Not able to get weather data'
-1
View File
@@ -1 +0,0 @@
-4
View File
@@ -1,5 +1 @@
from django import forms from django import forms
-1
View File
@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
+54 -60
View File
@@ -12,7 +12,7 @@ https://docs.djangoproject.com/en/1.9/ref/settings/
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
from YamJam import yamjam 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 # Read configuration (passwords, keys, secrets) from YamJam configuration
# You have to create your own config.yaml in the project directory # You have to create your own config.yaml in the project directory
@@ -20,8 +20,6 @@ CFG = yamjam()['rowsandallapp']
DEFAULT_CHARSET = 'UTF-8' DEFAULT_CHARSET = 'UTF-8'
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -39,10 +37,10 @@ TESTING = False
ALLOWED_HOSTS = CFG['allowed_hosts'] ALLOWED_HOSTS = CFG['allowed_hosts']
#OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = 'oauth2_provider.AccessToken' # OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = 'oauth2_provider.AccessToken'
#OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application' # OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application'
#OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = 'oauth2_provider.RefreshToken' # OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = 'oauth2_provider.RefreshToken'
#OAUTH2_PROVIDER_ACCESS_TOKEN_EXPIRE_SECONDS = 3600 # OAUTH2_PROVIDER_ACCESS_TOKEN_EXPIRE_SECONDS = 3600
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
@@ -51,20 +49,20 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
INSTALLED_APPS = [ INSTALLED_APPS = [
'rowers', 'rowers',
'survey', 'survey',
# 'cvkbrno', # 'cvkbrno',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
# 'suit', # 'suit',
# 'suit_rq', # 'suit_rq',
'leaflet', 'leaflet',
'django_rq', 'django_rq',
# 'django_rq_dashboard', # 'django_rq_dashboard',
# 'translation_manager', # 'translation_manager',
# 'django_mailbox', # 'django_mailbox',
'rest_framework', 'rest_framework',
'datetimewidget', 'datetimewidget',
'rest_framework_swagger', 'rest_framework_swagger',
@@ -91,12 +89,12 @@ MIDDLEWARE = [
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.common.BrokenLinkEmailsMiddleware', 'django.middleware.common.BrokenLinkEmailsMiddleware',
'django.middleware.gzip.GZipMiddleware', 'django.middleware.gzip.GZipMiddleware',
# 'htmlmin.middleware.HtmlMinifyMiddleware', # 'htmlmin.middleware.HtmlMinifyMiddleware',
# 'htmlmin.middleware.MarkRequestMiddleware', # 'htmlmin.middleware.MarkRequestMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
# 'django.middleware.locale.LocaleMiddleware', # 'django.middleware.locale.LocaleMiddleware',
'corsheaders.middleware.CorsMiddleware', 'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
@@ -106,14 +104,14 @@ MIDDLEWARE = [
'tz_detect.middleware.TimezoneMiddleware', 'tz_detect.middleware.TimezoneMiddleware',
'rowers.middleware.SurveyMiddleWare', 'rowers.middleware.SurveyMiddleWare',
'rowers.middleware.GDPRMiddleWare', 'rowers.middleware.GDPRMiddleWare',
# 'rowers.middleware.PowerTimeFitnessMetricMiddleWare', # 'rowers.middleware.PowerTimeFitnessMetricMiddleWare',
'rowers.middleware.RowerPlanMiddleWare', 'rowers.middleware.RowerPlanMiddleWare',
] ]
ROOT_URLCONF = 'rowsandall_app.urls' ROOT_URLCONF = 'rowsandall_app.urls'
HTML_MINIFY = True HTML_MINIFY = True
#EXCLUDE_FROM_MINIFYING = ('^rowers/flexall', # EXCLUDE_FROM_MINIFYING = ('^rowers/flexall',
# '^rowers/list-workouts', # '^rowers/list-workouts',
# '^rowers/list-graphs', # '^rowers/list-graphs',
# '^admin/', # '^admin/',
@@ -124,7 +122,7 @@ APPEND_SLASH = True
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')], 'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True, 'APP_DIRS': True,
'OPTIONS': { 'OPTIONS': {
'context_processors': [ 'context_processors': [
@@ -133,18 +131,17 @@ TEMPLATES = [
'django.contrib.auth.context_processors.auth', 'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
'django.template.context_processors.i18n', 'django.template.context_processors.i18n',
# 'context_processors.google_analytics', # 'context_processors.google_analytics',
'context_processors.warning_message', 'context_processors.warning_message',
'rowers.context_processors.braintree_merchant', 'rowers.context_processors.braintree_merchant',
], ],
'libraries' : { 'libraries': {
'staticfiles': 'django.templatetags.static', 'staticfiles': 'django.templatetags.static',
} }
# 'loaders': [ # 'loaders': [
# 'django.template.loaders.app_directories.Loader', # 'django.template.loaders.app_directories.Loader',
# ], # ],
}, },
}, },
] ]
@@ -229,12 +226,12 @@ DATE_FORMAT = 'Y-m-d'
USE_TZ = True USE_TZ = True
TIME_ZONE = 'UTC' TIME_ZONE = 'UTC'
TZ_DETECT_COUNTRIES = ('US','DE','GB','CZ','FR','IT') TZ_DETECT_COUNTRIES = ('US', 'DE', 'GB', 'CZ', 'FR', 'IT')
LOCALE_PATHS = ( LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'), os.path.join(BASE_DIR, 'locale'),
# os.path.join(BASE_DIR, 'cvkbrno/locale'), # os.path.join(BASE_DIR, 'cvkbrno/locale'),
) )
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'en-us'
@@ -244,19 +241,16 @@ LANGUAGE_COOKIE_NAME = 'wm_lang'
# https://docs.djangoproject.com/en/1.9/howto/static-files/ # https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_URL = '/static/' STATIC_URL = '/static/'
#STATIC_ROOT = BASE_DIR # 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/plots'),] STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static/plots'), ]
# os.path.join(BASE_DIR, 'static'), # os.path.join(BASE_DIR, 'static'),
MEDIA_URL = '/media/' MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# user authentication
# user authentication # user authentication
LOGIN_REDIRECT_URL = '/rowers/list-workouts/' LOGIN_REDIRECT_URL = '/rowers/list-workouts/'
LOGIN_URL = '/login/' LOGIN_URL = '/login/'
@@ -279,7 +273,7 @@ except KeyError: # pragma: no cover
C2_CLIENT_ID = CFG['c2_client_id'] C2_CLIENT_ID = CFG['c2_client_id']
C2_CLIENT_SECRET = CFG['c2_client_secret'] C2_CLIENT_SECRET = CFG['c2_client_secret']
C2_REDIRECT_URI = CFG['c2_callback'] C2_REDIRECT_URI = CFG['c2_callback']
#C2_REDIRECT_URI = "http://localhost:8000/call_back" # C2_REDIRECT_URI = "http://localhost:8000/call_back"
# Strava # Strava
@@ -316,8 +310,8 @@ UNDERARMOUR_CLIENT_ID = CFG['underarmour_client_name']
UNDERARMOUR_CLIENT_SECRET = CFG['underarmour_client_secret'] UNDERARMOUR_CLIENT_SECRET = CFG['underarmour_client_secret']
UNDERARMOUR_CLIENT_KEY = CFG['underarmour_client_key'] UNDERARMOUR_CLIENT_KEY = CFG['underarmour_client_key']
UNDERARMOUR_REDIRECT_URI = CFG['underarmour_callback'] UNDERARMOUR_REDIRECT_URI = CFG['underarmour_callback']
#UNDERARMOUR_REDIRECT_URI = "http://rowsandall.com/underarmour_callback" # UNDERARMOUR_REDIRECT_URI = "http://rowsandall.com/underarmour_callback"
#UNDERARMOUR_REDIRECT_URI = "http://localhost:8000/underarmour_callback" # UNDERARMOUR_REDIRECT_URI = "http://localhost:8000/underarmour_callback"
# TrainingPeaks # TrainingPeaks
TP_CLIENT_ID = CFG["tp_client_id"] TP_CLIENT_ID = CFG["tp_client_id"]
@@ -349,35 +343,35 @@ RQ_QUEUES = {
'HOST': 'localhost', 'HOST': 'localhost',
'PORT': 6379, 'PORT': 6379,
'DB': 0, 'DB': 0,
# 'PASSWORD': 'some-password', # 'PASSWORD': 'some-password',
'DEFAULT_TIMEOUT': 360, 'DEFAULT_TIMEOUT': 360,
}, },
'low': { 'low': {
'HOST': 'localhost', 'HOST': 'localhost',
'PORT': 6379, 'PORT': 6379,
'DB': 0, 'DB': 0,
# 'PASSWORD': 'some-password', # 'PASSWORD': 'some-password',
'DEFAULT_TIMEOUT': 360, 'DEFAULT_TIMEOUT': 360,
}, },
'high': { 'high': {
'HOST': 'localhost', 'HOST': 'localhost',
'PORT': 6379, 'PORT': 6379,
'DB': 0, 'DB': 0,
# 'PASSWORD': 'some-password', # 'PASSWORD': 'some-password',
'DEFAULT_TIMEOUT': 360, 'DEFAULT_TIMEOUT': 360,
}, },
} }
#SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies" # SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
#SESSION_ENGINE = "django.contrib.sessions.backends.cached_db" # SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_SAVE_EVERY_REQUEST = True SESSION_SAVE_EVERY_REQUEST = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# admin stuff for error reporting # admin stuff for error reporting
SERVER_EMAIL='admin@rowsandall.com' SERVER_EMAIL = 'admin@rowsandall.com'
ADMINS = [('Sander','roosendaalsander@gmail.com')] ADMINS = [('Sander', 'roosendaalsander@gmail.com')]
CACHES = { CACHES = {
'default': { 'default': {
@@ -385,20 +379,20 @@ CACHES = {
'LOCATION': 'localhost:11211', 'LOCATION': 'localhost:11211',
'TIMEOUT': 900, 'TIMEOUT': 900,
} }
} }
CACHE_MIDDLEWARE_ALIAS = 'default' CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 900 CACHE_MIDDLEWARE_SECONDS = 900
# email stuff # email stuff
#EMAIL_BACKEND = CFG['email_backend'] # EMAIL_BACKEND = CFG['email_backend']
#EMAIL_HOST = CFG['email_host'] # EMAIL_HOST = CFG['email_host']
#EMAIL_PORT = CFG['email_port'] # EMAIL_PORT = CFG['email_port']
#EMAIL_HOST_USER = CFG['email_host_user'] # EMAIL_HOST_USER = CFG['email_host_user']
#EMAIL_HOST_PASSWORD = CFG['email_host_password'] # EMAIL_HOST_PASSWORD = CFG['email_host_password']
#EMAIL_USE_TLS = CFG['email_use_tls'] # EMAIL_USE_TLS = CFG['email_use_tls']
#DEFAULT_FROM_EMAIL = 'admin@rowsandall.com' # DEFAULT_FROM_EMAIL = 'admin@rowsandall.com'
EMAIL_BACKEND = 'django_ses.SESBackend' EMAIL_BACKEND = 'django_ses.SESBackend'
@@ -435,7 +429,7 @@ OAUTH2_PROVIDER = {
'APPLICATION_MODEL': 'oauth2_provider.Application', 'APPLICATION_MODEL': 'oauth2_provider.Application',
'REFRESH_TOKEN_MODEL': 'oauth2_provider.RefreshToken', 'REFRESH_TOKEN_MODEL': 'oauth2_provider.RefreshToken',
'ACCESS_TOKEN_EXPIRE_SECONDS': 36000, 'ACCESS_TOKEN_EXPIRE_SECONDS': 36000,
#'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore' # 'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore'
} }
@@ -446,26 +440,26 @@ REST_FRAMEWORK = {
# or allow read-only access for unauthenticated users. # or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [ 'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated' 'rest_framework.permissions.IsAuthenticated'
# 'rest_framework.permissions.DjangoModelPermissions' # 'rest_framework.permissions.DjangoModelPermissions'
], ],
'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.BasicAuthentication',
# 'rest_framework.authentication.SessionAuthentication', # 'rest_framework.authentication.SessionAuthentication',
# 'rest_framework.authentication.TokenAuthentication', # 'rest_framework.authentication.TokenAuthentication',
'oauth2_provider.contrib.rest_framework.OAuth2Authentication', 'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
), ),
'PAGE_SIZE': 20, 'PAGE_SIZE': 20,
'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.LimitOffsetPagination', 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
} }
SWAGGER_SETTINGS = { SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': { 'SECURITY_DEFINITIONS': {
'basic': { 'basic': {
'type':'basic' 'type': 'basic'
}, },
'oauth2': { 'oauth2': {
'type':'oauth2', 'type': 'oauth2',
'authorizationUrl':'/rowers/o/authorize', 'authorizationUrl': '/rowers/o/authorize',
'flow': 'implicit', 'flow': 'implicit',
}, },
'api_key': { 'api_key': {
@@ -477,7 +471,7 @@ SWAGGER_SETTINGS = {
'SHOW_REQUEST_HEADERS': True, 'SHOW_REQUEST_HEADERS': True,
'USE_SESSION_AUTH': True, 'USE_SESSION_AUTH': True,
'JSON_EDITOR': True, 'JSON_EDITOR': True,
} }
# Analytics # Analytics
+13 -12
View File
@@ -21,8 +21,6 @@ for element in sys.argv:
if 'test' in element: if 'test' in element:
TESTING = True TESTING = True
if TESTING or use_sqlite: if TESTING or use_sqlite:
DATABASES = { DATABASES = {
'default': { 'default': {
@@ -31,7 +29,8 @@ if TESTING or use_sqlite:
'HOST': 'localhost', 'HOST': 'localhost',
'USER': '', 'USER': '',
'PASSWORD': 'roeidata', 'PASSWORD': 'roeidata',
'PORT': '3306', }, 'PORT': '3306',
},
# 'TEST': { # 'TEST': {
# 'CHARSET': 'utf8', # 'CHARSET': 'utf8',
# 'COLLATION': 'utf8_general_ci', # 'COLLATION': 'utf8_general_ci',
@@ -63,10 +62,10 @@ DEBUG = True
TEMPLATES[0]['OPTIONS']['debug'] = DEBUG 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 += ['debug_toolbar',]
#INSTALLED_APPS += ["sslserver"] # INSTALLED_APPS += ["sslserver"]
# MIDDLEWARE_CLASSES += ['debug_toolbar.middleware.DebugToolbarMiddleware',] # MIDDLEWARE_CLASSES += ['debug_toolbar.middleware.DebugToolbarMiddleware',]
@@ -75,17 +74,19 @@ CACHES = {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(BASE_DIR, 'django_cache'), 'LOCATION': os.path.join(BASE_DIR, 'django_cache'),
} }
} }
# Application definition # Application definition
STATIC_URL = '/static/' STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR 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'), STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static/plots'),] os.path.join(BASE_DIR, 'static'),
os.path.join(BASE_DIR, 'static/plots'),
]
INTERNAL_IPS = ['127.0.0.1'] INTERNAL_IPS = ['127.0.0.1']
@@ -99,10 +100,10 @@ SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
SITE_URL = "http://localhost:8000" 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.dummy.EmailBackend'
#EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_BACKEND = 'django_ses.SESBackend' EMAIL_BACKEND = 'django_ses.SESBackend'
-104
View File
@@ -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'
+50 -36
View File
@@ -25,69 +25,80 @@ from rowers import views as rowersviews
from survey import views as surveyviews from survey import views as surveyviews
import django import django
import django.views.i18n
# admin look # admin look
admin.site.enable_nav_sidebar = False admin.site.enable_nav_sidebar = False
import django.views.i18n
urlpatterns = [ urlpatterns = [
re_path('^', include('django.contrib.auth.urls')), re_path('^', include('django.contrib.auth.urls')),
re_path(r'^password_change_done/$',auth_views.PasswordChangeDoneView.as_view(),name='password_change_done'), re_path(
re_path(r'^password_change/$',auth_views.PasswordChangeView.as_view(),name='password_change'), r'^password_change_done/$',
re_path(r'^password_reset/$', 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(), auth_views.PasswordResetView.as_view(),
{'template_name': 'rowers/templates/registration/password_reset.html'}, {'template_name': 'rowers/templates/registration/password_reset.html'},
name='password_reset'), name='password_reset'),
re_path(r'^password_reset/done/$', re_path(
r'^password_reset/done/$',
auth_views.PasswordResetDoneView.as_view(), auth_views.PasswordResetDoneView.as_view(),
name='password_reset_done'), name='password_reset_done'),
re_path(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$', re_path(
r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
auth_views.PasswordResetConfirmView.as_view(), auth_views.PasswordResetConfirmView.as_view(),
name='password_reset_confirm'), name='password_reset_confirm'),
re_path(r'^reset/done/$', re_path(
r'^reset/done/$',
auth_views.PasswordResetCompleteView.as_view(), auth_views.PasswordResetCompleteView.as_view(),
name='password_reset_complete'), name='password_reset_complete'),
] ]
urlpatterns += [ urlpatterns += [
re_path(r'^robots\.txt$', TemplateView.as_view(template_name='robots.txt', re_path(r'^robots\.txt$', TemplateView.as_view(
template_name='robots.txt',
content_type='text/plain')), content_type='text/plain')),
re_path(r'^admin/', admin.site.urls), re_path(r'^admin/', admin.site.urls),
re_path(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework2')), re_path(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework2')),
re_path(r'^$',landingview), re_path(r'^$', landingview),
re_path(r'^landing/$',landingview), re_path(r'^landing/$', landingview),
re_path(r'^getblogs/$',rowersviews.get_blog_posts), re_path(r'^getblogs/$', rowersviews.get_blog_posts),
re_path(r'^login/', re_path(r'^login/',
# auth_views.LoginView, # auth_views.LoginView,
auth_views.LoginView.as_view(), auth_views.LoginView.as_view(),
name='login'), name='login'),
re_path(r'^logout/$', re_path(r'^logout/$',
auth_views.LogoutView.as_view(), auth_views.LogoutView.as_view(),
{'next_page': '/'}, {'next_page': '/'},
name='logout',), name='logout',),
re_path(r'^rowers/',include('rowers.urls')), re_path(r'^rowers/', include('rowers.urls')),
# re_path(r'^survey/',include('survey.urls')), # re_path(r'^survey/',include('survey.urls')),
# re_path(r'^cvkbrno/',include('cvkbrno.urls')), # re_path(r'^cvkbrno/',include('cvkbrno.urls')),
# re_path(r'^admin/rq/',include('django_rq_dashboard.urls')), # re_path(r'^admin/rq/',include('django_rq_dashboard.urls')),
re_path(r'^call\_back',rowersviews.rower_process_callback), re_path(r'^call\_back', rowersviews.rower_process_callback),
re_path(r'^nk\_callback',rowersviews.rower_process_nkcallback), re_path(r'^nk\_callback', rowersviews.rower_process_nkcallback),
re_path(r'^stravacall\_back',rowersviews.rower_process_stravacallback), re_path(r'^stravacall\_back', rowersviews.rower_process_stravacallback),
re_path(r'^garmin\_callback',rowersviews.rower_process_garmincallback), re_path(r'^garmin\_callback', rowersviews.rower_process_garmincallback),
re_path(r'^sporttracks\_callback',rowersviews.rower_process_sporttrackscallback), re_path(r'^sporttracks\_callback', rowersviews.rower_process_sporttrackscallback),
re_path(r'^polarflowcallback',rowersviews.rower_process_polarcallback), re_path(r'^polarflowcallback', rowersviews.rower_process_polarcallback),
re_path(r'^tp\_callback',rowersviews.rower_process_tpcallback), re_path(r'^tp\_callback', rowersviews.rower_process_tpcallback),
re_path(r'^rp3\_callback',rowersviews.rower_process_rp3callback), re_path(r'^rp3\_callback', rowersviews.rower_process_rp3callback),
re_path(r'^twitter\_callback',rowersviews.rower_process_twittercallback), re_path(r'^twitter\_callback', rowersviews.rower_process_twittercallback),
re_path(r'^i18n/', include('django.conf.urls.i18n')), re_path(r'^i18n/', include('django.conf.urls.i18n')),
re_path(r'^tz_detect/', include('tz_detect.urls')), re_path(r'^tz_detect/', include('tz_detect.urls')),
re_path(r'^logo/',logoview), re_path(r'^logo/', logoview),
re_path(r'^media/(?P<filename>.*\.fit)$',rowersviews.download_fit), re_path(r'^media/(?P<filename>.*\.fit)$', rowersviews.download_fit),
path('django-rq/', include('django_rq.urls')), path('django-rq/', include('django_rq.urls')),
# path('500/', rowersviews.error500_view), # path('500/', rowersviews.error500_view),
# re_path(r'^jsi18n/', django.views.i18n.javascript_catalog,name='jsi18n'), # re_path(r'^jsi18n/', django.views.i18n.javascript_catalog,name='jsi18n'),
] ]
js_info_dict = { js_info_dict = {
'packages': ('recurrence', ), 'packages': ('recurrence', ),
@@ -109,10 +120,13 @@ if settings.DEBUG: # pragma: no cover
kwargs={'document_root': settings.STATIC_ROOT+'plots/'}) kwargs={'document_root': settings.STATIC_ROOT+'plots/'})
] ]
urlpatterns += [ urlpatterns += [
# re_path(r'^__debug__/','debug_toolbar.urls'), # re_path(r'^__debug__/','debug_toolbar.urls'),
re_path(r'^static/(?P<path>.*)$', re_path(
r'^static/(?P<path>.*)$',
django.views.static.serve, django.views.static.serve,
kwargs={'document_root': settings.STATIC_ROOT, kwargs={
'show_indexes': True} 'document_root': settings.STATIC_ROOT,
'show_indexes': True
}
) )
] ]
+20 -21
View File
@@ -9,13 +9,14 @@ from rowingdata import main as rmain
import random import random
def landingview(request):
loginform = LoginForm()
return render(request, def landingview(request):
return render(
request,
'landingpage.html', '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() image_data = open(settings.STATIC_ROOT+"/img/apple-icon-144x144.png", "rb").read()
return HttpResponse(image_data, content_type="image/png") return HttpResponse(image_data, content_type="image/png")
@@ -27,48 +28,46 @@ def rootview(request): # pragma: no cover
planoffering = { planoffering = {
'name': 'PLAN', 'name': 'PLAN',
'image':'/static/img/Plan.png', '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.' '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 = { uploadoffering = {
'name': 'SYNC', 'name': 'SYNC',
'image':'/static/img/upload.png', 'image': '/static/img/upload.png',
'text':'Easily upload data from the most popular devices and apps' 'text': 'Easily upload data from the most popular devices and apps'
} }
logoffering = { logoffering = {
'name': 'LOG', 'name': 'LOG',
'image':'/static/img/log.png', 'image': '/static/img/log.png',
'text':'Maintain a consistent log for all your rowing (indoor and on the water)' 'text': 'Maintain a consistent log for all your rowing (indoor and on the water)'
} }
analyzeoffering = { analyzeoffering = {
'name': 'ANALYZE', 'name': 'ANALYZE',
'image':'/static/img/analyze.png', 'image': '/static/img/analyze.png',
'text':'Analyze your workouts with a consistent set of tools' 'text': 'Analyze your workouts with a consistent set of tools'
} }
compareoffering = { compareoffering = {
'name': 'COMPARE', 'name': 'COMPARE',
'image':'/static/img/compare.png', 'image': '/static/img/compare.png',
'text':'Compare your results between workouts and with other rowers in your team' 'text': 'Compare your results between workouts and with other rowers in your team'
} }
raceoffering = { raceoffering = {
'name': 'RACE', 'name': 'RACE',
'image':'/static/img/Race 01.png', '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' '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 = { coachoffering = {
'name': 'COACHING', 'name': 'COACHING',
'image':'/static/img/Remote coaching.png', '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' '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 = [ allofferings = [
planoffering, planoffering,
uploadoffering, uploadoffering,
@@ -88,6 +87,6 @@ def rootview(request): # pragma: no cover
'frontpage.html', 'frontpage.html',
{ {
'versionstring': magicsentence, 'versionstring': magicsentence,
'form':loginform, 'form': loginform,
'offerings':offerings, 'offerings': offerings,
}) })
+2 -2
View File
@@ -1,4 +1,4 @@
[flake8] [flake8]
ignore = F405, F403, E722, E226, W504, F401, W605 ignore = F405, F403, E722, E226, W504, F401, W605, E501
max-line-length = 120 max-line-length = 120
exclude = .git, rowers/migrations exclude = .git, rowers/migrations, rowers/tests, rowers/admin.py