Private
Public Access
1
0

c2stuff.create_async_workout start

works but is not async yet
This commit is contained in:
Sander Roosendaal
2018-01-19 13:14:23 +01:00
parent 8e6460eb06
commit 0d1be41e6e
5 changed files with 241 additions and 60 deletions

View File

@@ -9,6 +9,7 @@ import cgi
import requests import requests
import requests.auth import requests.auth
import json import json
import iso8601
from django.utils import timezone from django.utils import timezone
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
@@ -21,8 +22,8 @@ from django.conf import settings
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
import dataprep
import pytz
from rowingdata import rowingdata from rowingdata import rowingdata
import pandas as pd import pandas as pd
import numpy as np import numpy as np
@@ -34,6 +35,8 @@ from requests import Request, Session
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET
from rowers.tasks import handle_c2_import_stroke_data
# Custom error class - to raise a NoTokenError # Custom error class - to raise a NoTokenError
class C2NoTokenError(Exception): class C2NoTokenError(Exception):
def __init__(self,value): def __init__(self,value):
@@ -82,7 +85,96 @@ def c2_open(user):
return thetoken return thetoken
def add_stroke_data(user,c2id,workoutid,startdatetime,csvfilename):
r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None):
return custom_exception_handler(401,s)
s = "Token doesn't exist. Need to authorize"
elif (timezone.now()>r.tokenexpirydate):
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
else:
# ready to fetch. Hurray
res = handle_c2_import_stroke_data(r.c2token,
c2id,
workoutid,
startdatetime,
csvfilename)
return 1
# get workout metrics, then relay stroke data to an asynchronous task
def create_async_workout(user,c2id):
res = get_c2_workout(user,c2id)
if (res.status_code == 200):
data = res.json()['data']
splitdata = None
if 'workout' in data:
if 'splits' in data['workout']:
splitdata = data['workout']['splits']
if 'intervals' in data['workout']:
splitdata = data['workout']['intervals']
distance = data['distance']
c2id = data['id']
workouttype = data['type']
verified = data['verified']
startdatetime = iso8601.parse_date(data['date'])
weightclass = data['weight_class']
weightcategory = 'hwt'
if weightclass == "L":
weightcategory = 'lwt'
# Create CSV file name and save data to CSV file
csvfilename ='media/Import_'+str(c2id)+'.csv.gz'
totaltime = data['time']/10.
duration = dataprep.totaltime_sec_to_string(totaltime)
try:
timezone_str = tz(data['timezone'])
except:
timezone_str = 'UTC'
workoutdate = startdatetime.astimezone(
pytz.timezone(timezone_str)
).strftime('%Y-%m-%d')
starttime = startdatetime.astimezone(
pytz.timezone(timezone_str)
).strftime('%H:%M:%S')
r = Rower.objects.get(user=user)
w = Workout(
user=r,
workouttype = workouttype,
name = 'Imported workout',
date = workoutdate,
starttime = starttime,
startdatetime = startdatetime,
timezone = timezone_str,
duration = duration,
distance=distance,
weightcategory = weightcategory,
uploadedtoc2 = c2id,
csvfilename = csvfilename,
notes = 'imported from Concept2 log'
)
w.save()
# Check if workout has stroke data, and get the stroke data
if data['stroke_data']:
result = add_stroke_data(user,c2id,w.id,startdatetime,csvfilename)
else:
# create synthetic stroke data
pass
return w.id
# convert datetime object to seconds # convert datetime object to seconds
def makeseconds(t): def makeseconds(t):

View File

