Merge branch 'release/v21.0.0'
This commit is contained in:
+4
-2
@@ -1,6 +1,6 @@
|
|||||||
from rowers.models import Alert, Condition, User, Rower, Workout
|
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 getrowdata_db, read_data, remove_nulls_pl
|
||||||
import datetime
|
import datetime
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
import math
|
||||||
@@ -101,8 +101,10 @@ def alert_get_stats(alert, nperiod=0): # pragma: no cover
|
|||||||
ids = [w.id for w in workouts]
|
ids = [w.id for w in workouts]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
df = getsmallrowdata_db(columns, ids=ids, doclean=True,
|
df = getsmallrowdata_pd(columns, ids=ids, doclean=True,
|
||||||
workstrokesonly=workstrokesonly)
|
workstrokesonly=workstrokesonly)
|
||||||
|
df.dropna(axis=1,how='all',inplace=True)
|
||||||
|
df.dropna(axis=0,how='all',inplace=True)
|
||||||
except:
|
except:
|
||||||
return {
|
return {
|
||||||
'workouts': workouts.count(),
|
'workouts': workouts.count(),
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from rowers.courseutils import coursetime_paths, coursetime_first, time_in_path
|
from rowers.courseutils import coursetime_paths, coursetime_first, time_in_path
|
||||||
import pandas as pd
|
|
||||||
from rowers.models import (
|
from rowers.models import (
|
||||||
Rower, Workout,
|
Rower, Workout,
|
||||||
GeoPoint, GeoPolygon, GeoCourse,
|
GeoPoint, GeoPolygon, GeoCourse,
|
||||||
@@ -420,62 +419,6 @@ def createcourse(
|
|||||||
return c
|
return c
|
||||||
|
|
||||||
|
|
||||||
def get_time_course(ws, course): # pragma: no cover
|
|
||||||
coursetimeseconds = 0.0
|
|
||||||
coursecompleted = False
|
|
||||||
|
|
||||||
w = ws[0]
|
|
||||||
columns = ['time', ' latitude', ' longitude', 'cum_dist']
|
|
||||||
rowdata = dataprep.getsmallrowdata_db(
|
|
||||||
columns,
|
|
||||||
ids=[w.id],
|
|
||||||
doclean=False,
|
|
||||||
workstrokesonly=False
|
|
||||||
)
|
|
||||||
|
|
||||||
rowdata.rename(columns={
|
|
||||||
' latitude': 'latitude',
|
|
||||||
' longitude': 'longitude',
|
|
||||||
}, inplace=True)
|
|
||||||
|
|
||||||
rowdata['time'] = rowdata['time']/1000.
|
|
||||||
|
|
||||||
rowdata.fillna(method='backfill', inplace=True)
|
|
||||||
|
|
||||||
rowdata['time'] = rowdata['time']-rowdata.ix[0, 'time']
|
|
||||||
# we may want to expand the time (interpolate)
|
|
||||||
rowdata['dt'] = rowdata['time'].apply(
|
|
||||||
lambda x: timedelta(seconds=x)
|
|
||||||
)
|
|
||||||
rowdata = rowdata.resample('100ms', on='dt').mean()
|
|
||||||
rowdata = rowdata.interpolate()
|
|
||||||
|
|
||||||
# create path
|
|
||||||
polygons = GeoPolygon.objects.filter(
|
|
||||||
course=course).order_by("order_in_course")
|
|
||||||
paths = []
|
|
||||||
for polygon in polygons:
|
|
||||||
path = polygon_to_path(polygon)
|
|
||||||
paths.append(path)
|
|
||||||
|
|
||||||
(
|
|
||||||
coursetimeseconds,
|
|
||||||
coursemeters,
|
|
||||||
coursecompleted,
|
|
||||||
|
|
||||||
) = coursetime_paths(rowdata, paths)
|
|
||||||
(
|
|
||||||
coursetimefirst,
|
|
||||||
coursemetersfirst,
|
|
||||||
firstcompleted
|
|
||||||
) = coursetime_first(
|
|
||||||
rowdata, paths)
|
|
||||||
|
|
||||||
coursetimeseconds = coursetimeseconds-coursetimefirst
|
|
||||||
coursemeters = coursemeters-coursemetersfirst
|
|
||||||
|
|
||||||
return coursetimeseconds, coursemeters, coursecompleted
|
|
||||||
|
|
||||||
|
|
||||||
def replacecourse(course1, course2):
|
def replacecourse(course1, course2):
|
||||||
ps = PlannedSession.objects.filter(course=course1)
|
ps = PlannedSession.objects.filter(course=course1)
|
||||||
|
|||||||
+81
-105
@@ -8,6 +8,7 @@ from rowers.datautils import p0
|
|||||||
from scipy import optimize
|
from scipy import optimize
|
||||||
from rowers.utils import calculate_age
|
from rowers.utils import calculate_age
|
||||||
import datetime
|
import datetime
|
||||||
|
import gzip
|
||||||
from scipy.signal import savgol_filter
|
from scipy.signal import savgol_filter
|
||||||
from rowers.opaque import encoder
|
from rowers.opaque import encoder
|
||||||
from rowers.database import *
|
from rowers.database import *
|
||||||
@@ -27,6 +28,8 @@ from fitparse import FitFile
|
|||||||
import itertools
|
import itertools
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import polars as pl
|
||||||
|
from polars.exceptions import ColumnNotFoundError
|
||||||
from zipfile import BadZipFile
|
from zipfile import BadZipFile
|
||||||
import zipfile
|
import zipfile
|
||||||
import os
|
import os
|
||||||
@@ -73,6 +76,7 @@ import pytz
|
|||||||
import collections
|
import collections
|
||||||
import pendulum
|
import pendulum
|
||||||
from rowingdata import rowingdata as rrdata
|
from rowingdata import rowingdata as rrdata
|
||||||
|
from rowingdata import rowingdata_pl as rrdata_pl
|
||||||
|
|
||||||
from rowingdata import rower as rrower
|
from rowingdata import rower as rrower
|
||||||
|
|
||||||
@@ -88,10 +92,9 @@ from rowers.dataroutines import *
|
|||||||
|
|
||||||
from rowers.tasks import (
|
from rowers.tasks import (
|
||||||
handle_sendemail_newftp,
|
handle_sendemail_newftp,
|
||||||
handle_sendemail_unrecognized, handle_setcp,
|
handle_sendemail_unrecognized,
|
||||||
handle_getagegrouprecords, handle_update_wps,
|
handle_getagegrouprecords, handle_update_wps,
|
||||||
handle_request_post, handle_calctrimp,
|
handle_request_post, handle_calctrimp,
|
||||||
handle_updatecp, handle_updateergcp,
|
|
||||||
handle_sendemail_breakthrough,
|
handle_sendemail_breakthrough,
|
||||||
handle_sendemail_hard,
|
handle_sendemail_hard,
|
||||||
)
|
)
|
||||||
@@ -123,6 +126,10 @@ from rq import Queue
|
|||||||
from rowers.datautils import rpetotss
|
from rowers.datautils import rpetotss
|
||||||
|
|
||||||
def rscore_approx(row):
|
def rscore_approx(row):
|
||||||
|
if isinstance(row, pl.DataFrame):
|
||||||
|
row = {'rscore': row['rscore'][0]}
|
||||||
|
if isinstance(row, pl.Series):
|
||||||
|
row = {'rscore': row['rscore'][0]}
|
||||||
if row['rscore'] > 0:
|
if row['rscore'] > 0:
|
||||||
return row['rscore']
|
return row['rscore']
|
||||||
if row['rscore'] == 0: # pragma: no cover
|
if row['rscore'] == 0: # pragma: no cover
|
||||||
@@ -215,18 +222,18 @@ def check_marker(workout):
|
|||||||
ids.append(w.id)
|
ids.append(w.id)
|
||||||
gms.append(gmstandard)
|
gms.append(gmstandard)
|
||||||
|
|
||||||
df = pd.DataFrame({
|
df = pl.DataFrame({
|
||||||
'id': ids,
|
'id': ids,
|
||||||
'gms': gms,
|
'gms': gms,
|
||||||
})
|
})
|
||||||
|
|
||||||
if df.empty: # pragma: no cover
|
if df.is_empty(): # pragma: no cover
|
||||||
workout.ranking = True
|
workout.ranking = True
|
||||||
workout.save()
|
workout.save()
|
||||||
return workout
|
return workout
|
||||||
|
|
||||||
indexmax = df['gms'].idxmax()
|
theid = df.filter(pl.col("gms") == pl.col("gms").max())['id'][0]
|
||||||
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
|
||||||
@@ -322,7 +329,7 @@ def workout_summary_to_df(
|
|||||||
goldstandarddurations.append(int(goldstandardduration))
|
goldstandarddurations.append(int(goldstandardduration))
|
||||||
rankingpieces.append(w.rankingpiece)
|
rankingpieces.append(w.rankingpiece)
|
||||||
|
|
||||||
df = pd.DataFrame({
|
df = pl.DataFrame({
|
||||||
'ID': ids,
|
'ID': ids,
|
||||||
'date': startdatetimes,
|
'date': startdatetimes,
|
||||||
'name': names,
|
'name': names,
|
||||||
@@ -392,7 +399,7 @@ def resample(id, r, parent, overwrite='copy'):
|
|||||||
|
|
||||||
row.write_csv(parent.csvfilename, gzip=True)
|
row.write_csv(parent.csvfilename, gzip=True)
|
||||||
|
|
||||||
_ = dataprep(row.df, id=parent.id, bands=True, barchart=True,
|
_ = dataplep(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)
|
||||||
_ = check_marker(parent)
|
_ = check_marker(parent)
|
||||||
@@ -414,18 +421,23 @@ def resample(id, r, parent, overwrite='copy'):
|
|||||||
def calculate_goldmedalstandard(rower, workout, recurrance=True):
|
def calculate_goldmedalstandard(rower, workout, recurrance=True):
|
||||||
cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
||||||
try:
|
try:
|
||||||
df = pd.read_parquet(cpfile)
|
df = pl.read_parquet(cpfile)
|
||||||
except:
|
except:
|
||||||
|
df = read_data(['power'], ids=[workout.id])
|
||||||
|
df = remove_nulls_pl(df)
|
||||||
background = True
|
background = True
|
||||||
if settings.TESTING:
|
if settings.TESTING:
|
||||||
background = False
|
background = False
|
||||||
|
if recurrance:
|
||||||
df, delta, cpvalues = setcp(workout, background=background)
|
df, delta, cpvalues = setcp(workout, background=background)
|
||||||
if df.empty:
|
if df.is_empty():
|
||||||
|
return 0, 0
|
||||||
|
else:
|
||||||
return 0,0
|
return 0,0
|
||||||
|
|
||||||
if df.empty and recurrance: # pragma: no cover
|
if df.is_empty() and recurrance: # pragma: no cover
|
||||||
df, delta, cpvalues = setcp(workout, recurrance=False, background=True)
|
df, delta, cpvalues = setcp(workout, recurrance=False, background=True)
|
||||||
if df.empty:
|
if df.is_empty():
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
|
||||||
age = calculate_age(rower.birthdate, today=workout.date)
|
age = calculate_age(rower.birthdate, today=workout.date)
|
||||||
@@ -453,7 +465,7 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True):
|
|||||||
if getrecords: # pragma: no cover
|
if getrecords: # pragma: no cover
|
||||||
durations = [1, 4, 30, 60]
|
durations = [1, 4, 30, 60]
|
||||||
distances = [100, 500, 1000, 2000, 5000, 6000, 10000, 21097, 42195]
|
distances = [100, 500, 1000, 2000, 5000, 6000, 10000, 21097, 42195]
|
||||||
df2 = pd.DataFrame(
|
df2 = pl.DataFrame(
|
||||||
list(
|
list(
|
||||||
C2WorldClassAgePerformance.objects.filter(
|
C2WorldClassAgePerformance.objects.filter(
|
||||||
sex=rower.sex,
|
sex=rower.sex,
|
||||||
@@ -461,7 +473,7 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True):
|
|||||||
).values()
|
).values()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
jsondf = df2.to_json()
|
jsondf = df2.write_json()
|
||||||
_ = myqueue(queuelow, handle_getagegrouprecords,
|
_ = myqueue(queuelow, handle_getagegrouprecords,
|
||||||
jsondf, distances, durations, age, rower.sex, rower.weightcategory)
|
jsondf, distances, durations, age, rower.sex, rower.weightcategory)
|
||||||
|
|
||||||
@@ -489,9 +501,10 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True):
|
|||||||
scores = 100.*powers/wcpowers
|
scores = 100.*powers/wcpowers
|
||||||
|
|
||||||
try:
|
try:
|
||||||
indexmax = scores.idxmax()
|
df = pl.DataFrame({'times': times, 'scores': scores})
|
||||||
delta = int(df.loc[indexmax, 'delta'])
|
df = df.filter(pl.col("scores") == pl.col("scores").max())
|
||||||
maxvalue = scores.max()
|
delta = df[0, "times"]
|
||||||
|
maxvalue = df[0, "scores"]
|
||||||
except (ValueError, TypeError, KeyError): # pragma: no cover
|
except (ValueError, TypeError, KeyError): # pragma: no cover
|
||||||
indexmax = 0
|
indexmax = 0
|
||||||
delta = 0
|
delta = 0
|
||||||
@@ -504,21 +517,22 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True):
|
|||||||
def setcp(workout, background=False, recurrance=True):
|
def setcp(workout, background=False, recurrance=True):
|
||||||
try:
|
try:
|
||||||
filename = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
filename = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
||||||
df = pd.read_parquet(filename)
|
df = pl.read_parquet(filename)
|
||||||
|
|
||||||
if not df.empty:
|
if not df.is_empty():
|
||||||
# check dts
|
# check dts
|
||||||
tarr = datautils.getlogarr(4000)
|
tarr = datautils.getlogarr(4000)
|
||||||
if df['delta'][0] in tarr:
|
if df['delta'][0] in tarr:
|
||||||
return(df, df['delta'], df['cp'])
|
return(df, df['delta'], df['cp'])
|
||||||
except:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
strokesdf = getsmallrowdata_db(
|
strokesdf = read_data(
|
||||||
['power', 'workoutid', 'time'], ids=[workout.id])
|
['power', 'workoutid', 'time'], ids=[workout.id])
|
||||||
|
strokesdf = remove_nulls_pl(strokesdf)
|
||||||
|
|
||||||
if strokesdf.empty:
|
if strokesdf.is_empty():
|
||||||
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
|
return pl.DataFrame({'delta': [], 'cp': []}), pl.Series(dtype=pl.Float64), pl.Series(dtype=pl.Float64)
|
||||||
|
|
||||||
totaltime = strokesdf['time'].max()
|
totaltime = strokesdf['time'].max()
|
||||||
maxt = totaltime/1000.
|
maxt = totaltime/1000.
|
||||||
@@ -533,7 +547,7 @@ def setcp(workout, background=False, recurrance=True):
|
|||||||
elif os.path.exists(csvfilename+'.gz'): # pragma: no cover
|
elif os.path.exists(csvfilename+'.gz'): # pragma: no cover
|
||||||
csvfile = csvfilename+'.gz'
|
csvfile = csvfilename+'.gz'
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
|
return pl.DataFrame({'delta': [], 'cp': []}), pl.Series(dtype=pl.Float64), pl.Series(dtype=pl.Float64)
|
||||||
csvfile = os.path.abspath(csvfile)
|
csvfile = os.path.abspath(csvfile)
|
||||||
|
|
||||||
|
|
||||||
@@ -547,7 +561,7 @@ def setcp(workout, background=False, recurrance=True):
|
|||||||
grpc.channel_ready_future(channel).result(timeout=10)
|
grpc.channel_ready_future(channel).result(timeout=10)
|
||||||
except grpc.FutureTimeoutError: # pragma: no cover
|
except grpc.FutureTimeoutError: # pragma: no cover
|
||||||
dologging('metrics.log','grpc channel time out in setcp')
|
dologging('metrics.log','grpc channel time out in setcp')
|
||||||
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
|
return pl.DataFrame({'delta': [], 'cp': []}), pl.Series(dtype=pl.Float64), pl.Series(dtype=pl.Float64)
|
||||||
|
|
||||||
stub = metrics_pb2_grpc.MetricsStub(channel)
|
stub = metrics_pb2_grpc.MetricsStub(channel)
|
||||||
req = metrics_pb2.CPRequest(filename = csvfile, filetype = "CSV", tarr = logarr)
|
req = metrics_pb2.CPRequest(filename = csvfile, filetype = "CSV", tarr = logarr)
|
||||||
@@ -556,25 +570,29 @@ def setcp(workout, background=False, recurrance=True):
|
|||||||
response = stub.GetCP(req, timeout=60)
|
response = stub.GetCP(req, timeout=60)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
dologging('metrics.log', traceback.format_exc())
|
dologging('metrics.log', traceback.format_exc())
|
||||||
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
|
return pl.DataFrame({'delta': [], 'cp': []}), pl.Series(dtype=pl.Float64), pl.Series(dtype=pl.Float64)
|
||||||
|
|
||||||
delta = pd.Series(np.array(response.delta))
|
delta = pl.Series(np.array(response.delta))
|
||||||
cpvalues = pd.Series(np.array(response.power))
|
cpvalues = pl.Series(np.array(response.power))
|
||||||
powermean = response.avgpower
|
powermean = response.avgpower
|
||||||
|
|
||||||
|
df = pl.DataFrame({
|
||||||
|
|
||||||
df = pd.DataFrame({
|
|
||||||
'delta': delta,
|
'delta': delta,
|
||||||
'cp': cpvalues,
|
'cp': cpvalues,
|
||||||
'id': workout.id,
|
'id': workout.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
df.to_parquet(filename, engine='fastparquet', compression='GZIP')
|
df = df.drop_nulls()
|
||||||
|
|
||||||
|
with gzip.open(filename, 'w') as f:
|
||||||
|
df.write_parquet(f)
|
||||||
|
|
||||||
|
|
||||||
|
#df.to_parquet(filename, engine='fastparquet', compression='GZIP')
|
||||||
|
|
||||||
if recurrance:
|
if recurrance:
|
||||||
goldmedalstandard, goldmedalduration = calculate_goldmedalstandard(
|
goldmedalstandard, goldmedalduration = calculate_goldmedalstandard(
|
||||||
workout.user, workout)
|
workout.user, workout, recurrance=False)
|
||||||
workout.goldmedalstandard = goldmedalstandard
|
workout.goldmedalstandard = goldmedalstandard
|
||||||
workout.goldmedalduration = goldmedalduration
|
workout.goldmedalduration = goldmedalduration
|
||||||
workout.save()
|
workout.save()
|
||||||
@@ -602,14 +620,10 @@ def update_wps(r, types, mode='water', asynchron=True):
|
|||||||
mode
|
mode
|
||||||
)
|
)
|
||||||
|
|
||||||
df = getsmallrowdata_db(['time', 'driveenergy'], ids=ids)
|
df = read_data(['time', 'driveenergy'], ids=ids)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mask = df['driveenergy'] > 100
|
wps_median = int(df.filter(pl.col("driveenergy")>100)["driveenergy"].median())
|
||||||
except (KeyError, TypeError):
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
wps_median = int(df.loc[mask, 'driveenergy'].median())
|
|
||||||
if mode == 'water':
|
if mode == 'water':
|
||||||
r.median_wps = wps_median
|
r.median_wps = wps_median
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
@@ -618,6 +632,10 @@ def update_wps(r, types, mode='water', asynchron=True):
|
|||||||
r.save()
|
r.save()
|
||||||
except ValueError: # pragma: no cover
|
except ValueError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
except OverflowError:
|
||||||
|
pass
|
||||||
|
except ColumnNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -718,77 +736,28 @@ def fetchcp_new(rower, workouts):
|
|||||||
data = []
|
data = []
|
||||||
|
|
||||||
for workout in workouts:
|
for workout in workouts:
|
||||||
cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
|
|
||||||
try:
|
|
||||||
df, delta, cpvalues = setcp(workout)
|
df, delta, cpvalues = setcp(workout)
|
||||||
df = pd.read_parquet(cpfile)
|
df = df.drop('id')
|
||||||
df['workout'] = str(workout)
|
df = df.with_columns((pl.lit(str(workout))).alias("workout"))
|
||||||
df['url'] = workout.url()
|
df = df.with_columns((pl.lit(workout.url())).alias("url"))
|
||||||
data.append(df)
|
if not df.is_empty():
|
||||||
except:
|
|
||||||
# CP data file doesn't exist yet. has to be created
|
|
||||||
df, delta, cpvalues = setcp(workout)
|
|
||||||
df['workout'] = str(workout)
|
|
||||||
df['url'] = workout.url()
|
|
||||||
data.append(df)
|
data.append(df)
|
||||||
|
|
||||||
if len(data) == 0:
|
if len(data) == 0:
|
||||||
return pd.Series(dtype='float'), pd.Series(dtype='float'), 0, pd.Series(dtype='float'), pd.Series(dtype='float')
|
return pl.Series(dtype=pl.Float64), pl.Series(dtype=pl.Float64), 0, pl.Series(dtype=pl.Float64), pl.Series(dtype=pl.Float64)
|
||||||
if len(data) > 1:
|
if len(data) > 1:
|
||||||
df = pd.concat(data, axis=0)
|
df = pl.concat(data)
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
df = df[df['cp'] == df.groupby(['delta'])['cp'].transform('max')]
|
df = df.group_by(pl.col("delta")).agg(pl.max("cp"), pl.max("workout"), pl.max("url")).sort("delta")
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
return pd.Series(dtype='float'), pd.Series(dtype='float'), 0, pd.Series(dtype='float'), pd.Series(dtype='float')
|
return pl.Series(dtype=pl.Float64), pl.Series(dtype=pl.Float64), 0, pl.Series(dtype=pl.Float64), pl.Series(dtype=pl.Float64)
|
||||||
|
|
||||||
df = df.sort_values(['delta']).reset_index()
|
|
||||||
df = df[df['cp']>20]
|
|
||||||
|
|
||||||
|
df = df.filter(pl.col("cp")>20)
|
||||||
|
|
||||||
return df['delta'], df['cp'], 0, df['workout'], df['url']
|
return df['delta'], df['cp'], 0, df['workout'], df['url']
|
||||||
|
|
||||||
|
|
||||||
def fetchcp(rower, theworkouts, table='cpdata'): # pragma: no cover
|
|
||||||
# get all power data from database (plus workoutid)
|
|
||||||
theids = [int(w.id) for w in theworkouts]
|
|
||||||
columns = ['power', 'workoutid', 'time']
|
|
||||||
df = getsmallrowdata_db(columns, ids=theids)
|
|
||||||
df.dropna(inplace=True, axis=0)
|
|
||||||
if df.empty:
|
|
||||||
avgpower2 = {}
|
|
||||||
for id in theids:
|
|
||||||
avgpower2[id] = 0
|
|
||||||
return pd.Series([], dtype='float'), pd.Series([], dtype='float'), avgpower2
|
|
||||||
|
|
||||||
try:
|
|
||||||
dfgrouped = df.groupby(['workoutid'])
|
|
||||||
except KeyError:
|
|
||||||
avgpower2 = {}
|
|
||||||
return pd.Series([], dtype='float'), pd.Series([], dtype='float'), avgpower2
|
|
||||||
try:
|
|
||||||
avgpower2 = dict(dfgrouped.mean()['power'].astype(int))
|
|
||||||
except KeyError:
|
|
||||||
avgpower2 = {}
|
|
||||||
for id in theids:
|
|
||||||
avgpower2[id] = 0
|
|
||||||
return pd.Series([], dtype='float'), pd.Series([], dtype='float'), avgpower2
|
|
||||||
|
|
||||||
cpdf = getcpdata_sql(rower.id, table=table)
|
|
||||||
|
|
||||||
if not cpdf.empty:
|
|
||||||
return cpdf['delta'], cpdf['cp'], avgpower2
|
|
||||||
else:
|
|
||||||
_ = myqueue(queuelow,
|
|
||||||
handle_updatecp,
|
|
||||||
rower.id,
|
|
||||||
theids,
|
|
||||||
table=table)
|
|
||||||
|
|
||||||
return pd.Series([], dtype='float'), pd.Series([], dtype='float'), avgpower2
|
|
||||||
|
|
||||||
return pd.Series([], dtype='float'), pd.Series([], dtype='float'), avgpower2
|
|
||||||
|
|
||||||
|
|
||||||
def update_rolling_cp(r, types, mode='water', dosend=False):
|
def update_rolling_cp(r, types, mode='water', dosend=False):
|
||||||
@@ -801,15 +770,17 @@ def update_rolling_cp(r, types, mode='water', dosend=False):
|
|||||||
|
|
||||||
delta, cp, avgpower, workoutnames, urls = fetchcp_new(r, workouts)
|
delta, cp, avgpower, workoutnames, urls = fetchcp_new(r, workouts)
|
||||||
|
|
||||||
powerdf = pd.DataFrame({
|
powerdf = pl.DataFrame({
|
||||||
'Delta': delta,
|
'Delta': delta,
|
||||||
'CP': cp,
|
'CP': cp,
|
||||||
})
|
})
|
||||||
|
|
||||||
powerdf = powerdf[powerdf['CP'] > 0]
|
powerdf = powerdf.filter(pl.col("CP")>0)
|
||||||
powerdf.dropna(axis=0, inplace=True)
|
powerdf = powerdf.fill_nan(None).drop_nulls().sort(["Delta", "CP"])
|
||||||
powerdf.sort_values(['Delta', 'CP'], ascending=[1, 0], inplace=True)
|
powerdf = powerdf.unique(subset=["Delta"], keep="first")
|
||||||
powerdf.drop_duplicates(subset='Delta', keep='first', inplace=True)
|
|
||||||
|
if powerdf.is_empty():
|
||||||
|
return False
|
||||||
|
|
||||||
res2 = datautils.cpfit(powerdf)
|
res2 = datautils.cpfit(powerdf)
|
||||||
p1 = res2[0]
|
p1 = res2[0]
|
||||||
@@ -1051,7 +1022,7 @@ def checkbreakthrough(w, r):
|
|||||||
workouttype = w.workouttype
|
workouttype = w.workouttype
|
||||||
if workouttype in rowtypes:
|
if workouttype in rowtypes:
|
||||||
cpdf, delta, cpvalues = setcp(w)
|
cpdf, delta, cpvalues = setcp(w)
|
||||||
if not cpdf.empty:
|
if not cpdf.is_empty():
|
||||||
if workouttype in otwtypes:
|
if workouttype in otwtypes:
|
||||||
try:
|
try:
|
||||||
res, btvalues, res2 = utils.isbreakthrough(
|
res, btvalues, res2 = utils.isbreakthrough(
|
||||||
@@ -1397,7 +1368,12 @@ 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
|
||||||
_ = dataprep(row.df, id=w.id, bands=True,
|
try:
|
||||||
|
row = rrdata_pl(df=pl.from_pandas(row.df))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
_ = dataplep(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)
|
||||||
|
|||||||
+827
-54
File diff suppressed because it is too large
Load Diff
+19
-32
@@ -1,8 +1,10 @@
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import polars as pl
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy.interpolate import griddata
|
from scipy.interpolate import griddata
|
||||||
from scipy import optimize
|
from scipy import optimize
|
||||||
|
|
||||||
|
|
||||||
from rowers.mytypes import otwtypes, otetypes, rowtypes
|
from rowers.mytypes import otwtypes, otetypes, rowtypes
|
||||||
from rowers.models import Workout
|
from rowers.models import Workout
|
||||||
|
|
||||||
@@ -81,8 +83,9 @@ def cpfit(powerdf, fraclimit=0.0001, nmax=1000):
|
|||||||
|
|
||||||
p1 = p0
|
p1 = p0
|
||||||
|
|
||||||
thesecs = powerdf['Delta']
|
thesecs = powerdf['Delta'].to_numpy()
|
||||||
theavpower = powerdf['CP']
|
theavpower = powerdf['CP'].to_numpy()
|
||||||
|
|
||||||
|
|
||||||
if len(thesecs) >= 4:
|
if len(thesecs) >= 4:
|
||||||
try:
|
try:
|
||||||
@@ -96,13 +99,14 @@ def cpfit(powerdf, fraclimit=0.0001, nmax=1000):
|
|||||||
factor = fitfunc(p0, thesecs.mean())/theavpower.mean()
|
factor = fitfunc(p0, thesecs.mean())/theavpower.mean()
|
||||||
p1 = [p0[0]/factor, p0[1]/factor, p0[2], p0[3]]
|
p1 = [p0[0]/factor, p0[1]/factor, p0[2], p0[3]]
|
||||||
|
|
||||||
|
|
||||||
p1 = [abs(p) for p in p1]
|
p1 = [abs(p) for p in p1]
|
||||||
fitt = pd.Series(10**(4*np.arange(100)/100.))
|
fitt = pd.Series(10**(4*np.arange(100)/100.))
|
||||||
|
|
||||||
fitpower = fitfunc(p1, fitt)
|
fitpower = fitfunc(p1, fitt)
|
||||||
|
|
||||||
fitpoints = fitfunc(p1, thesecs)
|
fitpoints = fitfunc(p1, thesecs)
|
||||||
fitpoints0 = fitpoints.copy()
|
fitpoints0 = fitpoints
|
||||||
dd = fitpoints-theavpower
|
dd = fitpoints-theavpower
|
||||||
|
|
||||||
ddmin = dd.min()
|
ddmin = dd.min()
|
||||||
@@ -356,8 +360,8 @@ def getmaxwattinterval(tt, ww, i):
|
|||||||
|
|
||||||
|
|
||||||
def getfastest(df, thevalue, mode='distance'):
|
def getfastest(df, thevalue, mode='distance'):
|
||||||
tt = df['time'].copy()
|
tt = df['time'].clone()
|
||||||
dd = df['cumdist'].copy()
|
dd = df['cumdist'].clone()
|
||||||
|
|
||||||
tmax = tt.max()
|
tmax = tt.max()
|
||||||
if mode == 'distance': # pragma: no cover
|
if mode == 'distance': # pragma: no cover
|
||||||
@@ -368,40 +372,28 @@ def getfastest(df, thevalue, mode='distance'):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
# if tmax > 500000:
|
|
||||||
# newlen=int(tmax/2000.)
|
|
||||||
# newt = np.arange(newlen)*tmax/float(newlen)
|
|
||||||
# deltat = newt[1]-newt[0]
|
|
||||||
# else:
|
|
||||||
# newt = np.arange(0,tmax,10.)
|
|
||||||
# deltat = 10.
|
|
||||||
|
|
||||||
newlen = 1000
|
newlen = 1000
|
||||||
newt = np.arange(newlen)*tmax/float(newlen)
|
newt = np.arange(newlen)*tmax/float(newlen)
|
||||||
deltat = newt[1]-newt[0]
|
deltat = newt[1]-newt[0]
|
||||||
|
|
||||||
dd = griddata(tt.values,
|
dd = griddata(tt.to_numpy(),
|
||||||
dd.values, newt, method='linear', rescale=True)
|
dd.to_numpy(), newt, method='linear', rescale=True)
|
||||||
|
|
||||||
tt = pd.Series(newt, dtype='float')
|
tt = pl.Series(newt, dtype=pl.Float64)
|
||||||
dd = pd.Series(dd, dtype='float')
|
dd = pl.Series(dd, dtype=pl.Float64)
|
||||||
|
|
||||||
|
G = pl.concat([pl.Series([0.0]), dd])
|
||||||
|
|
||||||
G = pd.concat([pd.Series([0]), dd])
|
|
||||||
# T = pd.concat([pd.Series([0]), dd])
|
|
||||||
# h = np.mgrid[0:len(tt)+1:1, 0:len(tt)+1:1]
|
|
||||||
# distances = pd.DataFrame(h[1]-h[0])
|
|
||||||
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)
|
|
||||||
# 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
|
||||||
Gdif = pd.DataFrame(Gdif)
|
Gdif = pl.DataFrame(Gdif)
|
||||||
F = Gdif
|
F = Gdif
|
||||||
|
|
||||||
F.fillna(inplace=True, method='ffill', axis=1)
|
F = F.fill_nan(0)
|
||||||
F.fillna(inplace=True, value=0)
|
|
||||||
|
|
||||||
restime = []
|
restime = []
|
||||||
distance = []
|
distance = []
|
||||||
@@ -412,7 +404,7 @@ def getfastest(df, thevalue, mode='distance'):
|
|||||||
restime.append(deltat*i)
|
restime.append(deltat*i)
|
||||||
cp = np.diag(F, i).max()
|
cp = np.diag(F, i).max()
|
||||||
loc = np.argmax(np.diag(F, i))
|
loc = np.argmax(np.diag(F, i))
|
||||||
thestarttime = tt[loc]
|
thestarttime = tt.to_numpy()[loc]
|
||||||
starttimes.append(thestarttime)
|
starttimes.append(thestarttime)
|
||||||
distance.append(cp)
|
distance.append(cp)
|
||||||
|
|
||||||
@@ -422,10 +414,6 @@ def getfastest(df, thevalue, mode='distance'):
|
|||||||
distance = np.array(distance)
|
distance = np.array(distance)
|
||||||
starttimes = np.array(starttimes)
|
starttimes = np.array(starttimes)
|
||||||
|
|
||||||
# for i in range(len(restime)):
|
|
||||||
# if restime[i]<thevalue*60*1000:
|
|
||||||
# print(i,restime[i],distance[i],60*1000*thevalue)
|
|
||||||
|
|
||||||
if mode == 'distance':
|
if mode == 'distance':
|
||||||
duration = griddata(distance, restime, [
|
duration = griddata(distance, restime, [
|
||||||
thevalue], method='linear', rescale=True)
|
thevalue], method='linear', rescale=True)
|
||||||
@@ -434,7 +422,6 @@ def getfastest(df, thevalue, mode='distance'):
|
|||||||
distance = griddata(distance, distance, [
|
distance = griddata(distance, distance, [
|
||||||
thevalue], method='linear', rescale=True)
|
thevalue], method='linear', rescale=True)
|
||||||
endtime = starttime+duration
|
endtime = starttime+duration
|
||||||
# print(duration,starttime,endtime,'aa')
|
|
||||||
return duration[0]/1000., starttime[0]/1000., endtime[0]/1000.
|
return duration[0]/1000., starttime[0]/1000., endtime[0]/1000.
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
distance = griddata(restime, distance, [
|
distance = griddata(restime, distance, [
|
||||||
|
|||||||
+10
-83
@@ -74,27 +74,6 @@ class ResampleForm(forms.Form):
|
|||||||
|
|
||||||
|
|
||||||
class TrainingZonesForm(forms.Form):
|
class TrainingZonesForm(forms.Form):
|
||||||
zoneschoices = (
|
|
||||||
('power', 'Power Zones'),
|
|
||||||
('hr', 'Heart Rate Zones')
|
|
||||||
)
|
|
||||||
|
|
||||||
datechoices = (
|
|
||||||
('month', 'By Month'),
|
|
||||||
('week', 'By Week'),
|
|
||||||
)
|
|
||||||
|
|
||||||
yaxischoices = (
|
|
||||||
('time', 'Time'),
|
|
||||||
('percentage', 'Percentage of Time')
|
|
||||||
)
|
|
||||||
|
|
||||||
zones = forms.ChoiceField(
|
|
||||||
initial='hr', label='Training Zones', choices=zoneschoices)
|
|
||||||
dates = forms.ChoiceField(
|
|
||||||
initial='week', label='Date Aggregation', choices=datechoices)
|
|
||||||
yaxis = forms.ChoiceField(initial='percentage',
|
|
||||||
label='Y axis', choices=yaxischoices)
|
|
||||||
startdate = forms.DateField(
|
startdate = forms.DateField(
|
||||||
initial=timezone.now()-datetime.timedelta(days=42),
|
initial=timezone.now()-datetime.timedelta(days=42),
|
||||||
widget=AdminDateWidget(), # format='%Y-%m-%d'),
|
widget=AdminDateWidget(), # format='%Y-%m-%d'),
|
||||||
@@ -778,59 +757,7 @@ class PredictedPieceFormNoDistance(forms.Form):
|
|||||||
value = forms.FloatField(initial=10, label='Free ranking piece')
|
value = forms.FloatField(initial=10, label='Free ranking piece')
|
||||||
|
|
||||||
|
|
||||||
# On the Geeky side, to update stream information for river dwellers
|
|
||||||
class UpdateStreamForm(forms.Form):
|
|
||||||
unitchoices = (
|
|
||||||
('m', 'm/s'),
|
|
||||||
('f', 'foot/s'),
|
|
||||||
('k', 'knots'),
|
|
||||||
('p', 'pace difference (sec/500m)'),
|
|
||||||
)
|
|
||||||
dist1 = forms.FloatField(initial=0, label='Distance 1')
|
|
||||||
dist2 = forms.FloatField(initial=1000, label='Distance 2')
|
|
||||||
stream1 = forms.FloatField(initial=0, label='Stream velocity 1')
|
|
||||||
stream2 = forms.FloatField(initial=0, label='Stream velocity 2')
|
|
||||||
streamunit = forms.ChoiceField(required=True,
|
|
||||||
choices=unitchoices,
|
|
||||||
initial='m',
|
|
||||||
label='Unit')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
fields = ['dist1', 'dist2', 'stream1', 'stream2', 'streamunit']
|
|
||||||
|
|
||||||
# add wind information to your workout
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateWindForm(forms.Form):
|
|
||||||
unitchoices = (
|
|
||||||
('m', 'm/s'),
|
|
||||||
('k', 'knots'),
|
|
||||||
('b', 'beaufort'),
|
|
||||||
('kmh', 'km/h'),
|
|
||||||
('mph', 'miles/hour'),
|
|
||||||
)
|
|
||||||
dist1 = forms.FloatField(initial=0, label='Distance 1')
|
|
||||||
dist2 = forms.FloatField(initial=1000, label='Distance 2')
|
|
||||||
vwind1 = forms.FloatField(initial=0, required=False, label='Wind Speed 1')
|
|
||||||
vwind2 = forms.FloatField(initial=0, required=False, label='Wind Speed 2')
|
|
||||||
windunit = forms.ChoiceField(required=True,
|
|
||||||
choices=unitchoices,
|
|
||||||
initial='m',
|
|
||||||
label='Unit')
|
|
||||||
winddirection1 = forms.IntegerField(initial=0, required=False,
|
|
||||||
label='Wind Direction 1')
|
|
||||||
winddirection2 = forms.IntegerField(initial=0, required=False,
|
|
||||||
label='Wind Direction 2')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
fields = ['dist1', 'dist2',
|
|
||||||
'vwind1', 'vwind2',
|
|
||||||
'windunit',
|
|
||||||
'winddirection1', 'winddirection2']
|
|
||||||
|
|
||||||
# Form to select a data range to show workouts from a certain time period
|
# Form to select a data range to show workouts from a certain time period
|
||||||
|
|
||||||
|
|
||||||
class DateRangeForm(forms.Form):
|
class DateRangeForm(forms.Form):
|
||||||
startdate = forms.DateField(
|
startdate = forms.DateField(
|
||||||
initial=timezone.now()-datetime.timedelta(days=365),
|
initial=timezone.now()-datetime.timedelta(days=365),
|
||||||
@@ -1859,27 +1786,27 @@ class FlexOptionsForm(forms.Form):
|
|||||||
|
|
||||||
class ForceCurveOptionsForm(forms.Form):
|
class ForceCurveOptionsForm(forms.Form):
|
||||||
includereststrokes = forms.BooleanField(initial=False, required=False,
|
includereststrokes = forms.BooleanField(initial=False, required=False,
|
||||||
label='Include Rest Strokes')
|
label='Include Rest Strokes',
|
||||||
|
widget=forms.CheckboxInput(attrs={'class':'hidden'}))
|
||||||
|
|
||||||
spm_min = forms.FloatField(initial=15.0,label='SPM Min',widget=HiddenInput,required=False)
|
spm_min = forms.FloatField(initial=15.0,label='SPM Min',widget=HiddenInput,required=False)
|
||||||
spm_max = forms.FloatField(initial=55.0,label='SPM Max',widget=HiddenInput,required=False)
|
spm_max = forms.FloatField(initial=55.0,label='SPM Max',widget=HiddenInput,required=False)
|
||||||
dist_min = forms.IntegerField(initial=0,label='Dist Min',widget=HiddenInput,required=False)
|
dist_min = forms.IntegerField(initial=0,label='Dist Min',widget=HiddenInput,required=False)
|
||||||
dist_max = forms.IntegerField(initial=0,label='Dist Max',widget=HiddenInput,required=False)
|
dist_max = forms.IntegerField(initial=150000,label='Dist Max',widget=HiddenInput,required=False)
|
||||||
work_min = forms.IntegerField(initial=0,label='Work Min',widget=HiddenInput,required=False)
|
work_min = forms.IntegerField(initial=0,label='Work Min',widget=HiddenInput,required=False)
|
||||||
work_max = forms.IntegerField(initial=1500,label='Work Max',widget=HiddenInput,required=False)
|
work_max = forms.IntegerField(initial=1500,label='Work Max',widget=HiddenInput,required=False)
|
||||||
|
|
||||||
notes = forms.CharField(initial="", label='notes', widget=HiddenInput, required=False)
|
notes = forms.CharField(initial="", label='notes', widget=HiddenInput, required=False)
|
||||||
|
|
||||||
plotchoices = (
|
|
||||||
('line', 'Force Curve Collection Plot'),
|
|
||||||
('scatter', 'Peak Force Scatter Plot'),
|
|
||||||
('none', 'Only aggregrate data')
|
|
||||||
)
|
|
||||||
plottype = forms.ChoiceField(choices=plotchoices, initial='line',
|
|
||||||
label='Individual Stroke Chart Type')
|
|
||||||
|
|
||||||
name = forms.CharField(initial="", label='Name',required=False)
|
name = forms.CharField(initial="", label='Name',required=False)
|
||||||
|
|
||||||
|
plotcircles = forms.BooleanField(initial=False,
|
||||||
|
widget=forms.CheckboxInput(attrs={'class':'hidden'}),
|
||||||
|
required=False)
|
||||||
|
plotlines = forms.BooleanField(initial=False,
|
||||||
|
widget=forms.CheckboxInput(attrs={'class':'hidden'}),
|
||||||
|
required=False)
|
||||||
|
|
||||||
|
|
||||||
axchoices = list(
|
axchoices = list(
|
||||||
(ax[0], ax[1]) for ax in axes if ax[0] not in ['cumdist', 'None']
|
(ax[0], ax[1]) for ax in axes if ax[0] not in ['cumdist', 'None']
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from .integrations import SyncIntegration, NoTokenError, create_or_update_syncre
|
|||||||
from rowers.models import User, Rower, Workout, TombStone
|
from rowers.models import User, Rower, Workout, TombStone
|
||||||
from django.db.utils import IntegrityError
|
from django.db.utils import IntegrityError
|
||||||
|
|
||||||
from rowingdata import rowingdata
|
from rowingdata import rowingdata, rowingdata_pl
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
|||||||
+904
-5759
File diff suppressed because it is too large
Load Diff
@@ -364,6 +364,7 @@ for key, dict in rowingmetrics:
|
|||||||
metricsdicts[key] = dict
|
metricsdicts[key] = dict
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
metricsgroups = list(set([d['group'] for n, d in rowingmetrics]))
|
metricsgroups = list(set([d['group'] for n, d in rowingmetrics]))
|
||||||
|
|
||||||
dtypes = {}
|
dtypes = {}
|
||||||
|
|||||||
+6
-1
@@ -3833,8 +3833,11 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
|
|||||||
# remove parquet file
|
# remove parquet file
|
||||||
try:
|
try:
|
||||||
dirname = 'media/strokedata_{id}.parquet.gz'.format(id=instance.id)
|
dirname = 'media/strokedata_{id}.parquet.gz'.format(id=instance.id)
|
||||||
shutil.rmtree(dirname)
|
os.remove(dirname)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
try:
|
||||||
|
shutil.rmtree(dirname)
|
||||||
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# remove parquet file
|
# remove parquet file
|
||||||
@@ -5257,6 +5260,8 @@ class ForceCurveAnalysis(models.Model):
|
|||||||
average_spm = models.FloatField(default=23)
|
average_spm = models.FloatField(default=23)
|
||||||
average_boatspeed = models.FloatField(default=4.0)
|
average_boatspeed = models.FloatField(default=4.0)
|
||||||
include_rest_strokes = models.BooleanField(default=False)
|
include_rest_strokes = models.BooleanField(default=False)
|
||||||
|
plotcircles = models.BooleanField(default=False)
|
||||||
|
plotlines = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = 'Force Curve Analysis {name} ({date})'.format(name = self.name,
|
s = 'Force Curve Analysis {name} ({date})'.format(name = self.name,
|
||||||
|
|||||||
+11
-17
@@ -18,13 +18,12 @@ import rowers.dataprep as dataprep
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import rowers.metrics as metrics
|
import rowers.metrics as metrics
|
||||||
import rowers.mytypes as mytypes
|
import rowers.mytypes as mytypes
|
||||||
from rowers.courses import get_time_course
|
|
||||||
from rowers.utils import to_pace
|
from rowers.utils import to_pace
|
||||||
from rowers.opaque import encoder
|
from rowers.opaque import encoder
|
||||||
from rowingdata import rower as rrower
|
from rowingdata import rower as rrower
|
||||||
from rowingdata import rowingdata as rrdata
|
from rowingdata import rowingdata as rrdata
|
||||||
import arrow
|
import arrow
|
||||||
import pandas as pd
|
import polars as pl
|
||||||
import json
|
import json
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
@@ -203,16 +202,8 @@ def get_execution_report(rower, startdate, enddate, plan=None):
|
|||||||
startdate__gte=enddate)
|
startdate__gte=enddate)
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
plans = TrainingPlan.objects.filter(rowers__in=[rower])
|
plans = TrainingPlan.objects.filter(rowers__in=[rower])
|
||||||
#plans2 = TrainingPlan.objects.filter(
|
|
||||||
# enddate__lte=enddate, startdate__lte=enddate, rowers__in=[rower])
|
|
||||||
#plans = plans | plans2
|
|
||||||
|
|
||||||
#plans = plans.exclude(status=False).order_by("-enddate")
|
|
||||||
|
|
||||||
if not plans:
|
if not plans:
|
||||||
# make week cycles here
|
|
||||||
# get monday before startdate
|
|
||||||
|
|
||||||
micros = []
|
micros = []
|
||||||
else:
|
else:
|
||||||
sorted_plans = sorted(plans, key= lambda t: t.overlap(startdate,enddate))
|
sorted_plans = sorted(plans, key= lambda t: t.overlap(startdate,enddate))
|
||||||
@@ -290,7 +281,7 @@ def get_execution_report(rower, startdate, enddate, plan=None):
|
|||||||
else:
|
else:
|
||||||
plannedscore += 60
|
plannedscore += 60
|
||||||
actualscore += 0
|
actualscore += 0
|
||||||
elif w.hrtss != 0:
|
elif w.hrtss >= 0:
|
||||||
if ratio > 0:
|
if ratio > 0:
|
||||||
plannedscore += w.hrtss/ratio
|
plannedscore += w.hrtss/ratio
|
||||||
actualscore += w.hrtss
|
actualscore += w.hrtss
|
||||||
@@ -313,7 +304,7 @@ def get_execution_report(rower, startdate, enddate, plan=None):
|
|||||||
planned += [plannedscore]
|
planned += [plannedscore]
|
||||||
executed += [actualscore]
|
executed += [actualscore]
|
||||||
|
|
||||||
data = pd.DataFrame({
|
data = pl.DataFrame({
|
||||||
'startdate': startdates,
|
'startdate': startdates,
|
||||||
'planned': planned,
|
'planned': planned,
|
||||||
'executed': executed,
|
'executed': executed,
|
||||||
@@ -444,8 +435,9 @@ def add_workouts_plannedsession(ws, ps, r):
|
|||||||
for record in records:
|
for record in records:
|
||||||
record.delete()
|
record.delete()
|
||||||
|
|
||||||
df = dataprep.getsmallrowdata_db(
|
df = dataprep.read_data(
|
||||||
['time', 'cumdist'], ids=[w.id])
|
['time', 'cumdist'], ids=[w.id])
|
||||||
|
df = dataprep.remove_nulls_pl(df)
|
||||||
fastest_milliseconds, starttime, endtime = datautils.getfastest(
|
fastest_milliseconds, starttime, endtime = datautils.getfastest(
|
||||||
df, ps.sessionvalue, mode='distance')
|
df, ps.sessionvalue, mode='distance')
|
||||||
|
|
||||||
@@ -475,11 +467,11 @@ def add_workouts_plannedsession(ws, ps, r):
|
|||||||
for record in records:
|
for record in records:
|
||||||
record.delete()
|
record.delete()
|
||||||
|
|
||||||
df = dataprep.getsmallrowdata_db(
|
df = dataprep.read_data(
|
||||||
['time', 'cumdist'], ids=[w.id])
|
['time', 'cumdist'], ids=[w.id])
|
||||||
|
df = dataprep.remove_nulls_pl(df)
|
||||||
fastest_meters, starttime, endtime = datautils.getfastest(
|
fastest_meters, starttime, endtime = datautils.getfastest(
|
||||||
df, ps.sessionvalue, mode='time')
|
df, ps.sessionvalue, mode='time')
|
||||||
|
|
||||||
if fastest_meters > 0:
|
if fastest_meters > 0:
|
||||||
w.plannedsession = ps
|
w.plannedsession = ps
|
||||||
w.save()
|
w.save()
|
||||||
@@ -1694,8 +1686,9 @@ def add_workout_fastestrace(ws, race, r, recordid=0, doregister=False):
|
|||||||
record.coursecompleted = True
|
record.coursecompleted = True
|
||||||
record.workoutid = ws[0].id
|
record.workoutid = ws[0].id
|
||||||
if race.sessiontype == 'fastest_distance':
|
if race.sessiontype == 'fastest_distance':
|
||||||
df = dataprep.getsmallrowdata_db(
|
df = dataprep.read_data(
|
||||||
['time', 'cumdist'], ids=[ws[0].id])
|
['time', 'cumdist'], ids=[ws[0].id])
|
||||||
|
df = dataprep.remove_nulls_pl(df)
|
||||||
fastest_milliseconds, startsecond, endsecond = datautils.getfastest(
|
fastest_milliseconds, startsecond, endsecond = datautils.getfastest(
|
||||||
df, race.sessionvalue, mode='distance')
|
df, race.sessionvalue, mode='distance')
|
||||||
velo = race.sessionvalue/fastest_milliseconds
|
velo = race.sessionvalue/fastest_milliseconds
|
||||||
@@ -1711,8 +1704,9 @@ def add_workout_fastestrace(ws, race, r, recordid=0, doregister=False):
|
|||||||
record.endsecond = endsecond
|
record.endsecond = endsecond
|
||||||
record.save()
|
record.save()
|
||||||
if race.sessiontype == 'fastest_time': # pragma: no cover
|
if race.sessiontype == 'fastest_time': # pragma: no cover
|
||||||
df = dataprep.getsmallrowdata_db(
|
df = dataprep.read_data(
|
||||||
['time', 'cumdist'], ids=[ws[0].id])
|
['time', 'cumdist'], ids=[ws[0].id])
|
||||||
|
df = dataprep.remove_nulls_pl(df)
|
||||||
fastest_meters, startsecond, endsecond = datautils.getfastest(
|
fastest_meters, startsecond, endsecond = datautils.getfastest(
|
||||||
df, race.sessionvalue, mode='time')
|
df, race.sessionvalue, mode='time')
|
||||||
velo = fastest_meters/(60.*race.sessionvalue)
|
velo = fastest_meters/(60.*race.sessionvalue)
|
||||||
|
|||||||
+17
-1
@@ -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,
|
||||||
GeoPolygon, GeoPoint, PlannedSession,
|
GeoPolygon, GeoPoint, PlannedSession, ForceCurveAnalysis
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
@@ -297,6 +297,22 @@ class GeoPointSerializer(serializers.ModelSerializer):
|
|||||||
)
|
)
|
||||||
extra_kwargs = {'id': {'read_only': False, 'required': True}}
|
extra_kwargs = {'id': {'read_only': False, 'required': True}}
|
||||||
|
|
||||||
|
class ForceCurveAnalysisSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = ForceCurveAnalysis
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'workout',
|
||||||
|
'dist_min',
|
||||||
|
'dist_max',
|
||||||
|
'spm_min',
|
||||||
|
'spm_max',
|
||||||
|
'work_min',
|
||||||
|
'work_max',
|
||||||
|
'include_rest_strokes'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GeoPolygonSerializer(serializers.ModelSerializer):
|
class GeoPolygonSerializer(serializers.ModelSerializer):
|
||||||
points = GeoPointSerializer(many=True)
|
points = GeoPointSerializer(many=True)
|
||||||
|
|||||||
+37
-117
@@ -56,7 +56,7 @@ from scipy.signal import savgol_filter
|
|||||||
from scipy.interpolate import griddata
|
from scipy.interpolate import griddata
|
||||||
|
|
||||||
import rowingdata
|
import rowingdata
|
||||||
from rowingdata import make_cumvalues
|
from rowingdata import make_cumvalues, make_cumvalues_array
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from rowingdata import rowingdata as rdata
|
from rowingdata import rowingdata as rdata
|
||||||
|
|
||||||
@@ -115,6 +115,9 @@ tpapilocation = TP_API_LOCATION
|
|||||||
from requests_oauthlib import OAuth1, OAuth1Session
|
from requests_oauthlib import OAuth1, OAuth1Session
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import polars as pl
|
||||||
|
from polars.exceptions import ColumnNotFoundError
|
||||||
|
|
||||||
|
|
||||||
from django_rq import job
|
from django_rq import job
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
@@ -127,7 +130,8 @@ from rowers import mytypes
|
|||||||
|
|
||||||
|
|
||||||
from rowers.dataroutines import (
|
from rowers.dataroutines import (
|
||||||
getsmallrowdata_db, updatecpdata_sql, update_c2id_sql,
|
getsmallrowdata_pd, updatecpdata_sql, update_c2id_sql,
|
||||||
|
read_data,
|
||||||
#update_workout_field_sql,
|
#update_workout_field_sql,
|
||||||
update_agegroup_db, update_strokedata,
|
update_agegroup_db, update_strokedata,
|
||||||
add_c2_stroke_data_db, totaltime_sec_to_string,
|
add_c2_stroke_data_db, totaltime_sec_to_string,
|
||||||
@@ -2549,9 +2553,10 @@ def handle_otwsetpower(self, f1, boattype, boatclass, coastalbrand, weightvalue,
|
|||||||
totaltime = totaltime + rowdata.df.loc[0, ' ElapsedTime (sec)']
|
totaltime = totaltime + rowdata.df.loc[0, ' ElapsedTime (sec)']
|
||||||
except KeyError: # pragma: no cover
|
except KeyError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
df = getsmallrowdata_db(
|
df = getsmallrowdata_pd(
|
||||||
['power', 'workoutid', 'time'], ids=[workoutid],
|
['power', 'workoutid', 'time'], ids=[workoutid],
|
||||||
debug=debug)
|
debug=debug)
|
||||||
|
|
||||||
thesecs = totaltime
|
thesecs = totaltime
|
||||||
maxt = 1.05 * thesecs
|
maxt = 1.05 * thesecs
|
||||||
logarr = datautils.getlogarr(maxt)
|
logarr = datautils.getlogarr(maxt)
|
||||||
@@ -2583,53 +2588,6 @@ def handle_otwsetpower(self, f1, boattype, boatclass, coastalbrand, weightvalue,
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
|
||||||
def handle_updateergcp(rower_id, workoutfilenames, debug=False, **kwargs):
|
|
||||||
therows = []
|
|
||||||
for f1 in workoutfilenames:
|
|
||||||
try:
|
|
||||||
rowdata = rdata(csvfile=f1)
|
|
||||||
except IOError: # pragma: no cover
|
|
||||||
try:
|
|
||||||
rowdata = rdata(csvfile=f1 + '.csv')
|
|
||||||
except IOError:
|
|
||||||
try:
|
|
||||||
rowdata = rdata(csvfile=f1 + '.gz')
|
|
||||||
except IOError:
|
|
||||||
rowdata = 0
|
|
||||||
if rowdata != 0:
|
|
||||||
therows.append(rowdata)
|
|
||||||
|
|
||||||
cpdata = rowingdata.cumcpdata(therows)
|
|
||||||
cpdata.columns = cpdata.columns.str.lower()
|
|
||||||
|
|
||||||
updatecpdata_sql(rower_id, cpdata['delta'], cpdata['cp'],
|
|
||||||
table='ergcpdata', distance=cpdata['distance'],
|
|
||||||
debug=debug)
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
|
||||||
def handle_updatecp(rower_id, workoutids, debug=False, table='cpdata', **kwargs):
|
|
||||||
columns = ['power', 'workoutid', 'time']
|
|
||||||
df = getsmallrowdata_db(columns, ids=workoutids, debug=debug)
|
|
||||||
|
|
||||||
if df.empty: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
maxt = 1.05*df['time'].max()/1000.
|
|
||||||
|
|
||||||
logarr = datautils.getlogarr(maxt)
|
|
||||||
|
|
||||||
dfgrouped = df.groupby(['workoutid'])
|
|
||||||
|
|
||||||
delta, cpvalue, avgpower = datautils.getcp(dfgrouped, logarr)
|
|
||||||
|
|
||||||
updatecpdata_sql(rower_id, delta, cpvalue, debug=debug, table=table)
|
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename,
|
def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename,
|
||||||
@@ -3179,43 +3137,6 @@ def handle_sendemail_invite_reject(email, name, teamname, managername,
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
|
||||||
def handle_setcp(strokesdf, filename, workoutid, debug=False, **kwargs):
|
|
||||||
try:
|
|
||||||
os.remove(filename)
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
if not strokesdf.empty:
|
|
||||||
|
|
||||||
try:
|
|
||||||
totaltime = strokesdf['time'].max()
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
try:
|
|
||||||
powermean = strokesdf['power'].mean()
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
powermean = 0
|
|
||||||
|
|
||||||
if powermean != 0:
|
|
||||||
thesecs = totaltime
|
|
||||||
maxt = 1.05 * thesecs
|
|
||||||
|
|
||||||
if maxt > 0:
|
|
||||||
logarr = datautils.getlogarr(maxt)
|
|
||||||
dfgrouped = strokesdf.groupby(['workoutid'])
|
|
||||||
delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr)
|
|
||||||
|
|
||||||
df = pd.DataFrame({
|
|
||||||
'delta': delta,
|
|
||||||
'cp': cpvalues,
|
|
||||||
'id': workoutid,
|
|
||||||
})
|
|
||||||
df.to_parquet(filename, engine='fastparquet',
|
|
||||||
compression='GZIP')
|
|
||||||
return 1
|
|
||||||
|
|
||||||
return 1 # pragma: no cover
|
|
||||||
|
|
||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def handle_sendemail_invite_accept(email, name, teamname, managername,
|
def handle_sendemail_invite_accept(email, name, teamname, managername,
|
||||||
@@ -3251,23 +3172,22 @@ graphql_url = "https://rp3rowing-app.com/graphql"
|
|||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def handle_update_wps(rid, types, ids, mode, debug=False, **kwargs):
|
def handle_update_wps(rid, types, ids, mode, debug=False, **kwargs):
|
||||||
df = getsmallrowdata_db(['time', 'driveenergy'], ids=ids)
|
df = read_data(['time', 'driveenergy'], ids=ids)
|
||||||
try:
|
try:
|
||||||
mask = df['driveenergy'] > 100
|
wps_median = int(df.filter(pl.col("driveenergy")>100)["driveenergy"].median())
|
||||||
except (KeyError, TypeError): # pragma: no cover
|
|
||||||
return 0
|
|
||||||
try:
|
|
||||||
wps_median = int(df.loc[mask, 'driveenergy'].median())
|
|
||||||
except ValueError: # pragma: no cover
|
|
||||||
return 0
|
|
||||||
|
|
||||||
rower = Rower.objects.get(id=rid)
|
rower = Rower.objects.get(id=rid)
|
||||||
if mode == 'water':
|
if mode == 'water':
|
||||||
rower.median_wps = wps_median
|
rower.median_wps = wps_median
|
||||||
else:
|
else: # pragma: no cover
|
||||||
rower.median_wps_erg = wps_median
|
rower.median_wps_erg = wps_median
|
||||||
|
|
||||||
rower.save()
|
rower.save()
|
||||||
|
except ValueError: # pragma: no cover
|
||||||
|
wps_median = 0
|
||||||
|
except OverflowError:
|
||||||
|
wps_median = 0
|
||||||
|
except ColumnNotFoundError:
|
||||||
|
wps_median = 0
|
||||||
|
|
||||||
return wps_median
|
return wps_median
|
||||||
|
|
||||||
@@ -3901,7 +3821,7 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid,
|
|||||||
pace[np.isinf(pace)] = 0.0
|
pace[np.isinf(pace)] = 0.0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
strokedata = pd.DataFrame({'t': 10*t,
|
strokedata = pl.DataFrame({'t': 10*t,
|
||||||
'd': 10*d,
|
'd': 10*d,
|
||||||
'p': 10*pace,
|
'p': 10*pace,
|
||||||
'spm': spm,
|
'spm': spm,
|
||||||
@@ -3947,18 +3867,18 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid,
|
|||||||
|
|
||||||
starttimeunix = arrow.get(rowdatetime).timestamp()
|
starttimeunix = arrow.get(rowdatetime).timestamp()
|
||||||
|
|
||||||
res = make_cumvalues(0.1*strokedata['t'])
|
res = make_cumvalues_array(0.1*strokedata['t'].to_numpy())
|
||||||
cum_time = res[0]
|
cum_time = pl.Series(res[0])
|
||||||
lapidx = res[1]
|
lapidx = pl.Series(res[1])
|
||||||
|
|
||||||
unixtime = cum_time+starttimeunix
|
unixtime = cum_time+starttimeunix
|
||||||
seconds = 0.1*strokedata.loc[:, 't']
|
seconds = 0.1*strokedata['t']
|
||||||
|
|
||||||
nr_rows = len(unixtime)
|
nr_rows = len(unixtime)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
latcoord = strokedata.loc[:, 'lat']
|
latcoord = strokedata['lat']
|
||||||
loncoord = strokedata.loc[:, 'lon']
|
loncoord = strokedata['lon']
|
||||||
if latcoord.std() == 0 and loncoord.std() == 0 and workouttype == 'water': # pragma: no cover
|
if latcoord.std() == 0 and loncoord.std() == 0 and workouttype == 'water': # pragma: no cover
|
||||||
workouttype = 'rower'
|
workouttype = 'rower'
|
||||||
except: # pragma: no cover
|
except: # pragma: no cover
|
||||||
@@ -3968,29 +3888,29 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid,
|
|||||||
workouttype = 'rower'
|
workouttype = 'rower'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
strokelength = strokedata.loc[:, 'strokelength']
|
strokelength = strokedata['strokelength']
|
||||||
except: # pragma: no cover
|
except: # pragma: no cover
|
||||||
strokelength = np.zeros(nr_rows)
|
strokelength = np.zeros(nr_rows)
|
||||||
|
|
||||||
dist2 = 0.1*strokedata.loc[:, 'd']
|
dist2 = 0.1*strokedata['d']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
spm = strokedata.loc[:, 'spm']
|
spm = strokedata['spm']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
spm = 0*dist2
|
spm = 0*dist2
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hr = strokedata.loc[:, 'hr']
|
hr = strokedata['hr']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
hr = 0*spm
|
hr = 0*spm
|
||||||
pace = strokedata.loc[:, 'p']/10.
|
pace = strokedata['p']/10.
|
||||||
pace = np.clip(pace, 0, 1e4)
|
pace = np.clip(pace, 0, 1e4)
|
||||||
pace = pace.replace(0, 300)
|
pace = pl.Series(pace).replace(0, 300)
|
||||||
|
|
||||||
velo = 500./pace
|
velo = 500./pace
|
||||||
|
|
||||||
try:
|
try:
|
||||||
power = strokedata.loc[:, 'power']
|
power = strokedata['power']
|
||||||
except KeyError: # pragma: no cover
|
except KeyError: # pragma: no cover
|
||||||
power = 2.8*velo**3
|
power = 2.8*velo**3
|
||||||
|
|
||||||
@@ -3999,7 +3919,7 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid,
|
|||||||
|
|
||||||
# save csv
|
# save csv
|
||||||
# Create data frame with all necessary data to write to csv
|
# Create data frame with all necessary data to write to csv
|
||||||
df = pd.DataFrame({'TimeStamp (sec)': unixtime,
|
df = pl.DataFrame({'TimeStamp (sec)': unixtime,
|
||||||
' Horizontal (meters)': dist2,
|
' Horizontal (meters)': dist2,
|
||||||
' Cadence (stokes/min)': spm,
|
' Cadence (stokes/min)': spm,
|
||||||
' HRCur (bpm)': hr,
|
' HRCur (bpm)': hr,
|
||||||
@@ -4019,10 +3939,10 @@ def fetch_strava_workout(stravatoken, oauth_data, stravaid, csvfilename, userid,
|
|||||||
'cum_dist': dist2,
|
'cum_dist': dist2,
|
||||||
})
|
})
|
||||||
|
|
||||||
df.sort_values(by='TimeStamp (sec)', ascending=True)
|
df.sort('TimeStamp (sec)')
|
||||||
|
|
||||||
row = rowingdata.rowingdata(df=df)
|
row = rowingdata.rowingdata_pl(df=df)
|
||||||
row.write_csv(csvfilename, gzip=False)
|
row.write_csv(csvfilename, compressed=False)
|
||||||
|
|
||||||
# summary = row.allstats()
|
# summary = row.allstats()
|
||||||
# maxdist = df['cum_dist'].max()
|
# maxdist = df['cum_dist'].max()
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
<div class="mapdiv">
|
<div class="mapdiv">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
|
||||||
|
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -37,8 +37,9 @@
|
|||||||
<div class="mapdiv">
|
<div class="mapdiv">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
|
||||||
|
<script>
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -45,7 +45,9 @@
|
|||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div class="mapdiv">
|
<div class="mapdiv">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
<script>
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -54,7 +54,6 @@
|
|||||||
<div class="mapdiv">
|
<div class="mapdiv">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
|
||||||
|
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -102,14 +102,11 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
|
{{ interactiveplot |safe }}
|
||||||
|
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ function copyText() {
|
|||||||
</li>
|
</li>
|
||||||
{% if user.is_authenticated and user == workout.user.user and not locked %}
|
{% if user.is_authenticated and user == workout.user.user and not locked %}
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<p>Paste link to you tube video below</p>
|
<p>Paste link to Youtube video below</p>
|
||||||
<p>Use the slider to locate start point for video on workout map</p>
|
<p>Use the slider to locate start point for video on workout map</p>
|
||||||
<p>Playing the video will advance the data in synchonization. Use the regular YouTube
|
<p>Playing the video will advance the data in synchonization. Use the regular YouTube
|
||||||
controls
|
controls
|
||||||
@@ -169,9 +169,8 @@ function copyText() {
|
|||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<div id="player"></div>
|
<div id="player"></div>
|
||||||
<script>
|
|
||||||
// 1. Code for the map
|
|
||||||
{{ mapscript | safe }}
|
{{ mapscript | safe }}
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
// 2. This code loads the IFrame Player API code asynchronously.
|
// 2. This code loads the IFrame Player API code asynchronously.
|
||||||
@@ -189,6 +188,7 @@ function copyText() {
|
|||||||
|
|
||||||
var videotime = 0;
|
var videotime = 0;
|
||||||
var data = JSON.parse('{{ data|safe }}');
|
var data = JSON.parse('{{ data|safe }}');
|
||||||
|
|
||||||
{% for id, metric in metrics.items %}
|
{% for id, metric in metrics.items %}
|
||||||
var {{ id }}_values = data["{{ id }}"];
|
var {{ id }}_values = data["{{ id }}"];
|
||||||
// console.log("{{ id }}_values",{{ id }}_values);
|
// console.log("{{ id }}_values",{{ id }}_values);
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
|
||||||
|
{% block title %}Rowsandall {% endblock %}
|
||||||
|
{% block meta %}
|
||||||
|
<style type="text/css">
|
||||||
|
|
||||||
|
circle {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.axis path,
|
||||||
|
.axis line {
|
||||||
|
fill: none;
|
||||||
|
stroke: black;
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
}
|
||||||
|
|
||||||
|
.axis text {
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
padding: 1em;
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
background-color: #f00;
|
||||||
|
color: #fff;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<script src="https://d3js.org/d3.v3.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<h1>Film Deaths</h1>
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
|
||||||
|
|
||||||
|
<li class="grid_4">
|
||||||
|
<div id="id_chart">
|
||||||
|
<script>
|
||||||
|
{{ the_script| safe }}
|
||||||
|
</script>
|
||||||
|
{{ the_div|safe }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% include 'menu_analytics.html' %}
|
||||||
|
{% endblock %}
|
||||||
@@ -8,16 +8,6 @@
|
|||||||
{% localtime on %}
|
{% localtime on %}
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
{{ js_res | safe }}
|
|
||||||
{{ css_res| safe }}
|
|
||||||
|
|
||||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ the_script |safe }}
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{% if workout|previousworkout:rower.user %}
|
{% if workout|previousworkout:rower.user %}
|
||||||
@@ -34,10 +24,9 @@
|
|||||||
<h1>Flexible Chart</h1>
|
<h1>Flexible Chart</h1>
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="theplot" class="flexplot">
|
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<form enctype="multipart/form-data"
|
<form enctype="multipart/form-data"
|
||||||
@@ -96,6 +85,10 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
|
{{ the_script |safe }}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endlocaltime %}
|
{% endlocaltime %}
|
||||||
|
|
||||||
|
|||||||
@@ -8,16 +8,8 @@
|
|||||||
{% localtime on %}
|
{% localtime on %}
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
{{ js_res | safe }}
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
{{ css_res| safe }}
|
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ the_script |safe }}
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{% if workout|previousworkout:rower.user %}
|
{% if workout|previousworkout:rower.user %}
|
||||||
@@ -34,6 +26,7 @@
|
|||||||
<h1>Chart Stack</h1>
|
<h1>Chart Stack</h1>
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="theplot">
|
<div id="theplot">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
@@ -57,6 +50,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
{{ the_script |safe }}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endlocaltime %}
|
{% endlocaltime %}
|
||||||
|
|||||||
@@ -6,25 +6,20 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
{{ js_res | safe }}
|
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
||||||
{{ css_res| safe }}
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ the_script |safe }}
|
|
||||||
|
|
||||||
<h1>Force Curve Analysis for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
|
<h1>Force Curve Analysis for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
|
||||||
|
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
{% if the_div %}
|
{% if the_div %}
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="theplot" class="flexplot">
|
<div id="theplot" class="flexplot">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
|
{{ the_script |safe }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -8,23 +8,17 @@
|
|||||||
{% localtime on %}
|
{% localtime on %}
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
{{ js_res | safe }}
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
{{ css_res| safe }}
|
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ the_script |safe }}
|
|
||||||
|
|
||||||
<h1>Empower Force Curve</h1>
|
<h1>Empower Force Curve</h1>
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="theplot" class="flexplot">
|
<div id="theplot" class="flexplot">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
|
{{ the_script |safe }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -52,27 +46,13 @@
|
|||||||
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var slider_min_spm = Bokeh.documents[0].get_model_by_name('min_spm_slider')
|
var label = $('label[for="' + $("#id_plotcircles").attr('id') + '"]');
|
||||||
slider_min_spm.value = {{ spm_min }}
|
label.attr("class", "hidden")
|
||||||
console.log('min spm value after:', slider_min_spm.value)
|
var label2 = $('label[for="' + $("#id_plotlines").attr('id') + '"]');
|
||||||
var slider_max_spm = Bokeh.documents[0].get_model_by_name('max_spm_slider')
|
label2.attr("class", "hidden")
|
||||||
slider_max_spm.value = {{ spm_max }}
|
var label3 = $('label[for="' + $("#id_includereststrokes").attr('id') + '"]');
|
||||||
console.log('max spm value after:', slider_max_spm.value)
|
label3.attr("class", "hidden")
|
||||||
var slider_min_work = Bokeh.documents[0].get_model_by_name('min_work_slider')
|
|
||||||
slider_min_work.value = {{ work_min }}
|
|
||||||
console.log('min work value after:', slider_min_work.value)
|
|
||||||
var slider_max_work = Bokeh.documents[0].get_model_by_name('max_work_slider')
|
|
||||||
slider_max_work.value = {{ work_max }}
|
|
||||||
console.log('max work value after:', slider_max_work.value)
|
|
||||||
var slider_min_dist = Bokeh.documents[0].get_model_by_name('min_dist_slider')
|
|
||||||
slider_min_dist.value = {{ dist_min }}
|
|
||||||
console.log('min dist value after:', slider_min_dist.value)
|
|
||||||
var slider_max_dist = Bokeh.documents[0].get_model_by_name('max_dist_slider')
|
|
||||||
slider_max_dist.value = {{ dist_max }}
|
|
||||||
console.log('max dist value after:', slider_max_dist.value)
|
|
||||||
var annotation = Bokeh.documents[0].get_model_by_name('annotation')
|
|
||||||
annotation.value = "{{ annotation }}"
|
|
||||||
console.log('Annotation set to ', annotation.value)
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -60,17 +60,6 @@
|
|||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="id_script">
|
|
||||||
{{ chartscript |safe }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% if rower.user %}
|
{% if rower.user %}
|
||||||
<h1>Gold Medal Scores for {{ rower.user.first_name }} </h1>
|
<h1>Gold Medal Scores for {{ rower.user.first_name }} </h1>
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -79,6 +68,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<p>Hover over the workout to see details, click on the workout to open in a
|
<p>Hover over the workout to see details, click on the workout to open in a
|
||||||
separate page.</p>
|
separate page.</p>
|
||||||
@@ -136,6 +126,11 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||||
|
|
||||||
|
<div id="id_script">
|
||||||
|
{{ chartscript |safe }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
||||||
|
<script src="https://d3js.org/d3/v6/js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
@@ -86,7 +87,6 @@
|
|||||||
|
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="id_chart">
|
<div id="id_chart">
|
||||||
|
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -129,6 +129,7 @@
|
|||||||
var counter=0;
|
var counter=0;
|
||||||
var script = json.script;
|
var script = json.script;
|
||||||
var div = json.div;
|
var div = json.div;
|
||||||
|
console.log(div)
|
||||||
console.log('set vars');
|
console.log('set vars');
|
||||||
$("#id_sitready").remove();
|
$("#id_sitready").remove();
|
||||||
console.log('sitready removed');
|
console.log('sitready removed');
|
||||||
|
|||||||
@@ -6,12 +6,9 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -24,6 +21,7 @@
|
|||||||
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
{{ interactiveplot |safe }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -5,25 +5,14 @@
|
|||||||
{% block title %}Rowsandall {% endblock %}
|
{% block title %}Rowsandall {% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div id="id_css_res">
|
|
||||||
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.css" type="text/css" />
|
|
||||||
</div>
|
|
||||||
<div id="id_js_res">
|
<div id="id_js_res">
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.js"></script>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="id_script">
|
<div id="id_script">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="t_script">
|
|
||||||
{{ tscript|safe}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="activities_script">
|
<div id="activities_script">
|
||||||
</div>
|
</div>
|
||||||
@@ -90,6 +79,10 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
{{ tdiv|safe }}
|
{{ tdiv|safe }}
|
||||||
|
<div id="t_script">
|
||||||
|
{{ tscript|safe}}
|
||||||
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<div id="id_chart">
|
<div id="id_chart">
|
||||||
@@ -157,7 +150,6 @@
|
|||||||
var activities_chart = json.activities_chart
|
var activities_chart = json.activities_chart
|
||||||
$("#id_sitready").remove();
|
$("#id_sitready").remove();
|
||||||
$("#id_chart").append(div);
|
$("#id_chart").append(div);
|
||||||
// $("#id_script").append("<s"+"cript>"+script+"</s"+"cript>");
|
|
||||||
$("#id_script").append(script);
|
$("#id_script").append(script);
|
||||||
$("#id_activities").append(activities_chart)
|
$("#id_activities").append(activities_chart)
|
||||||
$("#activities_script").append(activities_script)
|
$("#activities_script").append(activities_script)
|
||||||
@@ -165,6 +157,8 @@
|
|||||||
$("#total_maxhr").append(totalsdict.hrmax);
|
$("#total_maxhr").append(totalsdict.hrmax);
|
||||||
$("#total_power").append(totalsdict.powermean);
|
$("#total_power").append(totalsdict.powermean);
|
||||||
$("#total_maxpower").append(totalsdict.powermax);
|
$("#total_maxpower").append(totalsdict.powermax);
|
||||||
|
$("#selectors").hide();
|
||||||
|
|
||||||
listofdicts.forEach(function(item){
|
listofdicts.forEach(function(item){
|
||||||
var id = "#"+item.id+"_hr";
|
var id = "#"+item.id+"_hr";
|
||||||
$(id).append(item.hrmean);
|
$(id).append(item.hrmean);
|
||||||
|
|||||||
@@ -6,24 +6,20 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
{{ js_res | safe }}
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
{{ css_res| safe }}
|
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{{ the_script |safe }}
|
|
||||||
|
|
||||||
<h1>In-Stroke Analysis for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
|
<h1>In-Stroke Analysis for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
{% if the_div %}
|
{% if the_div %}
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="theplot" class="flexplot">
|
<div id="theplot" class="flexplot">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
|
{{ the_script |safe }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -11,10 +11,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>jQuery UI Slider - Range slider</title>
|
<title>jQuery UI Slider - Range slider</title>
|
||||||
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
|
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
|
||||||
<link rel="stylesheet" href="/resources/demos/style.css">
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
|
||||||
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
|
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function submit_form() {
|
function submit_form() {
|
||||||
console.log("form changed");
|
console.log("form changed");
|
||||||
@@ -30,11 +28,14 @@
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
|
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
console.log(data);
|
|
||||||
$("#id_script").replaceWith('<div id="id_script">'+data.script+'</d'+'iv>');
|
|
||||||
$("#id_chart").replaceWith('<div id="id_chart">'+data.div+'</d'+'iv>');
|
$("#id_chart").replaceWith('<div id="id_chart">'+data.div+'</d'+'iv>');
|
||||||
$("#ds").replaceWith('<div id="ds">'+data.ds+'</d'+'iv>');
|
$("#id_script").replaceWith('<div id="id_script">'+data.script+'</d'+'iv>');
|
||||||
$("#dd").replaceWith('<div id="dd">'+data.dd+'</d'+'iv>');
|
|
||||||
|
|
||||||
|
$("#dd").empty();
|
||||||
|
$("#dd").html(data.dd);
|
||||||
|
$("#ds").empty();
|
||||||
|
$('#ds').html(data.ds)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -119,15 +120,10 @@ $( function() {
|
|||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="id_script">
|
|
||||||
{{ the_script |safe }}
|
|
||||||
</div>
|
|
||||||
<div id="ds">
|
|
||||||
{{ ds |safe }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1>In Stroke Metrics</h1>
|
<h1>In Stroke Metrics</h1>
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
<li class="grid_4" >
|
<li class="grid_4" >
|
||||||
{% if user.rower|is_basic %}
|
{% if user.rower|is_basic %}
|
||||||
|
|
||||||
@@ -144,7 +140,7 @@ $( function() {
|
|||||||
</table>
|
</table>
|
||||||
<div id="slider-range"></div>
|
<div id="slider-range"></div>
|
||||||
<p>
|
<p>
|
||||||
<label for="amountspm">Active Range:</label>
|
<label for="amountspm">Stroke Rate:</label>
|
||||||
<input type="text" id="amountspm" readonly style="border:0; color:#1c75bc; font-weight:bold;">
|
<input type="text" id="amountspm" readonly style="border:0; color:#1c75bc; font-weight:bold;">
|
||||||
</p>
|
</p>
|
||||||
<div id="slider-timerange"></div>
|
<div id="slider-timerange"></div>
|
||||||
@@ -168,14 +164,23 @@ $( function() {
|
|||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<div id="id_chart" class="flexplot">
|
<div id="id_chart" class="flexplot">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
</div>
|
</div>
|
||||||
|
<div id="id_script">
|
||||||
|
{{ the_script |safe }}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_4">
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
|
<li class="grid_2" id="interactive">
|
||||||
<div id="dd" class="flexplot">
|
<div id="dd" class="flexplot">
|
||||||
{{ dd|safe }}
|
{{ dd|safe }}
|
||||||
</div>
|
</div>
|
||||||
|
<div id="ds">
|
||||||
|
{{ ds |safe }}
|
||||||
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|||||||
@@ -229,22 +229,11 @@
|
|||||||
Total meters: {{ totalmeters }}. Total time {{ totalhours }}:{{ totalminutes }}h.
|
Total meters: {{ totalmeters }}. Total time {{ totalhours }}:{{ totalminutes }}h.
|
||||||
<a href="/rowers/history/">Dig deeper</a>.
|
<a href="/rowers/history/">Dig deeper</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||||
Activity chart by
|
|
||||||
<a href="{{ request.get_path }}?yaxis=trimp">TRIMP</a>,
|
|
||||||
<a href="{{ request.get_path }}?yaxis=rscore">rScore</a>,
|
|
||||||
<a href="{{ request.get_path }}?yaxis=duration">Time</a>.
|
|
||||||
</p>
|
|
||||||
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.css" type="text/css" />
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/text/javascript">
|
|
||||||
Bokeh.set_log_level("info")
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
{{ the_div |safe }}
|
{{ the_div |safe }}
|
||||||
|
{{ interactiveplot |safe }}
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
{% if announcements %}
|
{% if announcements %}
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
<div style="height:100%;" id="theplot" class="flexplot mapdiv">
|
<div style="height:100%;" id="theplot" class="flexplot mapdiv">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
|
||||||
|
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
<div class="mapdiv">
|
<div class="mapdiv">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
<script>
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -101,11 +101,6 @@
|
|||||||
<i class="fas fa-dumbbell fa-fw"></i> Force Curve
|
<i class="fas fa-dumbbell fa-fw"></i> Force Curve
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li id="chart-otwpower">
|
|
||||||
<a href="/rowers/workout/{{ workout.id|encode }}/interactiveotwplot/">
|
|
||||||
<i class="fal fa-calculator-alt fa-fw"></i> Corrected Pace Plot
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
@@ -294,26 +289,6 @@
|
|||||||
<label for="group-advanced">Advanced</label>
|
<label for="group-advanced">Advanced</label>
|
||||||
<ul>
|
<ul>
|
||||||
{% if workout|water %}
|
{% if workout|water %}
|
||||||
<li id="advanced-wind">
|
|
||||||
<a href="/rowers/workout/{{ workout.id|encode }}/wind/">
|
|
||||||
<i class="fas fa-pennant fa-fw"></i> Wind
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li id="advanced-stream">
|
|
||||||
<a href="/rowers/workout/{{ workout.id|encode }}/stream/">
|
|
||||||
<i class="fas fa-stream fa-fw"></i> Stream
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li id="advanced-otwpower">
|
|
||||||
<a href="/rowers/workout/{{ workout.id|encode }}/otwsetpower/">
|
|
||||||
<i class="fas fa-calculator-alt fa-fw"></i> OTW Power
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li id="advanced-otwpower">
|
|
||||||
<a href="/rowers/workout/{{ workout.id|encode }}/zeropower-confirm/">
|
|
||||||
<i class="fas fa-eraser fa-fw"></i> Remove Power Data
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% if 'speedcoach2' in workout.workoutsource or 'nklinklogbook' in workout.workoutsource %}
|
{% if 'speedcoach2' in workout.workoutsource or 'nklinklogbook' in workout.workoutsource %}
|
||||||
<li id="advanced-usegps">
|
<li id="advanced-usegps">
|
||||||
<a href="/rowers/workout/{{ workout.id|encode }}/otwusegps/">
|
<a href="/rowers/workout/{{ workout.id|encode }}/otwusegps/">
|
||||||
|
|||||||
@@ -6,12 +6,9 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
<h1>Interactive Comparison</h1>
|
<h1>Interactive Comparison</h1>
|
||||||
|
|
||||||
@@ -20,6 +17,7 @@
|
|||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div>
|
<div>
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
|
{{ interactiveplot |safe }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
<div class="mapdiv">
|
<div class="mapdiv">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
|
||||||
|
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -8,6 +8,15 @@
|
|||||||
<script type='text/javascript'
|
<script type='text/javascript'
|
||||||
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
|
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
|
||||||
</script>
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://d3js.org/d3.v6.js">
|
||||||
|
</script>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function submit_form() {
|
function submit_form() {
|
||||||
@@ -25,11 +34,14 @@
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
|
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
console.log(data.div);
|
|
||||||
|
|
||||||
// var parsedJSON = $.parseJSON(data); //
|
// var parsedJSON = $.parseJSON(data); //
|
||||||
$("#id_script").replaceWith('<div id="id_script">'+data.script+'</d'+'iv>');
|
$("#id_script").replaceWith('<div id="id_script">'+data.script+'</d'+'iv>');
|
||||||
|
|
||||||
|
// $('#id_script').remove()
|
||||||
|
|
||||||
$("#id_chart").replaceWith('<div id="id_chart">'+data.div+'</d'+'iv>');
|
$("#id_chart").replaceWith('<div id="id_chart">'+data.div+'</d'+'iv>');
|
||||||
|
$("#id_chart").append(data.script)
|
||||||
$("#endfitness").html(data.endfitness)
|
$("#endfitness").html(data.endfitness)
|
||||||
$("#endfatigue").html(data.endfatigue)
|
$("#endfatigue").html(data.endfatigue)
|
||||||
$("#endform").html(data.endform)
|
$("#endform").html(data.endform)
|
||||||
@@ -59,19 +71,6 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block main %}
|
|
||||||
|
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="id_script">
|
|
||||||
{{ chartscript |safe }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -83,10 +82,12 @@
|
|||||||
|
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="id_chart">
|
<div id="id_chart">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_1">
|
<li class="grid_1">
|
||||||
<form id="performanceform" enctype="multipart/form-data" method="post">
|
<form id="performanceform" enctype="multipart/form-data" method="post">
|
||||||
@@ -188,6 +189,9 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div id="id_script">
|
||||||
|
{{ chartscript |safe }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
|
||||||
|
{% block title %}Rowsandall {% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
<div id="id_css_res">
|
||||||
|
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.css" type="text/css" />
|
||||||
|
</div>
|
||||||
|
<div id="id_js_res">
|
||||||
|
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.1.1.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.1.1.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.1.1.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.1.1.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-3.1.1.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-api-3.1.1.min.js"></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h1>Sleep</h1>
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
|
||||||
|
|
||||||
|
<li class="grid_4">
|
||||||
|
<div id="id_chart">
|
||||||
|
<script>
|
||||||
|
{{ the_script| safe }}
|
||||||
|
</script>
|
||||||
|
{{ the_div|safe }}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% include 'menu_analytics.html' %}
|
||||||
|
{% endblock %}
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
|
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -89,14 +89,11 @@
|
|||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
{{ the_div |safe }}
|
{{ the_div |safe }}
|
||||||
|
{{ interactiveplot |safe }}
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<h1>Feeling lucky?</h1>
|
<h1>Feeling lucky?</h1>
|
||||||
|
|||||||
@@ -6,25 +6,22 @@
|
|||||||
|
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<h1>Training Plan - {{ plan.name }}</h1>
|
<h1>Training Plan - {{ plan.name }}</h1>
|
||||||
|
|
||||||
{{ the_script | safe }}
|
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="theplot" class="flexplot">
|
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
|
{{ the_script | safe }}
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
|||||||
@@ -11,17 +11,15 @@
|
|||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
<div id="id_js_res">
|
||||||
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h1>Training Zones</h1>
|
<h1>Training Zones</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="id_script">
|
<div id="id_script">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="id_chart">
|
<div id="id_chart">
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
||||||
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
@@ -387,29 +388,11 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="id_css_res">
|
|
||||||
</div>
|
|
||||||
<div id="id_js_res">
|
|
||||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-3.1.1.min.js"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.1.1.min.js"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.1.1.min.js"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.1.1.min.js"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.1.1.min.js"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="id_script">
|
<div id="id_script">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
<canvas hidden id="canvas"></canvas>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="id_chart">
|
<div id="id_chart">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
|
|||||||
@@ -67,7 +67,9 @@
|
|||||||
<div class="mapdiv">
|
<div class="mapdiv">
|
||||||
|
|
||||||
{{ gmapdiv |safe }}
|
{{ gmapdiv |safe }}
|
||||||
|
<script>
|
||||||
{{ gmap |safe }}
|
{{ gmap |safe }}
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -98,14 +98,11 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
|
{{ interactiveplot |safe }}
|
||||||
|
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
|
|||||||
@@ -16,10 +16,6 @@
|
|||||||
{% block meta %}
|
{% block meta %}
|
||||||
{% leaflet_js %}
|
{% leaflet_js %}
|
||||||
{% leaflet_css %}
|
{% leaflet_css %}
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% for chart in charts %}
|
{% for chart in charts %}
|
||||||
{{ chart.script |safe }}
|
{{ chart.script |safe }}
|
||||||
@@ -51,7 +47,7 @@
|
|||||||
"<a href=\"/rowers/workout/"+workoutid+"/flexchart?favoritechart="+counter+"\">"+element.div+"</a>"+
|
"<a href=\"/rowers/workout/"+workoutid+"/flexchart?favoritechart="+counter+"\">"+element.div+"</a>"+
|
||||||
"</li>");
|
"</li>");
|
||||||
|
|
||||||
$("#id_thumbscripts").append(element.script);
|
$("#id_thumbs").append(element.script);
|
||||||
counter += 1;
|
counter += 1;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -64,6 +60,7 @@
|
|||||||
|
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<p>
|
<p>
|
||||||
{% if workout|previousworkout:rower.user %}
|
{% if workout|previousworkout:rower.user %}
|
||||||
<a href="/rowers/workout/{{ workout|previousworkout:rower.user }}/workflow"
|
<a href="/rowers/workout/{{ workout|previousworkout:rower.user }}/workflow"
|
||||||
|
|||||||
@@ -217,9 +217,9 @@
|
|||||||
<div class="mapdiv">
|
<div class="mapdiv">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
|
</script>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for graph in graphs %}
|
{% for graph in graphs %}
|
||||||
|
|||||||
@@ -131,21 +131,16 @@
|
|||||||
|
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
|
||||||
|
<script>
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-3.1.1.min.js"></script>
|
<script src="https://d3js.org/d3.v6.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
|
{{ interactiveplot |safe }}
|
||||||
</li>
|
</li>
|
||||||
{% for graph in graphs %}
|
{% for graph in graphs %}
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
+18
-6
@@ -38,6 +38,7 @@ from nose.tools import assert_true
|
|||||||
from mock import Mock, patch
|
from mock import Mock, patch
|
||||||
#from minimocktest import MockTestCase
|
#from minimocktest import MockTestCase
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import polars as pl
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
@@ -271,7 +272,7 @@ def mocked_fetchcperg(*args, **kwargs):
|
|||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
import pandas as pd
|
|
||||||
def mocked_read_df_sql(id): # pragma: no cover
|
def mocked_read_df_sql(id): # pragma: no cover
|
||||||
df = pd.read_csv('rowers/tests/testdata/fake_strokedata.csv')
|
df = pd.read_csv('rowers/tests/testdata/fake_strokedata.csv')
|
||||||
|
|
||||||
@@ -300,7 +301,7 @@ def mocked_getrowdata_db(*args, **kwargs):
|
|||||||
return df,row
|
return df,row
|
||||||
|
|
||||||
def mocked_getrowdata_uh(*args, **kwargs): # pragma: no cover
|
def mocked_getrowdata_uh(*args, **kwargs): # pragma: no cover
|
||||||
df = pd.read_csv('rowers/tests/testdata/uhfull.csv')
|
df = pl.read_csv('rowers/tests/testdata/uhfull.csv')
|
||||||
|
|
||||||
id = kwargs['id']
|
id = kwargs['id']
|
||||||
|
|
||||||
@@ -308,13 +309,19 @@ def mocked_getrowdata_uh(*args, **kwargs): # pragma: no cover
|
|||||||
|
|
||||||
return df, row
|
return df, row
|
||||||
|
|
||||||
|
|
||||||
def mocked_getsmallrowdata_uh(*args, **kwargs): # pragma: no cover
|
def mocked_getsmallrowdata_uh(*args, **kwargs): # pragma: no cover
|
||||||
|
df = pl.read_csv('rowers/tests/testdata/uhfull.csv')
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def mocked_getsmallrowdata_uh_pd(*args, **kwargs): # pragma: no cover
|
||||||
df = pd.read_csv('rowers/tests/testdata/uhfull.csv')
|
df = pd.read_csv('rowers/tests/testdata/uhfull.csv')
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def mocked_getsmallrowdata_forfusion(*args, **kwargs):
|
def mocked_getsmallrowdata_forfusion(*args, **kwargs):
|
||||||
df = pd.read_csv('rowers/tests/testdata/getrowdata_mock.csv')
|
df = pl.read_csv('rowers/tests/testdata/getrowdata_mock.csv')
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
@@ -335,6 +342,11 @@ def mocked_getsmallrowdata_db(*args, **kwargs):
|
|||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
def mocked_read_data(*args, **kwargs):
|
||||||
|
df = pl.read_csv('rowers/tests/testdata/colsfromdb.csv')
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
def mocked_getsmallrowdata_db_updatecp(*args, **kwargs): # pragma: no cover
|
def mocked_getsmallrowdata_db_updatecp(*args, **kwargs): # pragma: no cover
|
||||||
df = pd.read_csv('rowers/tests/testdata/colsfromdb.csv')
|
df = pd.read_csv('rowers/tests/testdata/colsfromdb.csv')
|
||||||
|
|
||||||
@@ -351,8 +363,8 @@ def mocked_getsmallrowdata_db_water(*args, **kwargs): # pragma: no cover
|
|||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def mocked_getsmallrowdata_db_wps(*args, **kwargs): # pragma: no cover
|
def mocked_read_data_wps(*args, **kwargs): # pragma: no cover
|
||||||
df = pd.read_csv('rowers/tests/testdata/driveenergies.csv')
|
df = pl.read_csv('rowers/tests/testdata/driveenergies.csv')
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
@@ -384,7 +396,7 @@ def mocked_read_cols_df_sql(*args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
def mock_workout_summaries(*args, **kwargs):
|
def mock_workout_summaries(*args, **kwargs):
|
||||||
df = pd.read_csv('rowers/tests/testdata/workout_summaries.csv')
|
df = pl.read_csv('rowers/tests/testdata/workout_summaries.csv')
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def mocked_read_df_cols_sql_multi(ids, columns, convertnewtons=True): # pragma: no cover
|
def mocked_read_df_cols_sql_multi(ids, columns, convertnewtons=True): # pragma: no cover
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ from nose.tools import assert_true
|
|||||||
from mock import Mock, patch
|
from mock import Mock, patch
|
||||||
#from minimocktest import MockTestCase
|
#from minimocktest import MockTestCase
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import polars as pl
|
||||||
import rowers.c2stuff as c2stuff
|
import rowers.c2stuff as c2stuff
|
||||||
|
|
||||||
import rowers.rojabo_stuff as rojabo_stuff
|
import rowers.rojabo_stuff as rojabo_stuff
|
||||||
|
|||||||
@@ -43,10 +43,10 @@ class ListWorkoutTest(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.dataprep.myqueue')
|
@patch('rowers.dataprep.myqueue')
|
||||||
def test_list_workouts(self, mocked_sqlalchemy,
|
def test_list_workouts(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mocked_myqueue):
|
mocked_myqueue):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
@@ -169,8 +169,8 @@ class ForcecurveTest(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect = mocked_getempowerdata_db)
|
@patch('rowers.dataprep.read_data',side_effect = mocked_read_data)
|
||||||
def test_forcecurve_plot(self, mocked_getsmallrowdata_db):
|
def test_forcecurve_plot(self, mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password = self.password)
|
login = self.c.login(username=self.u.username, password = self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -296,9 +296,9 @@ class WorkoutCompareTestNew(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_workouts_compare(self, mocked_sqlalchemy,
|
def test_workouts_compare(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -309,9 +309,9 @@ class WorkoutCompareTestNew(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_workouts_compare_submit(self, mocked_sqlalchemy,
|
def test_workouts_compare_submit(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -398,9 +398,9 @@ class WorkoutBoxPlotTestNew(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_workouts_boxplot(self, mocked_sqlalchemy,
|
def test_workouts_boxplot(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -411,9 +411,9 @@ class WorkoutBoxPlotTestNew(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_workouts_boxplot_submit(self, mocked_sqlalchemy,
|
def test_workouts_boxplot_submit(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -499,9 +499,9 @@ class WorkoutHistoTestNew(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_workouts_histo(self, mocked_sqlalchemy,
|
def test_workouts_histo(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -512,9 +512,9 @@ class WorkoutHistoTestNew(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_workouts_histo_submit(self, mocked_sqlalchemy,
|
def test_workouts_histo_submit(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -600,9 +600,9 @@ class History(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_workouts_history(self, mocked_sqlalchemy,
|
def test_workouts_history(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -618,9 +618,9 @@ class History(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_workouts_history_submit(self, mocked_sqlalchemy,
|
def test_workouts_history_submit(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -713,9 +713,9 @@ class GoldMedalScores(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_workouts_goldmedalscores(self, mocked_sqlalchemy,
|
def test_workouts_goldmedalscores(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
ws = Workout.objects.filter(rankingpiece=True)
|
ws = Workout.objects.filter(rankingpiece=True)
|
||||||
self.assertEqual(ws.count(),2)
|
self.assertEqual(ws.count(),2)
|
||||||
@@ -729,9 +729,9 @@ class GoldMedalScores(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_workouts_goldmedalscores_submit(self, mocked_sqlalchemy,
|
def test_workouts_goldmedalscores_submit(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -795,9 +795,9 @@ class WorkoutFlexallTestNew(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_workouts_flexall(self, mocked_sqlalchemy,
|
def test_workouts_flexall(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -808,9 +808,9 @@ class WorkoutFlexallTestNew(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_workouts_flexall_submit(self, mocked_sqlalchemy,
|
def test_workouts_flexall_submit(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -903,9 +903,9 @@ class WorkoutStatsTestNew(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_workouts_stats(self, mocked_sqlalchemy,
|
def test_workouts_stats(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -916,11 +916,11 @@ class WorkoutStatsTestNew(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
@patch('rowers.dataprep.read_cols_df_sql', side_effect=mocked_read_cols_df_sql)
|
@patch('rowers.dataprep.read_cols_df_sql', side_effect=mocked_read_cols_df_sql)
|
||||||
def test_analysis_data(self,
|
def test_analysis_data(self,
|
||||||
mocked_sqlalchemy,
|
mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mocked_read_cols_df_sql,
|
mocked_read_cols_df_sql,
|
||||||
):
|
):
|
||||||
|
|
||||||
@@ -979,11 +979,11 @@ class WorkoutStatsTestNew(TestCase):
|
|||||||
script, div = comparisondata(workouts,options)
|
script, div = comparisondata(workouts,options)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
@patch('rowers.dataprep.read_cols_df_sql', side_effect=mocked_read_cols_df_sql)
|
@patch('rowers.dataprep.read_cols_df_sql', side_effect=mocked_read_cols_df_sql)
|
||||||
def test_analysis_data2(self,
|
def test_analysis_data2(self,
|
||||||
mocked_sqlalchemy,
|
mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mocked_read_cols_df_sql,
|
mocked_read_cols_df_sql,
|
||||||
):
|
):
|
||||||
|
|
||||||
@@ -1042,11 +1042,11 @@ class WorkoutStatsTestNew(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
@patch('rowers.dataprep.read_cols_df_sql', side_effect=mocked_read_cols_df_sql)
|
@patch('rowers.dataprep.read_cols_df_sql', side_effect=mocked_read_cols_df_sql)
|
||||||
def test_analysis_data2(self,
|
def test_analysis_data2(self,
|
||||||
mocked_sqlalchemy,
|
mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mocked_read_cols_df_sql,
|
mocked_read_cols_df_sql,
|
||||||
):
|
):
|
||||||
|
|
||||||
@@ -1120,9 +1120,9 @@ class WorkoutStatsTestNew(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_workouts_stats_submit(self, mocked_sqlalchemy,
|
def test_workouts_stats_submit(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -1241,9 +1241,9 @@ class MarkerPerformanceTest(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_create_marker_workouts(self, mocked_sqlalchemy,
|
def test_create_marker_workouts(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -1257,8 +1257,8 @@ class MarkerPerformanceTest(TestCase):
|
|||||||
|
|
||||||
self.assertRedirects(response, expected_url=expected_url, status_code=302,target_status_code=200)
|
self.assertRedirects(response, expected_url=expected_url, status_code=302,target_status_code=200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_uh)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_getsmallrowdata_uh)
|
||||||
def test_trainingzones_view(self,mocked_getsmallrowdata_db):
|
def test_trainingzones_view(self,mocked_getsmallrowdata_uh):
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -1326,9 +1326,9 @@ class MarkerPerformanceTest(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_performancemanager_view(self, mocked_sqlalchemy,
|
def test_performancemanager_view(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -1356,36 +1356,6 @@ class MarkerPerformanceTest(TestCase):
|
|||||||
response = self.c.post(url,form_data)
|
response = self.c.post(url,form_data)
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
|
||||||
def test_ranking_view2(self, mocked_sqlalchemy,
|
|
||||||
mocked_getsmallrowdata_db):
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
|
||||||
self.assertTrue(login)
|
|
||||||
|
|
||||||
startdate = (self.user_workouts[0].startdatetime-datetime.timedelta(days=3)).date()
|
|
||||||
enddate = (self.user_workouts[0].startdatetime+datetime.timedelta(days=3)).date()
|
|
||||||
|
|
||||||
url = reverse('rankings_view2')
|
|
||||||
response = self.c.get(url)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
form_data = {
|
|
||||||
'startdate':startdate.strftime("%Y-%m-%d"),
|
|
||||||
'enddate': enddate.strftime("%Y-%m-%d"),
|
|
||||||
'doform': True,
|
|
||||||
'dofatigue': True,
|
|
||||||
'metricchoice':'rscore',
|
|
||||||
'modelchoice': 'coggan',
|
|
||||||
'daterange': '',
|
|
||||||
}
|
|
||||||
form = DateRangeForm(form_data)
|
|
||||||
if not form.is_valid():
|
|
||||||
print(form.errors)
|
|
||||||
self.assertTrue(form.is_valid())
|
|
||||||
|
|
||||||
response = self.c.post(url,form_data)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
class AlertTest(TestCase):
|
class AlertTest(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -1443,9 +1413,9 @@ class AlertTest(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.alerts.getsmallrowdata_db')
|
@patch('rowers.alerts.read_data')
|
||||||
def test_alerts(self, mocked_sqlalchemy,
|
def test_alerts(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
login = self.c.login(username=self.u.username,password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ class OwnApi(TestCase):
|
|||||||
response = self.c.get(url)
|
response = self.c.get(url)
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
|
with patch('rowers.dataprep.read_data') as mock_read_data:
|
||||||
|
mock_read_data.return_value = pl.read_csv('rowers/tests/testdata/colsfromdb.csv')
|
||||||
url = reverse('strokedatajson',kwargs={'id':w.id})
|
url = reverse('strokedatajson',kwargs={'id':w.id})
|
||||||
|
|
||||||
request = self.factory.get(url)
|
request = self.factory.get(url)
|
||||||
@@ -67,10 +69,11 @@ class OwnApi(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
# response must be json
|
# response must be json
|
||||||
strokedata = json.loads(response.content)
|
|
||||||
df = pd.DataFrame(strokedata)
|
|
||||||
|
|
||||||
self.assertFalse(df.empty)
|
strokedata = json.loads(response.content)
|
||||||
|
df = pl.from_dict(strokedata)
|
||||||
|
|
||||||
|
self.assertFalse(df.is_empty())
|
||||||
|
|
||||||
form_data = {
|
form_data = {
|
||||||
"distance": [23, 46, 48],
|
"distance": [23, 46, 48],
|
||||||
@@ -119,13 +122,16 @@ class OwnApi(TestCase):
|
|||||||
request = self.factory.get(url)
|
request = self.factory.get(url)
|
||||||
request.user = self.u
|
request.user = self.u
|
||||||
force_authenticate(request, user=self.u)
|
force_authenticate(request, user=self.u)
|
||||||
|
with patch('rowers.dataprep.read_data') as mock_read_data:
|
||||||
|
mock_read_data.return_value = pl.read_csv('rowers/tests/testdata/colsfromdb.csv')
|
||||||
response = strokedatajson_v2(request,id=w.id)
|
response = strokedatajson_v2(request,id=w.id)
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
# response must be json
|
# response must be json
|
||||||
strokedata = json.loads(response.content)
|
strokedata = json.loads(response.content)
|
||||||
df = pd.DataFrame(strokedata)
|
df = pl.from_dicts(strokedata['data'])
|
||||||
self.assertFalse(df.empty)
|
|
||||||
|
self.assertFalse(df.is_empty())
|
||||||
|
|
||||||
|
|
||||||
form_data = {
|
form_data = {
|
||||||
|
|||||||
@@ -484,54 +484,10 @@ class AsyncTaskTests(TestCase):
|
|||||||
res = tasks.handle_c2_import_stroke_data(c2token,c2id,workoutid,starttimeunix,csvfilename)
|
res = tasks.handle_c2_import_stroke_data(c2token,c2id,workoutid,starttimeunix,csvfilename)
|
||||||
self.assertEqual(res,1)
|
self.assertEqual(res,1)
|
||||||
|
|
||||||
@patch('rowers.tasks.grpc',side_effect=mocked_grpc)
|
|
||||||
@patch('rowers.tasks.send_template_email',side_effect=mocked_send_template_email)
|
|
||||||
def test_handle_otwsetpower(self,mocked_send_template_email,mocked_grpc):
|
|
||||||
f1 = get_random_file(filename='rowers/tests/testdata/sprintervals.csv')['filename']
|
|
||||||
boattype = '1x'
|
|
||||||
boatclass = 'water'
|
|
||||||
coastalbrand = 'other'
|
|
||||||
weightvalue = 80.
|
|
||||||
first_name = self.u.first_name
|
|
||||||
last_name = self.u.last_name
|
|
||||||
email = self.u.email
|
|
||||||
workoutid = self.wwater.id
|
|
||||||
job = fakerequest()
|
|
||||||
|
|
||||||
res = tasks.handle_otwsetpower(f1,boattype,boatclass,coastalbrand,
|
|
||||||
weightvalue,first_name,last_name,email,workoutid,
|
|
||||||
jobkey='23')
|
|
||||||
|
|
||||||
self.assertEqual(res,1)
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
def test_handle_updateergcp(self,mocked_sqlalchemy):
|
|
||||||
f1 = get_random_file()['filename']
|
|
||||||
res = tasks.handle_updateergcp(1,[f1])
|
|
||||||
self.assertEqual(res,1)
|
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_handle_updatecp(self,mocked_getsmallrowdata_db_updatecp):
|
def test_handle_update_wps(self,mocked_read_data_wps):
|
||||||
rower_id = 1
|
|
||||||
workoutids = [1]
|
|
||||||
res = tasks.handle_updatecp(rower_id,workoutids)
|
|
||||||
self.assertEqual(res,1)
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
|
||||||
def test_handle_setcp(self,mocked_getsmallrowdata_db_setcp):
|
|
||||||
strokesdf = pd.read_csv('rowers/tests/testdata/uhfull.csv')
|
|
||||||
filename = 'rowers/tests/testdata/temp/pq.gz'
|
|
||||||
workoutids = 1
|
|
||||||
res = tasks.handle_setcp(strokesdf,filename,1)
|
|
||||||
self.assertEqual(res,1)
|
|
||||||
try:
|
|
||||||
os.remove(filename)
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
|
||||||
def test_handle_update_wps(self,mocked_getsmallrowdata_db_wps):
|
|
||||||
ids = [1,2,3]
|
ids = [1,2,3]
|
||||||
|
|
||||||
result = tasks.handle_update_wps(self.r.id,['water'],ids,mode='water')
|
result = tasks.handle_update_wps(self.r.id,['water'],ids,mode='water')
|
||||||
|
|||||||
+33
-178
@@ -62,10 +62,10 @@ class ListWorkoutTest(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.dataprep.myqueue')
|
@patch('rowers.dataprep.myqueue')
|
||||||
def test_list_workouts(self, mocked_sqlalchemy,
|
def test_list_workouts(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mocked_myqueue):
|
mocked_myqueue):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
@@ -87,10 +87,10 @@ class ListWorkoutTest(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.dataprep.myqueue')
|
@patch('rowers.dataprep.myqueue')
|
||||||
def test_bulk_workouts(self, mocked_sqlalchemy,
|
def test_bulk_workouts(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mocked_myqueue):
|
mocked_myqueue):
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
@@ -234,9 +234,9 @@ class WorkoutViewTest(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.middleware.myqueue')
|
@patch('rowers.middleware.myqueue')
|
||||||
def test_forcecurve(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
|
def test_forcecurve(self, mocked_sqlalchemy, mocked_read_data,
|
||||||
mocked_myqueue):
|
mocked_myqueue):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -255,9 +255,9 @@ class WorkoutViewTest(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.middleware.myqueue')
|
@patch('rowers.middleware.myqueue')
|
||||||
def test_resample(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
|
def test_resample(self, mocked_sqlalchemy, mocked_read_data,
|
||||||
mocked_myqueue):
|
mocked_myqueue):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -283,9 +283,9 @@ class WorkoutViewTest(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@pytest.mark.django_db(transaction=True)
|
@pytest.mark.django_db(transaction=True)
|
||||||
def test_joins(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
def test_joins(self, mocked_sqlalchemy, mocked_read_data):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -350,10 +350,10 @@ class WorkoutViewTest(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.weather.requests.get', side_effect=mocked_requests)
|
@patch('rowers.weather.requests.get', side_effect=mocked_requests)
|
||||||
def test_waterworkout_view(self,
|
def test_waterworkout_view(self,
|
||||||
mocked_sqlalchemy, mocked_getsmallrowdata_db, mocked_requests):
|
mocked_sqlalchemy, mocked_read_data, mocked_requests):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -362,22 +362,6 @@ class WorkoutViewTest(TestCase):
|
|||||||
response = self.c.get(url)
|
response = self.c.get(url)
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
url = reverse('workout_downloadmetar_view',kwargs={
|
|
||||||
'id': encoder.encode_hex(self.wwater.id),
|
|
||||||
'airportcode': 'LKHO'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
response = self.c.get(url,follow=True)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
url = reverse('workout_downloadwind_view',kwargs={
|
|
||||||
'id': encoder.encode_hex(self.wwater.id),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
response = self.c.get(url,follow=True)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
# Stacked Flex Chart
|
# Stacked Flex Chart
|
||||||
url = reverse('workout_flexchart_stacked_view',kwargs={
|
url = reverse('workout_flexchart_stacked_view',kwargs={
|
||||||
@@ -422,8 +406,8 @@ class WorkoutViewTest(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_smoothen(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
def test_smoothen(self, mocked_sqlalchemy, mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -459,125 +443,12 @@ class WorkoutViewTest(TestCase):
|
|||||||
status_code=302,target_status_code=200)
|
status_code=302,target_status_code=200)
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
|
||||||
def test_windform(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
|
||||||
self.assertTrue(login)
|
|
||||||
|
|
||||||
|
|
||||||
url = reverse('workout_wind_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})
|
|
||||||
|
|
||||||
response = self.c.get(url)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
form_data = {
|
|
||||||
'dist1':1000,
|
|
||||||
'dist2':2000,
|
|
||||||
'vwind1':2.0,
|
|
||||||
'vwind2':1.4,
|
|
||||||
'windunit':'m',
|
|
||||||
'winddirection1': 0,
|
|
||||||
'winddirection2': 90,
|
|
||||||
}
|
|
||||||
|
|
||||||
form = UpdateWindForm(form_data)
|
|
||||||
self.assertTrue(form.is_valid())
|
|
||||||
|
|
||||||
response = self.c.post(url,form_data)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
|
||||||
def test_streamform(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
|
||||||
self.assertTrue(login)
|
|
||||||
|
|
||||||
|
|
||||||
url = reverse('workout_stream_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})
|
|
||||||
|
|
||||||
response = self.c.get(url)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
form_data = {
|
|
||||||
'dist1':1000,
|
|
||||||
'dist2':2000,
|
|
||||||
'stream1':2.0,
|
|
||||||
'stream2':1.4,
|
|
||||||
'streamunit':'m',
|
|
||||||
}
|
|
||||||
|
|
||||||
form = UpdateStreamForm(form_data)
|
|
||||||
self.assertTrue(form.is_valid())
|
|
||||||
|
|
||||||
response = self.c.post(url,form_data)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.middleware.myqueue')
|
def test_commentview(self, mocked_sqlalchemy, mocked_read_data):
|
||||||
def test_setpowerform(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
|
|
||||||
mocked_myqueue):
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
|
||||||
self.assertTrue(login)
|
|
||||||
|
|
||||||
url = reverse('instroke_view',kwargs={'id':encoder.encode_hex(self.winstroke.id)})
|
|
||||||
|
|
||||||
response = self.c.get(url)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
rowdata = rowingdata.rowingdata(csvfile=self.winstroke.csvfilename)
|
|
||||||
instrokemetrics = rowdata.get_instroke_columns()
|
|
||||||
|
|
||||||
self.assertTrue(len(instrokemetrics)>0)
|
|
||||||
|
|
||||||
url = reverse('instroke_chart',
|
|
||||||
kwargs={
|
|
||||||
'id':encoder.encode_hex(self.winstroke.id),
|
|
||||||
'metric':instrokemetrics[0],
|
|
||||||
})
|
|
||||||
url2 = reverse(self.r.defaultlandingpage,kwargs={'id':encoder.encode_hex(self.winstroke.id)})
|
|
||||||
response = self.c.get(url)
|
|
||||||
self.assertRedirects(response,
|
|
||||||
expected_url=url2,
|
|
||||||
status_code=302,target_status_code=200)
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
|
||||||
def test_setpowerform(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
|
||||||
self.assertTrue(login)
|
|
||||||
|
|
||||||
|
|
||||||
url = reverse('workout_otwsetpower_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})
|
|
||||||
|
|
||||||
response = self.c.get(url)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
form_data = {
|
|
||||||
'quick_calc':True,
|
|
||||||
'boattype': '1x',
|
|
||||||
'weightvalue': 75.0,
|
|
||||||
'boatbrand':'maas',
|
|
||||||
}
|
|
||||||
|
|
||||||
form = AdvancedWorkoutForm(form_data)
|
|
||||||
self.assertTrue(form.is_valid())
|
|
||||||
|
|
||||||
response = self.c.post(url,form_data,follow=True)
|
|
||||||
self.assertEqual(response.status_code,200)
|
|
||||||
|
|
||||||
expected_url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})
|
|
||||||
|
|
||||||
self.assertRedirects(response,
|
|
||||||
expected_url=expected_url,
|
|
||||||
status_code=302,target_status_code=200)
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
|
||||||
def test_commentview(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -602,8 +473,8 @@ class WorkoutViewTest(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_mapview(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
def test_mapview(self, mocked_sqlalchemy, mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -614,9 +485,9 @@ class WorkoutViewTest(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def notworking_test_workout_image(self, mocked_sqlalchemy,
|
def notworking_test_workout_image(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -642,10 +513,10 @@ class WorkoutViewTest(TestCase):
|
|||||||
status_code=302,target_status_code=200)
|
status_code=302,target_status_code=200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
|
@patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
|
||||||
@pytest.mark.django_db(transaction=True)
|
@pytest.mark.django_db(transaction=True)
|
||||||
def test_workout_split(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
|
def test_workout_split(self, mocked_sqlalchemy, mocked_read_data,
|
||||||
mocked_getrowdata_db):
|
mocked_getrowdata_db):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
@@ -670,9 +541,9 @@ class WorkoutViewTest(TestCase):
|
|||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
|
@patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_forfusion)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_getsmallrowdata_forfusion)
|
||||||
def test_workout_fusion(self, mocked_sqlalchemy, mocked_getrowdata_db,
|
def test_workout_fusion(self, mocked_sqlalchemy, mocked_getrowdata_db,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -699,27 +570,11 @@ class WorkoutViewTest(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
|
|
||||||
def test_remove_power_view(self):
|
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
|
||||||
self.assertTrue(login)
|
|
||||||
|
|
||||||
url = reverse('remove_power_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})
|
|
||||||
url2 = reverse(self.r.defaultlandingpage,
|
|
||||||
kwargs={
|
|
||||||
'id':encoder.encode_hex(self.wwater.id)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
response = self.c.get(url)
|
|
||||||
self.assertRedirects(response,
|
|
||||||
expected_url=url2,
|
|
||||||
status_code=302,
|
|
||||||
target_status_code=200
|
|
||||||
)
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.dataprep.get_video_data',side_effect=mocked_videodata)
|
@patch('rowers.dataprep.get_video_data',side_effect=mocked_videodata)
|
||||||
def test_workout_video_view(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
|
def test_workout_video_view(self, mocked_sqlalchemy, mocked_read_data,
|
||||||
mocked_videodata):
|
mocked_videodata):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -779,9 +634,9 @@ class WorkoutViewTest(TestCase):
|
|||||||
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
|
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('rowers.dataprep.get_video_data',side_effect=mocked_videodata)
|
@patch('rowers.dataprep.get_video_data',side_effect=mocked_videodata)
|
||||||
def test_workout_video_view_erg(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
|
def test_workout_video_view_erg(self, mocked_sqlalchemy, mocked_read_data,
|
||||||
mocked_videodata):
|
mocked_videodata):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -843,7 +698,7 @@ class WorkoutViewTest(TestCase):
|
|||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
|
@patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
|
||||||
@patch('rowers.dataprep.get_video_data',side_effect=mocked_videodata)
|
@patch('rowers.dataprep.get_video_data',side_effect=mocked_videodata)
|
||||||
def test_video_selectworkout(self, mocked_sqlalchemy, mocked_getsmallrowdata_db,
|
def test_video_selectworkout(self, mocked_sqlalchemy, mocked_read_data,
|
||||||
mocked_videodata):
|
mocked_videodata):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
@@ -874,8 +729,8 @@ class WorkoutViewTest(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_editsummaryview(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
def test_editsummaryview(self, mocked_sqlalchemy, mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -940,8 +795,8 @@ class WorkoutViewTest(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_workout_delete(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
|
def test_workout_delete(self, mocked_sqlalchemy, mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
|
|||||||
@@ -166,65 +166,3 @@ class CPChartTest(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.fetchcperg', side_effect = mocked_fetchcperg)
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
|
||||||
def test_rankingpieces(self, mocked_fetchcperg, mocked_sqlalchemy):
|
|
||||||
url = '/rowers/ote-bests2/'
|
|
||||||
|
|
||||||
login = self.c.login(username=self.u.username,password=self.password)
|
|
||||||
self.assertTrue(login)
|
|
||||||
|
|
||||||
# update_records(url='rowers/tests/c2worldrecords.html',verbose=False)
|
|
||||||
|
|
||||||
form_data = {
|
|
||||||
'name': faker.word(),
|
|
||||||
'date': nu.date(),
|
|
||||||
'timezone': 'UTC',
|
|
||||||
'duration': '00:02:00.0',
|
|
||||||
'starttime': '10:01:43',
|
|
||||||
'distance': 500,
|
|
||||||
'workouttype': 'rower',
|
|
||||||
'boattype': '1x',
|
|
||||||
'weightcategory': 'hwt',
|
|
||||||
'adaptiveclass': 'None',
|
|
||||||
'notes': faker.text(),
|
|
||||||
'rankingpiece': True,
|
|
||||||
'duplicate': False,
|
|
||||||
'avghr': '160',
|
|
||||||
'avgpwr': 0,
|
|
||||||
'avgspm': 40,
|
|
||||||
}
|
|
||||||
|
|
||||||
url2 = '/rowers/workout/addmanual/'
|
|
||||||
|
|
||||||
response = self.c.post(url2, form_data, follow=True)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
form_data['distance'] = 100
|
|
||||||
form_data['duration'] = '00:00:18.5'
|
|
||||||
|
|
||||||
response = self.c.post(url2, form_data, follow=True)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
form_data['distance'] = 2000
|
|
||||||
form_data['duration'] = '00:06:56.5'
|
|
||||||
response = self.c.post(url2, form_data, follow=True)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
form_data['distance'] = 5000
|
|
||||||
form_data['duration'] = '00:20:48.0'
|
|
||||||
response = self.c.post(url2, form_data, follow=True)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
form_data['distance'] = 6000
|
|
||||||
form_data['duration'] = '00:22:17.6'
|
|
||||||
response = self.c.post(url2, form_data, follow=True)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
form_data['distance'] = 10000
|
|
||||||
form_data['duration'] = '00:38:16.5'
|
|
||||||
response = self.c.post(url2, form_data, follow=True)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
response = self.c.get(url)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ class EmailUpload(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_uploadapi(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_uploadapi(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
form_data = {
|
form_data = {
|
||||||
'title': 'test',
|
'title': 'test',
|
||||||
'workouttype':'rower',
|
'workouttype':'rower',
|
||||||
@@ -108,8 +108,8 @@ class EmailUpload(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_uploadapi2(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_uploadapi2(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
form_data = {"secret": settings.UPLOAD_SERVICE_SECRET,
|
form_data = {"secret": settings.UPLOAD_SERVICE_SECRET,
|
||||||
"user": 1,
|
"user": 1,
|
||||||
"file": 'media/mailbox_attachments/colin3.csv',
|
"file": 'media/mailbox_attachments/colin3.csv',
|
||||||
@@ -140,8 +140,8 @@ class EmailUpload(TestCase):
|
|||||||
|
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_uploadapi3(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_uploadapi3(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
form_data = {
|
form_data = {
|
||||||
'title': 'test',
|
'title': 'test',
|
||||||
@@ -167,8 +167,8 @@ class EmailUpload(TestCase):
|
|||||||
self.assertEqual(w.notes,'aap noot mies')
|
self.assertEqual(w.notes,'aap noot mies')
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_uploadapi_credentials(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_uploadapi_credentials(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
form_data = {
|
form_data = {
|
||||||
'title': 'test',
|
'title': 'test',
|
||||||
'workouttype':'rower',
|
'workouttype':'rower',
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ class WorkoutViewTest(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_flexchart_water(self, mocked_sqlalechemy, mocked_getsmallrowdata_db):
|
def test_flexchart_water(self, mocked_sqlalechemy, mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -151,8 +151,8 @@ class WorkoutViewTest(TestCase):
|
|||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_flexchart_erg(self, mocked_sqlalechemy, mocked_getsmallrowdata_db):
|
def test_flexchart_erg(self, mocked_sqlalechemy, mocked_read_data):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
|
|||||||
@@ -720,8 +720,8 @@ class NKObjects(DjangoTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_nk_intervals(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_nk_intervals(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
with open('rowers/tests/testdata/carlos_workout.json','r') as f:
|
with open('rowers/tests/testdata/carlos_workout.json','r') as f:
|
||||||
workoutdata = json.load(f)
|
workoutdata = json.load(f)
|
||||||
with open('rowers/tests/testdata/carlos_strokes.json','r') as f:
|
with open('rowers/tests/testdata/carlos_strokes.json','r') as f:
|
||||||
@@ -817,10 +817,10 @@ class NKObjects(DjangoTestCase):
|
|||||||
@patch('rowers.integrations.nk.requests.get', side_effect=mocked_requests)
|
@patch('rowers.integrations.nk.requests.get', side_effect=mocked_requests)
|
||||||
@patch('rowers.integrations.nk.requests.post', side_effect=mocked_requests)
|
@patch('rowers.integrations.nk.requests.post', side_effect=mocked_requests)
|
||||||
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_nk_import(self, mock_get, mock_post,
|
def test_nk_import(self, mock_get, mock_post,
|
||||||
mocked_session,
|
mocked_session,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
integration = NKIntegration(self.u)
|
integration = NKIntegration(self.u)
|
||||||
result = integration.token_refresh()
|
result = integration.token_refresh()
|
||||||
@@ -854,10 +854,10 @@ class NKObjects(DjangoTestCase):
|
|||||||
@patch('rowers.integrations.nk.requests.get', side_effect=mocked_requests)
|
@patch('rowers.integrations.nk.requests.get', side_effect=mocked_requests)
|
||||||
@patch('rowers.integrations.nk.requests.post', side_effect=mocked_requests)
|
@patch('rowers.integrations.nk.requests.post', side_effect=mocked_requests)
|
||||||
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_nk_import_task(self, mock_get, mock_post,
|
def test_nk_import_task(self, mock_get, mock_post,
|
||||||
mocked_session,
|
mocked_session,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
alldata = {
|
alldata = {
|
||||||
469: {'elapsedTime': 3901900,
|
469: {'elapsedTime': 3901900,
|
||||||
'totalDistanceImp': 0,
|
'totalDistanceImp': 0,
|
||||||
@@ -904,10 +904,10 @@ class NKObjects(DjangoTestCase):
|
|||||||
@patch('rowers.integrations.nk.requests.get', side_effect=mocked_requests)
|
@patch('rowers.integrations.nk.requests.get', side_effect=mocked_requests)
|
||||||
@patch('rowers.integrations.nk.requests.post', side_effect=mocked_requests)
|
@patch('rowers.integrations.nk.requests.post', side_effect=mocked_requests)
|
||||||
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_nk_import_impeller(self, mock_get, mock_post,
|
def test_nk_import_impeller(self, mock_get, mock_post,
|
||||||
mocked_session,
|
mocked_session,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
integration = NKIntegration(self.u)
|
integration = NKIntegration(self.u)
|
||||||
result = integration.token_refresh()
|
result = integration.token_refresh()
|
||||||
@@ -1083,9 +1083,9 @@ class RP3Objects(DjangoTestCase):
|
|||||||
|
|
||||||
@patch('rowers.integrations.rp3.requests.get', side_effect=mocked_requests)
|
@patch('rowers.integrations.rp3.requests.get', side_effect=mocked_requests)
|
||||||
@patch('rowers.integrations.rp3.requests.post', side_effect=mocked_requests)
|
@patch('rowers.integrations.rp3.requests.post', side_effect=mocked_requests)
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_rp3_import(self, mock_get, mockpost,
|
def test_rp3_import(self, mock_get, mockpost,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
response = self.c.get('/rowers/workout/rp3import/591621',follow=True)
|
response = self.c.get('/rowers/workout/rp3import/591621',follow=True)
|
||||||
|
|
||||||
@@ -1268,9 +1268,9 @@ class StravaObjects(DjangoTestCase):
|
|||||||
|
|
||||||
@patch('rowers.utils.requests.get', side_effect=mocked_requests)
|
@patch('rowers.utils.requests.get', side_effect=mocked_requests)
|
||||||
@patch('rowers.integrations.strava.requests.post', side_effect=mocked_requests)
|
@patch('rowers.integrations.strava.requests.post', side_effect=mocked_requests)
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
def test_strava_import(self, mock_get, mock_post,
|
def test_strava_import(self, mock_get, mock_post,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
|
|
||||||
response = self.c.get('/rowers/workout/stravaimport/12',follow=True)
|
response = self.c.get('/rowers/workout/stravaimport/12',follow=True)
|
||||||
expected_url = reverse('workout_import_view',kwargs={'source':'strava'})
|
expected_url = reverse('workout_import_view',kwargs={'source':'strava'})
|
||||||
@@ -1307,7 +1307,7 @@ class STObjects(DjangoTestCase):
|
|||||||
|
|
||||||
|
|
||||||
self.r.sporttrackstoken = '12'
|
self.r.sporttrackstoken = '12'
|
||||||
self.r.sporttracksrefreshtoken = '12'
|
self.r.sporttroacksrefreshtoken = '12'
|
||||||
self.r.sporttrackstokenexpirydate = arrow.get(datetime.datetime.now()+datetime.timedelta(days=1)).datetime
|
self.r.sporttrackstokenexpirydate = arrow.get(datetime.datetime.now()+datetime.timedelta(days=1)).datetime
|
||||||
self.r.save()
|
self.r.save()
|
||||||
|
|
||||||
|
|||||||
@@ -51,16 +51,16 @@ class InteractiveChartTest(TestCase):
|
|||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_interactive_chart1(self, mocked_sqlalchemy,mocked_read_df_sql,
|
def test_interactive_chart1(self, mocked_sqlalchemy,mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
res = iplots.interactive_chart(self.wote.id)
|
res = iplots.interactive_chart(self.wote.id)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_interactive_chart2(self, mocked_sqlalchemy,mocked_read_df_sql,
|
def test_interactive_chart2(self, mocked_sqlalchemy,mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
res = iplots.interactive_chart(self.wote.id,promember=1)
|
res = iplots.interactive_chart(self.wote.id,promember=1)
|
||||||
|
|
||||||
|
|
||||||
@@ -80,52 +80,52 @@ class InteractiveChartTest(TestCase):
|
|||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_interactive_chart7(self, mocked_sqlalchemy,mocked_read_df_sql,
|
def test_interactive_chart7(self, mocked_sqlalchemy,mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
res = iplots.interactive_flex_chart2(self.wote.id,self.r,promember=0,
|
res = iplots.interactive_flex_chart2(self.wote.id,self.r,promember=0,
|
||||||
xparam='time',
|
xparam='time',
|
||||||
yparam1='pace',yparam2='spm',mode='water')
|
yparam1='pace',yparam2='spm',mode='water')
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_interactive_chart8(self, mocked_sqlalchemy,mocked_read_df_sql,
|
def test_interactive_chart8(self, mocked_sqlalchemy,mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
||||||
promember=0,xparam='distance',
|
promember=0,xparam='distance',
|
||||||
yparam1='pace',yparam2='spm',mode='water')
|
yparam1='pace',yparam2='spm',mode='water')
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_interactive_chart9(self, mocked_sqlalchemy,mocked_read_df_sql,
|
def test_interactive_chart9(self, mocked_sqlalchemy,mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
||||||
promember=1,xparam='time',
|
promember=1,xparam='time',
|
||||||
yparam1='pace',yparam2='hr',mode='water')
|
yparam1='pace',yparam2='hr',mode='water')
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_interactive_chart10(self, mocked_sqlalchemy,mocked_read_df_sql,
|
def test_interactive_chart10(self, mocked_sqlalchemy,mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
||||||
promember=1,xparam='distance',
|
promember=1,xparam='distance',
|
||||||
yparam1='pace',yparam2='hr',mode='water')
|
yparam1='pace',yparam2='hr',mode='water')
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_interactive_chart11(self, mocked_sqlalchemy,mocked_read_df_sql,
|
def test_interactive_chart11(self, mocked_sqlalchemy,mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
||||||
promember=1,xparam='time',
|
promember=1,xparam='time',
|
||||||
yparam1='pace',yparam2='spm',mode='water')
|
yparam1='pace',yparam2='spm',mode='water')
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_interactive_chart12(self, mocked_sqlalchemy,mocked_read_df_sql,
|
def test_interactive_chart12(self, mocked_sqlalchemy,mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
res = iplots.interactive_flex_chart2(self.wote.id,self.r,
|
||||||
promember=1,
|
promember=1,
|
||||||
xparam='distance',
|
xparam='distance',
|
||||||
|
|||||||
@@ -911,8 +911,8 @@ class PermissionsViewTests(TestCase):
|
|||||||
|
|
||||||
## Coach can upload on behalf of athlete - if team allows
|
## Coach can upload on behalf of athlete - if team allows
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_coach_edit_athlete_upload(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_coach_edit_athlete_upload(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
self.rbasic.team.add(self.teamcoach)
|
self.rbasic.team.add(self.teamcoach)
|
||||||
self.rbasic.coachinggroups.add(self.coachinggroup)
|
self.rbasic.coachinggroups.add(self.coachinggroup)
|
||||||
|
|
||||||
@@ -957,8 +957,8 @@ class PermissionsViewTests(TestCase):
|
|||||||
|
|
||||||
## Coach can upload on behalf of athlete - if team allows
|
## Coach can upload on behalf of athlete - if team allows
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_coach_edit_athlete_uploadnot(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_coach_edit_athlete_uploadnot(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
self.rbasic.team.add(self.teamcoach)
|
self.rbasic.team.add(self.teamcoach)
|
||||||
|
|
||||||
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
|
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
|
||||||
@@ -1168,8 +1168,8 @@ class PermissionsViewTests(TestCase):
|
|||||||
|
|
||||||
## Self Coach cannot upload on behalf of athlete
|
## Self Coach cannot upload on behalf of athlete
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_plan_edit_athlete_upload(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_plan_edit_athlete_upload(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
self.rpro.team.add(self.teamplan)
|
self.rpro.team.add(self.teamplan)
|
||||||
|
|
||||||
login = self.c.login(username=self.uplan2.username, password=self.uplan2password)
|
login = self.c.login(username=self.uplan2.username, password=self.uplan2password)
|
||||||
@@ -1291,8 +1291,8 @@ class PermissionsViewTests(TestCase):
|
|||||||
|
|
||||||
## Self Coach cannot upload on behalf of athlete
|
## Self Coach cannot upload on behalf of athlete
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_plan_edit_athlete_upload(self,mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_plan_edit_athlete_upload(self,mocked_sqlalchemy,mocked_read_data):
|
||||||
self.rpro.team.add(self.teamplan)
|
self.rpro.team.add(self.teamplan)
|
||||||
|
|
||||||
login = self.c.login(username=self.uplan2.username, password=self.uplan2password)
|
login = self.c.login(username=self.uplan2.username, password=self.uplan2password)
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ class PermissionsViewTests(TestCase):
|
|||||||
@patch('rowers.integrations.c2.C2Integration.open')
|
@patch('rowers.integrations.c2.C2Integration.open')
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('requests.get',side_effect=mocked_requests)
|
@patch('requests.get',side_effect=mocked_requests)
|
||||||
@patch('requests.post',side_effect=mocked_requests)
|
@patch('requests.post',side_effect=mocked_requests)
|
||||||
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
||||||
@@ -228,7 +228,7 @@ class PermissionsViewTests(TestCase):
|
|||||||
mock_c2open,
|
mock_c2open,
|
||||||
mocked_sqlalchemy,
|
mocked_sqlalchemy,
|
||||||
mocked_read_df_sql,
|
mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mock_get,
|
mock_get,
|
||||||
mock_post,
|
mock_post,
|
||||||
mocked_get_video_data,
|
mocked_get_video_data,
|
||||||
@@ -253,7 +253,7 @@ class PermissionsViewTests(TestCase):
|
|||||||
@patch('rowers.integrations.c2.C2Integration.open')
|
@patch('rowers.integrations.c2.C2Integration.open')
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('requests.get',side_effect=mocked_requests)
|
@patch('requests.get',side_effect=mocked_requests)
|
||||||
@patch('requests.post',side_effect=mocked_requests)
|
@patch('requests.post',side_effect=mocked_requests)
|
||||||
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
||||||
@@ -263,7 +263,7 @@ class PermissionsViewTests(TestCase):
|
|||||||
mock_c2open,
|
mock_c2open,
|
||||||
mocked_sqlalchemy,
|
mocked_sqlalchemy,
|
||||||
mocked_read_df_sql,
|
mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mock_get,
|
mock_get,
|
||||||
mock_post,
|
mock_post,
|
||||||
mocked_get_video_data,
|
mocked_get_video_data,
|
||||||
@@ -335,7 +335,7 @@ class PermissionsViewTests(TestCase):
|
|||||||
@patch('rowers.integrations.c2.C2Integration.open')
|
@patch('rowers.integrations.c2.C2Integration.open')
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('requests.get',side_effect=mocked_requests)
|
@patch('requests.get',side_effect=mocked_requests)
|
||||||
@patch('requests.post',side_effect=mocked_requests)
|
@patch('requests.post',side_effect=mocked_requests)
|
||||||
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
||||||
@@ -345,7 +345,7 @@ class PermissionsViewTests(TestCase):
|
|||||||
mock_c2open,
|
mock_c2open,
|
||||||
mocked_sqlalchemy,
|
mocked_sqlalchemy,
|
||||||
mocked_read_df_sql,
|
mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mock_get,
|
mock_get,
|
||||||
mock_post,
|
mock_post,
|
||||||
mocked_get_video_data,
|
mocked_get_video_data,
|
||||||
@@ -418,7 +418,7 @@ class PermissionsViewTests(TestCase):
|
|||||||
@patch('rowers.integrations.c2.C2Integration.open')
|
@patch('rowers.integrations.c2.C2Integration.open')
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('requests.get',side_effect=mocked_requests)
|
@patch('requests.get',side_effect=mocked_requests)
|
||||||
@patch('requests.post',side_effect=mocked_requests)
|
@patch('requests.post',side_effect=mocked_requests)
|
||||||
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
||||||
@@ -428,7 +428,7 @@ class PermissionsViewTests(TestCase):
|
|||||||
mock_c2open,
|
mock_c2open,
|
||||||
mocked_sqlalchemy,
|
mocked_sqlalchemy,
|
||||||
mocked_read_df_sql,
|
mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mock_get,
|
mock_get,
|
||||||
mock_post,
|
mock_post,
|
||||||
mocked_get_video_data,
|
mocked_get_video_data,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from django.db import transaction
|
|||||||
nu = datetime.datetime.now()
|
nu = datetime.datetime.now()
|
||||||
import datetime
|
import datetime
|
||||||
import pytz
|
import pytz
|
||||||
|
import polars as pl
|
||||||
|
|
||||||
# interactive plots
|
# interactive plots
|
||||||
from rowers import interactiveplots
|
from rowers import interactiveplots
|
||||||
@@ -581,7 +582,7 @@ class DataPrepTests(TestCase):
|
|||||||
age = dataprep.calculate_age(born,today=today)
|
age = dataprep.calculate_age(born,today=today)
|
||||||
self.assertEqual(age,49)
|
self.assertEqual(age,49)
|
||||||
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_uh)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_getsmallrowdata_uh)
|
||||||
def test_goldmedalstandard(self,mocked_getsmallrowdata_uh):
|
def test_goldmedalstandard(self,mocked_getsmallrowdata_uh):
|
||||||
maxvalue, delta = dataprep.calculate_goldmedalstandard(self.r,self.wuh_otw)
|
maxvalue, delta = dataprep.calculate_goldmedalstandard(self.r,self.wuh_otw)
|
||||||
records = CalcAgePerformance.objects.filter(
|
records = CalcAgePerformance.objects.filter(
|
||||||
@@ -596,8 +597,8 @@ class DataPrepTests(TestCase):
|
|||||||
result = getagegrouprecord(25)
|
result = getagegrouprecord(25)
|
||||||
self.assertEqual(int(result),590)
|
self.assertEqual(int(result),590)
|
||||||
|
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_uh)
|
@patch('rowers.dataprep.getsmallrowdata_pd',side_effect=mocked_getsmallrowdata_uh_pd)
|
||||||
def test_get_videodata(self,mocked_getsmallrowdata_uh):
|
def test_get_videodata(self,mocked_getsmallrowdata_uh_pd):
|
||||||
data, metrics, maxtime = dataprep.get_video_data(self.wuh_otw)
|
data, metrics, maxtime = dataprep.get_video_data(self.wuh_otw)
|
||||||
|
|
||||||
self.assertEqual(len(data),9)
|
self.assertEqual(len(data),9)
|
||||||
@@ -659,7 +660,7 @@ class InteractivePlotTests(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def test_interactive_hr_piechart(self):
|
def test_interactive_hr_piechart(self):
|
||||||
df = pd.read_csv('rowers/tests/testdata/getrowdata_mock.csv')
|
df = pl.read_csv('rowers/tests/testdata/getrowdata_mock.csv')
|
||||||
|
|
||||||
script, div = interactiveplots.interactive_hr_piechart(df, self.r,'')
|
script, div = interactiveplots.interactive_hr_piechart(df, self.r,'')
|
||||||
self.assertFalse(len(script)==0)
|
self.assertFalse(len(script)==0)
|
||||||
@@ -672,7 +673,8 @@ class InteractivePlotTests(TestCase):
|
|||||||
self.assertFalse(len(div)==0)
|
self.assertFalse(len(div)==0)
|
||||||
|
|
||||||
def test_interactive_boxchart(self):
|
def test_interactive_boxchart(self):
|
||||||
df = pd.read_csv('rowers/tests/testdata/boxplotdata.csv')
|
df = pl.read_csv('rowers/tests/testdata/boxplotdata.csv')
|
||||||
|
df = df.with_columns(pl.col("date").str.to_datetime("%Y-%m-%d"))
|
||||||
|
|
||||||
script, div = interactiveplots.interactive_boxchart(df, 'spm')
|
script, div = interactiveplots.interactive_boxchart(df, 'spm')
|
||||||
|
|
||||||
@@ -685,12 +687,12 @@ class InteractivePlotTests(TestCase):
|
|||||||
|
|
||||||
startdate = workouts[0].date-datetime.timedelta(days=5)
|
startdate = workouts[0].date-datetime.timedelta(days=5)
|
||||||
enddate = workouts2[0].date+datetime.timedelta(days=5)
|
enddate = workouts2[0].date+datetime.timedelta(days=5)
|
||||||
script, div = interactiveplots.interactive_activitychart(workouts,startdate,enddate)
|
script, div = interactiveplots.interactive_activitychart2(workouts,startdate,enddate)
|
||||||
self.assertFalse(len(script)==0)
|
self.assertFalse(len(script)==0)
|
||||||
self.assertFalse(len(div)==0)
|
self.assertFalse(len(div)==0)
|
||||||
|
|
||||||
def test_interactive_otwcpchart(self):
|
def test_interactive_otwcpchart(self):
|
||||||
df = pd.read_csv('rowers/tests/testdata/otwcp.csv')
|
df = pl.read_csv('rowers/tests/testdata/otwcp.csv')
|
||||||
|
|
||||||
script, div, p1, ratio, message = interactiveplots.interactive_otwcpchart(df,r=self.r,cpfit='data')
|
script, div, p1, ratio, message = interactiveplots.interactive_otwcpchart(df,r=self.r,cpfit='data')
|
||||||
self.assertFalse(len(script)==0)
|
self.assertFalse(len(script)==0)
|
||||||
@@ -701,9 +703,9 @@ class InteractivePlotTests(TestCase):
|
|||||||
self.assertFalse(len(div)==0)
|
self.assertFalse(len(div)==0)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_interactive_chart(self, mocked_sqlalchemy,
|
def test_interactive_chart(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
workout = Workout.objects.filter(user=self.r,workouttype__in=mytypes.rowtypes)[0]
|
workout = Workout.objects.filter(user=self.r,workouttype__in=mytypes.rowtypes)[0]
|
||||||
id = workout.id
|
id = workout.id
|
||||||
|
|
||||||
@@ -733,12 +735,12 @@ class InteractivePlotTests(TestCase):
|
|||||||
self.assertFalse(len(div)==0)
|
self.assertFalse(len(div)==0)
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||||
def test_interactive_flexchart_stacked(self, mocked_sqlalchemy,
|
def test_interactive_flexchart_stacked(self, mocked_sqlalchemy,
|
||||||
mocked_getsmallrowdata_db):
|
mocked_read_data):
|
||||||
workout = Workout.objects.filter(user=self.r,workouttype__in=mytypes.rowtypes)[0]
|
workout = Workout.objects.filter(user=self.r,workouttype__in=mytypes.rowtypes)[0]
|
||||||
id = workout.id
|
id = workout.id
|
||||||
|
|
||||||
script, div, js_res, css_res, comment = interactiveplots.interactive_flexchart_stacked(id,self.r)
|
script, div = interactiveplots.interactive_flexchart_stacked(id,self.r)
|
||||||
self.assertFalse(len(script)==0)
|
self.assertFalse(len(script)==0)
|
||||||
self.assertFalse(len(div)==0)
|
self.assertFalse(len(div)==0)
|
||||||
|
|||||||
@@ -71,9 +71,10 @@ class ForceUnits(TestCase):
|
|||||||
w = Workout.objects.get(id=1)
|
w = Workout.objects.get(id=1)
|
||||||
self.assertEqual(w.forceunit,'lbs')
|
self.assertEqual(w.forceunit,'lbs')
|
||||||
|
|
||||||
df = dataprep.getsmallrowdata_db(['averageforce'],ids=[13])
|
df = dataprep.read_data(['averageforce'],ids=[13])
|
||||||
|
df = dataprep.remove_nulls_pl(df)
|
||||||
average_N = int(df['averageforce'].mean())
|
average_N = int(df['averageforce'].mean())
|
||||||
self.assertEqual(average_N,398)
|
self.assertEqual(average_N,400)
|
||||||
|
|
||||||
data = dataprep.read_df_sql(13)
|
data = dataprep.read_df_sql(13)
|
||||||
average_N = int(data['averageforce'].mean())
|
average_N = int(data['averageforce'].mean())
|
||||||
@@ -119,9 +120,10 @@ class ForceUnits(TestCase):
|
|||||||
w = Workout.objects.get(id=13)
|
w = Workout.objects.get(id=13)
|
||||||
self.assertEqual(w.forceunit,'N')
|
self.assertEqual(w.forceunit,'N')
|
||||||
|
|
||||||
df = dataprep.getsmallrowdata_db(['averageforce'],ids=[13])
|
df = dataprep.read_data(['averageforce'],ids=[13])
|
||||||
|
df = dataprep.remove_nulls_pl(df)
|
||||||
average_N = int(df['averageforce'].mean())
|
average_N = int(df['averageforce'].mean())
|
||||||
self.assertEqual(average_N,263)
|
self.assertEqual(average_N,271)
|
||||||
|
|
||||||
def test_upload_speedcoach_colin(self):
|
def test_upload_speedcoach_colin(self):
|
||||||
login = self.c.login(username=self.u.username, password=self.password)
|
login = self.c.login(username=self.u.username, password=self.password)
|
||||||
@@ -155,9 +157,10 @@ class ForceUnits(TestCase):
|
|||||||
w = Workout.objects.get(id=13)
|
w = Workout.objects.get(id=13)
|
||||||
self.assertEqual(w.forceunit,'N')
|
self.assertEqual(w.forceunit,'N')
|
||||||
|
|
||||||
df = dataprep.getsmallrowdata_db(['averageforce'],ids=[13])
|
df = dataprep.read_data(['averageforce'],ids=[13])
|
||||||
|
df = dataprep.remove_nulls_pl(df)
|
||||||
average_N = int(df['averageforce'].mean())
|
average_N = int(df['averageforce'].mean())
|
||||||
self.assertEqual(average_N,105)
|
self.assertEqual(average_N,122)
|
||||||
|
|
||||||
@override_settings(TESTING=True)
|
@override_settings(TESTING=True)
|
||||||
class TestForceUnit(TestCase):
|
class TestForceUnit(TestCase):
|
||||||
@@ -206,7 +209,7 @@ class TestForceUnit(TestCase):
|
|||||||
|
|
||||||
rowdata = dataprep.rdata('rowers/tests/testdata/PainsledForce.csv')
|
rowdata = dataprep.rdata('rowers/tests/testdata/PainsledForce.csv')
|
||||||
df = dataprep.dataprep(rowdata.df)
|
df = dataprep.dataprep(rowdata.df)
|
||||||
#df = dataprep.getsmallrowdata_db(['averageforce'],ids=[w[0].id],doclean=False,
|
#df = dataprep.read_data(['averageforce'],ids=[w[0].id],doclean=False,
|
||||||
# compute=False)
|
# compute=False)
|
||||||
try:
|
try:
|
||||||
average_N = int(df['averageforce'].mean())
|
average_N = int(df['averageforce'].mean())
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ class ViewTest(TestCase):
|
|||||||
self.nu = datetime.datetime.now()
|
self.nu = datetime.datetime.now()
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_upload_view_sled(self, mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_upload_view_sled(self, mocked_sqlalchemy,mocked_read_data):
|
||||||
login = self.c.login(username='john',password='koeinsloot')
|
login = self.c.login(username='john',password='koeinsloot')
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
@@ -74,10 +74,6 @@ class ViewTest(TestCase):
|
|||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
response = self.c.get('/rowers/workout/'+encoded1+'/histo/', form_data, follow=True)
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
@@ -124,8 +120,8 @@ class ViewTest(TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.read_data',side_effect=mocked_read_data)
|
||||||
def test_upload_view_sled_bg(self, mocked_sqlalchemy,mocked_getsmallrowdata_db):
|
def test_upload_view_sled_bg(self, mocked_sqlalchemy,mocked_read_data):
|
||||||
login = self.c.login(username='john',password='koeinsloot')
|
login = self.c.login(username='john',password='koeinsloot')
|
||||||
self.assertTrue(login)
|
self.assertTrue(login)
|
||||||
|
|
||||||
|
|||||||
@@ -79,11 +79,6 @@ class URLTests(TestCase):
|
|||||||
'/rowers/502/',
|
'/rowers/502/',
|
||||||
'/rowers/about/',
|
'/rowers/about/',
|
||||||
'/rowers/workout/addmanual/',
|
'/rowers/workout/addmanual/',
|
||||||
'/rowers/agegroupcp/30/',
|
|
||||||
'/rowers/agegroupcp/30/1/',
|
|
||||||
'/rowers/agegrouprecords/male/hwt/',
|
|
||||||
'/rowers/agegrouprecords/male/hwt/2000m/',
|
|
||||||
'/rowers/agegrouprecords/male/hwt/30min/',
|
|
||||||
'/rowers/ajax_agegroup/45/hwt/male/1/',
|
'/rowers/ajax_agegroup/45/hwt/male/1/',
|
||||||
'/rowers/analysis/',
|
'/rowers/analysis/',
|
||||||
'/rowers/analysis/user/1/',
|
'/rowers/analysis/user/1/',
|
||||||
@@ -122,8 +117,6 @@ class URLTests(TestCase):
|
|||||||
'/rowers/me/workflowconfig2/',
|
'/rowers/me/workflowconfig2/',
|
||||||
'/rowers/me/workflowconfig2/user/1/',
|
'/rowers/me/workflowconfig2/user/1/',
|
||||||
'/rowers/me/workflowdefault/',
|
'/rowers/me/workflowdefault/',
|
||||||
'/rowers/ote-bests2/',
|
|
||||||
'/rowers/ote-bests2/user/1/',
|
|
||||||
'/rowers/partners/',
|
'/rowers/partners/',
|
||||||
'/rowers/physics/',
|
'/rowers/physics/',
|
||||||
'/rowers/planrequired/',
|
'/rowers/planrequired/',
|
||||||
@@ -148,29 +141,23 @@ class URLTests(TestCase):
|
|||||||
'/rowers/workout/'+encoded1+'/addtimeplot/',
|
'/rowers/workout/'+encoded1+'/addtimeplot/',
|
||||||
'/rowers/workout/'+encoded1+'/addtimeplot2/',
|
'/rowers/workout/'+encoded1+'/addtimeplot2/',
|
||||||
'/rowers/workout/'+encoded1+'/comment/',
|
'/rowers/workout/'+encoded1+'/comment/',
|
||||||
'/rowers/workout/'+encoded1+'/darkskywind/',
|
|
||||||
'/rowers/workout/'+encoded1+'/data/',
|
'/rowers/workout/'+encoded1+'/data/',
|
||||||
'/rowers/workout/'+encoded1+'/edit/',
|
'/rowers/workout/'+encoded1+'/edit/',
|
||||||
'/rowers/workout/'+encoded1+'/editintervals/',
|
'/rowers/workout/'+encoded1+'/editintervals/',
|
||||||
'/rowers/workout/'+encoded1+'/flexchart/',
|
'/rowers/workout/'+encoded1+'/flexchart/',
|
||||||
'/rowers/workout/'+encoded1+'/forcecurve/',
|
'/rowers/workout/'+encoded1+'/forcecurve/',
|
||||||
'/rowers/workout/'+encoded1+'/get-thumbnails/',
|
'/rowers/workout/'+encoded1+'/get-thumbnails/',
|
||||||
'/rowers/workout/'+encoded1+'/histo/',
|
|
||||||
'/rowers/workout/'+encoded1+'/image/',
|
'/rowers/workout/'+encoded1+'/image/',
|
||||||
'/rowers/workout/'+encoded1+'/instroke/',
|
'/rowers/workout/'+encoded1+'/instroke/',
|
||||||
'/rowers/workout/'+encoded1+'/interactiveotwplot/',
|
|
||||||
'/rowers/workout/'+encoded1+'/map/',
|
'/rowers/workout/'+encoded1+'/map/',
|
||||||
'/rowers/workout/'+encoded1+'/otwsetpower/',
|
|
||||||
'/rowers/workout/'+encoded1+'/recalcsummary/',
|
'/rowers/workout/'+encoded1+'/recalcsummary/',
|
||||||
'/rowers/workout/'+encoded1+'/restore/',
|
'/rowers/workout/'+encoded1+'/restore/',
|
||||||
'/rowers/workout/'+encoded1+'/smoothenpace/',
|
'/rowers/workout/'+encoded1+'/smoothenpace/',
|
||||||
'/rowers/workout/'+encoded1+'/split/',
|
'/rowers/workout/'+encoded1+'/split/',
|
||||||
'/rowers/workout/'+encoded1+'/stats/',
|
'/rowers/workout/'+encoded1+'/stats/',
|
||||||
'/rowers/workout/'+encoded1+'/stream/',
|
|
||||||
'/rowers/workout/'+encoded1+'/undosmoothenpace/',
|
'/rowers/workout/'+encoded1+'/undosmoothenpace/',
|
||||||
'/rowers/workout/'+encoded1+'/unsubscribe/',
|
'/rowers/workout/'+encoded1+'/unsubscribe/',
|
||||||
'/rowers/workout/'+encoded1+'/view/',
|
'/rowers/workout/'+encoded1+'/view/',
|
||||||
'/rowers/workout/'+encoded1+'/wind/',
|
|
||||||
'/rowers/workout/'+encoded1+'/workflow/',
|
'/rowers/workout/'+encoded1+'/workflow/',
|
||||||
'/rowers/workout/fusion/'+encoded1+'/',
|
'/rowers/workout/fusion/'+encoded1+'/',
|
||||||
'/rowers/workout/upload/',
|
'/rowers/workout/upload/',
|
||||||
@@ -206,7 +193,7 @@ class URLTests(TestCase):
|
|||||||
@parameterized.expand(lijst)
|
@parameterized.expand(lijst)
|
||||||
@patch('rowers.dataprep.create_engine')
|
@patch('rowers.dataprep.create_engine')
|
||||||
@patch('rowers.dataprep.read_df_sql')
|
@patch('rowers.dataprep.read_df_sql')
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db')
|
@patch('rowers.dataprep.read_data')
|
||||||
@patch('requests.get',side_effect=mocked_requests)
|
@patch('requests.get',side_effect=mocked_requests)
|
||||||
@patch('requests.post',side_effect=mocked_requests)
|
@patch('requests.post',side_effect=mocked_requests)
|
||||||
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
@patch('rowers.dataprep.get_video_data',side_effect=mocked_get_video_data)
|
||||||
@@ -214,7 +201,7 @@ class URLTests(TestCase):
|
|||||||
def test_url_generator(self,url,expected,
|
def test_url_generator(self,url,expected,
|
||||||
mocked_sqlalchemy,
|
mocked_sqlalchemy,
|
||||||
mocked_read_df_sql,
|
mocked_read_df_sql,
|
||||||
mocked_getsmallrowdata_db,
|
mocked_read_data,
|
||||||
mock_get,
|
mock_get,
|
||||||
mock_post,
|
mock_post,
|
||||||
mocked_get_video_data,
|
mocked_get_video_data,
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -1,9 +1,7 @@
|
|||||||
,id,view,function,anonymous,anonymous_response,own,own_response,own_nonperm,member,member_response,member_nonperm,coachee,coachee_response,coachee_nonperm,is_staff,userid,workoutid,dotest,realtest,kwargs
|
,id,view,function,anonymous,anonymous_response,own,own_response,own_nonperm,member,member_response,member_nonperm,coachee,coachee_response,coachee_nonperm,is_staff,userid,workoutid,dotest,realtest,kwargs
|
||||||
0,0,workouts_summaries_email_view,sends summary excel with workouts list and links to data to user,TRUE,302,basic,200,302,FALSE,403,403,FALSE,403,403,FALSE,FALSE,FALSE,TRUE,TRUE,
|
0,0,workouts_summaries_email_view,sends summary excel with workouts list and links to data to user,TRUE,302,basic,200,302,FALSE,403,403,FALSE,403,403,FALSE,FALSE,FALSE,TRUE,TRUE,
|
||||||
1,1,rower_update_empower_view,updates old Empower Oarlock files (corrects Power bug),TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
1,1,rower_update_empower_view,updates old Empower Oarlock files (corrects Power bug),TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
||||||
2,2,agegroupcpview,needs age,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
|
||||||
3,4,ajax_agegrouprecords,gets age group records from C2 ,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
3,4,ajax_agegrouprecords,gets age group records from C2 ,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
5,6,agegrouprecordview,shows ergo age group records,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
|
||||||
6,7,workouts_view,workouts list,TRUE,302,basic,200,302,basic,200,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
|
6,7,workouts_view,workouts list,TRUE,302,basic,200,302,basic,200,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE,
|
||||||
7,8,virtualevents_view,virtual races list,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
7,8,virtualevents_view,virtual races list,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
||||||
8,9,virtualevent_create_view,create virtual event,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
8,9,virtualevent_create_view,create virtual event,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
||||||
@@ -31,7 +29,6 @@
|
|||||||
33,35,kill_async_job,kill job,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
33,35,kill_async_job,kill job,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
34,36,post_progress,post progress,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
34,36,post_progress,post progress,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
35,37,graphs_view,view charts,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE,
|
35,37,graphs_view,view charts,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE,
|
||||||
38,40,rankings_view2,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE,
|
|
||||||
41,43,cum_flex,flex all chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
41,43,cum_flex,flex all chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
42,44,analysis_view_data,redirects to analysis direct,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
42,44,analysis_view_data,redirects to analysis direct,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
||||||
43,47,cum_flex_data,flex all chart data (json),TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
43,47,cum_flex_data,flex all chart data (json),TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
@@ -43,7 +40,6 @@
|
|||||||
52,58,workout_toggle_ranking,toggle ranking,TRUE,302,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
52,58,workout_toggle_ranking,toggle ranking,TRUE,302,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
53,59,team_workout_upload_view,upload workout for team member,TRUE,302,coach,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
53,59,team_workout_upload_view,upload workout for team member,TRUE,302,coach,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
||||||
54,60,workout_upload_view,upload a workout,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
54,60,workout_upload_view,upload a workout,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE,
|
||||||
55,61,workout_histo_view,histogram ,TRUE,302,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
|
||||||
56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
57,63,workout_unsubscribe_view,unsubscribe from comments,TRUE,302,basic,200,302,basic,200,302,basic,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
57,63,workout_unsubscribe_view,unsubscribe from comments,TRUE,302,basic,200,302,basic,200,302,basic,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
58,64,workout_comment_view,comment on workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
58,64,workout_comment_view,comment on workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
@@ -57,17 +53,11 @@
|
|||||||
67,73,instroke_view,Create in stroke chart,TRUE,403,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
67,73,instroke_view,Create in stroke chart,TRUE,403,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
68,74,workout_stats_view,View Workout Stats,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
68,74,workout_stats_view,View Workout Stats,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
69,75,workout_data_view,shows the detailed data for a workout,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
69,75,workout_data_view,shows the detailed data for a workout,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
70,76,workout_otwsetpower_view,set weight and start offline OTW power calculations,TRUE,403,pro,200,302,pro,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
|
||||||
71,77,workout_otwpowerplot_view,generates OTW power chart,TRUE,200,basic,200,200,basic,200,200,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
|
||||||
72,78,workout_wind_view,set wind,TRUE,403,pro,200,302,pro,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
|
||||||
73,79,workout_uploadimage_view,upload image,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
73,79,workout_uploadimage_view,upload image,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
74,80,virtualevent_compare_view,compare workouts from a virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
74,80,virtualevent_compare_view,compare workouts from a virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
75,81,virtualevent_uploadimage_view,upload image to virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
75,81,virtualevent_uploadimage_view,upload image to virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
76,82,virtualevent_setlogo_view,set logo of virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
76,82,virtualevent_setlogo_view,set logo of virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
77,83,logo_delete_view,delete logo,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
77,83,logo_delete_view,delete logo,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE,
|
||||||
78,84,workout_downloadwind_view,download Wind,TRUE,403,pro,302,302,pro,403,403,coach,302,403,FALSE,FALSE,TRUE,FALSE,FALSE,
|
|
||||||
79,85,workout_downloadmetar_view,download METAR,TRUE,403,pro,200,302,pro,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,FALSE,
|
|
||||||
80,86,workout_stream_view,edit stream (redirects as no data in test suite),TRUE,403,pro,200,302,pro,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
|
||||||
81,87,workout_summary_edit_view,edit workout summary,TRUE,302,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
81,87,workout_summary_edit_view,edit workout summary,TRUE,302,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
82,88,workout_summary_restore_view,restore workout summary,TRUE,403,basic,302,403,basic,403,403,coach,302,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
82,88,workout_summary_restore_view,restore workout summary,TRUE,403,basic,302,403,basic,403,403,coach,302,403,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
83,89,workout_split_view,split workout,TRUE,403,pro,200,302,pro,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
83,89,workout_split_view,split workout,TRUE,403,pro,200,302,pro,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE,
|
||||||
|
|||||||
|
+2
-23
@@ -273,19 +273,13 @@ urlpatterns = [
|
|||||||
re_path(r'^exportallworkouts/?/$', views.workouts_summaries_email_view,
|
re_path(r'^exportallworkouts/?/$', views.workouts_summaries_email_view,
|
||||||
name='workouts_summaries_email_view'),
|
name='workouts_summaries_email_view'),
|
||||||
path('failedjobs/', views.failed_queue_view, name='failed_queue_view'),
|
path('failedjobs/', views.failed_queue_view, name='failed_queue_view'),
|
||||||
|
path('sleep/', views.sleep_view, name='sleep_view'),
|
||||||
|
path('filmdeaths/', views.filmdeaths_view, name='filmdeaths_view'),
|
||||||
path('failedjobs/empty/', views.failed_queue_empty, name='failed_queue_empty'),
|
path('failedjobs/empty/', views.failed_queue_empty, name='failed_queue_empty'),
|
||||||
re_path('^failedjobs/(?P<id>\w+.*)/$',
|
re_path('^failedjobs/(?P<id>\w+.*)/$',
|
||||||
views.failed_job_view, name='failed_job_view'),
|
views.failed_job_view, name='failed_job_view'),
|
||||||
re_path(r'^update_empower/$', views.rower_update_empower_view,
|
re_path(r'^update_empower/$', views.rower_update_empower_view,
|
||||||
name='rower_update_empower_view'),
|
name='rower_update_empower_view'),
|
||||||
re_path(r'^agegroupcp/(?P<age>\d+)/$',
|
|
||||||
views.agegroupcpview, name='agegroupcpview'),
|
|
||||||
re_path(r'^agegroupcp/(?P<age>\d+)/user/(?P<userid>\d+)/$',
|
|
||||||
views.agegroupcpview, name='agegroupcpview'),
|
|
||||||
re_path(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)/$',
|
|
||||||
views.agegroupcpview, name='agegroupcpview'),
|
|
||||||
re_path(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)/user/(?P<userid>\d+)/$',
|
|
||||||
views.agegroupcpview, name='agegroupcpview'),
|
|
||||||
re_path(r'^ajax_agegroup/(?P<age>\d+)/(?P<weightcategory>\w+.*)/(?P<sex>\w+.*)/(?P<userid>\d+)/$',
|
re_path(r'^ajax_agegroup/(?P<age>\d+)/(?P<weightcategory>\w+.*)/(?P<sex>\w+.*)/(?P<userid>\d+)/$',
|
||||||
views.ajax_agegrouprecords, name='ajax_agegrouprecords'),
|
views.ajax_agegrouprecords, name='ajax_agegrouprecords'),
|
||||||
re_path(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<distance>\d+)m/$',
|
re_path(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<distance>\d+)m/$',
|
||||||
@@ -448,9 +442,6 @@ urlpatterns = [
|
|||||||
views.trainingzones_view_data, name="trainingzones_view_data"),
|
views.trainingzones_view_data, name="trainingzones_view_data"),
|
||||||
re_path(r'^trainingzones/data/$', views.trainingzones_view_data,
|
re_path(r'^trainingzones/data/$', views.trainingzones_view_data,
|
||||||
name="trainingzones_view_data"),
|
name="trainingzones_view_data"),
|
||||||
re_path(r'^ote-bests2/user/(?P<userid>\d+)/$',
|
|
||||||
views.rankings_view2, name='rankings_view2'),
|
|
||||||
re_path(r'^ote-bests2/$', views.rankings_view2, name='rankings_view2'),
|
|
||||||
re_path(r'^analysisdata/user/(?P<userid>\d+)/$', views.analysis_view_data,
|
re_path(r'^analysisdata/user/(?P<userid>\d+)/$', views.analysis_view_data,
|
||||||
name='analysis_view_data'),
|
name='analysis_view_data'),
|
||||||
re_path(r'^analysisdata/$', views.analysis_view_data,
|
re_path(r'^analysisdata/$', views.analysis_view_data,
|
||||||
@@ -475,8 +466,6 @@ urlpatterns = [
|
|||||||
views.workout_upload_view, name='workout_upload_view'),
|
views.workout_upload_view, name='workout_upload_view'),
|
||||||
re_path(r'^workout/upload/$', views.workout_upload_view,
|
re_path(r'^workout/upload/$', views.workout_upload_view,
|
||||||
name='workout_upload_view'),
|
name='workout_upload_view'),
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/histo/$', views.workout_histo_view,
|
|
||||||
name='workout_histo_view'),
|
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/forcecurve/$', views.workout_forcecurve_view,
|
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/forcecurve/$', views.workout_forcecurve_view,
|
||||||
name='workout_forcecurve_view'),
|
name='workout_forcecurve_view'),
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/forcecurve/(?P<analysis>\d+)/$', views.workout_forcecurve_view,
|
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/forcecurve/(?P<analysis>\d+)/$', views.workout_forcecurve_view,
|
||||||
@@ -513,14 +502,6 @@ urlpatterns = [
|
|||||||
name='workout_erase_column_view'),
|
name='workout_erase_column_view'),
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/zeropower-confirm/$', views.remove_power_confirm_view,
|
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/zeropower-confirm/$', views.remove_power_confirm_view,
|
||||||
name='remove_power_confirm_view'),
|
name='remove_power_confirm_view'),
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/zeropower/$', views.remove_power_view,
|
|
||||||
name='remove_power_view'),
|
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/otwsetpower/$',
|
|
||||||
views.workout_otwsetpower_view, name='workout_otwsetpower_view'),
|
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/interactiveotwplot/$',
|
|
||||||
views.workout_otwpowerplot_view, name='workout_otwpowerplot_view'),
|
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/wind/$',
|
|
||||||
views.workout_wind_view, name='workout_wind_view'),
|
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/image/$',
|
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/image/$',
|
||||||
views.workout_uploadimage_view, name='workout_uploadimage_view'),
|
views.workout_uploadimage_view, name='workout_uploadimage_view'),
|
||||||
re_path(r'^virtualevent/(?P<id>\d+)/compare/$',
|
re_path(r'^virtualevent/(?P<id>\d+)/compare/$',
|
||||||
@@ -543,8 +524,6 @@ urlpatterns = [
|
|||||||
views.workout_downloadwind_view, name='workout_downloadwind_view'),
|
views.workout_downloadwind_view, name='workout_downloadwind_view'),
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/metar/(?P<airportcode>\w+)/$',
|
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/metar/(?P<airportcode>\w+)/$',
|
||||||
views.workout_downloadmetar_view, name='workout_downloadmetar_view'),
|
views.workout_downloadmetar_view, name='workout_downloadmetar_view'),
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/stream/$',
|
|
||||||
views.workout_stream_view, name='workout_stream_view'),
|
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/editintervals/$', views.workout_summary_edit_view,
|
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/editintervals/$', views.workout_summary_edit_view,
|
||||||
name='workout_summary_edit_view'),
|
name='workout_summary_edit_view'),
|
||||||
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/restore/$',
|
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/restore/$',
|
||||||
|
|||||||
+20
-21
@@ -6,6 +6,8 @@ from django.utils import timezone
|
|||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import polars as pl
|
||||||
|
from polars.exceptions import ColumnNotFoundError
|
||||||
import colorsys
|
import colorsys
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import collections
|
import collections
|
||||||
@@ -155,12 +157,7 @@ def get_call():
|
|||||||
call1 = random.choice(coxes_calls)
|
call1 = random.choice(coxes_calls)
|
||||||
call2 = random.choice(info_calls)
|
call2 = random.choice(info_calls)
|
||||||
|
|
||||||
call = """<div id="id_sitready" class="successmessage">
|
call = """<div id="id_sitready" class="successmessage"><p>%s (%s)</p></div>""" % (call1, call2)
|
||||||
<p>
|
|
||||||
%s (%s)
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
""" % (call1, call2)
|
|
||||||
|
|
||||||
return call
|
return call
|
||||||
|
|
||||||
@@ -347,22 +344,22 @@ def isbreakthrough(delta, cpvalues, p0, p1, p2, p3, ratio):
|
|||||||
|
|
||||||
pwr *= ratio
|
pwr *= ratio
|
||||||
|
|
||||||
delta = delta.astype(int, errors='ignore').values
|
delta = delta.cast(pl.Int32)
|
||||||
cpvalues = cpvalues.astype(int, errors='ignore').values
|
cpvalues = cpvalues.cast(pl.Int32)
|
||||||
pwr = pwr.astype(int, errors='ignore').values
|
pwr = pwr.cast(pl.Int32)
|
||||||
|
|
||||||
res = np.sum(cpvalues > pwr+1)
|
btdf = pl.DataFrame({
|
||||||
res2 = np.sum(cpvalues > pwr2+1)
|
'delta': delta,
|
||||||
|
'cpvalues': cpvalues,
|
||||||
|
'pwr': pwr,
|
||||||
|
'pwr2': pwr2
|
||||||
|
})
|
||||||
|
|
||||||
btdf = pd.DataFrame(
|
res = btdf.select(pl.col("cpvalues")>pl.col("pwr")+1)['cpvalues'].sum()
|
||||||
{
|
res2 = btdf.select(pl.col("cpvalues")> pl.col("pwr2")+1)['cpvalues'].sum()
|
||||||
'delta': delta[cpvalues > pwr],
|
|
||||||
'cpvalues': cpvalues[cpvalues > pwr],
|
|
||||||
'pwr': pwr[cpvalues > pwr],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
btdf.sort_values('delta', axis=0, inplace=True)
|
btdf = btdf.filter(pl.col("cpvalues")>pl.col("pwr"))
|
||||||
|
btdf = btdf.sort('delta')
|
||||||
|
|
||||||
return res >= 1, btdf, res2 >= 1
|
return res >= 1, btdf, res2 >= 1
|
||||||
|
|
||||||
@@ -444,17 +441,19 @@ def wavg(group, avg_name, weight_name):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
d = group[avg_name]
|
d = group[avg_name]
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
return 0
|
return 0
|
||||||
try:
|
try:
|
||||||
w = group[weight_name]
|
w = group[weight_name]
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
return d.mean()
|
return d.mean()
|
||||||
try:
|
try:
|
||||||
return (d * w).sum() / w.sum()
|
return (d * w).sum() / w.sum()
|
||||||
except ZeroDivisionError: # pragma: no cover
|
except ZeroDivisionError: # pragma: no cover
|
||||||
return d.mean()
|
return d.mean()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
from string import Formatter
|
from string import Formatter
|
||||||
|
|
||||||
def totaltime_sec_to_string(totaltime, shorten=False):
|
def totaltime_sec_to_string(totaltime, shorten=False):
|
||||||
|
|||||||
+67
-598
@@ -296,7 +296,10 @@ def analysis_new(request,
|
|||||||
df = cpdata(tw, options)
|
df = cpdata(tw, options)
|
||||||
options['savedata'] = False
|
options['savedata'] = False
|
||||||
request.session['options'] = options
|
request.session['options'] = options
|
||||||
|
try:
|
||||||
response = HttpResponse(df.to_csv())
|
response = HttpResponse(df.to_csv())
|
||||||
|
except AttributeError:
|
||||||
|
response = HttpResponse(df.write_csv())
|
||||||
code = str(uuid4())
|
code = str(uuid4())
|
||||||
filename = code+'.csv'
|
filename = code+'.csv'
|
||||||
chartform.fields['savedata'].initial = False
|
chartform.fields['savedata'].initial = False
|
||||||
@@ -384,6 +387,9 @@ def trendflexdata(workouts, options, userid=0):
|
|||||||
datadf = dataprep.filter_df(datadf, 'driveneergy', workmax,
|
datadf = dataprep.filter_df(datadf, 'driveneergy', workmax,
|
||||||
largerthan=False)
|
largerthan=False)
|
||||||
|
|
||||||
|
if yparam == 'power':
|
||||||
|
datadf = dataprep.filter_df(datadf, 'power', 1, largerthan=True)
|
||||||
|
|
||||||
datadf.dropna(axis=0, how='any', inplace=True)
|
datadf.dropna(axis=0, how='any', inplace=True)
|
||||||
|
|
||||||
datemapping = {
|
datemapping = {
|
||||||
@@ -472,8 +478,8 @@ def trendflexdata(workouts, options, userid=0):
|
|||||||
'groupsize': groupsize,
|
'groupsize': groupsize,
|
||||||
})
|
})
|
||||||
|
|
||||||
if yparam == 'pace':
|
#if yparam == 'pace':
|
||||||
df['y'] = dataprep.paceformatsecs(df['y']/1.0e3)
|
# df['y'] = dataprep.paceformatsecs(df['y']/1.0e3)
|
||||||
|
|
||||||
aantal = len(df)
|
aantal = len(df)
|
||||||
|
|
||||||
@@ -568,7 +574,7 @@ def flexalldata(workouts, options):
|
|||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
columns = [xparam, yparam1, yparam2, 'spm', 'driveenergy', 'distance']
|
columns = [xparam, yparam1, yparam2, 'spm', 'driveenergy', 'distance']
|
||||||
ids = [int(w.id) for w in workouts]
|
ids = [int(w.id) for w in workouts]
|
||||||
df = dataprep.getsmallrowdata_db(columns, ids=ids,
|
df = dataprep.read_data(columns, ids=ids,
|
||||||
workstrokesonly=workstrokesonly,
|
workstrokesonly=workstrokesonly,
|
||||||
doclean=True,
|
doclean=True,
|
||||||
)
|
)
|
||||||
@@ -609,7 +615,7 @@ def histodata(workouts, options):
|
|||||||
if savedata: # pragma: no cover
|
if savedata: # pragma: no cover
|
||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
ids = [int(w.id) for w in workouts]
|
ids = [int(w.id) for w in workouts]
|
||||||
df = dataprep.getsmallrowdata_db([plotfield], ids=ids,
|
df = dataprep.read_data([plotfield], ids=ids,
|
||||||
workstrokesonly=workstrokesonly,
|
workstrokesonly=workstrokesonly,
|
||||||
doclean=True,
|
doclean=True,
|
||||||
)
|
)
|
||||||
@@ -625,6 +631,7 @@ def histodata(workouts, options):
|
|||||||
|
|
||||||
|
|
||||||
def cpdata(workouts, options):
|
def cpdata(workouts, options):
|
||||||
|
start = timezone.now()
|
||||||
userid = options['userid']
|
userid = options['userid']
|
||||||
cpfit = options['cpfit']
|
cpfit = options['cpfit']
|
||||||
cpoverlay = options['cpoverlay']
|
cpoverlay = options['cpoverlay']
|
||||||
@@ -635,7 +642,7 @@ def cpdata(workouts, options):
|
|||||||
delta, cpvalue, avgpower, workoutnames, urls = dataprep.fetchcp_new(
|
delta, cpvalue, avgpower, workoutnames, urls = dataprep.fetchcp_new(
|
||||||
r, workouts)
|
r, workouts)
|
||||||
|
|
||||||
powerdf = pd.DataFrame({
|
powerdf = pl.DataFrame({
|
||||||
'Delta': delta,
|
'Delta': delta,
|
||||||
'CP': cpvalue,
|
'CP': cpvalue,
|
||||||
'workout': workoutnames,
|
'workout': workoutnames,
|
||||||
@@ -644,16 +651,17 @@ def cpdata(workouts, options):
|
|||||||
|
|
||||||
savedata = options.get('savedata',False)
|
savedata = options.get('savedata',False)
|
||||||
if savedata: # pragma: no cover
|
if savedata: # pragma: no cover
|
||||||
return powerdf
|
return powerdf.to_pandas()
|
||||||
|
|
||||||
if powerdf.empty: # pragma: no cover
|
if powerdf.is_empty(): # pragma: no cover
|
||||||
return('', '<p>No valid data found</p>')
|
return('', '<p>No valid data found</p>')
|
||||||
|
|
||||||
|
|
||||||
powerdf = powerdf[powerdf['CP'] > 0]
|
powerdf = powerdf.lazy().filter(pl.col("CP")>0)
|
||||||
powerdf.dropna(axis=0, inplace=True)
|
powerdf = powerdf.sort(["Delta", "CP"], descending=[False, True])
|
||||||
powerdf.sort_values(['Delta', 'CP'], ascending=[1, 0], inplace=True)
|
powerdf = powerdf.unique(subset="Delta", keep="first")
|
||||||
powerdf.drop_duplicates(subset='Delta', keep='first', inplace=True)
|
powerdf = powerdf.fill_nan(None).drop_nulls()
|
||||||
|
powerdf = powerdf.collect()
|
||||||
|
|
||||||
rowername = r.user.first_name+" "+r.user.last_name
|
rowername = r.user.first_name+" "+r.user.last_name
|
||||||
|
|
||||||
@@ -880,7 +888,7 @@ def comparisondata(workouts, options):
|
|||||||
'time', 'pace', 'workoutstate',
|
'time', 'pace', 'workoutstate',
|
||||||
'workoutid']
|
'workoutid']
|
||||||
|
|
||||||
df = dataprep.getsmallrowdata_db(columns, ids=ids,
|
df = dataprep.read_data(columns, ids=ids,
|
||||||
workstrokesonly=workstrokesonly,
|
workstrokesonly=workstrokesonly,
|
||||||
doclean=True,
|
doclean=True,
|
||||||
)
|
)
|
||||||
@@ -923,28 +931,22 @@ def boxplotdata(workouts, options):
|
|||||||
ids = [w.id for w in workouts]
|
ids = [w.id for w in workouts]
|
||||||
|
|
||||||
# prepare data frame
|
# prepare data frame
|
||||||
datadf, extracols = dataprep.read_cols_df_sql(ids, fieldlist)
|
datadf = dataprep.read_data(fieldlist, ids)
|
||||||
|
|
||||||
datadf = dataprep.clean_df_stats(datadf, workstrokesonly=workstrokesonly)
|
datadf = dataprep.remove_nulls_pl(datadf)
|
||||||
|
|
||||||
datadf = dataprep.filter_df(datadf, 'spm', spmmin,
|
try:
|
||||||
largerthan=True)
|
datadf = datadf.filter(
|
||||||
datadf = dataprep.filter_df(datadf, 'spm', spmmax,
|
pl.col("spm")>spmmin,
|
||||||
largerthan=False)
|
pl.col("spm")<spmmax,
|
||||||
datadf = dataprep.filter_df(datadf, 'driveenergy', workmin,
|
pl.col("driveenergy")>workmin,
|
||||||
largerthan=True)
|
pl.col("driveenergy")<workmax,
|
||||||
datadf = dataprep.filter_df(datadf, 'driveneergy', workmax,
|
)
|
||||||
largerthan=False)
|
except ColumnNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
datadf.dropna(axis=0, how='any', inplace=True)
|
|
||||||
datadf = datadf[datadf['workoutid'].isin(ids) == True]
|
|
||||||
|
|
||||||
datadf['workoutid'].replace(datemapping, inplace=True)
|
datadf = datadf.with_columns((pl.col("workoutid").apply(lambda x: datemapping[x])).alias("date"))
|
||||||
datadf.rename(columns={"workoutid": "date"}, inplace=True)
|
|
||||||
|
|
||||||
datadf['date'] = pd.to_datetime(datadf['date'], errors='coerce')
|
|
||||||
datadf = datadf.dropna(subset=['date'])
|
|
||||||
datadf = datadf.sort_values(['date'])
|
|
||||||
|
|
||||||
if userid == 0: # pragma: no cover
|
if userid == 0: # pragma: no cover
|
||||||
extratitle = ''
|
extratitle = ''
|
||||||
@@ -954,7 +956,7 @@ def boxplotdata(workouts, options):
|
|||||||
|
|
||||||
savedata = options.get('savedata',False)
|
savedata = options.get('savedata',False)
|
||||||
if savedata: # pragma: no cover
|
if savedata: # pragma: no cover
|
||||||
return datadf
|
return datadf.to_pandas()
|
||||||
|
|
||||||
script, div = interactive_boxchart(datadf, plotfield,
|
script, div = interactive_boxchart(datadf, plotfield,
|
||||||
extratitle=extratitle,
|
extratitle=extratitle,
|
||||||
@@ -1149,9 +1151,6 @@ def trainingzones_view(request, userid=0):
|
|||||||
form = TrainingZonesForm({
|
form = TrainingZonesForm({
|
||||||
'startdate': startdate,
|
'startdate': startdate,
|
||||||
'enddate': enddate,
|
'enddate': enddate,
|
||||||
'zones': zones,
|
|
||||||
'dates': date_agg,
|
|
||||||
'yaxis': yaxis,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if request.method == 'POST': # pragma: no cover
|
if request.method == 'POST': # pragma: no cover
|
||||||
@@ -1160,9 +1159,6 @@ def trainingzones_view(request, userid=0):
|
|||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
startdate = form.cleaned_data['startdate']
|
startdate = form.cleaned_data['startdate']
|
||||||
enddate = form.cleaned_data['enddate']
|
enddate = form.cleaned_data['enddate']
|
||||||
zones = form.cleaned_data['zones']
|
|
||||||
date_agg = form.cleaned_data['dates']
|
|
||||||
yaxis = form.cleaned_data['yaxis']
|
|
||||||
|
|
||||||
if date_agg == 'week':
|
if date_agg == 'week':
|
||||||
startdate = startdate - datetime.timedelta(days=startdate.weekday())
|
startdate = startdate - datetime.timedelta(days=startdate.weekday())
|
||||||
@@ -1234,12 +1230,16 @@ def trainingzones_view_data(request, userid=0):
|
|||||||
request.GET.get('enddate'), "%Y-%m-%d")
|
request.GET.get('enddate'), "%Y-%m-%d")
|
||||||
enddate = arrow.get(enddate).datetime
|
enddate = arrow.get(enddate).datetime
|
||||||
|
|
||||||
data = get_zones_report(r, startdate, enddate,
|
if (enddate-startdate).days > 200:
|
||||||
|
date_agg = "month"
|
||||||
|
|
||||||
|
data = get_zones_report_pl(r, startdate, enddate,
|
||||||
trainingzones=zones, date_agg=date_agg, yaxis=yaxis)
|
trainingzones=zones, date_agg=date_agg, yaxis=yaxis)
|
||||||
|
|
||||||
script, div = interactive_zoneschart(
|
script, div = interactive_zoneschart2(
|
||||||
r, data, startdate, enddate, trainingzones=zones, date_agg=date_agg, yaxis=yaxis)
|
r, data, startdate, enddate, trainingzones=zones, date_agg=date_agg, yaxis=yaxis)
|
||||||
|
|
||||||
|
|
||||||
return JSONResponse({
|
return JSONResponse({
|
||||||
'script': script,
|
'script': script,
|
||||||
'div': div,
|
'div': div,
|
||||||
@@ -1384,547 +1384,6 @@ def ajax_agegrouprecords(request,
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Show ranking distances including predicted paces
|
|
||||||
@login_required()
|
|
||||||
@permission_required('rower.is_coach', fn=get_user_by_userid, raise_exception=True)
|
|
||||||
def rankings_view2(request, userid=0,
|
|
||||||
startdate=timezone.now()-datetime.timedelta(days=365),
|
|
||||||
enddate=timezone.now(),
|
|
||||||
deltadays=-1,
|
|
||||||
startdatestring="",
|
|
||||||
enddatestring=""):
|
|
||||||
|
|
||||||
if deltadays > 0: # pragma: no cover
|
|
||||||
startdate = enddate-datetime.timedelta(days=int(deltadays))
|
|
||||||
|
|
||||||
if startdatestring != "": # pragma: no cover
|
|
||||||
startdate = iso8601.parse_date(startdatestring)
|
|
||||||
|
|
||||||
if enddatestring != "": # pragma: no cover
|
|
||||||
enddate = iso8601.parse_date(enddatestring)
|
|
||||||
|
|
||||||
if enddate < startdate: # pragma: no cover
|
|
||||||
s = enddate
|
|
||||||
enddate = startdate
|
|
||||||
startdate = s
|
|
||||||
|
|
||||||
if userid == 0:
|
|
||||||
userid = request.user.id
|
|
||||||
else:
|
|
||||||
lastupdated = "1900-01-01"
|
|
||||||
|
|
||||||
promember = 0
|
|
||||||
r = getrequestrower(request, userid=userid)
|
|
||||||
theuser = r.user
|
|
||||||
|
|
||||||
wcdurations = []
|
|
||||||
wcpower = []
|
|
||||||
|
|
||||||
lastupdated = "1900-01-01"
|
|
||||||
userid = 0
|
|
||||||
if 'options' in request.session:
|
|
||||||
options = request.session['options']
|
|
||||||
try:
|
|
||||||
wcdurations = options['wcdurations']
|
|
||||||
wcpower = options['wcpower']
|
|
||||||
lastupdated = options['lastupdated']
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
userid = options['userid']
|
|
||||||
except KeyError: # pragma: no cover
|
|
||||||
userid = 0
|
|
||||||
else:
|
|
||||||
options = {}
|
|
||||||
|
|
||||||
lastupdatedtime = arrow.get(lastupdated).timestamp()
|
|
||||||
current_time = arrow.utcnow().timestamp()
|
|
||||||
|
|
||||||
deltatime_seconds = current_time - lastupdatedtime
|
|
||||||
recalc = False
|
|
||||||
if str(userid) != str(theuser) or deltatime_seconds > 3600:
|
|
||||||
recalc = True
|
|
||||||
options['lastupdated'] = arrow.utcnow().isoformat()
|
|
||||||
else: # pragma: no cover
|
|
||||||
recalc = False
|
|
||||||
|
|
||||||
options['userid'] = theuser.id
|
|
||||||
|
|
||||||
if r.birthdate:
|
|
||||||
age = calculate_age(r.birthdate)
|
|
||||||
else:
|
|
||||||
age = 0
|
|
||||||
|
|
||||||
agerecords = CalcAgePerformance.objects.filter(
|
|
||||||
age=age,
|
|
||||||
sex=r.sex,
|
|
||||||
weightcategory=r.weightcategory)
|
|
||||||
|
|
||||||
if len(agerecords) == 0:
|
|
||||||
recalc = True
|
|
||||||
wcpower = []
|
|
||||||
wcdurations = []
|
|
||||||
else:
|
|
||||||
wcdurations = []
|
|
||||||
wcpower = []
|
|
||||||
for record in agerecords:
|
|
||||||
wcdurations.append(record.duration)
|
|
||||||
wcpower.append(record.power)
|
|
||||||
|
|
||||||
options['wcpower'] = wcpower
|
|
||||||
options['wcdurations'] = wcdurations
|
|
||||||
if theuser:
|
|
||||||
options['userid'] = theuser.id
|
|
||||||
|
|
||||||
request.session['options'] = options
|
|
||||||
|
|
||||||
result = request.user.is_authenticated and ispromember(request.user)
|
|
||||||
if result:
|
|
||||||
promember = 1
|
|
||||||
|
|
||||||
# get all indoor rows in date range
|
|
||||||
|
|
||||||
# process form
|
|
||||||
if request.method == 'POST' and "daterange" in request.POST:
|
|
||||||
dateform = DateRangeForm(request.POST)
|
|
||||||
deltaform = DeltaDaysForm(request.POST)
|
|
||||||
if dateform.is_valid():
|
|
||||||
startdate = dateform.cleaned_data['startdate']
|
|
||||||
enddate = dateform.cleaned_data['enddate']
|
|
||||||
if startdate > enddate: # pragma: no cover
|
|
||||||
s = enddate
|
|
||||||
enddate = startdate
|
|
||||||
startdate = s
|
|
||||||
elif request.method == 'POST' and "datedelta" in request.POST: # pragma: no cover
|
|
||||||
deltaform = DeltaDaysForm(request.POST)
|
|
||||||
if deltaform.is_valid():
|
|
||||||
deltadays = deltaform.cleaned_data['deltadays']
|
|
||||||
if deltadays:
|
|
||||||
enddate = timezone.now()
|
|
||||||
startdate = enddate-datetime.timedelta(days=deltadays)
|
|
||||||
if startdate > enddate:
|
|
||||||
s = enddate
|
|
||||||
enddate = startdate
|
|
||||||
startdate = s
|
|
||||||
dateform = DateRangeForm(initial={
|
|
||||||
'startdate': startdate,
|
|
||||||
'enddate': enddate,
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
dateform = DateRangeForm()
|
|
||||||
deltaform = DeltaDaysForm()
|
|
||||||
|
|
||||||
else:
|
|
||||||
dateform = DateRangeForm(initial={
|
|
||||||
'startdate': startdate,
|
|
||||||
'enddate': enddate,
|
|
||||||
})
|
|
||||||
deltaform = DeltaDaysForm()
|
|
||||||
|
|
||||||
# get all 2k (if any) - this rower, in date range
|
|
||||||
try:
|
|
||||||
r = getrower(theuser)
|
|
||||||
except Rower.DoesNotExist: # pragma: no cover
|
|
||||||
r = 0
|
|
||||||
|
|
||||||
uu = theuser
|
|
||||||
|
|
||||||
# test to fix bug
|
|
||||||
startdate = datetime.datetime.combine(startdate, datetime.time())
|
|
||||||
enddate = datetime.datetime.combine(enddate, datetime.time(23, 59, 59))
|
|
||||||
startdate = arrow.get(startdate).datetime
|
|
||||||
enddate = arrow.get(enddate).datetime
|
|
||||||
|
|
||||||
thedistances = []
|
|
||||||
theworkouts = []
|
|
||||||
thesecs = []
|
|
||||||
|
|
||||||
rankingdistances.sort()
|
|
||||||
rankingdurations.sort()
|
|
||||||
|
|
||||||
for rankingdistance in rankingdistances:
|
|
||||||
|
|
||||||
workouts = Workout.objects.filter(
|
|
||||||
user=r, distance=rankingdistance,
|
|
||||||
workouttype__in=['rower', 'dynamic', 'slides'],
|
|
||||||
rankingpiece=True,
|
|
||||||
startdatetime__gte=startdate,
|
|
||||||
startdatetime__lte=enddate).order_by('duration')
|
|
||||||
if workouts:
|
|
||||||
thedistances.append(rankingdistance)
|
|
||||||
theworkouts.append(workouts[0])
|
|
||||||
|
|
||||||
timesecs = 3600*workouts[0].duration.hour
|
|
||||||
timesecs += 60*workouts[0].duration.minute
|
|
||||||
timesecs += workouts[0].duration.second
|
|
||||||
timesecs += 1.e-6*workouts[0].duration.microsecond
|
|
||||||
|
|
||||||
thesecs.append(timesecs)
|
|
||||||
|
|
||||||
for rankingduration in rankingdurations:
|
|
||||||
|
|
||||||
workouts = Workout.objects.filter(
|
|
||||||
user=r, duration=rankingduration,
|
|
||||||
workouttype='rower',
|
|
||||||
rankingpiece=True,
|
|
||||||
startdatetime__gte=startdate,
|
|
||||||
startdatetime__lte=enddate).order_by('-distance')
|
|
||||||
if workouts:
|
|
||||||
thedistances.append(workouts[0].distance)
|
|
||||||
theworkouts.append(workouts[0])
|
|
||||||
|
|
||||||
timesecs = 3600*workouts[0].duration.hour
|
|
||||||
timesecs += 60*workouts[0].duration.minute
|
|
||||||
timesecs += workouts[0].duration.second
|
|
||||||
timesecs += 1.e-5*workouts[0].duration.microsecond
|
|
||||||
|
|
||||||
thesecs.append(timesecs)
|
|
||||||
|
|
||||||
thedistances = np.array(thedistances)
|
|
||||||
thesecs = np.array(thesecs)
|
|
||||||
|
|
||||||
thevelos = thedistances/thesecs
|
|
||||||
theavpower = 2.8*(thevelos**3)
|
|
||||||
|
|
||||||
# create interactive plot
|
|
||||||
if len(thedistances) != 0:
|
|
||||||
res = interactive_cpchart(
|
|
||||||
r, thedistances, thesecs, theavpower,
|
|
||||||
theworkouts, promember=promember,
|
|
||||||
wcdurations=wcdurations, wcpower=wcpower
|
|
||||||
)
|
|
||||||
script = res[0]
|
|
||||||
div = res[1]
|
|
||||||
paulslope = res[2]
|
|
||||||
paulintercept = res[3]
|
|
||||||
p1 = res[4]
|
|
||||||
message = res[5]
|
|
||||||
else:
|
|
||||||
script = ''
|
|
||||||
div = '<p>No ranking pieces found.</p>'
|
|
||||||
paulslope = 1
|
|
||||||
paulintercept = 1
|
|
||||||
p1 = [1, 1, 1, 1]
|
|
||||||
message = ""
|
|
||||||
|
|
||||||
if request.method == 'POST' and "piece" in request.POST: # pragma: no cover
|
|
||||||
form = PredictedPieceForm(request.POST)
|
|
||||||
if form.is_valid():
|
|
||||||
value = form.cleaned_data['value']
|
|
||||||
hourvalue, value = divmod(value, 60)
|
|
||||||
if hourvalue >= 24:
|
|
||||||
hourvalue = 23
|
|
||||||
pieceunit = form.cleaned_data['pieceunit']
|
|
||||||
if pieceunit == 'd':
|
|
||||||
rankingdistances.append(value)
|
|
||||||
else:
|
|
||||||
rankingdurations.append(datetime.time(
|
|
||||||
minute=int(value), hour=int(hourvalue)))
|
|
||||||
else:
|
|
||||||
form = PredictedPieceForm()
|
|
||||||
|
|
||||||
rankingdistances.sort()
|
|
||||||
rankingdurations.sort()
|
|
||||||
|
|
||||||
predictions = []
|
|
||||||
cpredictions = []
|
|
||||||
|
|
||||||
for rankingdistance in rankingdistances:
|
|
||||||
# Paul's model
|
|
||||||
p = paulslope*np.log10(rankingdistance)+paulintercept
|
|
||||||
velo = 500./p
|
|
||||||
t = rankingdistance/velo
|
|
||||||
pwr = 2.8*(velo**3)
|
|
||||||
try:
|
|
||||||
pwr = int(pwr)
|
|
||||||
except (ValueError, AttributeError): # pragma: no cover
|
|
||||||
pwr = 0
|
|
||||||
|
|
||||||
a = {'distance': rankingdistance,
|
|
||||||
'duration': timedeltaconv(t),
|
|
||||||
'pace': timedeltaconv(p),
|
|
||||||
'power': int(pwr)}
|
|
||||||
predictions.append(a)
|
|
||||||
|
|
||||||
# CP model -
|
|
||||||
pwr2 = p1[0]/(1+t/p1[2])
|
|
||||||
pwr2 += p1[1]/(1+t/p1[3])
|
|
||||||
|
|
||||||
if pwr2 <= 0: # pragma: no cover
|
|
||||||
pwr2 = 50.
|
|
||||||
|
|
||||||
velo2 = (pwr2/2.8)**(1./3.)
|
|
||||||
|
|
||||||
if np.isnan(velo2) or velo2 <= 0: # pragma: no cover
|
|
||||||
velo2 = 1.0
|
|
||||||
|
|
||||||
t2 = rankingdistance/velo2
|
|
||||||
|
|
||||||
pwr3 = p1[0]/(1+t2/p1[2])
|
|
||||||
pwr3 += p1[1]/(1+t2/p1[3])
|
|
||||||
|
|
||||||
if pwr3 <= 0: # pragma: no cover
|
|
||||||
pwr3 = 50.
|
|
||||||
|
|
||||||
velo3 = (pwr3/2.8)**(1./3.)
|
|
||||||
if np.isnan(velo3) or velo3 <= 0: # pragma: no cover
|
|
||||||
velo3 = 1.0
|
|
||||||
|
|
||||||
t3 = rankingdistance/velo3
|
|
||||||
p3 = 500./velo3
|
|
||||||
|
|
||||||
a = {'distance': rankingdistance,
|
|
||||||
'duration': timedeltaconv(t3),
|
|
||||||
'pace': timedeltaconv(p3),
|
|
||||||
'power': int(pwr3)}
|
|
||||||
cpredictions.append(a)
|
|
||||||
|
|
||||||
for rankingduration in rankingdurations:
|
|
||||||
t = 3600.*rankingduration.hour
|
|
||||||
t += 60.*rankingduration.minute
|
|
||||||
t += rankingduration.second
|
|
||||||
t += rankingduration.microsecond/1.e6
|
|
||||||
|
|
||||||
# Paul's model
|
|
||||||
ratio = paulintercept/paulslope
|
|
||||||
|
|
||||||
u = ((2**(2+ratio))*(5.**(3+ratio))*t*np.log(10))/paulslope
|
|
||||||
|
|
||||||
d = 500*t*np.log(10.)
|
|
||||||
d = d/(paulslope*lambertw(u))
|
|
||||||
d = d.real
|
|
||||||
|
|
||||||
velo = d/t
|
|
||||||
p = 500./velo
|
|
||||||
pwr = 2.8*(velo**3)
|
|
||||||
try:
|
|
||||||
a = {'distance': int(d),
|
|
||||||
'duration': timedeltaconv(t),
|
|
||||||
'pace': timedeltaconv(p),
|
|
||||||
'power': int(pwr)}
|
|
||||||
predictions.append(a)
|
|
||||||
except: # pragma: no cover
|
|
||||||
pass
|
|
||||||
|
|
||||||
# CP model
|
|
||||||
pwr = p1[0] / (1 + t / p1[2])
|
|
||||||
pwr += p1[1] / (1 + t / p1[3])
|
|
||||||
|
|
||||||
if pwr <= 0: # pragma: no cover
|
|
||||||
pwr = 50.
|
|
||||||
|
|
||||||
velo = (pwr / 2.8)**(1. / 3.)
|
|
||||||
|
|
||||||
if np.isnan(velo) or velo <= 0: # pragma: no cover
|
|
||||||
velo = 1.0
|
|
||||||
|
|
||||||
d = t * velo
|
|
||||||
p = 500. / velo
|
|
||||||
a = {'distance': int(d),
|
|
||||||
'duration': timedeltaconv(t),
|
|
||||||
'pace': timedeltaconv(p),
|
|
||||||
'power': int(pwr)}
|
|
||||||
cpredictions.append(a)
|
|
||||||
|
|
||||||
if recalc:
|
|
||||||
wcdurations = []
|
|
||||||
wcpower = []
|
|
||||||
durations = [1, 4, 30, 60]
|
|
||||||
distances = [100, 500, 1000, 2000, 5000, 6000, 10000, 21097, 42195]
|
|
||||||
|
|
||||||
df = pd.DataFrame(
|
|
||||||
list(
|
|
||||||
C2WorldClassAgePerformance.objects.filter(
|
|
||||||
sex=r.sex,
|
|
||||||
weightcategory=r.weightcategory
|
|
||||||
).values()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
jsondf = df.to_json()
|
|
||||||
|
|
||||||
messages.error(request, message)
|
|
||||||
return render(request, 'rankings.html',
|
|
||||||
{'rankingworkouts': theworkouts,
|
|
||||||
'interactiveplot': script,
|
|
||||||
'the_div': div,
|
|
||||||
'predictions': predictions,
|
|
||||||
'cpredictions': cpredictions,
|
|
||||||
'nrdata': len(thedistances),
|
|
||||||
'form': form,
|
|
||||||
'dateform': dateform,
|
|
||||||
'deltaform': deltaform,
|
|
||||||
'id': theuser,
|
|
||||||
'theuser': uu,
|
|
||||||
'rower': r,
|
|
||||||
'active': 'nav-analysis',
|
|
||||||
'age': age,
|
|
||||||
'sex': r.sex,
|
|
||||||
'recalc': recalc,
|
|
||||||
'weightcategory': r.weightcategory,
|
|
||||||
'startdate': startdate,
|
|
||||||
'enddate': enddate,
|
|
||||||
'teams': get_my_teams(request.user),
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@login_required()
|
|
||||||
def otecp_toadmin_view(request, theuser=0,
|
|
||||||
startdate=timezone.now() - datetime.timedelta(days=365),
|
|
||||||
enddate=timezone.now(),
|
|
||||||
startdatestring="",
|
|
||||||
enddatestring="",
|
|
||||||
): # pragma: no cover
|
|
||||||
|
|
||||||
if startdatestring != "": # pragma: no cover
|
|
||||||
try:
|
|
||||||
startdate = iso8601.parse_date(startdatestring)
|
|
||||||
except ParseError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if enddatestring != "": # pragma: no cover
|
|
||||||
try:
|
|
||||||
enddate = iso8601.parse_date(enddatestring)
|
|
||||||
except ParseError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if theuser == 0: # pragma: no cover
|
|
||||||
theuser = request.user.id
|
|
||||||
|
|
||||||
u = User.objects.get(id=theuser)
|
|
||||||
r = Rower.objects.get(user=u)
|
|
||||||
|
|
||||||
startdate = datetime.datetime.combine(startdate, datetime.time())
|
|
||||||
enddate = datetime.datetime.combine(enddate, datetime.time(23, 59, 59))
|
|
||||||
|
|
||||||
theworkouts = Workout.objects.filter(
|
|
||||||
user=r, rankingpiece=True,
|
|
||||||
workouttype__in=[
|
|
||||||
'rower',
|
|
||||||
'dynamic',
|
|
||||||
'slides'
|
|
||||||
],
|
|
||||||
startdatetime__gte=startdate,
|
|
||||||
startdatetime__lte=enddate
|
|
||||||
).order_by("-startdatetime")
|
|
||||||
|
|
||||||
delta, cpvalue, avgpower = dataprep.fetchcp(
|
|
||||||
r, theworkouts, table='cpergdata'
|
|
||||||
)
|
|
||||||
|
|
||||||
powerdf = pd.DataFrame({
|
|
||||||
'Delta': delta,
|
|
||||||
'CP': cpvalue,
|
|
||||||
})
|
|
||||||
|
|
||||||
csvfilename = 'CP_data_user_{id}.csv'.format(
|
|
||||||
id=theuser
|
|
||||||
)
|
|
||||||
|
|
||||||
powerdf = powerdf[powerdf['CP'] > 0]
|
|
||||||
powerdf.dropna(axis=0, inplace=True)
|
|
||||||
powerdf.sort_values(['Delta', 'CP'], ascending=[1, 0], inplace=True)
|
|
||||||
powerdf.drop_duplicates(subset='Delta', keep='first', inplace=True)
|
|
||||||
powerdf.to_csv(csvfilename)
|
|
||||||
|
|
||||||
_ = myqueue(queuehigh,
|
|
||||||
handle_sendemailfile,
|
|
||||||
'Sander',
|
|
||||||
'Roosendaal',
|
|
||||||
'roosendaalsander@gmail.com',
|
|
||||||
csvfilename,
|
|
||||||
delete=True)
|
|
||||||
|
|
||||||
successmessage = "The CSV file was sent to the site admin per email"
|
|
||||||
messages.info(request, successmessage)
|
|
||||||
response = HttpResponseRedirect('/rowers/list-workouts/')
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
@login_required()
|
|
||||||
def otwcp_toadmin_view(request, theuser=0,
|
|
||||||
startdate=timezone.now() - datetime.timedelta(days=365),
|
|
||||||
enddate=timezone.now(),
|
|
||||||
startdatestring="",
|
|
||||||
enddatestring="",
|
|
||||||
): # pragma: no cover
|
|
||||||
|
|
||||||
if startdatestring != "":
|
|
||||||
try:
|
|
||||||
startdate = iso8601.parse_date(startdatestring)
|
|
||||||
except ParseError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if enddatestring != "":
|
|
||||||
try:
|
|
||||||
enddate = iso8601.parse_date(enddatestring)
|
|
||||||
except ParseError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if theuser == 0:
|
|
||||||
theuser = request.user.id
|
|
||||||
|
|
||||||
u = User.objects.get(id=theuser)
|
|
||||||
r = Rower.objects.get(user=u)
|
|
||||||
|
|
||||||
startdate = datetime.datetime.combine(startdate, datetime.time())
|
|
||||||
enddate = datetime.datetime.combine(enddate, datetime.time(23, 59, 59))
|
|
||||||
|
|
||||||
theworkouts = Workout.objects.filter(
|
|
||||||
user=r, rankingpiece=True,
|
|
||||||
workouttype='water',
|
|
||||||
startdatetime__gte=startdate,
|
|
||||||
startdatetime__lte=enddate
|
|
||||||
).order_by("-startdatetime")
|
|
||||||
|
|
||||||
delta, cpvalue, avgpower = dataprep.fetchcp(
|
|
||||||
r, theworkouts, table='cpdata'
|
|
||||||
)
|
|
||||||
|
|
||||||
powerdf = pd.DataFrame({
|
|
||||||
'Delta': delta,
|
|
||||||
'CP': cpvalue,
|
|
||||||
})
|
|
||||||
|
|
||||||
csvfilename = 'CP_data_user_{id}.csv'.format(
|
|
||||||
id=theuser
|
|
||||||
)
|
|
||||||
|
|
||||||
powerdf = powerdf[powerdf['CP'] > 0]
|
|
||||||
powerdf.dropna(axis=0, inplace=True)
|
|
||||||
powerdf.sort_values(['Delta', 'CP'], ascending=[1, 0], inplace=True)
|
|
||||||
powerdf.drop_duplicates(subset='Delta', keep='first', inplace=True)
|
|
||||||
powerdf.to_csv(csvfilename)
|
|
||||||
|
|
||||||
_ = myqueue(queuehigh,
|
|
||||||
handle_sendemailfile,
|
|
||||||
'Sander',
|
|
||||||
'Roosendaal',
|
|
||||||
'roosendaalsander@gmail.com',
|
|
||||||
csvfilename,
|
|
||||||
delete=True)
|
|
||||||
|
|
||||||
successmessage = "The CSV file was sent to the site admin per email"
|
|
||||||
messages.info(request, successmessage)
|
|
||||||
response = HttpResponseRedirect('/rowers/list-workouts/')
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
def agegroupcpview(request, age, normalize=0, userid=0):
|
|
||||||
script, div = interactive_agegroupcpchart(age, normalized=normalize)
|
|
||||||
|
|
||||||
response = render(request, 'agegroupcp.html',
|
|
||||||
{
|
|
||||||
'active': 'nav-analysis',
|
|
||||||
'interactiveplot': script,
|
|
||||||
'the_div': div,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
def agegrouprecordview(request, sex='male', weightcategory='hwt',
|
def agegrouprecordview(request, sex='male', weightcategory='hwt',
|
||||||
distance=2000, duration=None):
|
distance=2000, duration=None):
|
||||||
@@ -2761,15 +2220,16 @@ def history_view_data(request, userid=0):
|
|||||||
|
|
||||||
ids = [w.id for w in g_workouts]
|
ids = [w.id for w in g_workouts]
|
||||||
|
|
||||||
columns = ['hr', 'power', 'time']
|
columns = ['hr', 'power', 'time', 'workoutstate', 'workoutid']
|
||||||
|
|
||||||
|
df = dataprep.read_data(columns, ids=ids)
|
||||||
|
df = dataprep.remove_nulls_pl(df)
|
||||||
|
|
||||||
df = getsmallrowdata_db(columns, ids=ids)
|
|
||||||
try:
|
try:
|
||||||
df['deltat'] = df['time'].diff().clip(lower=0)
|
df = df.with_columns(pl.col('time').diff().clip(lower_bound=0).alias("deltat"))
|
||||||
except KeyError: # pragma: no cover
|
except KeyError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
df = dataprep.clean_df_stats(df, workstrokesonly=True,
|
|
||||||
ignoreadvanced=True, ignorehr=False)
|
|
||||||
|
|
||||||
totalmeters, totalhours, totalminutes, totalseconds = get_totals(
|
totalmeters, totalhours, totalminutes, totalseconds = get_totals(
|
||||||
g_workouts)
|
g_workouts)
|
||||||
@@ -2798,13 +2258,14 @@ def history_view_data(request, userid=0):
|
|||||||
whours=whours,
|
whours=whours,
|
||||||
wminutes=wminutes, wseconds=wseconds,
|
wminutes=wminutes, wseconds=wseconds,
|
||||||
)
|
)
|
||||||
ddf = getsmallrowdata_db(columns, ids=[w.id for w in a_workouts])
|
ddf = dataprep.read_data(columns, ids=[w.id for w in a_workouts])
|
||||||
|
ddf = dataprep.remove_nulls_pl(ddf)
|
||||||
try:
|
try:
|
||||||
ddf['deltat'] = ddf['time'].diff().clip(lower=0)
|
ddf = ddf.with_columns(pl.col("time").diff().clip(lower_bound=0).alias("deltat"))
|
||||||
except KeyError: # pragma: no cover
|
except KeyError: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
|
||||||
ddf = dataprep.clean_df_stats(ddf, workstrokesonly=False,
|
ddf = dataprep.clean_df_stats_pl(ddf, workstrokesonly=False,
|
||||||
ignoreadvanced=True)
|
ignoreadvanced=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -2812,14 +2273,14 @@ def history_view_data(request, userid=0):
|
|||||||
except (KeyError, ValueError, AttributeError): # pragma: no cover
|
except (KeyError, ValueError, AttributeError): # pragma: no cover
|
||||||
ddict['hrmean'] = 0
|
ddict['hrmean'] = 0
|
||||||
try:
|
try:
|
||||||
ddict['hrmax'] = ddf['hr'].max().astype(int)
|
ddict['hrmax'] = int(ddf['hr'].max())
|
||||||
except (KeyError, ValueError, AttributeError): # pragma: no cover
|
except (KeyError, ValueError, AttributeError): # pragma: no cover
|
||||||
ddict['hrmax'] = 0
|
ddict['hrmax'] = 0
|
||||||
|
|
||||||
ddict['powermean'] = int(wavg(ddf, 'power', 'deltat'))
|
ddict['powermean'] = int(wavg(ddf, 'power', 'deltat'))
|
||||||
try:
|
try:
|
||||||
ddict['powermax'] = ddf['power'].max().astype(int)
|
ddict['powermax'] = int(ddf['power'].max())
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
ddict['powermax'] = 0
|
ddict['powermax'] = 0
|
||||||
ddict['nrworkouts'] = a_workouts.count()
|
ddict['nrworkouts'] = a_workouts.count()
|
||||||
listofdicts.append(ddict)
|
listofdicts.append(ddict)
|
||||||
@@ -2833,14 +2294,14 @@ def history_view_data(request, userid=0):
|
|||||||
totalsdict['distance'] = totalmeters
|
totalsdict['distance'] = totalmeters
|
||||||
try:
|
try:
|
||||||
totalsdict['powermean'] = int(wavg(df, 'power', 'deltat'))
|
totalsdict['powermean'] = int(wavg(df, 'power', 'deltat'))
|
||||||
totalsdict['powermax'] = df['power'].max().astype(int)
|
totalsdict['powermax'] = int(df['power'].max())
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
totalsdict['powermean'] = 0
|
totalsdict['powermean'] = 0
|
||||||
totalsdict['powermax'] = 0
|
totalsdict['powermax'] = 0
|
||||||
try:
|
try:
|
||||||
totalsdict['hrmean'] = int(wavg(df, 'hr', 'deltat'))
|
totalsdict['hrmean'] = int(wavg(df, 'hr', 'deltat'))
|
||||||
totalsdict['hrmax'] = df['hr'].max().astype(int)
|
totalsdict['hrmax'] = int(df['hr'].max())
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
totalsdict['hrmean'] = 0
|
totalsdict['hrmean'] = 0
|
||||||
totalsdict['hrmax'] = 0
|
totalsdict['hrmax'] = 0
|
||||||
|
|
||||||
@@ -2859,14 +2320,22 @@ def history_view_data(request, userid=0):
|
|||||||
a_workouts = g_workouts.filter(workouttype=typeselect)
|
a_workouts = g_workouts.filter(workouttype=typeselect)
|
||||||
meters, hours, minutes, seconds = get_totals(a_workouts)
|
meters, hours, minutes, seconds = get_totals(a_workouts)
|
||||||
totalseconds = 3600 * hours + 60 * minutes + seconds
|
totalseconds = 3600 * hours + 60 * minutes + seconds
|
||||||
ddf = getsmallrowdata_db(columns, ids=[w.id for w in a_workouts])
|
ddf = dataprep.read_data(columns, ids=[w.id for w in a_workouts])
|
||||||
|
ddf = dataprep.remove_nulls_pl(ddf)
|
||||||
|
if ddf.is_empty():
|
||||||
|
totalscript = ""
|
||||||
|
totaldiv = "No data"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ddf['deltat'] = ddf['time'].diff().clip(lower=0)
|
ddf = ddf.with_columns(pl.col("time").diff().clip(lower_bound=0).alias("deltat"))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
except ColumnNotFoundError:
|
||||||
|
totalscript = ""
|
||||||
|
totaldiv = "No data"
|
||||||
|
|
||||||
ddf = dataprep.clean_df_stats(ddf, workstrokesonly=True,
|
|
||||||
|
ddf = dataprep.clean_df_stats_pl(ddf, workstrokesonly=True,
|
||||||
ignoreadvanced=True)
|
ignoreadvanced=True)
|
||||||
|
|
||||||
totalscript, totaldiv = interactive_hr_piechart(
|
totalscript, totaldiv = interactive_hr_piechart(
|
||||||
|
|||||||
+64
-61
@@ -69,102 +69,102 @@ def strokedataform(request, id=0):
|
|||||||
def api_get_dataframe(startdatetime, df):
|
def api_get_dataframe(startdatetime, df):
|
||||||
try:
|
try:
|
||||||
time = df['time']/1.e3
|
time = df['time']/1.e3
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
try:
|
try:
|
||||||
time = df['t']/10.
|
time = df['t']/10.
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
return 400, "Missing time", pd.DataFrame()
|
return 400, "Missing time", pl.DataFrame()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
spm = df['spm']
|
spm = df['spm']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
return 400, "Missing spm", pd.DataFrame()
|
return 400, "Missing spm", pl.DataFrame()
|
||||||
try:
|
try:
|
||||||
distance = df['distance']
|
distance = df['distance']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
try:
|
try:
|
||||||
distance = df['d']/10.
|
distance = df['d']/10.
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
return 400, "Missing distance", pd.DataFrame()
|
return 400, "Missing distance", pl.DataFrame()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pace = df['pace']/1.e3
|
pace = df['pace']/1.e3
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
try:
|
try:
|
||||||
pace = df['p']/10.
|
pace = df['p']/10.
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
return 400, "Missing pace", pd.DataFrame()
|
return 400, "Missing pace", pl.DataFrame()
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
power = df['power']
|
power = df['power']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
power = 0*time
|
power = 0*time
|
||||||
try:
|
try:
|
||||||
drivelength = df['drivelength']
|
drivelength = df['drivelength']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
drivelength = 0*time
|
drivelength = 0*time
|
||||||
try:
|
try:
|
||||||
dragfactor = df['dragfactor']
|
dragfactor = df['dragfactor']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
dragfactor = 0*time
|
dragfactor = 0*time
|
||||||
try:
|
try:
|
||||||
drivetime = df['drivetime']
|
drivetime = df['drivetime']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
drivetime = 0*time
|
drivetime = 0*time
|
||||||
try:
|
try:
|
||||||
strokerecoverytime = df['strokerecoverytime']
|
strokerecoverytime = df['strokerecoverytime']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
strokerecoverytime = 0*time
|
strokerecoverytime = 0*time
|
||||||
try:
|
try:
|
||||||
averagedriveforce = df['averagedriveforce']
|
averagedriveforce = df['averagedriveforce']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
averagedriveforce = 0*time
|
averagedriveforce = 0*time
|
||||||
try:
|
try:
|
||||||
peakdriveforce = df['peakdriveforce']
|
peakdriveforce = df['peakdriveforce']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
peakdriveforce = 0*time
|
peakdriveforce = 0*time
|
||||||
try:
|
try:
|
||||||
wash = df['wash']
|
wash = df['wash']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
wash = 0*time
|
wash = 0*time
|
||||||
try:
|
try:
|
||||||
catch = df['catch']
|
catch = df['catch']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
catch = 0*time
|
catch = 0*time
|
||||||
try:
|
try:
|
||||||
finish = df['finish']
|
finish = df['finish']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
finish = 0*time
|
finish = 0*time
|
||||||
try:
|
try:
|
||||||
peakforceangle = df['peakforceangle']
|
peakforceangle = df['peakforceangle']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
peakforceangle = 0*time
|
peakforceangle = 0*time
|
||||||
try:
|
try:
|
||||||
driveenergy = df['driveenergy']
|
driveenergy = df['driveenergy']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
driveenergy = 60.*power/spm
|
driveenergy = 60.*power/spm
|
||||||
try:
|
try:
|
||||||
slip = df['slip']
|
slip = df['slip']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
slip = 0*time
|
slip = 0*time
|
||||||
try:
|
try:
|
||||||
lapidx = df['lapidx']
|
lapidx = df['lapidx']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
lapidx = 0*time
|
lapidx = 0*time
|
||||||
try:
|
try:
|
||||||
hr = df['hr']
|
hr = df['hr']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
hr = 0*df['time']
|
hr = 0*df['time']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
latitude = df['latitude']
|
latitude = df['latitude']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
latitude = 0*df['time']
|
latitude = 0*df['time']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
longitude = df['longitude']
|
longitude = df['longitude']
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
longitude = 0*df['time']
|
longitude = 0*df['time']
|
||||||
|
|
||||||
starttime = totimestamp(startdatetime)+time[0]
|
starttime = totimestamp(startdatetime)+time[0]
|
||||||
@@ -172,7 +172,7 @@ def api_get_dataframe(startdatetime, df):
|
|||||||
|
|
||||||
dologging('apilog.log',"(strokedatajson_v2/3 POST - data parsed)")
|
dologging('apilog.log',"(strokedatajson_v2/3 POST - data parsed)")
|
||||||
|
|
||||||
data = pd.DataFrame({'TimeStamp (sec)': unixtime,
|
data = pl.DataFrame({'TimeStamp (sec)': unixtime,
|
||||||
' Horizontal (meters)': distance,
|
' Horizontal (meters)': distance,
|
||||||
' Cadence (stokes/min)': spm,
|
' Cadence (stokes/min)': spm,
|
||||||
' HRCur (bpm)': hr,
|
' HRCur (bpm)': hr,
|
||||||
@@ -526,7 +526,7 @@ def strokedatajson_v3(request):
|
|||||||
title = request.data.get('name','')
|
title = request.data.get('name','')
|
||||||
try:
|
try:
|
||||||
elapsedTime = request.data['elapsedTime']
|
elapsedTime = request.data['elapsedTime']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
try:
|
try:
|
||||||
duration = request.data['duration']
|
duration = request.data['duration']
|
||||||
try:
|
try:
|
||||||
@@ -538,7 +538,7 @@ def strokedatajson_v3(request):
|
|||||||
return HttpResponse("Missing Elapsed Time", status=400)
|
return HttpResponse("Missing Elapsed Time", status=400)
|
||||||
try:
|
try:
|
||||||
totalDistance = request.data['distance']
|
totalDistance = request.data['distance']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
return HttpResponse("Missing Total Distance", status=400)
|
return HttpResponse("Missing Total Distance", status=400)
|
||||||
timeZone = request.data.get('timezone','UTC')
|
timeZone = request.data.get('timezone','UTC')
|
||||||
workouttype = request.data.get('workouttype','rower')
|
workouttype = request.data.get('workouttype','rower')
|
||||||
@@ -556,23 +556,21 @@ def strokedatajson_v3(request):
|
|||||||
dologging('apilog.log',totalDistance)
|
dologging('apilog.log',totalDistance)
|
||||||
dologging('apilog.log',elapsedTime)
|
dologging('apilog.log',elapsedTime)
|
||||||
|
|
||||||
df = pd.DataFrame()
|
df = pl.DataFrame()
|
||||||
try:
|
try:
|
||||||
strokes = request.data['strokes']
|
strokes = request.data['strokes']
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
return HttpResponse("No Stroke Data in JSON", status=400)
|
return HttpResponse("No Stroke Data in JSON", status=400)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
df = pd.DataFrame(strokes['data'])
|
df = pl.DataFrame(strokes['data'])
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
try:
|
try:
|
||||||
df = pd.DataFrame(request.data['strokedata'])
|
df = pl.DataFrame(request.data['strokedata'])
|
||||||
except:
|
except:
|
||||||
return HttpResponse("No JSON Object could be decoded", status=400)
|
return HttpResponse("No JSON Object could be decoded", status=400)
|
||||||
|
|
||||||
df.index = df.index.astype(int)
|
df = df.sort("time")
|
||||||
df.sort_index(inplace=True)
|
|
||||||
|
|
||||||
status, comment, data = api_get_dataframe(startdatetime, df)
|
status, comment, data = api_get_dataframe(startdatetime, df)
|
||||||
|
|
||||||
if status != 200: # pragma: no cover
|
if status != 200: # pragma: no cover
|
||||||
@@ -580,7 +578,8 @@ def strokedatajson_v3(request):
|
|||||||
|
|
||||||
|
|
||||||
csvfilename = 'media/{code}.csv.gz'.format(code=uuid4().hex[:16])
|
csvfilename = 'media/{code}.csv.gz'.format(code=uuid4().hex[:16])
|
||||||
_ = data.to_csv(csvfilename, index_label='index', compression='gzip')
|
with gzip.open(csvfilename, 'w') as f:
|
||||||
|
_ = data.write_csv(f)
|
||||||
|
|
||||||
duration = datetime.time(0,0,1)
|
duration = datetime.time(0,0,1)
|
||||||
w = Workout(
|
w = Workout(
|
||||||
@@ -672,10 +671,11 @@ def strokedatajson_v2(request, id):
|
|||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
columns = ['spm', 'time', 'hr', 'pace', 'power', 'distance']
|
columns = ['spm', 'time', 'hr', 'pace', 'power', 'distance']
|
||||||
datadf = dataprep.getsmallrowdata_db(columns, ids=[id])
|
datadf = dataprep.read_data(columns, ids=[id])
|
||||||
|
datadf = dataprep.remove_nulls_pl(datadf)
|
||||||
dologging('apilog.log',request.user.username+"(strokedatajson_v2 GET)")
|
dologging('apilog.log',request.user.username+"(strokedatajson_v2 GET)")
|
||||||
|
|
||||||
data = datadf.to_json(orient='records')
|
data = datadf.write_json(row_oriented=True)
|
||||||
data2 = json.loads(data)
|
data2 = json.loads(data)
|
||||||
data2 = {"data": data2}
|
data2 = {"data": data2}
|
||||||
|
|
||||||
@@ -686,28 +686,27 @@ def strokedatajson_v2(request, id):
|
|||||||
try:
|
try:
|
||||||
for d in request.data['data']:
|
for d in request.data['data']:
|
||||||
dologging('apilog.log',json.dumps(d))
|
dologging('apilog.log',json.dumps(d))
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
try:
|
try:
|
||||||
for d in request.data['strokedata']:
|
for d in request.data['strokedata']:
|
||||||
dologging('apilog.log',json.dumps(d))
|
dologging('apilog.log',json.dumps(d))
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
dologging('apilog.log','No data in request.data')
|
dologging('apilog.log','No data in request.data')
|
||||||
checkdata, r = dataprep.getrowdata_db(id=row.id)
|
checkdata, r = dataprep.getrowdata_db(id=row.id)
|
||||||
if not checkdata.empty: # pragma: no cover
|
if not checkdata.empty: # pragma: no cover
|
||||||
return HttpResponse("Duplicate Error", status=409)
|
return HttpResponse("Duplicate Error", status=409)
|
||||||
|
|
||||||
df = pd.DataFrame()
|
df = pl.DataFrame()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
df = pd.DataFrame(request.data['data'])
|
df = pl.DataFrame(request.data['data'])
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
try:
|
try:
|
||||||
df = pd.DataFrame(request.data['strokedata'])
|
df = pl.DataFrame(request.data['strokedata'])
|
||||||
except:
|
except:
|
||||||
return HttpResponse("No JSON object could be decoded", status=400)
|
return HttpResponse("No JSON object could be decoded", status=400)
|
||||||
|
|
||||||
df.index = df.index.astype(int)
|
df = df.sort("time")
|
||||||
df.sort_index(inplace=True)
|
|
||||||
|
|
||||||
status, comment, data = api_get_dataframe(row.startdatetime, df)
|
status, comment, data = api_get_dataframe(row.startdatetime, df)
|
||||||
if status != 200: # pragma: no cover
|
if status != 200: # pragma: no cover
|
||||||
@@ -729,7 +728,8 @@ def strokedatajson_v2(request, id):
|
|||||||
row.duplicate = True
|
row.duplicate = True
|
||||||
row.save()
|
row.save()
|
||||||
|
|
||||||
_ = data.to_csv(csvfilename+'.gz', index_label='index', compression='gzip')
|
with gzip.open(csvfilename+'.gz', 'w') as f:
|
||||||
|
_ = data.write_csv(f)
|
||||||
row.csvfilename = csvfilename
|
row.csvfilename = csvfilename
|
||||||
row.save()
|
row.save()
|
||||||
|
|
||||||
@@ -748,7 +748,7 @@ def strokedatajson_v2(request, id):
|
|||||||
powerperc=powerperc, powerzones=r.powerzones)
|
powerperc=powerperc, powerzones=r.powerzones)
|
||||||
rowdata = rdata(csvfile=row.csvfilename, rower=rr).df
|
rowdata = rdata(csvfile=row.csvfilename, rower=rr).df
|
||||||
|
|
||||||
datadf = dataprep.dataprep(
|
datadf = dataprep.dataplep(
|
||||||
rowdata, id=row.id, bands=True, barchart=True, otwpower=True, empower=True)
|
rowdata, id=row.id, bands=True, barchart=True, otwpower=True, empower=True)
|
||||||
|
|
||||||
_ = myqueue(queuehigh, handle_calctrimp, row.id,
|
_ = myqueue(queuehigh, handle_calctrimp, row.id,
|
||||||
@@ -802,7 +802,11 @@ def strokedatajson(request, id=0):
|
|||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# currently only returns a subset.
|
# currently only returns a subset.
|
||||||
columns = ['spm', 'time', 'hr', 'pace', 'power', 'distance']
|
columns = ['spm', 'time', 'hr', 'pace', 'power', 'distance']
|
||||||
datadf = dataprep.getsmallrowdata_db(columns, ids=[id])
|
|
||||||
|
datadf = dataprep.read_data(columns, ids=[id])
|
||||||
|
datadf = dataprep.remove_nulls_pl(datadf)
|
||||||
|
datadf = datadf.to_pandas()
|
||||||
|
|
||||||
dologging("apilog.log",request.user.username+"(strokedatajson GET) ")
|
dologging("apilog.log",request.user.username+"(strokedatajson GET) ")
|
||||||
return JSONResponse(datadf)
|
return JSONResponse(datadf)
|
||||||
|
|
||||||
@@ -823,14 +827,13 @@ def strokedatajson(request, id=0):
|
|||||||
return HttpResponse("No JSON object could be decoded", status=400)
|
return HttpResponse("No JSON object could be decoded", status=400)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
df = pd.DataFrame(strokedata)
|
df = pl.DataFrame(strokedata)
|
||||||
except ValueError: # pragma: no cover
|
except ValueError: # pragma: no cover
|
||||||
return HttpResponse("Arrays must all be same length", status=400)
|
return HttpResponse("Arrays must all be same length", status=400)
|
||||||
df.index = df.index.astype(int)
|
df = df.sort("time")
|
||||||
df.sort_index(inplace=True)
|
|
||||||
try:
|
try:
|
||||||
time = df['time']/1.e3
|
time = df['time']/1.e3
|
||||||
except KeyError: # pragma: no cover
|
except (KeyError, ColumnNotFoundError): # pragma: no cover
|
||||||
return HttpResponse("There must be time values", status=400)
|
return HttpResponse("There must be time values", status=400)
|
||||||
aantal = len(time)
|
aantal = len(time)
|
||||||
pace = df['pace']/1.e3
|
pace = df['pace']/1.e3
|
||||||
@@ -869,7 +872,7 @@ def strokedatajson(request, id=0):
|
|||||||
|
|
||||||
dologging("apilog.log",request.user.username+"(POST)")
|
dologging("apilog.log",request.user.username+"(POST)")
|
||||||
|
|
||||||
data = pd.DataFrame({'TimeStamp (sec)': unixtime,
|
data = pl.DataFrame({'TimeStamp (sec)': unixtime,
|
||||||
' Horizontal (meters)': distance,
|
' Horizontal (meters)': distance,
|
||||||
' Cadence (stokes/min)': spm,
|
' Cadence (stokes/min)': spm,
|
||||||
' HRCur (bpm)': hr,
|
' HRCur (bpm)': hr,
|
||||||
@@ -896,8 +899,8 @@ def strokedatajson(request, id=0):
|
|||||||
timestr = row.startdatetime.strftime("%Y%m%d-%H%M%S")
|
timestr = row.startdatetime.strftime("%Y%m%d-%H%M%S")
|
||||||
csvfilename = 'media/Import_'+timestr+'.csv'
|
csvfilename = 'media/Import_'+timestr+'.csv'
|
||||||
|
|
||||||
res = data.to_csv(csvfilename+'.gz', index_label='index',
|
with gzip.open(csvfilename+'.gz','w') as f:
|
||||||
compression='gzip')
|
res = data.write_csv(f)
|
||||||
row.csvfilename = csvfilename
|
row.csvfilename = csvfilename
|
||||||
row.save()
|
row.save()
|
||||||
|
|
||||||
@@ -916,7 +919,7 @@ def strokedatajson(request, id=0):
|
|||||||
powerperc=powerperc, powerzones=r.powerzones)
|
powerperc=powerperc, powerzones=r.powerzones)
|
||||||
rowdata = rdata(csvfile=row.csvfilename, rower=rr).df
|
rowdata = rdata(csvfile=row.csvfilename, rower=rr).df
|
||||||
|
|
||||||
datadf = dataprep.dataprep(
|
datadf = dataprep.dataplep(
|
||||||
rowdata, id=row.id, bands=True, barchart=True, otwpower=True, empower=True)
|
rowdata, id=row.id, bands=True, barchart=True, otwpower=True, empower=True)
|
||||||
# mangling
|
# mangling
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ def workouts_summaries_email_view(request):
|
|||||||
)
|
)
|
||||||
df = dataprep.workout_summary_to_df(
|
df = dataprep.workout_summary_to_df(
|
||||||
r, startdate=startdate, enddate=enddate)
|
r, startdate=startdate, enddate=enddate)
|
||||||
df.to_csv(filename, encoding='utf-8')
|
df.write_csv(filename)
|
||||||
_ = myqueue(queuehigh, handle_sendemailsummary,
|
_ = myqueue(queuehigh, handle_sendemailsummary,
|
||||||
r.user.first_name,
|
r.user.first_name,
|
||||||
r.user.last_name,
|
r.user.last_name,
|
||||||
|
|||||||
@@ -1,10 +1,33 @@
|
|||||||
|
|
||||||
from rowers.views.statements import *
|
from rowers.views.statements import *
|
||||||
|
from rowers.interactiveplots import sleep
|
||||||
|
|
||||||
from rq import Queue
|
from rq import Queue
|
||||||
from redis import Redis
|
from redis import Redis
|
||||||
from rq.job import Job
|
from rq.job import Job
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def sleep_view(request):
|
||||||
|
|
||||||
|
script, div = sleep()
|
||||||
|
|
||||||
|
return render(request,
|
||||||
|
"sleep.html",
|
||||||
|
{
|
||||||
|
"the_div": div,
|
||||||
|
"the_script": script,
|
||||||
|
})
|
||||||
|
|
||||||
|
def filmdeaths_view(request):
|
||||||
|
script, div = filmdeaths()
|
||||||
|
|
||||||
|
return render(request,
|
||||||
|
"filmdeaths.html",
|
||||||
|
{
|
||||||
|
"the_div": div,
|
||||||
|
"the_script": script,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
def download_fit(request, filename=''):
|
def download_fit(request, filename=''):
|
||||||
|
|||||||
@@ -3569,7 +3569,7 @@ def rower_trainingplan_execution_view(request,
|
|||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
data, message = get_execution_report(r, startdate, enddate)
|
data, message = get_execution_report(r, startdate, enddate)
|
||||||
|
|
||||||
if not data.empty:
|
if not data.is_empty():
|
||||||
script, div = interactive_planchart(data, startdate, enddate)
|
script, div = interactive_planchart(data, startdate, enddate)
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
script = ''
|
script = ''
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from rowers.utils import (
|
|||||||
from rowers.celery import result as celery_result
|
from rowers.celery import result as celery_result
|
||||||
from rowers.interactiveplots import *
|
from rowers.interactiveplots import *
|
||||||
from scipy.interpolate import griddata
|
from scipy.interpolate import griddata
|
||||||
from rowers.dataprep import getsmallrowdata_db
|
from rowers.dataprep import getsmallrowdata_pd, read_data
|
||||||
from rowers.dataprep import timedeltaconv
|
from rowers.dataprep import timedeltaconv
|
||||||
from scipy.special import lambertw
|
from scipy.special import lambertw
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
@@ -35,6 +35,7 @@ import threading
|
|||||||
import redis
|
import redis
|
||||||
import colorsys
|
import colorsys
|
||||||
import re
|
import re
|
||||||
|
import gzip
|
||||||
import zipfile
|
import zipfile
|
||||||
import bleach
|
import bleach
|
||||||
import arrow
|
import arrow
|
||||||
@@ -136,9 +137,9 @@ from rowers.forms import (
|
|||||||
FitnessMetricForm, PredictedPieceFormNoDistance,
|
FitnessMetricForm, PredictedPieceFormNoDistance,
|
||||||
EmailForm, RegistrationForm, RegistrationFormTermsOfService,
|
EmailForm, RegistrationForm, RegistrationFormTermsOfService,
|
||||||
RegistrationFormUniqueEmail, RegistrationFormSex,
|
RegistrationFormUniqueEmail, RegistrationFormSex,
|
||||||
CNsummaryForm, UpdateWindForm,
|
CNsummaryForm,
|
||||||
StandardsForm,
|
StandardsForm,
|
||||||
UpdateStreamForm, WorkoutMultipleCompareForm, ChartParamChoiceForm,
|
WorkoutMultipleCompareForm, ChartParamChoiceForm,
|
||||||
FusionMetricChoiceForm, BoxPlotChoiceForm, MultiFlexChoiceForm,
|
FusionMetricChoiceForm, BoxPlotChoiceForm, MultiFlexChoiceForm,
|
||||||
TrendFlexModalForm, WorkoutSplitForm, WorkoutJoinParamForm,
|
TrendFlexModalForm, WorkoutSplitForm, WorkoutJoinParamForm,
|
||||||
AnalysisOptionsForm, AnalysisChoiceForm,
|
AnalysisOptionsForm, AnalysisChoiceForm,
|
||||||
@@ -205,6 +206,7 @@ from rowers.rojabo_stuff import rojabo_open
|
|||||||
|
|
||||||
from rowers.integrations import *
|
from rowers.integrations import *
|
||||||
|
|
||||||
|
from polars.exceptions import ColumnNotFoundError
|
||||||
|
|
||||||
import rowers.ownapistuff as ownapistuff
|
import rowers.ownapistuff as ownapistuff
|
||||||
from rowers.ownapistuff import TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_REDIRECT_URI
|
from rowers.ownapistuff import TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_REDIRECT_URI
|
||||||
@@ -251,7 +253,7 @@ from rowers.tasks import (
|
|||||||
handle_sendemailfile,
|
handle_sendemailfile,
|
||||||
handle_sendemailkml,
|
handle_sendemailkml,
|
||||||
handle_sendemailnewresponse, handle_updatedps,
|
handle_sendemailnewresponse, handle_updatedps,
|
||||||
handle_updatecp, long_test_task, long_test_task2,
|
long_test_task, long_test_task2,
|
||||||
handle_zip_file, handle_getagegrouprecords,
|
handle_zip_file, handle_getagegrouprecords,
|
||||||
handle_update_empower,
|
handle_update_empower,
|
||||||
handle_sendemailics,
|
handle_sendemailics,
|
||||||
@@ -1344,9 +1346,9 @@ def trydf(df, aantal, column): # pragma: no cover
|
|||||||
s = df[column]
|
s = df[column]
|
||||||
if len(s) != aantal:
|
if len(s) != aantal:
|
||||||
return np.zeros(aantal)
|
return np.zeros(aantal)
|
||||||
if not np.issubdtype(s, np.number):
|
if not s.dtype in pl.NUMERIC_DTYPES:
|
||||||
return np.zeros(aantal)
|
return np.zeros(aantal)
|
||||||
except KeyError:
|
except (KeyError, ColumnNotFoundError):
|
||||||
s = np.zeros(aantal)
|
s = np.zeros(aantal)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|||||||
+38
-494
@@ -126,8 +126,7 @@ def workout_video_view_mini(request, id=''):
|
|||||||
hascoordinates = pd.Series(data['latitude']).std() > 0
|
hascoordinates = pd.Series(data['latitude']).std() > 0
|
||||||
# create map
|
# create map
|
||||||
if hascoordinates and mode == 'water':
|
if hascoordinates and mode == 'water':
|
||||||
mapscript, mapdiv = leaflet_chart_video(data['latitude'], data['longitude'],
|
mapscript, mapdiv = leaflet_chart(data['latitude'], data['longitude'])
|
||||||
w.name)
|
|
||||||
else:
|
else:
|
||||||
mapscript, mapdiv = interactive_chart_video(data)
|
mapscript, mapdiv = interactive_chart_video(data)
|
||||||
data['longitude'] = data['spm']
|
data['longitude'] = data['spm']
|
||||||
@@ -237,8 +236,7 @@ def workout_video_view(request, id=''):
|
|||||||
hascoordinates = pd.Series(data['latitude']).std() > 0
|
hascoordinates = pd.Series(data['latitude']).std() > 0
|
||||||
# create map
|
# create map
|
||||||
if hascoordinates and mode == 'water':
|
if hascoordinates and mode == 'water':
|
||||||
mapscript, mapdiv = leaflet_chart_video(data['latitude'], data['longitude'],
|
mapscript, mapdiv = leaflet_chart(data['latitude'], data['longitude'])
|
||||||
w.name)
|
|
||||||
else:
|
else:
|
||||||
mapscript, mapdiv = interactive_chart_video(data)
|
mapscript, mapdiv = interactive_chart_video(data)
|
||||||
data['longitude'] = data['spm']
|
data['longitude'] = data['spm']
|
||||||
@@ -349,12 +347,12 @@ def workout_video_create_view(request, id=0):
|
|||||||
# get data
|
# get data
|
||||||
data, metrics, maxtime = dataprep.get_video_data(
|
data, metrics, maxtime = dataprep.get_video_data(
|
||||||
w, groups=metricsgroups, mode=mode)
|
w, groups=metricsgroups, mode=mode)
|
||||||
|
|
||||||
hascoordinates = pd.Series(data['latitude']).std() > 0
|
hascoordinates = pd.Series(data['latitude']).std() > 0
|
||||||
|
|
||||||
# create map
|
# create map
|
||||||
if hascoordinates and mode == 'water':
|
if hascoordinates and mode == 'water':
|
||||||
mapscript, mapdiv = leaflet_chart_video(data['latitude'], data['longitude'],
|
mapscript, mapdiv = leaflet_chart(data['latitude'], data['longitude'])
|
||||||
w.name)
|
|
||||||
else:
|
else:
|
||||||
mapscript, mapdiv = interactive_chart_video(data)
|
mapscript, mapdiv = interactive_chart_video(data)
|
||||||
data['longitude'] = data['spm']
|
data['longitude'] = data['spm']
|
||||||
@@ -380,6 +378,7 @@ def workout_video_create_view(request, id=0):
|
|||||||
|
|
||||||
template = 'embedded_video.html'
|
template = 'embedded_video.html'
|
||||||
|
|
||||||
|
|
||||||
return render(request,
|
return render(request,
|
||||||
template,
|
template,
|
||||||
{
|
{
|
||||||
@@ -429,12 +428,14 @@ def workout_forcecurve_view(request, id=0, analysis=0, userid=0, workstrokesonly
|
|||||||
work_max = forceanalysis.work_max
|
work_max = forceanalysis.work_max
|
||||||
notes = forceanalysis.notes
|
notes = forceanalysis.notes
|
||||||
name = forceanalysis.name
|
name = forceanalysis.name
|
||||||
|
plotcircles = forceanalysis.plotcircles
|
||||||
|
plotlines = forceanalysis.plotlines
|
||||||
includereststrokes = forceanalysis.include_rest_strokes
|
includereststrokes = forceanalysis.include_rest_strokes
|
||||||
except (ForceCurveAnalysis.DoesNotExist, ValueError):
|
except (ForceCurveAnalysis.DoesNotExist, ValueError):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
dist_min = 0
|
dist_min = 0
|
||||||
dist_max = 0
|
dist_max = row.distance
|
||||||
spm_min = 15
|
spm_min = 15
|
||||||
spm_max = 55
|
spm_max = 55
|
||||||
work_min = 0
|
work_min = 0
|
||||||
@@ -442,6 +443,8 @@ def workout_forcecurve_view(request, id=0, analysis=0, userid=0, workstrokesonly
|
|||||||
notes = ''
|
notes = ''
|
||||||
includereststrokes = False
|
includereststrokes = False
|
||||||
name = ''
|
name = ''
|
||||||
|
plotcircles = True
|
||||||
|
plotlines = False
|
||||||
|
|
||||||
form = ForceCurveOptionsForm(initial={
|
form = ForceCurveOptionsForm(initial={
|
||||||
'spm_min': spm_min,
|
'spm_min': spm_min,
|
||||||
@@ -451,10 +454,10 @@ def workout_forcecurve_view(request, id=0, analysis=0, userid=0, workstrokesonly
|
|||||||
'work_min': work_min,
|
'work_min': work_min,
|
||||||
'work_max': work_max,
|
'work_max': work_max,
|
||||||
'notes': notes,
|
'notes': notes,
|
||||||
'plottype': 'line',
|
|
||||||
'name': name,
|
'name': name,
|
||||||
|
'plotcircles': plotcircles,
|
||||||
|
'plotlines': plotlines,
|
||||||
})
|
})
|
||||||
plottype = 'line'
|
|
||||||
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
@@ -468,10 +471,11 @@ def workout_forcecurve_view(request, id=0, analysis=0, userid=0, workstrokesonly
|
|||||||
work_max = form.cleaned_data['work_max']
|
work_max = form.cleaned_data['work_max']
|
||||||
notes = form.cleaned_data['notes']
|
notes = form.cleaned_data['notes']
|
||||||
name = form.cleaned_data['name']
|
name = form.cleaned_data['name']
|
||||||
|
plotlines = form.cleaned_data['plotlines']
|
||||||
|
plotcircles = form.cleaned_data['plotcircles']
|
||||||
if not name:
|
if not name:
|
||||||
name = row.name
|
name = row.name
|
||||||
includereststrokes = form.cleaned_data['includereststrokes']
|
includereststrokes = form.cleaned_data['includereststrokes']
|
||||||
plottype = form.cleaned_data['plottype']
|
|
||||||
workstrokesonly = not includereststrokes
|
workstrokesonly = not includereststrokes
|
||||||
|
|
||||||
if "_save" in request.POST and "new" not in request.POST: # pragma: no cover
|
if "_save" in request.POST and "new" not in request.POST: # pragma: no cover
|
||||||
@@ -488,6 +492,8 @@ def workout_forcecurve_view(request, id=0, analysis=0, userid=0, workstrokesonly
|
|||||||
spm_min = spm_min,
|
spm_min = spm_min,
|
||||||
spm_max = spm_max,
|
spm_max = spm_max,
|
||||||
rower=row.user,
|
rower=row.user,
|
||||||
|
plotlines = plotlines,
|
||||||
|
plotcircles = plotcircles,
|
||||||
include_rest_strokes = includereststrokes,
|
include_rest_strokes = includereststrokes,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -501,6 +507,8 @@ def workout_forcecurve_view(request, id=0, analysis=0, userid=0, workstrokesonly
|
|||||||
forceanalysis.work_max = work_max
|
forceanalysis.work_max = work_max
|
||||||
forceanalysis.spm_min = spm_min
|
forceanalysis.spm_min = spm_min
|
||||||
forceanalysis.spm_max = spm_max
|
forceanalysis.spm_max = spm_max
|
||||||
|
forceanalysis.plotcircles = plotcircles
|
||||||
|
forceanalysis.plotlines = plotlines
|
||||||
forceanalysis.include_rest_strokes = includereststrokes
|
forceanalysis.include_rest_strokes = includereststrokes
|
||||||
forceanalysis.save()
|
forceanalysis.save()
|
||||||
dosave = True
|
dosave = True
|
||||||
@@ -526,20 +534,10 @@ def workout_forcecurve_view(request, id=0, analysis=0, userid=0, workstrokesonly
|
|||||||
|
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
workstrokesonly = True
|
workstrokesonly = True
|
||||||
plottype = 'line'
|
|
||||||
|
|
||||||
|
|
||||||
script, div, js_resources, css_resources = interactive_forcecurve(
|
script, div = interactive_forcecurve(
|
||||||
[row],
|
[row]
|
||||||
workstrokesonly=workstrokesonly,
|
|
||||||
plottype=plottype,
|
|
||||||
dist_min = dist_min,
|
|
||||||
dist_max = dist_max,
|
|
||||||
spm_min = spm_min,
|
|
||||||
spm_max = spm_max,
|
|
||||||
work_min = work_min,
|
|
||||||
work_max = work_max,
|
|
||||||
notes=notes,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
@@ -580,8 +578,6 @@ def workout_forcecurve_view(request, id=0, analysis=0, userid=0, workstrokesonly
|
|||||||
'work_max': work_max,
|
'work_max': work_max,
|
||||||
'annotation': notes,
|
'annotation': notes,
|
||||||
'the_div': div,
|
'the_div': div,
|
||||||
'js_res': js_resources,
|
|
||||||
'css_res': css_resources,
|
|
||||||
'id': id,
|
'id': id,
|
||||||
'mayedit': mayedit,
|
'mayedit': mayedit,
|
||||||
'teams': get_my_teams(request.user),
|
'teams': get_my_teams(request.user),
|
||||||
@@ -633,50 +629,6 @@ def otw_use_gps(request, id=0):
|
|||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
# Show Stroke power histogram for a workout
|
|
||||||
@login_required()
|
|
||||||
@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)
|
|
||||||
def workout_histo_view(request, id=0):
|
|
||||||
w = get_workoutuser(id, request)
|
|
||||||
r = getrequestrower(request)
|
|
||||||
|
|
||||||
mayedit = 0
|
|
||||||
if w.user == r:
|
|
||||||
mayedit = 1
|
|
||||||
|
|
||||||
res = interactive_histoall([w], 'power', False)
|
|
||||||
script = res[0]
|
|
||||||
div = res[1]
|
|
||||||
|
|
||||||
breadcrumbs = [
|
|
||||||
{
|
|
||||||
'url': '/rowers/list-workouts/',
|
|
||||||
'name': 'Workouts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': get_workout_default_page(request, id),
|
|
||||||
'name': w.name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': reverse('workout_histo_view', kwargs={'id': id}),
|
|
||||||
'name': 'Histogram'
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
return render(request,
|
|
||||||
'histo_single.html',
|
|
||||||
{'interactiveplot': script,
|
|
||||||
'breadcrumbs': breadcrumbs,
|
|
||||||
'active': 'nav-workouts',
|
|
||||||
'workout': w,
|
|
||||||
'rower': r,
|
|
||||||
'the_div': div,
|
|
||||||
'id': id,
|
|
||||||
'mayedit': mayedit,
|
|
||||||
'teams': get_my_teams(request.user),
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
# add a workout manually
|
# add a workout manually
|
||||||
@login_required()
|
@login_required()
|
||||||
@@ -1343,7 +1295,7 @@ def remove_power_view(request, id=0):
|
|||||||
row = rdata(csvfile=f, rower=rr)
|
row = rdata(csvfile=f, rower=rr)
|
||||||
row.df[' Power (watts)'] = 0
|
row.df[' Power (watts)'] = 0
|
||||||
row.write_csv(f)
|
row.write_csv(f)
|
||||||
_ = dataprep.dataprep(row.df, id=workout.id)
|
_ = dataprep.dataplep(row.df, id=workout.id)
|
||||||
cpdf, delta, cpvalues = dataprep.setcp(workout)
|
cpdf, delta, cpvalues = dataprep.setcp(workout)
|
||||||
|
|
||||||
workout.normp = 0
|
workout.normp = 0
|
||||||
@@ -1667,15 +1619,10 @@ def course_compare_view(request, id=0):
|
|||||||
except: # pragma: no cover
|
except: # pragma: no cover
|
||||||
labeldict = {}
|
labeldict = {}
|
||||||
|
|
||||||
res = interactive_multiple_compare_chart(workoutids, xparam, yparam,
|
script, div = interactive_multiple_compare_chart(workoutids, xparam, yparam,
|
||||||
promember=promember,
|
promember=promember,
|
||||||
plottype=plottype,
|
plottype=plottype,
|
||||||
labeldict=labeldict, startenddict=startenddict)
|
labeldict=labeldict, startenddict=startenddict)
|
||||||
script = res[0]
|
|
||||||
div = res[1]
|
|
||||||
errormessage = res[3]
|
|
||||||
if errormessage != '': # pragma: no cover
|
|
||||||
messages.error(request, errormessage)
|
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
{
|
{
|
||||||
@@ -1849,15 +1796,10 @@ def virtualevent_compare_view(request, id=0):
|
|||||||
except: # pragma: no cover
|
except: # pragma: no cover
|
||||||
labeldict = {}
|
labeldict = {}
|
||||||
|
|
||||||
res = interactive_multiple_compare_chart(workoutids, xparam, yparam,
|
script, div = interactive_multiple_compare_chart(workoutids, xparam, yparam,
|
||||||
promember=promember,
|
promember=promember,
|
||||||
plottype=plottype,
|
plottype=plottype,
|
||||||
labeldict=labeldict, startenddict=startenddict)
|
labeldict=labeldict, startenddict=startenddict)
|
||||||
script = res[0]
|
|
||||||
div = res[1]
|
|
||||||
errormessage = res[3]
|
|
||||||
if errormessage != '': # pragma: no cover
|
|
||||||
messages.error(request, errormessage)
|
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
{
|
{
|
||||||
@@ -2237,10 +2179,6 @@ def workouts_view(request, message='', successmessage='',
|
|||||||
for w in workoutsnohr: # pragma: no cover
|
for w in workoutsnohr: # pragma: no cover
|
||||||
_ = dataprep.workout_trimp(w)
|
_ = dataprep.workout_trimp(w)
|
||||||
|
|
||||||
# ids = [w.id for w in workouts]
|
|
||||||
# df = dataprep.getsmallrowdata_db(['time','power'],ids=ids)
|
|
||||||
# polarization = dataprep.polarization_index(df,r)
|
|
||||||
|
|
||||||
if query: # pragma: no cover
|
if query: # pragma: no cover
|
||||||
query_list = query.split()
|
query_list = query.split()
|
||||||
workouts = workouts.filter(
|
workouts = workouts.filter(
|
||||||
@@ -2278,7 +2216,7 @@ def workouts_view(request, message='', successmessage='',
|
|||||||
if yaxis not in ['duration', 'trimp', 'rscore']: # pragma: no cover
|
if yaxis not in ['duration', 'trimp', 'rscore']: # pragma: no cover
|
||||||
yaxis = 'duration'
|
yaxis = 'duration'
|
||||||
|
|
||||||
script, div = interactive_activitychart(g_workouts,
|
script, div = interactive_activitychart2(g_workouts,
|
||||||
g_startdate,
|
g_startdate,
|
||||||
g_enddate,
|
g_enddate,
|
||||||
stack=stack,
|
stack=stack,
|
||||||
@@ -2823,348 +2761,6 @@ def workout_downloadmetar_view(request, id=0,
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
# Show form to update wind data
|
|
||||||
@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)
|
|
||||||
@user_passes_test(ispromember,
|
|
||||||
login_url="/rowers/paidplans",
|
|
||||||
message="This functionality requires a Pro plan or higher."
|
|
||||||
" If you are already a Pro user, please log in to access this functionality",
|
|
||||||
redirect_field_name=None)
|
|
||||||
def workout_wind_view(request, id=0, message="", successmessage=""):
|
|
||||||
row = get_workoutuser(id, request)
|
|
||||||
r = getrower(request.user)
|
|
||||||
breadcrumbs = [
|
|
||||||
{
|
|
||||||
'url': '/rowers/list-workouts/',
|
|
||||||
'name': 'Workouts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': get_workout_default_page(request, id),
|
|
||||||
'name': row.name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': reverse('workout_wind_view', kwargs={'id': id}),
|
|
||||||
'name': 'Wind'
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
# get data
|
|
||||||
f1 = row.csvfilename
|
|
||||||
u = row.user.user
|
|
||||||
r = getrower(u)
|
|
||||||
|
|
||||||
# create bearing
|
|
||||||
rowdata = rdata(csvfile=f1)
|
|
||||||
if row == 0: # pragma: no cover
|
|
||||||
return HttpResponse("Error: CSV Data File Not Found")
|
|
||||||
|
|
||||||
hascoordinates = 1
|
|
||||||
try:
|
|
||||||
latitude = rowdata.df.loc[:, ' latitude']
|
|
||||||
except KeyError:
|
|
||||||
hascoordinates = 0
|
|
||||||
|
|
||||||
if hascoordinates and not latitude.std(): # pragma: no cover
|
|
||||||
hascoordinates = 0
|
|
||||||
|
|
||||||
try:
|
|
||||||
_ = rowdata.df.loc[:, 'bearing'].values
|
|
||||||
except KeyError:
|
|
||||||
rowdata.add_bearing()
|
|
||||||
rowdata.write_csv(f1, gzip=True)
|
|
||||||
|
|
||||||
if hascoordinates:
|
|
||||||
avglat = rowdata.df[' latitude'].mean()
|
|
||||||
avglon = rowdata.df[' longitude'].mean()
|
|
||||||
airportcode, newlat, newlon, airportdistance = get_airport_code(
|
|
||||||
avglat, avglon)
|
|
||||||
airportcode = airportcode.upper()
|
|
||||||
airportdistance = airportdistance[0]
|
|
||||||
else:
|
|
||||||
airportcode = 'UNKNOWN'
|
|
||||||
airportdistance = 0
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
# process form
|
|
||||||
form = UpdateWindForm(request.POST)
|
|
||||||
|
|
||||||
if form.is_valid():
|
|
||||||
|
|
||||||
vwind1 = form.cleaned_data['vwind1']
|
|
||||||
vwind2 = form.cleaned_data['vwind2']
|
|
||||||
dist1 = form.cleaned_data['dist1']
|
|
||||||
dist2 = form.cleaned_data['dist2']
|
|
||||||
winddirection1 = form.cleaned_data['winddirection1']
|
|
||||||
winddirection2 = form.cleaned_data['winddirection2']
|
|
||||||
windunit = form.cleaned_data['windunit']
|
|
||||||
|
|
||||||
rowdata.update_wind(vwind1, vwind2,
|
|
||||||
winddirection1,
|
|
||||||
winddirection2,
|
|
||||||
dist1, dist2,
|
|
||||||
units=windunit)
|
|
||||||
|
|
||||||
rowdata.write_csv(f1, gzip=True)
|
|
||||||
|
|
||||||
else: # pragma: no cover
|
|
||||||
message = "Invalid Form"
|
|
||||||
messages.error(request, message)
|
|
||||||
kwargs = {
|
|
||||||
'id': id
|
|
||||||
}
|
|
||||||
url = reverse('workout_wind_view', kwargs=kwargs)
|
|
||||||
_ = HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
else:
|
|
||||||
form = UpdateWindForm()
|
|
||||||
|
|
||||||
# create interactive plot
|
|
||||||
res = interactive_windchart(encoder.decode_hex(id), promember=1)
|
|
||||||
script = res[0]
|
|
||||||
div = res[1]
|
|
||||||
|
|
||||||
if hascoordinates:
|
|
||||||
gmscript, gmdiv = leaflet_chart(
|
|
||||||
rowdata.df[' latitude'],
|
|
||||||
rowdata.df[' longitude'],
|
|
||||||
row.name)
|
|
||||||
else:
|
|
||||||
gmscript = ""
|
|
||||||
gmdiv = "No GPS data available"
|
|
||||||
|
|
||||||
messages.info(request, successmessage)
|
|
||||||
messages.error(request, message)
|
|
||||||
|
|
||||||
return render(request,
|
|
||||||
'windedit.html',
|
|
||||||
{'workout': row,
|
|
||||||
'rower': r,
|
|
||||||
'breadcrumbs': breadcrumbs,
|
|
||||||
'active': 'nav-workouts',
|
|
||||||
'teams': get_my_teams(request.user),
|
|
||||||
'interactiveplot': script,
|
|
||||||
'form': form,
|
|
||||||
'airport': airportcode,
|
|
||||||
'airportdistance': airportdistance,
|
|
||||||
'the_div': div,
|
|
||||||
'gmap': gmscript,
|
|
||||||
'gmapdiv': gmdiv})
|
|
||||||
|
|
||||||
|
|
||||||
# Show form to update River stream data (for river dwellers)
|
|
||||||
@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)
|
|
||||||
@user_passes_test(ispromember,
|
|
||||||
login_url="/rowers/paidplans",
|
|
||||||
message="This functionality requires a Pro plan or higher."
|
|
||||||
" If you are already a Pro user, please log in to access this functionality",
|
|
||||||
redirect_field_name=None)
|
|
||||||
def workout_stream_view(request, id=0, message="", successmessage=""):
|
|
||||||
row = get_workoutuser(id, request)
|
|
||||||
r = getrower(request.user)
|
|
||||||
|
|
||||||
# create interactive plot
|
|
||||||
f1 = row.csvfilename
|
|
||||||
u = row.user.user
|
|
||||||
r = getrower(u)
|
|
||||||
|
|
||||||
rowdata = rdata(csvfile=f1)
|
|
||||||
if rowdata == 0: # pragma: no cover
|
|
||||||
messages.info(request, "Error: CSV data file not found")
|
|
||||||
url = reverse('workout_edit_view', kwargs={
|
|
||||||
'id': encoder.encode_hex(row.id)})
|
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
# process form
|
|
||||||
form = UpdateStreamForm(request.POST)
|
|
||||||
|
|
||||||
if form.is_valid():
|
|
||||||
|
|
||||||
dist1 = form.cleaned_data['dist1']
|
|
||||||
dist2 = form.cleaned_data['dist2']
|
|
||||||
stream1 = form.cleaned_data['stream1']
|
|
||||||
stream2 = form.cleaned_data['stream2']
|
|
||||||
streamunit = form.cleaned_data['streamunit']
|
|
||||||
|
|
||||||
rowdata.update_stream(stream1, stream2, dist1, dist2,
|
|
||||||
units=streamunit)
|
|
||||||
|
|
||||||
rowdata.write_csv(f1, gzip=True)
|
|
||||||
|
|
||||||
else: # pragma: no cover
|
|
||||||
message = "Invalid Form"
|
|
||||||
messages.error(request, message)
|
|
||||||
kwargs = {
|
|
||||||
'id': id}
|
|
||||||
url = reverse('workout_wind_view', kwargs=kwargs)
|
|
||||||
_ = HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
else:
|
|
||||||
form = UpdateStreamForm()
|
|
||||||
|
|
||||||
# create interactive plot
|
|
||||||
res = interactive_streamchart(encoder.decode_hex(id), promember=1)
|
|
||||||
script = res[0]
|
|
||||||
div = res[1]
|
|
||||||
|
|
||||||
breadcrumbs = [
|
|
||||||
{
|
|
||||||
'url': '/rowers/list-workouts/',
|
|
||||||
'name': 'Workouts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': get_workout_default_page(request, id),
|
|
||||||
'name': row.name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': reverse('workout_stream_view', kwargs={'id': id}),
|
|
||||||
'name': 'Stream'
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
messages.info(request, successmessage)
|
|
||||||
messages.error(request, message)
|
|
||||||
return render(request,
|
|
||||||
'streamedit.html',
|
|
||||||
{'workout': row,
|
|
||||||
'rower': r,
|
|
||||||
'breadcrumbs': breadcrumbs,
|
|
||||||
'active': 'nav-workouts',
|
|
||||||
'teams': get_my_teams(request.user),
|
|
||||||
'interactiveplot': script,
|
|
||||||
'form': form,
|
|
||||||
'the_div': div})
|
|
||||||
|
|
||||||
# Form to set average crew weight and boat type, then run power calcs
|
|
||||||
|
|
||||||
|
|
||||||
@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)
|
|
||||||
@user_passes_test(ispromember, login_url="/rowers/paidplans", redirect_field_name=None)
|
|
||||||
def workout_otwsetpower_view(request, id=0, message="", successmessage=""):
|
|
||||||
w = get_workoutuser(id, request)
|
|
||||||
r = getrower(request.user)
|
|
||||||
|
|
||||||
mayedit = 1
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
# process form
|
|
||||||
form = AdvancedWorkoutForm(request.POST)
|
|
||||||
|
|
||||||
if form.is_valid():
|
|
||||||
boattype = form.cleaned_data['boattype']
|
|
||||||
weightvalue = form.cleaned_data['weightvalue']
|
|
||||||
coastalbrand = form.cleaned_data['boatbrand']
|
|
||||||
boatclass = w.workouttype
|
|
||||||
w.boattype = boattype
|
|
||||||
w.weightvalue = weightvalue
|
|
||||||
w.boatbrand = coastalbrand
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
# load row data & create power/wind/bearing columns if not set
|
|
||||||
f1 = w.csvfilename
|
|
||||||
rowdata = rdata(csvfile=f1)
|
|
||||||
if rowdata == 0: # pragma: no cover
|
|
||||||
return HttpResponse("Error: CSV Data File Not Found")
|
|
||||||
try:
|
|
||||||
_ = rowdata.df['vstream']
|
|
||||||
except KeyError:
|
|
||||||
rowdata.add_stream(0)
|
|
||||||
rowdata.write_csv(f1, gzip=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
_ = rowdata.df['bearing']
|
|
||||||
except KeyError:
|
|
||||||
rowdata.add_bearing()
|
|
||||||
rowdata.write_csv(f1, gzip=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
_ = rowdata.df['vwind']
|
|
||||||
except KeyError:
|
|
||||||
rowdata.add_wind(0, 0)
|
|
||||||
rowdata.write_csv(f1, gzip=True)
|
|
||||||
|
|
||||||
# do power calculation (asynchronous)
|
|
||||||
r = w.user
|
|
||||||
u = r.user
|
|
||||||
|
|
||||||
first_name = u.first_name
|
|
||||||
last_name = u.last_name
|
|
||||||
emailaddress = u.email
|
|
||||||
|
|
||||||
job = myqueue(queue,
|
|
||||||
handle_otwsetpower, f1, boattype, boatclass, coastalbrand,
|
|
||||||
weightvalue,
|
|
||||||
first_name, last_name, emailaddress, encoder.decode_hex(
|
|
||||||
id),
|
|
||||||
ps=[r.p0, r.p1, r.p2, r.p3],
|
|
||||||
ratio=r.cpratio,
|
|
||||||
# quick_calc = quick_calc,
|
|
||||||
# go_service=go_service,
|
|
||||||
emailbounced=r.emailbounced
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
request.session['async_tasks'] += [(job.id, 'otwsetpower')]
|
|
||||||
except KeyError:
|
|
||||||
request.session['async_tasks'] = [(job.id, 'otwsetpower')]
|
|
||||||
|
|
||||||
successmessage = 'Your calculations have been submitted." \
|
|
||||||
" You will receive an email when they are done." \
|
|
||||||
" You can check the status of your calculations" \
|
|
||||||
" <a href="/rowers/jobs-status/" target="_blank">here</a>'
|
|
||||||
messages.info(request, successmessage)
|
|
||||||
kwargs = {
|
|
||||||
'id': id}
|
|
||||||
|
|
||||||
try:
|
|
||||||
url = request.session['referer']
|
|
||||||
except KeyError:
|
|
||||||
url = reverse('workout_edit_view', kwargs=kwargs)
|
|
||||||
|
|
||||||
response = HttpResponseRedirect(url)
|
|
||||||
return response
|
|
||||||
|
|
||||||
else: # pragma: no cover
|
|
||||||
message = "Invalid Form"
|
|
||||||
messages.error(request, message)
|
|
||||||
kwargs = {
|
|
||||||
'id': id}
|
|
||||||
url = reverse('workout_otwsetpower_view', kwargs=kwargs)
|
|
||||||
response = HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
else:
|
|
||||||
form = AdvancedWorkoutForm(instance=w)
|
|
||||||
|
|
||||||
breadcrumbs = [
|
|
||||||
{
|
|
||||||
'url': '/rowers/list-workouts/',
|
|
||||||
'name': 'Workouts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': get_workout_default_page(request, id),
|
|
||||||
'name': w.name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': reverse('workout_otwsetpower_view', kwargs={'id': id}),
|
|
||||||
'name': 'OTW Power'
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
messages.error(request, message)
|
|
||||||
messages.info(request, successmessage)
|
|
||||||
return render(request,
|
|
||||||
'otwsetpower.html',
|
|
||||||
{'workout': w,
|
|
||||||
'rower': w,
|
|
||||||
'mayedit': mayedit,
|
|
||||||
'active': 'nav-workouts',
|
|
||||||
'breadcrumbs': breadcrumbs,
|
|
||||||
'teams': get_my_teams(request.user),
|
|
||||||
'form': form,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)
|
@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)
|
||||||
@@ -3598,7 +3194,7 @@ def workout_erase_column_view(request, id=0, column=''):
|
|||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = dataprep.getsmallrowdata_db([column], ids=[w.id])
|
data = dataprep.read_data([column], ids=[w.id])
|
||||||
except: # pragma: no cover
|
except: # pragma: no cover
|
||||||
messages.error(request, 'Invalid column')
|
messages.error(request, 'Invalid column')
|
||||||
url = reverse('workout_data_view', kwargs={
|
url = reverse('workout_data_view', kwargs={
|
||||||
@@ -3654,12 +3250,18 @@ def workout_erase_column_view(request, id=0, column=''):
|
|||||||
|
|
||||||
row, workout = dataprep.getrowdata(id=w.id)
|
row, workout = dataprep.getrowdata(id=w.id)
|
||||||
row.df[columnl] = defaultvalue
|
row.df[columnl] = defaultvalue
|
||||||
|
try:
|
||||||
os.remove(w.csvfilename+'.gz')
|
os.remove(w.csvfilename+'.gz')
|
||||||
|
except FileNotFoundError:
|
||||||
|
try:
|
||||||
|
os.remove(w.csvfilename)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
row.write_csv(w.csvfilename, gzip=True)
|
row.write_csv(w.csvfilename, gzip=True)
|
||||||
|
|
||||||
row, workout = dataprep.getrowdata(id=w.id)
|
row, workout = dataprep.getrowdata(id=w.id)
|
||||||
_ = dataprep.dataprep(row.df, id=w.id)
|
_ = dataprep.dataplep(row.df, id=w.id)
|
||||||
|
|
||||||
if column == 'hr':
|
if column == 'hr':
|
||||||
w.hrtss = 0
|
w.hrtss = 0
|
||||||
@@ -4141,7 +3743,7 @@ def workout_workflow_view(request, id):
|
|||||||
|
|
||||||
if 'panel_map.html' in r.workflowmiddlepanel and rowhascoordinates(row):
|
if 'panel_map.html' in r.workflowmiddlepanel and rowhascoordinates(row):
|
||||||
rowdata = rdata(csvfile=row.csvfilename)
|
rowdata = rdata(csvfile=row.csvfilename)
|
||||||
mapscript, mapdiv = leaflet_chart2(rowdata.df[' latitude'],
|
mapscript, mapdiv = leaflet_chart(rowdata.df[' latitude'],
|
||||||
rowdata.df[' longitude'],
|
rowdata.df[' longitude'],
|
||||||
row.name)
|
row.name)
|
||||||
else:
|
else:
|
||||||
@@ -4370,7 +3972,7 @@ def workout_flexchart3_view(request, *args, **kwargs):
|
|||||||
|
|
||||||
# create interactive plot
|
# create interactive plot
|
||||||
(
|
(
|
||||||
script, div, js_resources, css_resources, workstrokesonly
|
script, div, workstrokesonly
|
||||||
) = interactive_flex_chart2(
|
) = interactive_flex_chart2(
|
||||||
encoder.decode_hex(id), request.user.rower,
|
encoder.decode_hex(id), request.user.rower,
|
||||||
xparam=xparam, yparam1=yparam1,
|
xparam=xparam, yparam1=yparam1,
|
||||||
@@ -4456,8 +4058,6 @@ def workout_flexchart3_view(request, *args, **kwargs):
|
|||||||
'workout': row,
|
'workout': row,
|
||||||
'chartform': flexaxesform,
|
'chartform': flexaxesform,
|
||||||
'optionsform': flexoptionsform,
|
'optionsform': flexoptionsform,
|
||||||
'js_res': js_resources,
|
|
||||||
'css_res': css_resources,
|
|
||||||
'teams': get_my_teams(request.user),
|
'teams': get_my_teams(request.user),
|
||||||
'id': id,
|
'id': id,
|
||||||
'xparam': xparam,
|
'xparam': xparam,
|
||||||
@@ -4505,7 +4105,7 @@ def workout_flexchart_stacked_view(request, *args, **kwargs):
|
|||||||
yparam4 = cd['yaxis4']
|
yparam4 = cd['yaxis4']
|
||||||
|
|
||||||
(
|
(
|
||||||
script, div, js_resources, css_resources, comment
|
script, div
|
||||||
) = interactive_flexchart_stacked(
|
) = interactive_flexchart_stacked(
|
||||||
encoder.decode_hex(id), r, xparam=xparam,
|
encoder.decode_hex(id), r, xparam=xparam,
|
||||||
yparam1=yparam1,
|
yparam1=yparam1,
|
||||||
@@ -4515,9 +4115,6 @@ def workout_flexchart_stacked_view(request, *args, **kwargs):
|
|||||||
mode=workout.workouttype,
|
mode=workout.workouttype,
|
||||||
)
|
)
|
||||||
|
|
||||||
if comment is not None: # pragma: no cover
|
|
||||||
messages.error(request, comment)
|
|
||||||
|
|
||||||
initial = {
|
initial = {
|
||||||
'xaxis': xparam,
|
'xaxis': xparam,
|
||||||
'yaxis1': yparam1,
|
'yaxis1': yparam1,
|
||||||
@@ -4554,8 +4151,6 @@ def workout_flexchart_stacked_view(request, *args, **kwargs):
|
|||||||
'active': 'nav-workouts',
|
'active': 'nav-workouts',
|
||||||
'workout': workout,
|
'workout': workout,
|
||||||
'chartform': flexaxesform,
|
'chartform': flexaxesform,
|
||||||
'js_res': js_resources,
|
|
||||||
'css_res': css_resources,
|
|
||||||
'id': id,
|
'id': id,
|
||||||
'xparam': xparam,
|
'xparam': xparam,
|
||||||
'yparam1': yparam1,
|
'yparam1': yparam1,
|
||||||
@@ -4568,57 +4163,6 @@ def workout_flexchart_stacked_view(request, *args, **kwargs):
|
|||||||
# The interactive plot with wind corrected pace for OTW outings
|
# The interactive plot with wind corrected pace for OTW outings
|
||||||
|
|
||||||
|
|
||||||
def workout_otwpowerplot_view(request, id=0, message="", successmessage=""):
|
|
||||||
w = get_workout(id)
|
|
||||||
r = getrower(request.user)
|
|
||||||
|
|
||||||
breadcrumbs = [
|
|
||||||
{
|
|
||||||
'url': '/rowers/list-workouts/',
|
|
||||||
'name': 'Workouts'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': get_workout_default_page(request, id),
|
|
||||||
'name': w.name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'url': reverse('workout_otwpowerplot_view', kwargs={'id': id}),
|
|
||||||
'name': 'Interactive OTW Power Plot'
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
# check if user is owner of this workout
|
|
||||||
|
|
||||||
# create interactive plot
|
|
||||||
|
|
||||||
promember = 0
|
|
||||||
mayedit = 0
|
|
||||||
result = request.user.is_authenticated and ispromember(request.user)
|
|
||||||
if result:
|
|
||||||
promember = 1
|
|
||||||
if request.user == w.user.user:
|
|
||||||
mayedit = 1
|
|
||||||
|
|
||||||
# create interactive plot
|
|
||||||
res = interactive_otw_advanced_pace_chart(
|
|
||||||
encoder.decode_hex(id), promember=promember)
|
|
||||||
script = res[0]
|
|
||||||
div = res[1]
|
|
||||||
|
|
||||||
messages.error(request, message)
|
|
||||||
messages.info(request, successmessage)
|
|
||||||
|
|
||||||
return render(request,
|
|
||||||
'otwinteractive.html',
|
|
||||||
{'workout': w,
|
|
||||||
'rower': r,
|
|
||||||
'active': 'nav-workouts',
|
|
||||||
'breadcrumbs': breadcrumbs,
|
|
||||||
'teams': get_my_teams(request.user),
|
|
||||||
'interactiveplot': script,
|
|
||||||
'the_div': div,
|
|
||||||
'mayedit': mayedit})
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -4780,7 +4324,7 @@ def workout_edit_view(request, id=0, message="", successmessage=""):
|
|||||||
row = get_workoutuser(id, request)
|
row = get_workoutuser(id, request)
|
||||||
|
|
||||||
if request.user.rower.rowerplan == 'basic' and 'speedcoach2' in row.workoutsource: # pragma: no cover
|
if request.user.rower.rowerplan == 'basic' and 'speedcoach2' in row.workoutsource: # pragma: no cover
|
||||||
data = getsmallrowdata_db(['wash'], ids=[encoder.decode_hex(id)])
|
data = read_data(['wash'], ids=[encoder.decode_hex(id)])
|
||||||
try:
|
try:
|
||||||
if data['wash'].std() != 0:
|
if data['wash'].std() != 0:
|
||||||
url = reverse('paidplans_view')
|
url = reverse('paidplans_view')
|
||||||
@@ -4793,7 +4337,7 @@ def workout_edit_view(request, id=0, message="", successmessage=""):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
if request.user.rower.rowerplan == 'basic' and 'nklinklogbook' in row.workoutsource: # pragma: no cover
|
if request.user.rower.rowerplan == 'basic' and 'nklinklogbook' in row.workoutsource: # pragma: no cover
|
||||||
data = getsmallrowdata_db(['wash'], ids=[encoder.decode_hex(id)])
|
data = read_data(['wash'], ids=[encoder.decode_hex(id)])
|
||||||
try:
|
try:
|
||||||
if data['wash'].std() != 0:
|
if data['wash'].std() != 0:
|
||||||
url = reverse('paidplans_view')
|
url = reverse('paidplans_view')
|
||||||
@@ -5063,7 +4607,7 @@ def workout_map_view(request, id=0):
|
|||||||
hascoordinates = 0
|
hascoordinates = 0
|
||||||
|
|
||||||
if hascoordinates:
|
if hascoordinates:
|
||||||
mapscript, mapdiv = leaflet_chart2(rowdata.df[' latitude'],
|
mapscript, mapdiv = leaflet_chart(rowdata.df[' latitude'],
|
||||||
rowdata.df[' longitude'],
|
rowdata.df[' longitude'],
|
||||||
w.name)
|
w.name)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -599,6 +599,13 @@ except KeyError: # pragma: no cover
|
|||||||
WORKOUTS_FIT_TOKEN = 'aapnootmies'
|
WORKOUTS_FIT_TOKEN = 'aapnootmies'
|
||||||
WORKOUTS_FIT_URL = 'http://localhost:50053/tojson'
|
WORKOUTS_FIT_URL = 'http://localhost:50053/tojson'
|
||||||
|
|
||||||
|
try:
|
||||||
|
ROWSANDALL_CHARTS_TOKEN = CFG['rowsandall_charts_token']
|
||||||
|
ROWSANDALL_CHARTS_URL = CFG['rowsandall_charts_url']
|
||||||
|
except KeyError:
|
||||||
|
ROWSANDALL_CHARTS_TOKEN = 'aapnootmies'
|
||||||
|
ROWSANDALL_CHARTS_URL = 'http://localhost:3000'
|
||||||
|
|
||||||
# Recaptcha
|
# Recaptcha
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -32,6 +32,16 @@
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chart {
|
||||||
|
background-image: url(/static/img/logo7.png);
|
||||||
|
background-size: 200px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: top 50px right 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chartlabel {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
.watermark {
|
.watermark {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
Reference in New Issue
Block a user