Private
Public Access
1
0

Merge branch 'feature/tasks' into develop

This commit is contained in:
Sander Roosendaal
2022-07-14 17:57:06 +02:00
13 changed files with 1983 additions and 2700 deletions

View File

@@ -23,12 +23,12 @@ def time_in_path(df, p, maxmin='max', getall=False, name='unknown', logfile=None
def f(x): def f(x):
return coordinate_in_path(x['latitude'], x['longitude'], p) return coordinate_in_path(x['latitude'], x['longitude'], p)
df['inpolygon'] = df.apply(f, axis=1) inpolygon = df.apply(lambda row:f(row), axis=1).copy()
if maxmin == 'max': if maxmin == 'max':
b = (~df['inpolygon']).shift(-1)+df['inpolygon'] b = (~inpolygon).shift(-1)+inpolygon
else: # pragma: no cover else: # pragma: no cover
b = (~df['inpolygon']).shift(1)+df['inpolygon'] b = (~inpolygon).shift(1)+inpolygon
if len(df[b == 2]): if len(df[b == 2]):
if logfile is not None: # pragma: no cover if logfile is not None: # pragma: no cover
@@ -90,7 +90,7 @@ def coursetime_first(data, paths, polygons=[], logfile=None):
try: try:
entrytime, entrydistance = time_in_path( entrytime, entrydistance = time_in_path(
data, paths[0], maxmin='max', name=polygons[0][1], logfile=logfile) data, paths[0], maxmin='max', name=str(polygons[0]), logfile=logfile)
coursecompleted = True coursecompleted = True
except InvalidTrajectoryError: # pragma: no cover except InvalidTrajectoryError: # pragma: no cover
entrytime = data['time'].max() entrytime = data['time'].max()
@@ -118,7 +118,7 @@ def coursetime_paths(data, paths, finalmaxmin='min', polygons=[], logfile=None):
( (
entrytime, entrytime,
entrydistance entrydistance
) = time_in_path(data, paths[0], maxmin=finalmaxmin, name=polygons[0][1], logfile=logfile) ) = time_in_path(data, paths[0], maxmin=finalmaxmin, name=str(polygons[0]), logfile=logfile)
coursecompleted = True coursecompleted = True
except InvalidTrajectoryError: # pragma: no cover except InvalidTrajectoryError: # pragma: no cover
entrytime = data['time'].max() entrytime = data['time'].max()
@@ -129,7 +129,7 @@ def coursetime_paths(data, paths, finalmaxmin='min', polygons=[], logfile=None):
if len(paths) > 1: if len(paths) > 1:
try: try:
time, dist = time_in_path( time, dist = time_in_path(
data, paths[0], name=polygons[0][1], logfile=logfile) data, paths[0], name=str(polygons[0]), logfile=logfile)
data2 = data[data['time'] > time].copy() data2 = data[data['time'] > time].copy()
data2['time'] = data2['time'].apply(lambda x: x-time) data2['time'] = data2['time'].apply(lambda x: x-time)
data2['cum_dist'] = data2['cum_dist'].apply(lambda x: x-dist) data2['cum_dist'] = data2['cum_dist'].apply(lambda x: x-dist)

View File

@@ -16,3 +16,7 @@ database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
if settings.DEBUG or user == '': if settings.DEBUG or user == '':
database_url = 'sqlite:///db.sqlite3' database_url = 'sqlite:///db.sqlite3'
#database_name_dev = DEV_DATABASES['default']['NAME']
database_url_debug = database_url

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@ from django.shortcuts import redirect
from django.http import HttpResponse from django.http import HttpResponse
from django.contrib import messages from django.contrib import messages
from rowers.mytypes import otwtypes from rowers.mytypes import otwtypes
from rowers.tasks import handle_sendemail_expired #from rowers.tasks import handle_sendemail_expired
from django.utils import timezone from django.utils import timezone
from rowers.models import Workout, PowerTimeFitnessMetric, Rower, PaidPlan from rowers.models import Workout, PowerTimeFitnessMetric, Rower, PaidPlan
import datetime import datetime
@@ -99,6 +99,7 @@ class RowerPlanMiddleWare(object):
# remove from Free Coach groups # remove from Free Coach groups
# send email # send email
from rowers.tasks import handle_sendemail_expired
_ = myqueue(queue, _ = myqueue(queue,
handle_sendemail_expired, handle_sendemail_expired,
r.user.email, r.user.email,

View File

@@ -553,8 +553,9 @@ def polygon_coord_center(polygon):
return latitudes.mean(), longitudes.mean() return latitudes.mean(), longitudes.mean()
def polygon_to_path(polygon): def polygon_to_path(polygon, debug=False):
points = GeoPoint.objects.filter(polygon=polygon).order_by("order_in_poly") points = GeoPoint.objects.filter(polygon=polygon).order_by("order_in_poly")
s = [] s = []
for point in points: for point in points:
s.append([point.latitude, point.longitude]) s.append([point.latitude, point.longitude])

View File

@@ -1,3 +1,22 @@
import os
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
from YamJam import yamjam
CFG = yamjam()['rowsandallapp']
try:
os.environ.setdefault("DJANGO_SETTINGS_MODULE",CFG['settings_name'])
except KeyError: # pragma: no cover
os.environ.setdefault("DJANGO_SETTINGS_MODULE","rowsandall_app.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
from rowers.models import (
Workout, GeoPolygon, GeoPoint, GeoCourse,
VirtualRaceResult, CourseTestResult, Rower
)
import math import math
from rowers.courseutils import ( from rowers.courseutils import (
coursetime_paths, coursetime_first, time_in_path, coursetime_paths, coursetime_first, time_in_path,
@@ -16,8 +35,7 @@ import rowers.longtask as longtask
import requests import requests
import rowers.datautils as datautils import rowers.datautils as datautils
""" Background tasks done by Celery (develop) or QR (production) """ """ Background tasks done by QR (production) """
import os
import time import time
import gc import gc
import gzip import gzip
@@ -36,8 +54,8 @@ import rowingdata
from rowingdata import make_cumvalues from rowingdata import make_cumvalues
from uuid import uuid4 from uuid import uuid4
from rowingdata import rowingdata as rdata from rowingdata import rowingdata as rdata
from datetime import timedelta from datetime import timedelta
from sqlalchemy import create_engine
from rowers.celery import app from rowers.celery import app
from celery import shared_task from celery import shared_task
@@ -61,13 +79,15 @@ import rowers.otw_power_calculator_pb2_grpc as calculator_pb2_grpc
import rowers.rowing_workout_metrics_pb2 as metrics_pb2 import rowers.rowing_workout_metrics_pb2 as metrics_pb2
import rowers.rowing_workout_metrics_pb2_grpc as metrics_pb2_grpc import rowers.rowing_workout_metrics_pb2_grpc as metrics_pb2_grpc
from rowsandall_app.settings import SITE_URL from django.conf import settings
from rowsandall_app.settings_dev import SITE_URL as SITE_URL_DEV SITE_URL = settings.SITE_URL
from rowsandall_app.settings import PROGRESS_CACHE_SECRET SITE_URL_DEV = settings.SITE_URL
from rowsandall_app.settings import SETTINGS_NAME PROGRESS_CACHE_SECRET = settings.PROGRESS_CACHE_SECRET
from rowsandall_app.settings import workoutemailbox SETTINGS_NAME = settings.SETTINGS_NAME
from rowsandall_app.settings import UPLOAD_SERVICE_SECRET, UPLOAD_SERVICE_URL
from rowsandall_app.settings import NK_API_LOCATION UPLOAD_SERVICE_URL = settings.UPLOAD_SERVICE_URL
UPLOAD_SERVICE_SECRET = settings.UPLOAD_SERVICE_SECRET
NK_API_LOCATION = settings.NK_API_LOCATION
from requests_oauthlib import OAuth1, OAuth1Session from requests_oauthlib import OAuth1, OAuth1Session
@@ -83,16 +103,19 @@ from rowers.emails import htmlstrip
from rowers import mytypes from rowers import mytypes
from rowers.dataprepnodjango import ( from rowers.dataprep import (
getsmallrowdata_db, updatecpdata_sql, update_c2id_sql, getsmallrowdata_db, updatecpdata_sql, update_c2id_sql,
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,
create_c2_stroke_data_db, update_empower, create_c2_stroke_data_db, update_empower,
database_url_debug, database_url, dataprep, # database_url_debug,
database_url, dataprep,
# create_strava_stroke_data_db # create_strava_stroke_data_db
) )
database_url_debug = database_url
from rowers.opaque import encoder from rowers.opaque import encoder
@@ -277,7 +300,9 @@ def summaryfromsplitdata(splitdata, data, filename, sep='|', workouttype='rower'
@app.task @app.task
def handle_request_post(url, data, debug=False, **kwargs): # pragma: no cover def handle_request_post(url, data, debug=False, **kwargs): # pragma: no cover
response = requests.post(url, data) if 'localhost' in url:
url = 'http'+url[5:]
response = requests.post(url, data, verify=False)
dologging('upload_api.log', data) dologging('upload_api.log', data)
dologging('upload_api.log', response.status_code) dologging('upload_api.log', response.status_code)
return response.status_code return response.status_code
@@ -297,10 +322,11 @@ def handle_c2_sync(workoutid, url, headers, data, debug=False, **kwargs):
s = response.json() s = response.json()
c2id = s['data']['id'] c2id = s['data']['id']
res = update_workout_field_sql( workout = Workout.objects.get(id=workoutid)
workoutid, 'uploadedtoc2', c2id, debug=debug) workout.uploadedtoc2 = c2id
workout.save()
return res return 1
@app.task @app.task
@@ -316,8 +342,10 @@ def handle_sporttracks_sync(workoutid, url, headers, data, debug=False, **kwargs
id = int(m) id = int(m)
_ = update_workout_field_sql( workout = Workout.objects.get(id=workoutid)
workoutid, 'uploadedtosporttracks', id, debug=debug) workout.uploadedtosporttracks = id
workout.save()
return 1 return 1
@@ -338,7 +366,7 @@ def handle_strava_sync(stravatoken, workoutid, filename, name, activity_type, de
tb = traceback.format_exc() tb = traceback.format_exc()
dologging('strava_fail.log', tb) dologging('strava_fail.log', tb)
failed = True failed = True
except stravalib.exc.TimeoutExceeded: except stravalib.exc.TimeoutExceeded: # pragma: no cover
dologging('strava_fail.log', 'Strava upload failed for Workout {id} TimeOutExceeded'.format( dologging('strava_fail.log', 'Strava upload failed for Workout {id} TimeOutExceeded'.format(
id=workoutid)) id=workoutid))
tb = traceback.format_exc() tb = traceback.format_exc()
@@ -378,8 +406,9 @@ def handle_strava_sync(stravatoken, workoutid, filename, name, activity_type, de
failed = True failed = True
if not failed: if not failed:
_ = update_workout_field_sql( workout = Workout.objects.get(id=workoutid)
workoutid, 'uploadedtostrava', res.id, debug=debug) workout.uploadedtostrava = res.id
workout.save()
try: try:
act = client.update_activity(res.id, activity_type=activity_type, act = client.update_activity(res.id, activity_type=activity_type,
description=description, device_name='Rowsandall.com') description=description, device_name='Rowsandall.com')
@@ -507,37 +536,14 @@ def getagegrouprecord(age, sex='male', weightcategory='hwt',
return power return power
def polygon_to_path(polygon, debug=True): from rowers.models import polygon_to_path
pid = polygon[0]
query = "SELECT id, latitude, longitude FROM rowers_geopoint WHERE polygon_id = {pid}"\
" ORDER BY order_in_poly ASC".format(
pid=pid)
if debug:
engine = create_engine(database_url_debug, echo=False)
else: # pragma: no cover
engine = create_engine(database_url, echo=False)
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
points = result.fetchall()
conn.close()
engine.dispose()
s = []
for point in points:
s.append([point[1], point[2]])
p = path.Path(s[:-1])
return p
@app.task(bind=True) @app.task(bind=True)
def handle_check_race_course(self, def handle_check_race_course(self,
f1, workoutid, courseid, f1, workoutid, courseid,
recordid, useremail, userfirstname, recordid, useremail, userfirstname,
**kwargs): # pragma: no cover **kwargs):
logfile = 'courselog_{workoutid}_{courseid}.log'.format( logfile = 'courselog_{workoutid}_{courseid}.log'.format(
workoutid=workoutid, courseid=courseid) workoutid=workoutid, courseid=courseid)
@@ -567,11 +573,11 @@ def handle_check_race_course(self,
mode = kwargs['mode'] mode = kwargs['mode']
summary = False summary = False
if 'summary' in kwargs: if 'summary' in kwargs: # pragma: no cover
summary = kwargs['summary'] summary = kwargs['summary']
successemail = False successemail = False
if 'successemail' in kwargs: if 'successemail' in kwargs: # pragma: no cover
successemail = kwargs['successemail'] successemail = kwargs['successemail']
try: try:
@@ -606,35 +612,21 @@ def handle_check_race_course(self,
rowdata.fillna(method='backfill', inplace=True) rowdata.fillna(method='backfill', inplace=True)
rowdata['time'] = rowdata['time']-rowdata.loc[0, 'time'] rowdata.loc[:, 'time'] = rowdata.loc[:, 'time'].copy()-rowdata.loc[0, 'time']
rowdata = rowdata[rowdata['time'] > splitsecond] rowdata = rowdata.copy()[rowdata['time'] > splitsecond]
# we may want to expand the time (interpolate) # we may want to expand the time (interpolate)
rowdata['dt'] = rowdata['time'].apply(
rowdata.loc[:,'dt'] = rowdata['time'].apply(
lambda x: safetimedelta(x) lambda x: safetimedelta(x)
) ).values
rowdata = rowdata.resample('100ms', on='dt').mean() rowdata = rowdata.resample('100ms', on='dt').mean()
rowdata = rowdata.interpolate() rowdata = rowdata.interpolate()
# initiate database engine course = GeoCourse.objects.get(id=courseid)
polygons = course.polygons.all()
if debug: # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
# get polygons
query = "SELECT id,name FROM rowers_geopolygon WHERE course_id = {courseid} ORDER BY order_in_course ASC".format(
courseid=courseid
)
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
polygons = result.fetchall()
conn.close()
engine.dispose()
paths = [] paths = []
for polygon in polygons: for polygon in polygons:
@@ -649,7 +641,7 @@ def handle_check_race_course(self,
try: try:
entrytimes, entrydistances = time_in_path(rowdata, paths[0], maxmin='max', getall=True, entrytimes, entrydistances = time_in_path(rowdata, paths[0], maxmin='max', getall=True,
name=polygons[0].name, logfile=logfile) name=polygons[0].name, logfile=logfile)
except AttributeError: # for testing except AttributeError: # pragma: no cover
entrytimes, entrydistances = time_in_path(rowdata, paths[0], maxmin='max', getall=True, entrytimes, entrydistances = time_in_path(rowdata, paths[0], maxmin='max', getall=True,
name='Start', logfile=logfile) name='Start', logfile=logfile)
with open(logfile, 'ab') as f: with open(logfile, 'ab') as f:
@@ -718,7 +710,8 @@ def handle_check_race_course(self,
'endsecond': endseconds, 'endsecond': endseconds,
}) })
records = records[records['coursecompleted'] is True] #records = records[records['coursecompleted'] is True]
records = records.loc[records['coursecompleted'], : ]
if len(records): if len(records):
coursecompleted = True coursecompleted = True
@@ -736,35 +729,29 @@ def handle_check_race_course(self,
coursedistance = coursemeters coursedistance = coursemeters
velo = coursedistance/coursetimeseconds velo = coursedistance/coursetimeseconds
points = 100*(2.-referencespeed/velo) points = 100*(2.-referencespeed/velo)
query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1,'\
' duration = "{duration}", distance = {distance},'\
' workoutid = {workoutid}, startsecond = {startsecond},'\
' endsecond = {endsecond}, points={points} WHERE id={recordid}'.format(
recordid=recordid,
duration=totaltime_sec_to_string(coursetimeseconds),
distance=int(coursemeters),
points=points,
workoutid=workoutid,
startsecond=startsecond,
endsecond=endsecond,)
if mode == 'coursetest': if mode != 'coursetest':
query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1,'\ record = VirtualRaceResult.objects.get(id=recordid)
' duration = "{duration}", distance = {distance},'\ record.duration = totaltime_sec_to_string(coursetimeseconds)
' workoutid = {workoutid}, startsecond = {startsecond},'\ record.distance=int(coursemeters)
' endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( record.points = points
recordid=recordid, record.startsecond = startsecond
duration=totaltime_sec_to_string(coursetimeseconds), record.endsecond = endsecond
distance=int(coursemeters), record.workoutid = workoutid
points=points, record.coursecompleted = 1
workoutid=workoutid, record.save()
startsecond=startsecond,
endsecond=endsecond,)
with engine.connect() as conn, conn.begin(): else: # pragma: no cover
result = conn.execute(query) record = CourseTestResult.objects.get(id=recordid)
record.duration = totaltime_sec_to_string(coursetimeseconds)
record.distance = int(coursemeters)
record.workoutid = workoutid
record.startsecond = startsecond
record.endsecond = endsecond
record.points = points
record.save()
if summary: if summary: # pragma: no cover
try: try:
row = rdata(csvfile=f1) row = rdata(csvfile=f1)
except IOError: # pragma: no cover except IOError: # pragma: no cover
@@ -784,17 +771,12 @@ def handle_check_race_course(self,
summary = row.allstats() summary = row.allstats()
row.write_csv(f1, gzip=True) row.write_csv(f1, gzip=True)
workout = Workout.objects.get(id=workoutid)
workout.summary = summary
workout.save()
query = "UPDATE `rowers_workout` SET `summary` = '%s' WHERE `id` = %s" % (
summary, workoutid)
with engine.connect() as conn, conn.begin(): if successemail: # pragma: no cover
result = conn.execute(query)
conn.close()
engine.dispose()
if successemail:
handle_sendemail_coursesucceed( handle_sendemail_coursesucceed(
useremail, userfirstname, logfile, workoutid useremail, userfirstname, logfile, workoutid
) )
@@ -804,36 +786,26 @@ def handle_check_race_course(self,
return 1 return 1
else: # pragma: no cover else: # pragma: no cover
query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 0,'\ record = VirtualRaceResult.object.get(id=recordid)
' duration = "{duration}", distance = {distance},'\ record.duration = totaltime_sec_to_string(0)
' workoutid = {workoutid}, startsecond = {startsecond},'\ record.distance = 0
' endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( record.workoutid = workoutid
recordid=recordid, record.startsecond = startsecond
duration=totaltime_sec_to_string(0), record.endsecond = endsecond
distance=0, record.points = 0
points=0.0, record.save()
workoutid=workoutid,
startsecond=startsecond,
endsecond=endsecond,)
if mode == 'coursetest': if mode == 'coursetest':
query = 'UPDATE rowers_coursetestresult SET coursecompleted = 0,'\ record = CourseTestResult.objects.get(id=recordid)
' duration = "{duration}", distance = {distance}, workoutid = {workoutid}'\ record.duration = totaltime_sec_to_string(0)
', startsecond = {startsecond}, endsecond = {endsecond}'\ record.distance = 0
', points={points} WHERE id={recordid}'.format( record.workoutid = workoutid
recordid=recordid, record.startsecond = startsecond
duration=totaltime_sec_to_string(0), record.endsecond = endsecond
distance=0, record.points = 0
points=0, record.save()
workoutid=workoutid,
startsecond=startsecond,
endsecond=endsecond,)
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
conn.close()
engine.dispose()
# add times for all gates to log file # add times for all gates to log file
with open(logfile, 'ab') as f: with open(logfile, 'ab') as f:
@@ -1086,10 +1058,7 @@ def handle_calctrimp(id,
hrmax, hrmax,
hrmin, hrmin,
debug=False, **kwargs): debug=False, **kwargs):
if debug: # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
tss = 0 tss = 0
normp = 0 normp = 0
@@ -1178,21 +1147,14 @@ def handle_calctrimp(id,
if hrtss > 1000: # pragma: no cover if hrtss > 1000: # pragma: no cover
hrtss = 0 hrtss = 0
query = 'UPDATE rowers_workout SET rscore = {tss},'\ workout = Workout.objects.get(id=id)
' normp = {normp}, trimp={trimp}, hrtss={hrtss},'\ workout.tss = int(tss)
' normv={normv}, normw={normw} WHERE id={id}'.format( workout.normp = int(normp)
tss=int(tss), workout.trimp = int(trimp)
normp=int(normp), workout.hrtss = int(hrtss)
trimp=int(trimp), workout.normv = normv
hrtss=int(hrtss), workout.normw = normw
normv=normv, workout.save()
normw=normw,
id=id,)
with engine.connect() as conn, conn.begin():
_ = conn.execute(query)
conn.close()
engine.dispose()
return 1 return 1
@@ -1974,7 +1936,7 @@ def handle_sendemail_ical(first_name, last_name, email, url, icsfile, **kwargs):
try: try:
os.remove(icsfile) os.remove(icsfile)
except: except: # pragma: no cover
pass pass
return 1 return 1
@@ -2834,23 +2796,13 @@ def handle_update_wps(rid, types, ids, mode, debug=False, **kwargs):
except ValueError: # pragma: no cover except ValueError: # pragma: no cover
return 0 return 0
rower = Rower.objects.get(id=rid)
if mode == 'water': if mode == 'water':
query = "UPDATE `rowers_rower` SET `median_wps` = '%s' WHERE `id` = '%s'" % ( rower.median_wps = wps_median
wps_median, rid)
else: else:
query = "UPDATE `rowers_rower` SET `median_wps_erg` = '%s' WHERE `id` = '%s'" % ( rower.median_wps_erg = wps_median
wps_median, rid)
if debug: # pragma: no cover rower.save()
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
with engine.connect() as conn, conn.begin():
_ = conn.execute(query)
conn.close()
engine.dispose()
return wps_median return wps_median
@@ -2999,23 +2951,8 @@ def handle_nk_async_workout(alldata, userid, nktoken, nkid, delaysec, defaulttim
workoutid, error = add_workout_from_data(userid, nkid, data, df) workoutid, error = add_workout_from_data(userid, nkid, data, df)
# dologging('nklog.log','NK Workout ID {id}'.format(id=workoutid)) # dologging('nklog.log','NK Workout ID {id}'.format(id=workoutid))
workout = Workout.objects.get(id=workoutid)
if debug: # pragma: no cover newnkid = workout.uploadedtonk
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
query = 'SELECT uploadedtonk from rowers_workout WHERE id ={workoutid}'.format(
workoutid=workoutid)
newnkid = 0
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
tdata = result.fetchall()
if tdata:
newnkid = tdata[0][0]
conn.close()
parkedids = [] parkedids = []
try: try:
@@ -3303,22 +3240,8 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim
workoutid = response.json()['id'] workoutid = response.json()['id']
if debug: # pragma: no cover workout = Workout.objects.get(id=workoutid)
engine = create_engine(database_url_debug, echo=False) newc2id = workout.uploadedtoc2
else:
engine = create_engine(database_url, echo=False)
query = 'SELECT uploadedtoc2 from rowers_workout WHERE id ={workoutid}'.format(
workoutid=workoutid)
newc2id = 0
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
tdata = result.fetchall()
if tdata: # pragma: no cover
newc2id = tdata[0][0]
conn.close()
parkedids = [] parkedids = []
with open('c2blocked.json', 'r') as c2blocked: with open('c2blocked.json', 'r') as c2blocked:
@@ -3335,14 +3258,10 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim
json.dump(tdata, c2blocked) json.dump(tdata, c2blocked)
# set distance, time # set distance, time
query = "UPDATE `rowers_workout` SET `distance` = '%s', `duration` = '%s' WHERE `id` = '%s'" % ( workout = Workout.objects.get(id=workoutid)
distance, duration, workoutid) workout.distance = distance
workout.duration = duration
with engine.connect() as conn, conn.begin(): workout.save()
result = conn.execute(query)
conn.close()
engine.dispose()
# summary # summary
if 'workout' in data: if 'workout' in data:
@@ -3359,14 +3278,9 @@ def handle_c2_async_workout(alldata, userid, c2token, c2id, delaysec, defaulttim
summary, sa, results = summaryfromsplitdata( summary, sa, results = summaryfromsplitdata(
splitdata, data, csvfilename, workouttype=workouttype) splitdata, data, csvfilename, workouttype=workouttype)
query = "UPDATE `rowers_workout` SET `summary` = '%s' WHERE `id` = %s" % ( workout = Workout.objects.get(id=workoutid)
summary, workoutid) workout.summary = summary
workout.save()
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
conn.close()
engine.dispose()
from rowingdata.trainingparser import getlist from rowingdata.trainingparser import getlist
if sa: if sa:

View File

@@ -81,10 +81,13 @@ class AsyncTaskTests(TestCase):
def test_polygons(self): def test_polygons(self):
polygons = GeoPolygon.objects.all() polygons = GeoPolygon.objects.all()
polygon = polygons[0] polygon = polygons[0]
obj = (polygon.id,polygon.name)
path = tasks.polygon_to_path(obj) #obj = (polygon.id,polygon.name)
self.assertEqual(len(path),4) path = tasks.polygon_to_path(polygon)
self.assertEqual(len(path),6)
def test_summaryfromsplitdata(self): def test_summaryfromsplitdata(self):
splitdata = [ splitdata = [
@@ -495,21 +498,21 @@ class AsyncTaskTests(TestCase):
self.assertEqual(res,1) self.assertEqual(res,1)
@patch('rowers.dataprepnodjango.create_engine') @patch('rowers.dataprep.create_engine')
def test_handle_updateergcp(self,mocked_sqlalchemy): def test_handle_updateergcp(self,mocked_sqlalchemy):
f1 = get_random_file()['filename'] f1 = get_random_file()['filename']
res = tasks.handle_updateergcp(1,[f1]) res = tasks.handle_updateergcp(1,[f1])
self.assertEqual(res,1) self.assertEqual(res,1)
@patch('rowers.dataprepnodjango.getsmallrowdata_db') @patch('rowers.dataprep.getsmallrowdata_db')
def test_handle_updatecp(self,mocked_getsmallrowdata_db_updatecp): def test_handle_updatecp(self,mocked_getsmallrowdata_db_updatecp):
rower_id = 1 rower_id = 1
workoutids = [1] workoutids = [1]
res = tasks.handle_updatecp(rower_id,workoutids) res = tasks.handle_updatecp(rower_id,workoutids)
self.assertEqual(res,1) self.assertEqual(res,1)
@patch('rowers.dataprepnodjango.getsmallrowdata_db') @patch('rowers.dataprep.getsmallrowdata_db')
def test_handle_setcp(self,mocked_getsmallrowdata_db_setcp): def test_handle_setcp(self,mocked_getsmallrowdata_db_setcp):
strokesdf = pd.read_csv('rowers/tests/testdata/uhfull.csv') strokesdf = pd.read_csv('rowers/tests/testdata/uhfull.csv')
filename = 'rowers/tests/testdata/temp/pq.gz' filename = 'rowers/tests/testdata/temp/pq.gz'
@@ -521,7 +524,7 @@ class AsyncTaskTests(TestCase):
except FileNotFoundError: except FileNotFoundError:
pass pass
@patch('rowers.dataprepnodjango.getsmallrowdata_db') @patch('rowers.dataprep.getsmallrowdata_db')
def test_handle_update_wps(self,mocked_getsmallrowdata_db_wps): def test_handle_update_wps(self,mocked_getsmallrowdata_db_wps):
ids = [1,2,3] ids = [1,2,3]

View File

@@ -130,7 +130,7 @@ class CPChartTest(TestCase):
# add some tests of complex form data (no hr, no spm, zero spm, etc) # add some tests of complex form data (no hr, no spm, zero spm, etc)
@patch('rowers.dataprepnodjango.create_engine') @patch('rowers.dataprep.create_engine')
def test_agerecords(self, mock_sqlalchemy): def test_agerecords(self, mock_sqlalchemy):
# update_records(url='rowers/tests/c2worldrecords.html',verbose=False) # update_records(url='rowers/tests/c2worldrecords.html',verbose=False)

View File

@@ -1554,6 +1554,36 @@ description: ""
self.instantplan.save() self.instantplan.save()
self.startdate = (datetime.datetime.now()-datetime.timedelta(days=1)).date()
self.enddate = (datetime.datetime.now()+datetime.timedelta(days=1)).date()
self.preferreddate = datetime.datetime.now().date()
self.ps = SessionFactory(startdate=self.startdate,enddate=self.enddate,
sessiontype='session',
sessionmode = 'time',
criterium = 'none',
sessionvalue = 60,
sessionunit='min',
preferreddate=self.preferreddate,
manager=self.u,
interval_string = '5x(800m/5min)'
)
self.ps.save()
result = plannedsessions.add_rower_session(self.r,self.ps)
self.step = PlannedSessionStep(
manager = self.u,
name = 'cd',
durationvalue = '50000',
durationtype = 'Distance',
)
self.step.save()
def tearDown(self): def tearDown(self):
@@ -1562,6 +1592,72 @@ description: ""
except (IOError, FileNotFoundError,OSError): except (IOError, FileNotFoundError,OSError):
pass pass
def test_stepadder(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = '/rowers/plans/stepeditor/{id}/'.format(id=self.ps.id)
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
url = '/rowers/plans/stepadder/{id}/'.format(id=self.ps.id)
bdy = json.dumps([self.step.id])
response = self.c.post(url, bdy, content_type='application/json',
**{'HTTP_X_REQUESTED_WITH':'XMLHttpRequest'})
self.assertEqual(response.status_code, 200)
def test_stepdelete(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = '/rowers/plans/step/{id}/delete'.format(id=self.step.id)
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
def test_stepedit(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = '/rowers/plans/step/{id}/edit/{psid}/'.format(
id=self.step.id, psid=self.ps.id
)
response = self.c.get(url)
self.assertEqual(response.status_code,200)
data = {
'durationtype': 'RepeatUntilStepsCmplt',
'durationvalue': '0.0',
#'targettype': None,
'targetvalue': '8',
'targetvaluelow': '0',
'targetvaluehigh': '0',
'intensity': 'Active',
'description': 'aap'
}
form = StepEditorForm(data)
self.assertTrue(form.is_valid())
reponse = self.c.post(url, data)
self.assertTrue(response.status_code,200)
def test_save_plan_yaml_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = '/rowers/sessions/saveasplan/?when={s}/{e}'.format(
s = self.startdate.strftime("%Y-%m-%d"),
e = self.enddate.strftime("%Y-%m-%d")
)
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
def test_clone_view(self): def test_clone_view(self):
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)

View File

@@ -888,8 +888,7 @@ class ChallengesTest(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@patch('rowers.tasks.create_engine', side_effect=mocked_sqlalchemy_courses) def test_virtualevent_check_view(self):
def notest_virtualevent_check_view(self,mocked_sqlalchemy_courses):
res = tasks.handle_check_race_course( res = tasks.handle_check_race_course(
self.wthyro.csvfilename, self.wthyro.csvfilename,
@@ -898,7 +897,6 @@ class ChallengesTest(TestCase):
self.result.id, self.result.id,
self.wthyro.user.user.email, self.wthyro.user.user.email,
self.wthyro.user.user.first_name, self.wthyro.user.user.first_name,
mode='coursetest',
) )
self.assertEqual(res,1) self.assertEqual(res,1)

View File

@@ -515,7 +515,7 @@ def rower_process_garmincallback(request): # pragma: no cover
# Process Rojabo callback # Process Rojabo callback
@login_required() @login_required()
def rower_process_rojabocallback(request): # prgrma: no cover def rower_process_rojabocallback(request): # pragma: no cover
# do stuff # do stuff
try: try:
code = request.GET.get('code', None) code = request.GET.get('code', None)

View File

@@ -1409,7 +1409,7 @@ def save_plan_yaml(request, userid=0):
steps = ps.steps steps = ps.steps
steps['filename'] = "" steps['filename'] = ""
workouts.append(steps) workouts.append(steps)
else: else: # pragma: no cover
if ps.sessionmode == 'distance': if ps.sessionmode == 'distance':
ps.interval_string = '{d}m'.format(d=ps.sessionvalue) ps.interval_string = '{d}m'.format(d=ps.sessionvalue)
elif ps.sessionmode == 'time': elif ps.sessionmode == 'time':
@@ -2994,7 +2994,8 @@ def rower_create_trainingplan(request, id=0):
redirect_field_name=None) redirect_field_name=None)
def stepadder(request, id=0): def stepadder(request, id=0):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest' is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
if not is_ajax:
if not is_ajax: # pragma: no cover
return JSONResponse( return JSONResponse(
status=403, data={ status=403, data={
'status': 'false', 'status': 'false',
@@ -3005,7 +3006,7 @@ def stepadder(request, id=0):
is_save = request.GET.get('save',0) is_save = request.GET.get('save',0)
if request.method != 'POST': if request.method != 'POST': # pragma: no cover
message = {'status': 'false', message = {'status': 'false',
'message': 'this view cannot be accessed through GET'} 'message': 'this view cannot be accessed through GET'}
return JSONResponse(status=403, data=message) return JSONResponse(status=403, data=message)
@@ -3013,14 +3014,16 @@ def stepadder(request, id=0):
try: try:
json_data = json.loads(request.body) json_data = json.loads(request.body)
post_data = json_data post_data = json_data
except (KeyError, JSONDecodeError): except (KeyError, JSONDecodeError): # pragma: no cover
q = request.POST q = request.POST
post_data = {k: q.getlist(k) if len( post_data = {k: q.getlist(k) if len(
q.getlist(k)) > 1 else v for k, v in q.items()} q.getlist(k)) > 1 else v for k, v in q.items()}
# only allow local host # only allow local host
hostt = request.get_host().split(':') hostt = request.get_host().split(':')
if hostt[0] not in ['localhost', '127.0.0.1', 'dev.rowsandall.com', 'rowsandall.com']:
if hostt[0] not in ['localhost', '127.0.0.1', 'dev.rowsandall.com', 'rowsandall.com',
'testserver']: # pragma: no cover
message = {'status': 'false', message = {'status': 'false',
'message': 'permission denied for host '+hostt[0]} 'message': 'permission denied for host '+hostt[0]}
return JSONResponse(status=403, data=message) return JSONResponse(status=403, data=message)
@@ -3028,7 +3031,7 @@ def stepadder(request, id=0):
if ps.steps: if ps.steps:
filename = ps.steps.get('filename','') filename = ps.steps.get('filename','')
sport = ps.steps.get('sport','rowing') sport = ps.steps.get('sport','rowing')
else: else: # pragma: no cover
filename = '' filename = ''
sport = 'rowing' sport = 'rowing'
@@ -3045,10 +3048,10 @@ def stepadder(request, id=0):
d = step.asdict() d = step.asdict()
d['stepId'] = nr d['stepId'] = nr
steps['steps'].append(d) steps['steps'].append(d)
except PlannedSessionStep.DoesNotExist: except PlannedSessionStep.DoesNotExist: # pragma: no cover
pass pass
if is_save: if is_save: # pragma: no cover
# save the darn thing # save the darn thing
ps.steps = steps ps.steps = steps
@@ -3066,9 +3069,12 @@ def stepdelete(request, id=0):
step.delete() step.delete()
backid = request.GET.get('id') backid = request.GET.get('id',0)
url = reverse(stepeditor,kwargs={'id':backid}) if backid: # pragma: no cover
url = reverse(stepeditor,kwargs={'id':backid})
else:
url = reverse('plannedsessions_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -3079,7 +3085,7 @@ def stepedit(request, id=0, psid=0):
step = get_object_or_404(PlannedSessionStep, pk=id) step = get_object_or_404(PlannedSessionStep, pk=id)
try: try:
ps = PlannedSession.objects.get(id=psid) ps = PlannedSession.objects.get(id=psid)
except PlannedSession.DoesNotExist: except PlannedSession.DoesNotExist: # pragma: no cover
ps = None ps = None
form = StepEditorForm(instance=step) form = StepEditorForm(instance=step)
@@ -3094,7 +3100,7 @@ def stepedit(request, id=0, psid=0):
ee = ss.copy() ee = ss.copy()
ee.pop('stepId') ee.pop('stepId')
if (dd == ee): if (dd == ee): # pragma: no cover
ss['durationType'] = form.cleaned_data['durationtype'] ss['durationType'] = form.cleaned_data['durationtype']
ss['durationValue'] = form.cleaned_data['durationvalue'] ss['durationValue'] = form.cleaned_data['durationvalue']
ss['targetType'] = form.cleaned_data['targettype'] ss['targetType'] = form.cleaned_data['targettype']
@@ -3126,15 +3132,15 @@ def stepedit(request, id=0, psid=0):
step.name = form.cleaned_data['name'] step.name = form.cleaned_data['name']
step.description = form.cleaned_data['description'] step.description = form.cleaned_data['description']
if step.durationtype == 'Time': if step.durationtype == 'Time': # pragma: no cover
step.durationvalue *= 60000 step.durationvalue *= 60000
elif step.durationtype == 'Distance': elif step.durationtype == 'Distance': # pragma: no cover
step.durationvalue *= 100 step.durationvalue *= 100
step.save() step.save()
if step.durationtype == 'Time': if step.durationtype == 'Time': # pragma: no cover
form.fields['durationvalue'].initial = step.durationvalue / 60000 form.fields['durationvalue'].initial = step.durationvalue / 60000
elif step.durationtype == 'Distance': elif step.durationtype == 'Distance':
form.fields['durationvalue'].initial = step.durationvalue / 100 form.fields['durationvalue'].initial = step.durationvalue / 100
@@ -3143,7 +3149,7 @@ def stepedit(request, id=0, psid=0):
stepdescription = step_to_string(step.asdict(), short=False)[0] stepdescription = step_to_string(step.asdict(), short=False)[0]
if request.method == 'POST': if request.method == 'POST':
if 'stepsave_and_return' in request.POST: if 'stepsave_and_return' in request.POST: # pragma: no cover
url = reverse('stepeditor',kwargs = {'id': ps.id}) url = reverse('stepeditor',kwargs = {'id': ps.id})
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -3204,7 +3210,7 @@ def stepeditor(request, id=0):
targetvaluehigh = targetvaluehigh, targetvaluehigh = targetvaluehigh,
intensity = intensity, intensity = intensity,
) )
if not archived_steps.count() and durationvalue != 0: if not archived_steps.count():
s = PlannedSessionStep( s = PlannedSessionStep(
manager = request.user, manager = request.user,
durationtype = durationtype, durationtype = durationtype,
@@ -3217,14 +3223,14 @@ def stepeditor(request, id=0):
name = step.get('wkt_step_name','Step') name = step.get('wkt_step_name','Step')
) )
s.save() s.save()
else: else: # pragma: no cover
s = archived_steps[0] s = archived_steps[0]
currentsteps.append(s) currentsteps.append(s)
form = StepEditorForm() form = StepEditorForm()
if request.method == 'POST': if request.method == 'POST': # pragma: no cover
form = StepEditorForm(request.POST) form = StepEditorForm(request.POST)
if form.is_valid(): if form.is_valid():
step = form.save(commit=False) step = form.save(commit=False)