@@ -723,9 +723,35 @@ def create_row_df(r,distance,duration,startdatetime,
return (id, message) return (id, message)
def totaltime_sec_to_string(totaltime):
hours = int(totaltime / 3600.)
if hours > 23:
message = 'Warning: The workout duration was longer than 23 hours. '
hours = 23
minutes = int((totaltime - 3600. * hours) / 60.)
if minutes > 59:
minutes = 59
if not message:
message = 'Warning: there is something wrong with the workout duration'
seconds = int(totaltime - 3600. * hours - 60. * minutes)
if seconds > 59:
seconds = 59
if not message:
message = 'Warning: there is something wrong with the workout duration'
tenths = int(10 * (totaltime - 3600. * hours - 60. * minutes - seconds))
if tenths > 9:
tenths = 9
if not message:
message = 'Warning: there is something wrong with the workout duration'
duration = "%s:%s:%s.%s" % (hours, minutes, seconds, tenths)
return duration
# Processes painsled CSV file to database # Processes painsled CSV file to database
def save_workout_database(f2, r, dosmooth=True, workouttype='rower', def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
dosummary=True, title='Workout', dosummary=True, title='Workout',
workoutsource='unknown', workoutsource='unknown',
@@ -838,30 +864,6 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
if np.isnan(totaltime): if np.isnan(totaltime):
totaltime = 0 totaltime = 0
hours = int(totaltime / 3600.)
if hours > 23:
message = 'Warning: The workout duration was longer than 23 hours. '
hours = 23
minutes = int((totaltime - 3600. * hours) / 60.)
if minutes > 59:
minutes = 59
if not message:
message = 'Warning: there is something wrong with the workout duration'
seconds = int(totaltime - 3600. * hours - 60. * minutes)
if seconds > 59:
seconds = 59
if not message:
message = 'Warning: there is something wrong with the workout duration'
tenths = int(10 * (totaltime - 3600. * hours - 60. * minutes - seconds))
if tenths > 9:
tenths = 9
if not message:
message = 'Warning: there is something wrong with the workout duration'
duration = "%s:%s:%s.%s" % (hours, minutes, seconds, tenths)
if dosummary: if dosummary:
summary = row.allstats() summary = row.allstats()
@@ -897,6 +899,8 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
except KeyError: except KeyError:
timezone_str = r.defaulttimezone timezone_str = r.defaulttimezone
duration = totaltime_sec_to_string(totaltime)
workoutdate = workoutstartdatetime.astimezone( workoutdate = workoutstartdatetime.astimezone(
pytz.timezone(timezone_str) pytz.timezone(timezone_str)
).strftime('%Y-%m-%d') ).strftime('%Y-%m-%d')

View File

@@ -1,10 +1,10 @@
# This is Data prep used for testing purposes (no Django environment) # This is Data prep used for testing purposes (no Django environment)
# Uses the debug SQLite database for stroke data # Uses the debug SQLite database for stroke data
from rowingdata import rowingdata as rrdata from rowingdata import rowingdata as rrdata
from rowingdata import make_cumvalues
from rowingdata import rower as rrower from rowingdata import rower as rrower
from rowingdata import main as rmain from rowingdata import main as rmain
from time import strftime
from pandas import DataFrame,Series from pandas import DataFrame,Series
import pandas as pd import pandas as pd
@@ -131,6 +131,89 @@ def rdata(file,rower=rrower()):
return res return res
# Saves C2 stroke data to CSV and database
def add_c2_stroke_data_db(strokedata,workoutid,starttimeunix,csvfilename,
debug=False):
res = make_cumvalues(0.1*strokedata['t'])
cum_time = res[0]
lapidx = res[1]
unixtime = cum_time+starttimeunix
# unixtime[0] = starttimeunix
seconds = 0.1*strokedata.ix[:,'t']
nr_rows = len(unixtime)
try:
latcoord = strokedata.ix[:,'lat']
loncoord = strokedata.ix[:,'lon']
except:
latcoord = np.zeros(nr_rows)
loncoord = np.zeros(nr_rows)
try:
strokelength = strokedata.ix[:,'strokelength']
except:
strokelength = np.zeros(nr_rows)
dist2 = 0.1*strokedata.ix[:,'d']
try:
spm = strokedata.ix[:,'spm']
except KeyError:
spm = 0*dist2
try:
hr = strokedata.ix[:,'hr']
except KeyError:
hr = 0*spm
pace = strokedata.ix[:,'p']/10.
pace = np.clip(pace,0,1e4)
pace = pace.replace(0,300)
velo = 500./pace
power = 2.8*velo**3
# save csv
# Create data frame with all necessary data to write to csv
df = pd.DataFrame({'TimeStamp (sec)':unixtime,
' Horizontal (meters)': dist2,
' Cadence (stokes/min)':spm,
' HRCur (bpm)':hr,
' longitude':loncoord,
' latitude':latcoord,
' Stroke500mPace (sec/500m)':pace,
' Power (watts)':power,
' DragFactor':np.zeros(nr_rows),
' DriveLength (meters)':np.zeros(nr_rows),
' StrokeDistance (meters)':strokelength,
' DriveTime (ms)':np.zeros(nr_rows),
' StrokeRecoveryTime (ms)':np.zeros(nr_rows),
' AverageDriveForce (lbs)':np.zeros(nr_rows),
' PeakDriveForce (lbs)':np.zeros(nr_rows),
' lapIdx':lapidx,
' ElapsedTime (sec)':seconds,
'cum_dist': dist2
})
df.sort_values(by='TimeStamp (sec)',ascending=True)
timestr = strftime("%Y%m%d-%H%M%S")
# Create CSV file name and save data to CSV file
res = df.to_csv(csvfilename,index_label='index',
compression='gzip')
data = dataprep(df,id=workoutid,bands=False,debug=debug)
return data
# Processes painsled CSV file to database # Processes painsled CSV file to database
def save_workout_database(f2,r,dosmooth=True,workouttype='rower', def save_workout_database(f2,r,dosmooth=True,workouttype='rower',
dosummary=True,title='Workout', dosummary=True,title='Workout',

View File

@@ -32,7 +32,8 @@ from utils import deserialize_list
from rowers.dataprepnodjango import ( from rowers.dataprepnodjango import (
update_strokedata, new_workout_from_file, update_strokedata, new_workout_from_file,
getsmallrowdata_db, updatecpdata_sql, getsmallrowdata_db, updatecpdata_sql,
update_agegroup_db,fitnessmetric_to_sql update_agegroup_db,fitnessmetric_to_sql,
add_c2_stroke_data_db
) )
from django.core.mail import send_mail, EmailMessage from django.core.mail import send_mail, EmailMessage
@@ -40,8 +41,9 @@ from django.db.utils import OperationalError
import datautils import datautils
import utils import utils
import requests
import longtask import longtask
import arrow
# testing task # testing task
@@ -50,6 +52,33 @@ import longtask
def add(x, y): def add(x, y):
return x + y return x + y
@app.task
def handle_c2_import_stroke_data(c2token,
c2id,workoutid,
startdatetime,
csvfilename,debug=True):
authorizationstring = str('Bearer ' + c2token)
headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal',
'Content-Type': 'application/json'}
url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes"
s = requests.get(url,headers=headers)
if s.status_code == 200:
strokedata = pd.DataFrame.from_dict(s.json()['data'])
starttimeunix = arrow.get(startdatetime).timestamp
result = add_c2_stroke_data_db(
strokedata,workoutid,starttimeunix,
csvfilename,debug=debug,
)
return 1
else:
return 0
return 0
def getagegrouprecord(age,sex='male',weightcategory='hwt', def getagegrouprecord(age,sex='male',weightcategory='hwt',
distance=2000,duration=None,indf=pd.DataFrame()): distance=2000,duration=None,indf=pd.DataFrame()):

View File

@@ -9115,34 +9115,7 @@ def workout_getc2workout_all(request,page=1,message=""):
]) ])
newids = [c2id for c2id in c2ids if not c2id in knownc2ids] newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
for c2id in newids: for c2id in newids:
res = c2stuff.get_c2_workout(request.user,c2id) workoutid = c2stuff.create_async_workout(request.user,c2id)
if (res.status_code == 200):
data = res.json()['data']
splitdata = None
if 'workout' in data:
if 'splits' in data['workout']:
splitdata = data['workout']['splits']
if 'intervals' in data['workout']:
splitdata = data['workout']['intervals']
# Check if workout has stroke data, and get the stroke data
if data['stroke_data']:
res2 = c2stuff.get_c2_workout_strokes(request.user,c2id)
# We have stroke data
if res2.status_code == 200:
strokedata = pd.DataFrame.from_dict(res2.json()['data'])
# create the workout
try:
id,message = add_workout_from_strokedata(
request.user,c2id,data,strokedata,
source='c2')
w = Workout.objects.get(id=id)
w.uploadedtoc2=c2id
w.save()
if message:
messages.error(request,message)
except KeyError:
pass
url = reverse(workouts_view) url = reverse(workouts_view)
return HttpResponseRedirect(url) return HttpResponseRedirect(url)