Merge branch 'feature/nkimprovements' into develop
This commit is contained in:
+20
-6
@@ -1853,9 +1853,16 @@ parsers = {
|
|||||||
'nklinklogbook': NKLiNKLogbookParser,
|
'nklinklogbook': NKLiNKLogbookParser,
|
||||||
}
|
}
|
||||||
|
|
||||||
def parsenonpainsled(fileformat,f2,summary,startdatetime=''):
|
def parsenonpainsled(fileformat,f2,summary,startdatetime='',empowerfirmware=None,inboard=None,oarlength=None):
|
||||||
try:
|
try:
|
||||||
row = parsers[fileformat](f2)
|
if fileformat == 'nklinklogbook' and empowerfirmware is not None:
|
||||||
|
if inboard is not None and oarlength is not None:
|
||||||
|
row = NKLiNKLogbookParser(f2,firmware=empowerfirmware,inboard=inboard,oarlength=oarlength)
|
||||||
|
print(row,'aap')
|
||||||
|
else:
|
||||||
|
row = NKLiNKLogbookParser(f2)
|
||||||
|
else:
|
||||||
|
row = parsers[fileformat](f2)
|
||||||
if startdatetime != '':
|
if startdatetime != '':
|
||||||
row.rowdatetime = arrow.get(startdatetime).datetime
|
row.rowdatetime = arrow.get(startdatetime).datetime
|
||||||
hasrecognized = True
|
hasrecognized = True
|
||||||
@@ -1875,6 +1882,8 @@ def parsenonpainsled(fileformat,f2,summary,startdatetime=''):
|
|||||||
summary = row.allstats()
|
summary = row.allstats()
|
||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
summary = ''
|
summary = ''
|
||||||
|
else:
|
||||||
|
fileformat = fileformat+'v'+str(empowerfirmware)
|
||||||
|
|
||||||
# handle FIT
|
# handle FIT
|
||||||
if (fileformat == 'fit'):
|
if (fileformat == 'fit'):
|
||||||
@@ -1889,13 +1898,14 @@ def parsenonpainsled(fileformat,f2,summary,startdatetime=''):
|
|||||||
|
|
||||||
return row,hasrecognized,summary,fileformat
|
return row,hasrecognized,summary,fileformat
|
||||||
|
|
||||||
def handle_nonpainsled(f2, fileformat, summary='',startdatetime=''):
|
def handle_nonpainsled(f2, fileformat, summary='',startdatetime='',empowerfirmware=None):
|
||||||
oarlength = 2.89
|
oarlength = 2.89
|
||||||
inboard = 0.88
|
inboard = 0.88
|
||||||
hasrecognized = False
|
hasrecognized = False
|
||||||
impeller = False
|
impeller = False
|
||||||
|
|
||||||
row,hasrecognized,summary,fileformat = parsenonpainsled(fileformat,f2,summary,startdatetime=startdatetime)
|
row,hasrecognized,summary,fileformat = parsenonpainsled(fileformat,f2,summary,startdatetime=startdatetime,
|
||||||
|
empowerfirmware=empowerfirmware)
|
||||||
|
|
||||||
# Handle c2log
|
# Handle c2log
|
||||||
if (fileformat == 'c2log' or fileformat == 'rowprolog'):
|
if (fileformat == 'c2log' or fileformat == 'rowprolog'):
|
||||||
@@ -1909,7 +1919,7 @@ def handle_nonpainsled(f2, fileformat, summary='',startdatetime=''):
|
|||||||
f2 = f2[:-4] + 'o.csv'
|
f2 = f2[:-4] + 'o.csv'
|
||||||
row2 = rrdata(df = row.df)
|
row2 = rrdata(df = row.df)
|
||||||
|
|
||||||
if 'speedcoach2' in fileformat:
|
if 'speedcoach2' in fileformat or 'nklinklogbook' in fileformat:
|
||||||
# impeller consistency
|
# impeller consistency
|
||||||
impellerdata, consistent, ratio = row.impellerconsistent(threshold=0.3)
|
impellerdata, consistent, ratio = row.impellerconsistent(threshold=0.3)
|
||||||
if impellerdata and consistent:
|
if impellerdata and consistent:
|
||||||
@@ -1990,6 +2000,9 @@ def new_workout_from_file(r, f2,
|
|||||||
makeprivate=False,
|
makeprivate=False,
|
||||||
startdatetime='',
|
startdatetime='',
|
||||||
notes='',
|
notes='',
|
||||||
|
oarlockfirmware='',
|
||||||
|
inboard=None,
|
||||||
|
oarlength=None,
|
||||||
uploadoptions={'boattype':'1x','workouttype':'rower'}):
|
uploadoptions={'boattype':'1x','workouttype':'rower'}):
|
||||||
message = ""
|
message = ""
|
||||||
impeller = False
|
impeller = False
|
||||||
@@ -2095,7 +2108,8 @@ def new_workout_from_file(r, f2,
|
|||||||
f2,
|
f2,
|
||||||
fileformat,
|
fileformat,
|
||||||
startdatetime=startdatetime,
|
startdatetime=startdatetime,
|
||||||
summary=summary
|
summary=summary,
|
||||||
|
empowerfirmware=oarlockfirmware,
|
||||||
)
|
)
|
||||||
if not f2:
|
if not f2:
|
||||||
message = 'Something went wrong'
|
message = 'Something went wrong'
|
||||||
|
|||||||
+2
-1
@@ -1002,7 +1002,7 @@ class Rower(models.Model):
|
|||||||
nkrefreshtoken = models.TextField(default='',max_length=1000,
|
nkrefreshtoken = models.TextField(default='',max_length=1000,
|
||||||
blank=True,null=True)
|
blank=True,null=True)
|
||||||
nk_owner_id = models.BigIntegerField(default=0)
|
nk_owner_id = models.BigIntegerField(default=0)
|
||||||
nk_auto_import = models.BooleanField(default=False)
|
nk_auto_import = models.BooleanField(default=False,verbose_name='NK LiNK auto import')
|
||||||
|
|
||||||
trainingpeaks_auto_export = models.BooleanField(default=False)
|
trainingpeaks_auto_export = models.BooleanField(default=False)
|
||||||
|
|
||||||
@@ -3852,6 +3852,7 @@ class RowerExportForm(ModelForm):
|
|||||||
'polar_auto_import',
|
'polar_auto_import',
|
||||||
'c2_auto_export',
|
'c2_auto_export',
|
||||||
'c2_auto_import',
|
'c2_auto_import',
|
||||||
|
'nk_auto_import',
|
||||||
'mapmyfitness_auto_export',
|
'mapmyfitness_auto_export',
|
||||||
'runkeeper_auto_export',
|
'runkeeper_auto_export',
|
||||||
'sporttracks_auto_export',
|
'sporttracks_auto_export',
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import datetime
|
||||||
|
from datetime import timedelta
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
from rowsandall_app.settings import UPLOAD_SERVICE_SECRET, UPLOAD_SERVICE_URL
|
||||||
|
from rowsandall_app.settings import NK_API_LOCATION
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def strfdelta(tdelta):
|
||||||
|
try:
|
||||||
|
minutes, seconds = divmod(tdelta.seconds, 60)
|
||||||
|
tenths = int(tdelta.microseconds / 1e5)
|
||||||
|
except AttributeError:
|
||||||
|
minutes, seconds = divmod(tdelta.view(np.int64), 60e9)
|
||||||
|
seconds, rest = divmod(seconds, 1e9)
|
||||||
|
tenths = int(rest / 1e8)
|
||||||
|
res = "{minutes:0>2}:{seconds:0>2}.{tenths:0>1}".format(
|
||||||
|
minutes=minutes,
|
||||||
|
seconds=seconds,
|
||||||
|
tenths=tenths,
|
||||||
|
)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def add_workout_from_data(userid,nkid,data,strokedata,source='nk',splitdata=None,
|
||||||
|
workoutsource='nklinklogbook'):
|
||||||
|
|
||||||
|
csvfilename = 'media/{code}_{nkid}.csv.gz'.format(
|
||||||
|
nkid=nkid,
|
||||||
|
code = uuid4().hex[:16]
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
userid=int(userid)
|
||||||
|
except TypeError:
|
||||||
|
userid = userid.id
|
||||||
|
|
||||||
|
strokedata.to_csv(csvfilename, index_label='index', compression='gzip')
|
||||||
|
|
||||||
|
title = data["name"]
|
||||||
|
speedInput = data["speedInput"]
|
||||||
|
elapsedTime = data["elapsedTime"]
|
||||||
|
totalDistanceGps = data["totalDistanceGps"]
|
||||||
|
totalDistanceImp = data["totalDistanceImp"]
|
||||||
|
intervals = data["intervals"] # add intervals
|
||||||
|
oarlockSessions = data["oarlockSessions"]
|
||||||
|
deviceId = data["deviceId"] # you could get the firmware version
|
||||||
|
|
||||||
|
|
||||||
|
summary = get_nk_allstats(data,strokedata)
|
||||||
|
|
||||||
|
speedInput = data['speedInput'] # 0 = GPS; 1 = Impeller
|
||||||
|
|
||||||
|
# oarlock inboard, length, boat name
|
||||||
|
if oarlockSessions:
|
||||||
|
oarlocksession = oarlockSessions[0] # should take seatIndex
|
||||||
|
boatName = oarlocksession["boatName"]
|
||||||
|
oarLength = oarlocksession["oarLength"] # cm
|
||||||
|
oarInboardLength = oarlocksession["oarInboardLength"] # cm
|
||||||
|
seatNumber = oarlocksession["seatNumber"]
|
||||||
|
try:
|
||||||
|
oarlockfirmware = oarlocksession["firmwareVersion"]
|
||||||
|
except KeyError:
|
||||||
|
oarlockfirmware = ''
|
||||||
|
else:
|
||||||
|
boatName = ''
|
||||||
|
oarLength = 289
|
||||||
|
oarInboardLength = 88
|
||||||
|
seatNumber = 1
|
||||||
|
oarlockfirmware = ''
|
||||||
|
|
||||||
|
workouttype = "water"
|
||||||
|
boattype = "1x"
|
||||||
|
|
||||||
|
uploadoptions = {
|
||||||
|
'secret': UPLOAD_SERVICE_SECRET,
|
||||||
|
'user':userid,
|
||||||
|
'file': csvfilename,
|
||||||
|
'title': title,
|
||||||
|
'workouttype': workouttype,
|
||||||
|
'boattype': boattype,
|
||||||
|
'nkid':nkid,
|
||||||
|
'inboard': oarInboardLength/100.,
|
||||||
|
'oarlength': oarLength/100.,
|
||||||
|
'summary':summary,
|
||||||
|
'oarlockfirmware':oarlockfirmware,
|
||||||
|
}
|
||||||
|
|
||||||
|
session = requests.session()
|
||||||
|
newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
|
||||||
|
session.headers.update(newHeaders)
|
||||||
|
|
||||||
|
response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
return 0,response.text
|
||||||
|
|
||||||
|
try:
|
||||||
|
workoutid = response.json()['id']
|
||||||
|
except KeyError:
|
||||||
|
workoutid = 1
|
||||||
|
|
||||||
|
|
||||||
|
# evt update workout summary
|
||||||
|
|
||||||
|
# return
|
||||||
|
return workoutid,""
|
||||||
|
|
||||||
|
def get_nk_intervalstats(workoutdata,strokedata):
|
||||||
|
intervals = workoutdata['intervals']
|
||||||
|
separator = "|"
|
||||||
|
stri = "Workout Details\n"
|
||||||
|
stri += "#-{sep}SDist{sep}-Split-{sep}-SPace-{sep}-Pwr-{sep}-SPM--{sep}-AvgHR-{sep}DPS-\n".format(
|
||||||
|
sep=separator)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
for interval in intervals:
|
||||||
|
id = interval['id']
|
||||||
|
sdist = interval['totalDistanceGps']
|
||||||
|
avgpace = interval['avgPaceGps']/1000.
|
||||||
|
avgpacetd = timedelta(seconds=avgpace)
|
||||||
|
newpacestring = strfdelta(avgpacetd)
|
||||||
|
|
||||||
|
elapsedSeconds = interval['elapsedTime']/1000. # secs
|
||||||
|
elapsedTime = datetime.datetime.utcfromtimestamp(elapsedSeconds)
|
||||||
|
|
||||||
|
newsplitstring = "%s.%i" % (elapsedTime.strftime("%M:%S"), elapsedTime.microsecond/100000)
|
||||||
|
|
||||||
|
pwr = interval['avgPower']
|
||||||
|
avghr = interval['avgHeartRate']
|
||||||
|
spm = interval['avgStrokeRate']
|
||||||
|
dps = interval['distStrokeGps']
|
||||||
|
|
||||||
|
stri += "{i:0>2}{sep}{sdist:0>5}{sep}{split}{sep}{space}{sep} {pwr:0>3} {sep}".format(
|
||||||
|
i=i + 1,
|
||||||
|
sdist=int(float(sdist)),
|
||||||
|
split=newsplitstring,
|
||||||
|
space=newpacestring,
|
||||||
|
pwr=int(pwr),
|
||||||
|
sep=separator,
|
||||||
|
)
|
||||||
|
stri += " {spm} {sep} {avghr:0>3} {sep}{dps:0>4.1f}\n".format(
|
||||||
|
sep=separator,
|
||||||
|
avghr=avghr,
|
||||||
|
spm=spm,
|
||||||
|
dps=dps,
|
||||||
|
)
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return stri
|
||||||
|
|
||||||
|
def get_nk_summary(workoutdata,strokedata):
|
||||||
|
|
||||||
|
name = workoutdata['name']
|
||||||
|
|
||||||
|
avgpace = workoutdata['avgPaceGps']/1000. # secs
|
||||||
|
avgpacetd = timedelta(seconds=avgpace)
|
||||||
|
avgpacestring = strfdelta(avgpacetd)
|
||||||
|
|
||||||
|
elapsedSeconds = workoutdata['elapsedTime']/1000. # secs
|
||||||
|
elapsedTime = datetime.datetime.utcfromtimestamp(elapsedSeconds)
|
||||||
|
|
||||||
|
timestring = "%s.%i" % (elapsedTime.strftime("%H:%M:%S"), elapsedTime.microsecond/100000)
|
||||||
|
|
||||||
|
dist = workoutdata['totalDistanceGps']
|
||||||
|
spm = workoutdata['avgStrokeRate']
|
||||||
|
avghr = workoutdata['avgHeartRate']
|
||||||
|
avgdps = workoutdata['distStrokeGps']
|
||||||
|
maxhr = strokedata['heartRate'].max()
|
||||||
|
pwr = workoutdata['avgPower']
|
||||||
|
|
||||||
|
sep = "|"
|
||||||
|
|
||||||
|
|
||||||
|
stri1 = "Workout Summary - " + name + "\n"
|
||||||
|
stri1 += "--{sep}Total{sep}--Total---{sep}--Avg--{sep}-Avg-{sep}-Avg--{sep}-Avg-{sep}-Max-{sep}-Avg\n".format(
|
||||||
|
sep=sep)
|
||||||
|
stri1 += "--{sep}Dist-{sep}--Time----{sep}-Pace--{sep}-Pwr-{sep}-SPM--{sep}-HR--{sep}-HR--{sep}-DPS\n".format(
|
||||||
|
sep=sep)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
stri1 += "--{sep}{dist:0>5.0f}{sep}".format(
|
||||||
|
sep=sep,
|
||||||
|
dist=dist,
|
||||||
|
)
|
||||||
|
|
||||||
|
stri1 += timestring + sep + avgpacestring
|
||||||
|
|
||||||
|
stri1 += "{sep}{avgpower:0>5.1f}".format(
|
||||||
|
sep=sep,
|
||||||
|
avgpower=pwr,
|
||||||
|
)
|
||||||
|
|
||||||
|
stri1 += "{sep} {avgsr:2.1f} {sep}{avghr:0>5.1f}{sep}".format(
|
||||||
|
avgsr=spm,
|
||||||
|
sep=sep,
|
||||||
|
avghr=avghr
|
||||||
|
)
|
||||||
|
|
||||||
|
stri1 += "{maxhr:0>5.1f}{sep}{avgdps:0>4.1f}\n".format(
|
||||||
|
sep=sep,
|
||||||
|
maxhr=maxhr,
|
||||||
|
avgdps=avgdps
|
||||||
|
)
|
||||||
|
|
||||||
|
return stri1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return stri1
|
||||||
|
|
||||||
|
def get_nk_allstats(data,workoutdata):
|
||||||
|
stri = get_nk_summary(data, workoutdata) + \
|
||||||
|
get_nk_intervalstats(data, workoutdata)
|
||||||
|
return stri
|
||||||
|
|
||||||
|
#def get_workout(user,nkid):
|
||||||
|
def getdict(x, seatIndex=1):
|
||||||
|
seatStrokes = pd.DataFrame(x)
|
||||||
|
try:
|
||||||
|
seatStrokes = seatStrokes.set_index('seatIndex')
|
||||||
|
return dict(seatStrokes.loc[seatIndex])
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def strokeDataToDf(strokeData):
|
||||||
|
|
||||||
|
df = pd.DataFrame.from_dict(strokeData)
|
||||||
|
|
||||||
|
oarlockData = df['oarlockStrokes']
|
||||||
|
|
||||||
|
oarlockData = oarlockData.apply(lambda x:getdict(x, seatIndex=1))
|
||||||
|
df2 = pd.DataFrame.from_records(oarlockData.values)
|
||||||
|
|
||||||
|
#df.set_index('timestamp',inplace=True)
|
||||||
|
|
||||||
|
if not df2.empty:
|
||||||
|
#df2.set_index('timestamp',inplace=True)
|
||||||
|
df = df.merge(df2,left_index=True,right_index=True)
|
||||||
|
df = df.rename(columns={"timestamp_x":"timestamp"})
|
||||||
|
|
||||||
|
df = df.drop('oarlockStrokes',axis=1)
|
||||||
|
df.sort_values(by='timestamp',ascending=True,inplace=True)
|
||||||
|
df.fillna(inplace=True,method='ffill')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return df
|
||||||
+11
-99
@@ -22,7 +22,7 @@ queuehigh = django_rq.get_queue('low')
|
|||||||
from rowers.rower_rules import is_workout_user, ispromember
|
from rowers.rower_rules import is_workout_user, ispromember
|
||||||
|
|
||||||
from iso8601 import ParseError
|
from iso8601 import ParseError
|
||||||
from rowers.utils import myqueue,get_nk_summary, get_nk_allstats, get_nk_intervalstats,getdict
|
from rowers.utils import myqueue
|
||||||
|
|
||||||
import rowers.mytypes as mytypes
|
import rowers.mytypes as mytypes
|
||||||
import gzip
|
import gzip
|
||||||
@@ -42,6 +42,7 @@ except ImportError:
|
|||||||
JSONDecodeError = ValueError
|
JSONDecodeError = ValueError
|
||||||
|
|
||||||
from rowers.imports import *
|
from rowers.imports import *
|
||||||
|
from rowers.nkimportutils import *
|
||||||
|
|
||||||
oauth_data = {
|
oauth_data = {
|
||||||
'client_id': NK_CLIENT_ID,
|
'client_id': NK_CLIENT_ID,
|
||||||
@@ -209,7 +210,7 @@ def rower_nk_token_refresh(user):
|
|||||||
def make_authorization_url(request):
|
def make_authorization_url(request):
|
||||||
return imports_make_authorization_url(oauth_data)
|
return imports_make_authorization_url(oauth_data)
|
||||||
|
|
||||||
def get_nk_workout_list(user,fake=False):
|
def get_nk_workout_list(user,fake=False,startTime=0,endTime=0):
|
||||||
r = Rower.objects.get(user=user)
|
r = Rower.objects.get(user=user)
|
||||||
|
|
||||||
if (r.nktoken == '') or (r.nktoken is None):
|
if (r.nktoken == '') or (r.nktoken is None):
|
||||||
@@ -220,10 +221,12 @@ def get_nk_workout_list(user,fake=False):
|
|||||||
return custom_exception_handler(401,s)
|
return custom_exception_handler(401,s)
|
||||||
else:
|
else:
|
||||||
# ready to fetch. Hurray
|
# ready to fetch. Hurray
|
||||||
endTime = int(arrow.now().timestamp())*1000
|
if not endTime:
|
||||||
endTime = str(endTime)
|
endTime = int(arrow.now().timestamp())*1000
|
||||||
startTime = arrow.now()-timedelta(days=30)*1000
|
endTime = str(endTime)
|
||||||
startTime = str(int(startTime.timestamp()))
|
if not startTime:
|
||||||
|
startTime = arrow.now()-timedelta(days=30)
|
||||||
|
startTime = str(int(startTime.timestamp())*1000)
|
||||||
authorizationstring = str('Bearer ' + r.nktoken)
|
authorizationstring = str('Bearer ' + r.nktoken)
|
||||||
headers = {'Authorization': authorizationstring,
|
headers = {'Authorization': authorizationstring,
|
||||||
'user-agent': 'sanderroosendaal',
|
'user-agent': 'sanderroosendaal',
|
||||||
@@ -244,81 +247,6 @@ def get_nk_workout_list(user,fake=False):
|
|||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
def add_workout_from_data(user,nkid,data,strokedata,source='nk',splitdata=None,
|
|
||||||
workoutsource='nklinklogbook'):
|
|
||||||
|
|
||||||
csvfilename = 'media/{code}_{nkid}.csv.gz'.format(
|
|
||||||
nkid=nkid,
|
|
||||||
code = uuid4().hex[:16]
|
|
||||||
)
|
|
||||||
|
|
||||||
strokedata.to_csv(csvfilename, index_label='index', compression='gzip')
|
|
||||||
|
|
||||||
userid = user.id
|
|
||||||
|
|
||||||
title = data["name"]
|
|
||||||
speedInput = data["speedInput"]
|
|
||||||
elapsedTime = data["elapsedTime"]
|
|
||||||
totalDistanceGps = data["totalDistanceGps"]
|
|
||||||
totalDistanceImp = data["totalDistanceImp"]
|
|
||||||
intervals = data["intervals"] # add intervals
|
|
||||||
oarlockSessions = data["oarlockSessions"]
|
|
||||||
deviceId = data["deviceId"] # you could get the firmware version
|
|
||||||
|
|
||||||
summary = get_nk_allstats(data,strokedata)
|
|
||||||
|
|
||||||
# oarlock inboard, length, boat name
|
|
||||||
if oarlockSessions:
|
|
||||||
oarlocksession = oarlockSessions[0] # should take seatIndex
|
|
||||||
boatName = oarlocksession["boatName"]
|
|
||||||
oarLength = oarlocksession["oarLength"] # cm
|
|
||||||
oarInboardLength = oarlocksession["oarInboardLength"] # cm
|
|
||||||
seatNumber = oarlocksession["seatNumber"]
|
|
||||||
else:
|
|
||||||
boatName = ''
|
|
||||||
oarLength = 289
|
|
||||||
oarInboardLength = 88
|
|
||||||
seatNumber = 1
|
|
||||||
|
|
||||||
workouttype = "water"
|
|
||||||
boattype = "1x"
|
|
||||||
|
|
||||||
uploadoptions = {
|
|
||||||
'secret': UPLOAD_SERVICE_SECRET,
|
|
||||||
'user':userid,
|
|
||||||
'file': csvfilename,
|
|
||||||
'title': title,
|
|
||||||
'workouttype': workouttype,
|
|
||||||
'boattype': boattype,
|
|
||||||
'nkid':nkid,
|
|
||||||
'inboard': oarInboardLength/100.,
|
|
||||||
'oarlength': oarLength/100.,
|
|
||||||
'summary':summary,
|
|
||||||
}
|
|
||||||
|
|
||||||
session = requests.session()
|
|
||||||
newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
|
|
||||||
session.headers.update(newHeaders)
|
|
||||||
|
|
||||||
response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return 0,response.text
|
|
||||||
|
|
||||||
try:
|
|
||||||
workoutid = response.json()['id']
|
|
||||||
except KeyError:
|
|
||||||
workoutid = 1
|
|
||||||
|
|
||||||
|
|
||||||
# evt update workout summary
|
|
||||||
|
|
||||||
# return
|
|
||||||
return workoutid,""
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_workout(user,nkid):
|
def get_workout(user,nkid):
|
||||||
r = Rower.objects.get(user=user)
|
r = Rower.objects.get(user=user)
|
||||||
if (r.nktoken == '') or (r.nktoken is None):
|
if (r.nktoken == '') or (r.nktoken is None):
|
||||||
@@ -338,8 +266,6 @@ def get_workout(user,nkid):
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# get strokes
|
# get strokes
|
||||||
url = NK_API_LOCATION+"api/v1/sessions/strokes"
|
url = NK_API_LOCATION+"api/v1/sessions/strokes"
|
||||||
response = requests.get(url,headers=headers,params=params)
|
response = requests.get(url,headers=headers,params=params)
|
||||||
@@ -353,22 +279,7 @@ def get_workout(user,nkid):
|
|||||||
|
|
||||||
strokeData = jsonData[str(nkid)]
|
strokeData = jsonData[str(nkid)]
|
||||||
|
|
||||||
df = pd.DataFrame.from_dict(strokeData)
|
df = strokeDataToDf(strokeData)
|
||||||
oarlockData = df['oarlockStrokes']
|
|
||||||
|
|
||||||
oarlockData = oarlockData.apply(lambda x:getdict(x, seatIndex=1))
|
|
||||||
df2 = pd.DataFrame.from_records(oarlockData.values)
|
|
||||||
|
|
||||||
df.set_index('timestamp')
|
|
||||||
|
|
||||||
if not df2.empty:
|
|
||||||
df2.set_index('timestamp')
|
|
||||||
df = df.merge(df2,left_index=True,right_index=True)
|
|
||||||
df = df.rename(columns={"timestamp_x":"timestamp"})
|
|
||||||
|
|
||||||
df = df.drop('oarlockStrokes',axis=1)
|
|
||||||
df.sort_values(by='timestamp',ascending=True,inplace=True)
|
|
||||||
df.fillna(inplace=True,method='ffill')
|
|
||||||
|
|
||||||
# get workout data
|
# get workout data
|
||||||
timestampbegin = df['timestamp'].min()
|
timestampbegin = df['timestamp'].min()
|
||||||
@@ -379,6 +290,7 @@ def get_workout(user,nkid):
|
|||||||
'startTime':timestampbegin-1,
|
'startTime':timestampbegin-1,
|
||||||
'endTime': timestampend+1,
|
'endTime': timestampend+1,
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.get(url, headers=headers,params=params)
|
response = requests.get(url, headers=headers,params=params)
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
|
|||||||
+7
-70
@@ -111,7 +111,10 @@ def safetimedelta(x):
|
|||||||
|
|
||||||
siteurl = SITE_URL
|
siteurl = SITE_URL
|
||||||
|
|
||||||
from rowers.utils import get_nk_summary, get_nk_allstats, get_nk_intervalstats,getdict
|
from rowers.nkimportutils import (
|
||||||
|
get_nk_summary, get_nk_allstats, get_nk_intervalstats,getdict,strokeDataToDf,
|
||||||
|
add_workout_from_data
|
||||||
|
)
|
||||||
|
|
||||||
# testing task
|
# testing task
|
||||||
|
|
||||||
@@ -2958,6 +2961,7 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts,de
|
|||||||
@app.task
|
@app.task
|
||||||
def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone,debug=False,**kwargs):
|
def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone,debug=False,**kwargs):
|
||||||
time.sleep(delaysec)
|
time.sleep(delaysec)
|
||||||
|
|
||||||
data = alldata[nkid]
|
data = alldata[nkid]
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
@@ -2981,22 +2985,8 @@ def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone
|
|||||||
|
|
||||||
jsonData = response.json()
|
jsonData = response.json()
|
||||||
strokeData = jsonData[str(nkid)]
|
strokeData = jsonData[str(nkid)]
|
||||||
df = pd.DataFrame.from_dict(strokeData)
|
|
||||||
oarlockData = df['oarlockStrokes']
|
|
||||||
|
|
||||||
oarlockData = oarlockData.apply(lambda x:getdict(x, seatIndex=1))
|
df = strokeDataToDf(strokeData)
|
||||||
df2 = pd.DataFrame.from_records(oarlockData.values)
|
|
||||||
|
|
||||||
df.set_index('timestamp')
|
|
||||||
|
|
||||||
if not df2.empty:
|
|
||||||
df2.set_index('timestamp')
|
|
||||||
df = df.merge(df2,left_index=True,right_index=True)
|
|
||||||
df = df.rename(columns={"timestamp_x":"timestamp"})
|
|
||||||
|
|
||||||
df = df.drop('oarlockStrokes',axis=1)
|
|
||||||
df.sort_values(by='timestamp',ascending=True,inplace=True)
|
|
||||||
df.fillna(inplace=True,method='ffill')
|
|
||||||
|
|
||||||
# get workout data
|
# get workout data
|
||||||
timestampbegin = df['timestamp'].min()
|
timestampbegin = df['timestamp'].min()
|
||||||
@@ -3009,60 +2999,7 @@ def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone
|
|||||||
|
|
||||||
df.to_csv(csvfilename, index_label='index', compression='gzip')
|
df.to_csv(csvfilename, index_label='index', compression='gzip')
|
||||||
|
|
||||||
|
workoutid,error = add_workout_from_data(userid,nkid,data,df)
|
||||||
title = data["name"]
|
|
||||||
speedInput = data["speedInput"]
|
|
||||||
elapsedTime = data["elapsedTime"]
|
|
||||||
totalDistanceGps = data["totalDistanceGps"]
|
|
||||||
totalDistanceImp = data["totalDistanceImp"]
|
|
||||||
intervals = data["intervals"] # add intervals
|
|
||||||
oarlockSessions = data["oarlockSessions"]
|
|
||||||
deviceId = data["deviceId"] # you could get the firmware version
|
|
||||||
|
|
||||||
summary = get_nk_allstats(data,df)
|
|
||||||
|
|
||||||
# oarlock inboard, length, boat name
|
|
||||||
if oarlockSessions:
|
|
||||||
oarlocksession = oarlockSessions[0] # should take seatIndex
|
|
||||||
boatName = oarlocksession["boatName"]
|
|
||||||
oarLength = oarlocksession["oarLength"] # cm
|
|
||||||
oarInboardLength = oarlocksession["oarInboardLength"] # cm
|
|
||||||
seatNumber = oarlocksession["seatNumber"]
|
|
||||||
else:
|
|
||||||
boatName = ''
|
|
||||||
oarLength = 289
|
|
||||||
oarInboardLength = 88
|
|
||||||
seatNumber = 1
|
|
||||||
|
|
||||||
workouttype = "water"
|
|
||||||
boattype = "1x"
|
|
||||||
|
|
||||||
uploadoptions = {
|
|
||||||
'secret': UPLOAD_SERVICE_SECRET,
|
|
||||||
'user':userid,
|
|
||||||
'file': csvfilename,
|
|
||||||
'title': title,
|
|
||||||
'workouttype': workouttype,
|
|
||||||
'boattype': boattype,
|
|
||||||
'nkid':nkid,
|
|
||||||
'inboard': oarInboardLength/100.,
|
|
||||||
'oarlength': oarLength/100.,
|
|
||||||
'summary':summary,
|
|
||||||
}
|
|
||||||
|
|
||||||
session = requests.session()
|
|
||||||
newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
|
|
||||||
session.headers.update(newHeaders)
|
|
||||||
|
|
||||||
response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return 0,response.text
|
|
||||||
|
|
||||||
try:
|
|
||||||
workoutid = response.json()['id']
|
|
||||||
except KeyError:
|
|
||||||
workoutid = 1
|
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
engine = create_engine(database_url_debug, echo=False)
|
engine = create_engine(database_url_debug, echo=False)
|
||||||
|
|||||||
@@ -335,7 +335,7 @@
|
|||||||
<i class="fas fa-eraser fa-fw"></i> Remove Power Data
|
<i class="fas fa-eraser fa-fw"></i> Remove Power Data
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if 'speedcoach2' 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/">
|
||||||
<i class="fas fa-satellite"></i>
|
<i class="fas fa-satellite"></i>
|
||||||
|
|||||||
+12
-2
@@ -623,6 +623,12 @@ def mocked_requests(*args, **kwargs):
|
|||||||
with open('rowers/tests/testdata/nk_list.json','r') as infile:
|
with open('rowers/tests/testdata/nk_list.json','r') as infile:
|
||||||
nkworkoutlist = json.load(infile)
|
nkworkoutlist = json.load(infile)
|
||||||
|
|
||||||
|
with open('rowers/tests/testdata/example-session-strokes-with-impeller-data.json','r') as infile:
|
||||||
|
nkimpellerstrokedata = json.load(infile)
|
||||||
|
|
||||||
|
with open('rowers/tests/testdata/example-session-with-impeller-data.json','r') as infile:
|
||||||
|
nkimpellerworkoutlist = json.load(infile)
|
||||||
|
|
||||||
polar_json = {
|
polar_json = {
|
||||||
'available-user-data': []
|
'available-user-data': []
|
||||||
}
|
}
|
||||||
@@ -960,10 +966,14 @@ def mocked_requests(*args, **kwargs):
|
|||||||
}
|
}
|
||||||
return MockResponse(json_data,200)
|
return MockResponse(json_data,200)
|
||||||
if nkstrokestester.match(args[0]):
|
if nkstrokestester.match(args[0]):
|
||||||
|
params = kwargs.pop('params',{})
|
||||||
|
if 'sessionIds' in params and params['sessionIds'] == '404':
|
||||||
|
return MockResponse(nkimpellerstrokedata, 200)
|
||||||
return MockResponse(nkstrokedata,200)
|
return MockResponse(nkstrokedata,200)
|
||||||
if nkworkoutlisttester.match(args[0]):
|
if nkworkoutlisttester.match(args[0]):
|
||||||
|
params = kwargs.pop('params',{})
|
||||||
|
if 'startTime' in params and params['startTime'] == 1267136372998:
|
||||||
|
return MockResponse(nkimpellerworkoutlist,200)
|
||||||
return MockResponse(nkworkoutlist,200)
|
return MockResponse(nkworkoutlist,200)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -424,9 +424,44 @@ class NKObjects(DjangoTestCase):
|
|||||||
|
|
||||||
self.assertEqual(response.status_code,200)
|
self.assertEqual(response.status_code,200)
|
||||||
|
|
||||||
|
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
||||||
|
@patch('rowers.tasks.requests.get', side_effects=mocked_requests)
|
||||||
|
def test_handle_nk_get_workouts(self, mocked_session, mock_get):
|
||||||
|
with open('rowers/tests/testdata/nk_list.json','r') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
with open('rowers/tests/testdata/nk_strokes.json','r') as f:
|
||||||
|
strokeData = json.load(f)
|
||||||
|
|
||||||
|
alldata = {}
|
||||||
|
for item in data:
|
||||||
|
alldata[item['id']] = item
|
||||||
|
|
||||||
|
result = rowers.nkstuff.rower_nk_token_refresh(self.u)
|
||||||
|
|
||||||
|
res = tasks.handle_nk_async_workout(
|
||||||
|
alldata,self.r.user.id,self.r.nktoken,469,0,'UTC'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@patch('rowers.nkstuff.requests.get', side_effect=mocked_requests)
|
@patch('rowers.nkstuff.requests.get', side_effect=mocked_requests)
|
||||||
@patch('rowers.nkstuff.requests.post', side_effect=mocked_requests)
|
@patch('rowers.nkstuff.requests.post', side_effect=mocked_requests)
|
||||||
@patch('rowers.nkstuff.requests.session', side_effect=mocked_session)
|
def test_nk_get_workouts(self, mock_get, mockpost):
|
||||||
|
result = rowers.nkstuff.nk_open(self.u)
|
||||||
|
self.assertEqual(result,"TA3n1vrNjuQJWw0TdCDHnjSmrjIPULhTlejMIWqq")
|
||||||
|
response = self.c.get('/rowers/workout/nkimport/all/',follow=True)
|
||||||
|
|
||||||
|
expected = reverse('workouts_view')
|
||||||
|
|
||||||
|
self.assertRedirects(response,
|
||||||
|
expected_url=expected,
|
||||||
|
status_code=302,target_status_code=200)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
@patch('rowers.nkstuff.requests.get', side_effect=mocked_requests)
|
||||||
|
@patch('rowers.nkstuff.requests.post', side_effect=mocked_requests)
|
||||||
|
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
||||||
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
||||||
def test_nk_import(self, mock_get, mock_post,
|
def test_nk_import(self, mock_get, mock_post,
|
||||||
mocked_session,
|
mocked_session,
|
||||||
@@ -441,6 +476,34 @@ class NKObjects(DjangoTestCase):
|
|||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
w = Workout.objects.get(id=1)
|
||||||
|
#self.assertEqual(w.inboard,0.89)
|
||||||
|
#self.assertEqual(w.oarlength,2.87)
|
||||||
|
|
||||||
|
@patch('rowers.nkstuff.requests.get', side_effect=mocked_requests)
|
||||||
|
@patch('rowers.nkstuff.requests.post', side_effect=mocked_requests)
|
||||||
|
@patch('rowers.nkimportutils.requests.session', side_effect=mocked_session)
|
||||||
|
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
|
||||||
|
def test_nk_import_impeller(self, mock_get, mock_post,
|
||||||
|
mocked_session,
|
||||||
|
mocked_getsmallrowdata_db):
|
||||||
|
|
||||||
|
result = rowers.nkstuff.rower_nk_token_refresh(self.u)
|
||||||
|
response = self.c.get('/rowers/workout/nkimport/404',follow=True)
|
||||||
|
|
||||||
|
self.assertRedirects(response,
|
||||||
|
expected_url='/rowers/workout/'+encoded1+'/edit/',
|
||||||
|
status_code=301,target_status_code=200)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
response = self.c.get('/rowers/workout/'+encoded1+'/otwuseimpeller/', follow=True)
|
||||||
|
self.assertRedirects(response,
|
||||||
|
expected_url='/rowers/workout/'+encoded1+'/edit/',
|
||||||
|
status_code=302,target_status_code=200)
|
||||||
|
|
||||||
|
w = Workout.objects.get(id=1)
|
||||||
|
#self.assertTrue(w.impeller)
|
||||||
|
|
||||||
|
|
||||||
#@pytest.mark.django_db
|
#@pytest.mark.django_db
|
||||||
|
|||||||
@@ -548,6 +548,19 @@ def do_sync(w,options, quick=False):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
if options['inboard'] != 0 and options['inboard'] != '':
|
||||||
|
w.inboard = options['inboard']
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
if options['oarlength'] != 0 and options['oarlength'] != '':
|
||||||
|
w.oarlength = options['oarlength']
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if options['garminid'] != 0 and options['garminid'] != '':
|
if options['garminid'] != 0 and options['garminid'] != '':
|
||||||
w.uploadedtogarmin = options['garminid']
|
w.uploadedtogarmin = options['garminid']
|
||||||
|
|||||||
@@ -568,6 +568,7 @@ urlpatterns = [
|
|||||||
re_path(r'^workout/c2import/all/$',views.workout_getc2workout_all,name='workout_getc2workout_all'),
|
re_path(r'^workout/c2import/all/$',views.workout_getc2workout_all,name='workout_getc2workout_all'),
|
||||||
re_path(r'^workout/c2import/all/(?P<page>\d+)/$',views.workout_getc2workout_all,name='workout_getc2workout_all'),
|
re_path(r'^workout/c2import/all/(?P<page>\d+)/$',views.workout_getc2workout_all,name='workout_getc2workout_all'),
|
||||||
re_path(r'^workout/nkimport/$',views.workout_nkimport_view,name='workout_nkimport_view'),
|
re_path(r'^workout/nkimport/$',views.workout_nkimport_view,name='workout_nkimport_view'),
|
||||||
|
re_path(r'^workout/nkimport/(?P<startTime>\d+)/(?P<endTime>\d+)/$',views.workout_nkimport_view,name='workout_nkimport_view'),
|
||||||
re_path(r'^workout/nkimport/all/$',views.workout_getnkworkout_all,name='workout_getnkworkout_all'),
|
re_path(r'^workout/nkimport/all/$',views.workout_getnkworkout_all,name='workout_getnkworkout_all'),
|
||||||
re_path(r'^workout/rp3import/(?P<externalid>\d+)/$',views.workout_getrp3importview,
|
re_path(r'^workout/rp3import/(?P<externalid>\d+)/$',views.workout_getrp3importview,
|
||||||
name='workout_getrp3importview'),
|
name='workout_getrp3importview'),
|
||||||
|
|||||||
-123
@@ -1108,126 +1108,3 @@ def strfdelta(tdelta):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def get_nk_intervalstats(workoutdata,strokedata):
|
|
||||||
intervals = workoutdata['intervals']
|
|
||||||
separator = "|"
|
|
||||||
stri = "Workout Details\n"
|
|
||||||
stri += "#-{sep}SDist{sep}-Split-{sep}-SPace-{sep}-Pwr-{sep}-SPM--{sep}-AvgHR-{sep}DPS-\n".format(
|
|
||||||
sep=separator)
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
for interval in intervals:
|
|
||||||
id = interval['id']
|
|
||||||
sdist = interval['totalDistanceGps']
|
|
||||||
avgpace = interval['avgPaceGps']/1000.
|
|
||||||
avgpacetd = timedelta(seconds=avgpace)
|
|
||||||
newpacestring = strfdelta(avgpacetd)
|
|
||||||
|
|
||||||
elapsedSeconds = interval['elapsedTime']/1000. # secs
|
|
||||||
elapsedTime = datetime.datetime.utcfromtimestamp(elapsedSeconds)
|
|
||||||
|
|
||||||
newsplitstring = "%s.%i" % (elapsedTime.strftime("%M:%S"), elapsedTime.microsecond/100000)
|
|
||||||
|
|
||||||
pwr = interval['avgPower']
|
|
||||||
avghr = interval['avgHeartRate']
|
|
||||||
spm = interval['avgStrokeRate']
|
|
||||||
dps = interval['distStrokeGps']
|
|
||||||
|
|
||||||
stri += "{i:0>2}{sep}{sdist:0>5}{sep}{split}{sep}{space}{sep} {pwr:0>3} {sep}".format(
|
|
||||||
i=i + 1,
|
|
||||||
sdist=int(float(sdist)),
|
|
||||||
split=newsplitstring,
|
|
||||||
space=newpacestring,
|
|
||||||
pwr=int(pwr),
|
|
||||||
sep=separator,
|
|
||||||
)
|
|
||||||
stri += " {spm} {sep} {avghr:0>3} {sep}{dps:0>4.1f}\n".format(
|
|
||||||
sep=separator,
|
|
||||||
avghr=avghr,
|
|
||||||
spm=spm,
|
|
||||||
dps=dps,
|
|
||||||
)
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
return stri
|
|
||||||
|
|
||||||
def get_nk_summary(workoutdata,strokedata):
|
|
||||||
|
|
||||||
name = workoutdata['name']
|
|
||||||
|
|
||||||
avgpace = workoutdata['avgPaceGps']/1000. # secs
|
|
||||||
avgpacetd = timedelta(seconds=avgpace)
|
|
||||||
avgpacestring = strfdelta(avgpacetd)
|
|
||||||
|
|
||||||
elapsedSeconds = workoutdata['elapsedTime']/1000. # secs
|
|
||||||
elapsedTime = datetime.datetime.utcfromtimestamp(elapsedSeconds)
|
|
||||||
|
|
||||||
timestring = "%s.%i" % (elapsedTime.strftime("%H:%M:%S"), elapsedTime.microsecond/100000)
|
|
||||||
|
|
||||||
dist = workoutdata['totalDistanceGps']
|
|
||||||
spm = workoutdata['avgStrokeRate']
|
|
||||||
avghr = workoutdata['avgHeartRate']
|
|
||||||
avgdps = workoutdata['distStrokeGps']
|
|
||||||
maxhr = strokedata['heartRate'].max()
|
|
||||||
pwr = workoutdata['avgPower']
|
|
||||||
|
|
||||||
sep = "|"
|
|
||||||
|
|
||||||
|
|
||||||
stri1 = "Workout Summary - " + name + "\n"
|
|
||||||
stri1 += "--{sep}Total{sep}--Total---{sep}--Avg--{sep}-Avg-{sep}-Avg--{sep}-Avg-{sep}-Max-{sep}-Avg\n".format(
|
|
||||||
sep=sep)
|
|
||||||
stri1 += "--{sep}Dist-{sep}--Time----{sep}-Pace--{sep}-Pwr-{sep}-SPM--{sep}-HR--{sep}-HR--{sep}-DPS\n".format(
|
|
||||||
sep=sep)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
stri1 += "--{sep}{dist:0>5.0f}{sep}".format(
|
|
||||||
sep=sep,
|
|
||||||
dist=dist,
|
|
||||||
)
|
|
||||||
|
|
||||||
stri1 += timestring + sep + avgpacestring
|
|
||||||
|
|
||||||
stri1 += "{sep}{avgpower:0>5.1f}".format(
|
|
||||||
sep=sep,
|
|
||||||
avgpower=pwr,
|
|
||||||
)
|
|
||||||
|
|
||||||
stri1 += "{sep} {avgsr:2.1f} {sep}{avghr:0>5.1f}{sep}".format(
|
|
||||||
avgsr=spm,
|
|
||||||
sep=sep,
|
|
||||||
avghr=avghr
|
|
||||||
)
|
|
||||||
|
|
||||||
stri1 += "{maxhr:0>5.1f}{sep}{avgdps:0>4.1f}\n".format(
|
|
||||||
sep=sep,
|
|
||||||
maxhr=maxhr,
|
|
||||||
avgdps=avgdps
|
|
||||||
)
|
|
||||||
|
|
||||||
return stri1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return stri1
|
|
||||||
|
|
||||||
def get_nk_allstats(data,workoutdata):
|
|
||||||
stri = get_nk_summary(data, workoutdata) + \
|
|
||||||
get_nk_intervalstats(data, workoutdata)
|
|
||||||
return stri
|
|
||||||
|
|
||||||
#def get_workout(user,nkid):
|
|
||||||
def getdict(x, seatIndex=1):
|
|
||||||
seatStrokes = pd.DataFrame(x)
|
|
||||||
try:
|
|
||||||
seatStrokes = seatStrokes.set_index('seatIndex')
|
|
||||||
return dict(seatStrokes.loc[seatIndex])
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return {}
|
|
||||||
|
|||||||
@@ -836,14 +836,14 @@ def workout_getnkworkout_all(request):
|
|||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
@permission_required('rower.is_coach',fn=get_user_by_userid, raise_exception=True)
|
@permission_required('rower.is_coach',fn=get_user_by_userid, raise_exception=True)
|
||||||
def workout_nkimport_view(request,userid=0):
|
def workout_nkimport_view(request,userid=0,startTime=0,endTime=0):
|
||||||
r = getrequestrower(request,userid=userid)
|
r = getrequestrower(request,userid=userid)
|
||||||
try:
|
try:
|
||||||
thetoken = nk_open(request.user)
|
thetoken = nk_open(request.user)
|
||||||
except NoTokenError:
|
except NoTokenError:
|
||||||
return HttpResponseRedirect("/rowers/me/nkauthorize/")
|
return HttpResponseRedirect("/rowers/me/nkauthorize/")
|
||||||
|
|
||||||
res = nkstuff.get_nk_workout_list(request.user)
|
res = nkstuff.get_nk_workout_list(request.user,startTime=startTime,endTime=endTime)
|
||||||
|
|
||||||
if (res.status_code != 200):
|
if (res.status_code != 200):
|
||||||
if (res.status_code == 401):
|
if (res.status_code == 401):
|
||||||
@@ -882,6 +882,9 @@ def workout_nkimport_view(request,userid=0):
|
|||||||
'start_date':arrow.get(item['startTime']),
|
'start_date':arrow.get(item['startTime']),
|
||||||
} for item in res.json()]
|
} for item in res.json()]
|
||||||
|
|
||||||
|
#for item in res.json():
|
||||||
|
# print(item['startTime'],arrow.get(item['startTime']),item['name'])
|
||||||
|
|
||||||
workouts = []
|
workouts = []
|
||||||
|
|
||||||
for item in res.json():
|
for item in res.json():
|
||||||
|
|||||||
@@ -636,7 +636,6 @@ def upgrade_checkouts_view(request):
|
|||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
def downgrade_checkouts_view(request):
|
def downgrade_checkouts_view(request):
|
||||||
print('aap')
|
|
||||||
if not PAYMENT_PROCESSING_ON:
|
if not PAYMENT_PROCESSING_ON:
|
||||||
url = reverse('promembership')
|
url = reverse('promembership')
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@@ -336,6 +336,8 @@ def rower_exportsettings_view(request,userid=0):
|
|||||||
'strava_auto_import':'stravatoken',
|
'strava_auto_import':'stravatoken',
|
||||||
'strava_auto_delete':'stravatoken',
|
'strava_auto_delete':'stravatoken',
|
||||||
'trainingpeaks_auto_export':'tptoken',
|
'trainingpeaks_auto_export':'tptoken',
|
||||||
|
'rp3_auto_import':'rp3token',
|
||||||
|
'nk_auto_import':'nktoken'
|
||||||
}
|
}
|
||||||
r = getrequestrowercoachee(request,userid=userid)
|
r = getrequestrowercoachee(request,userid=userid)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
|||||||
@@ -4859,8 +4859,6 @@ def workout_upload_api(request):
|
|||||||
message = {'status':'false','message':'this view cannot be accessed through GET'}
|
message = {'status':'false','message':'this view cannot be accessed through GET'}
|
||||||
return JSONResponse(status=403,data=message)
|
return JSONResponse(status=403,data=message)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# test if JSON
|
# test if JSON
|
||||||
try:
|
try:
|
||||||
json_data = json.loads(request.body)
|
json_data = json.loads(request.body)
|
||||||
@@ -4939,6 +4937,22 @@ def workout_upload_api(request):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
startdatetime = ''
|
startdatetime = ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
oarlockfirmware = post_data['oarlockfirmware']
|
||||||
|
except:
|
||||||
|
oarlockfirmware = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
inboard = post_data['inboard']
|
||||||
|
except:
|
||||||
|
inboard = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
oarlength = post_data['oarlength']
|
||||||
|
except:
|
||||||
|
oarlength = None
|
||||||
|
|
||||||
|
|
||||||
r = None
|
r = None
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
t = form.cleaned_data['title']
|
t = form.cleaned_data['title']
|
||||||
@@ -5011,6 +5025,9 @@ def workout_upload_api(request):
|
|||||||
notes=notes,
|
notes=notes,
|
||||||
uploadoptions=post_data,
|
uploadoptions=post_data,
|
||||||
startdatetime=startdatetime,
|
startdatetime=startdatetime,
|
||||||
|
oarlockfirmware=oarlockfirmware,
|
||||||
|
inboard=inboard,
|
||||||
|
oarlength=oarlength,
|
||||||
)
|
)
|
||||||
|
|
||||||
if id == 0:
|
if id == 0:
|
||||||
|
|||||||
Reference in New Issue
Block a user