understands interval string when defining workout
This commit is contained in:
@@ -180,7 +180,7 @@ ratelim==0.1.6
|
|||||||
redis==3.5.3
|
redis==3.5.3
|
||||||
requests==2.23.0
|
requests==2.23.0
|
||||||
requests-oauthlib==1.2.0
|
requests-oauthlib==1.2.0
|
||||||
rowingdata==3.1.1
|
rowingdata==3.1.3
|
||||||
rowingphysics==0.5.0
|
rowingphysics==0.5.0
|
||||||
rq==0.13.0
|
rq==0.13.0
|
||||||
rules==2.1
|
rules==2.1
|
||||||
|
|||||||
@@ -196,7 +196,6 @@ def get_c2_workouts(rower,do_async=True):
|
|||||||
knownc2ids = uniqify(knownc2ids+tombstones+parkedids)
|
knownc2ids = uniqify(knownc2ids+tombstones+parkedids)
|
||||||
|
|
||||||
newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
|
newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
|
||||||
print(newids,'aap')
|
|
||||||
|
|
||||||
newparkedids = uniqify(newids+parkedids)
|
newparkedids = uniqify(newids+parkedids)
|
||||||
|
|
||||||
|
|||||||
@@ -2275,6 +2275,11 @@ class PlannedSession(models.Model):
|
|||||||
|
|
||||||
is_template = models.BooleanField(default=False)
|
is_template = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
fitfile = models.CharField(default=None,max_length=150,blank=True,null=True)
|
||||||
|
json_string = models.TextField(max_length=1000,default=None,blank=True,null=True)
|
||||||
|
interval_string = models.TextField(max_length=1000,default=None,blank=True,null=True,
|
||||||
|
verbose_name='Interval String (optional)')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
||||||
name = self.name
|
name = self.name
|
||||||
@@ -2493,6 +2498,7 @@ class PlannedSessionForm(ModelForm):
|
|||||||
'sessionunit',
|
'sessionunit',
|
||||||
'course',
|
'course',
|
||||||
'comment',
|
'comment',
|
||||||
|
'interval_string'
|
||||||
]
|
]
|
||||||
|
|
||||||
dateTimeOptions = {
|
dateTimeOptions = {
|
||||||
@@ -2505,6 +2511,7 @@ class PlannedSessionForm(ModelForm):
|
|||||||
'startdate': AdminDateWidget(),
|
'startdate': AdminDateWidget(),
|
||||||
'enddate': AdminDateWidget(),
|
'enddate': AdminDateWidget(),
|
||||||
'preferreddate': AdminDateWidget(),
|
'preferreddate': AdminDateWidget(),
|
||||||
|
'interval_string': forms.Textarea(attrs={'rows':2,'cols':50})
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self,*args,**kwargs):
|
def __init__(self,*args,**kwargs):
|
||||||
@@ -4330,6 +4337,7 @@ class PlannedSessionComment(models.Model):
|
|||||||
user = models.ForeignKey(User,on_delete=models.PROTECT)
|
user = models.ForeignKey(User,on_delete=models.PROTECT)
|
||||||
plannedsession = models.ForeignKey(PlannedSession,on_delete=models.CASCADE)
|
plannedsession = models.ForeignKey(PlannedSession,on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return u'Comment to: {w} by {u1} {u2}'.format(
|
return u'Comment to: {w} by {u1} {u2}'.format(
|
||||||
w=self.workout,
|
w=self.workout,
|
||||||
|
|||||||
@@ -16,11 +16,15 @@ from django.conf import settings
|
|||||||
import pytz
|
import pytz
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
from rowers.utils import myqueue,calculate_age,totaltime_sec_to_string
|
from rowers.utils import myqueue,calculate_age,totaltime_sec_to_string
|
||||||
|
|
||||||
|
from fitparse import FitFile
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import django_rq
|
import django_rq
|
||||||
queue = django_rq.get_queue('default')
|
queue = django_rq.get_queue('default')
|
||||||
queuelow = django_rq.get_queue('low')
|
queuelow = django_rq.get_queue('low')
|
||||||
queuehigh = django_rq.get_queue('low')
|
queuehigh = django_rq.get_queue('low')
|
||||||
|
import json
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
@@ -77,6 +81,176 @@ from rowers.tasks import (
|
|||||||
)
|
)
|
||||||
from rowers.utils import totaltime_sec_to_string
|
from rowers.utils import totaltime_sec_to_string
|
||||||
|
|
||||||
|
def step_to_string(step):
|
||||||
|
|
||||||
|
target_dict = {
|
||||||
|
'heart_rate': {
|
||||||
|
'name':'Heart Rate between',
|
||||||
|
'low':'custom_target_heart_rate_low',
|
||||||
|
'high': 'custom_target_heart_rate_high'
|
||||||
|
},
|
||||||
|
'speed':{
|
||||||
|
'name': 'Speed between',
|
||||||
|
'low': 'custom_target_speed_low',
|
||||||
|
'high': 'custom_target_speed_high',
|
||||||
|
},
|
||||||
|
'cadence':{
|
||||||
|
'name': 'SPM between',
|
||||||
|
'low': 'custom_target_cadence_low',
|
||||||
|
'high': 'custom_target_cadence_high',
|
||||||
|
},
|
||||||
|
'open':{
|
||||||
|
'name': 'between',
|
||||||
|
'low': 'custom_target_value_low',
|
||||||
|
'high': 'custom_target_value_high',
|
||||||
|
},
|
||||||
|
'power':{
|
||||||
|
'name': 'Power between',
|
||||||
|
'low': 'custom_target_power_low',
|
||||||
|
'high': 'custom_target_power_high',
|
||||||
|
},
|
||||||
|
'stroke_type':{
|
||||||
|
'name': 'Stroke type',
|
||||||
|
'low': 'target_swim_stroke',
|
||||||
|
'high': '',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
duration = ''
|
||||||
|
repeat = ''
|
||||||
|
target = ''
|
||||||
|
intensity = ''
|
||||||
|
nr = ''
|
||||||
|
name = ''
|
||||||
|
|
||||||
|
for key, value in step.items():
|
||||||
|
|
||||||
|
if key == 'duration_distance':
|
||||||
|
duration = '{v} m'.format(v=value)
|
||||||
|
if key == 'duration_time':
|
||||||
|
dd = timedelta(seconds=value)
|
||||||
|
duration = '{v} min'.format(v=str(dd))
|
||||||
|
if key in ['duration_hr']:
|
||||||
|
duration = 'until HR reaches {v}'.format(v=value)
|
||||||
|
if key == 'target_type' and value is not None:
|
||||||
|
dd = target_dict[value]
|
||||||
|
t = dd['name']
|
||||||
|
l = ''
|
||||||
|
h = ''
|
||||||
|
if dd['low']:
|
||||||
|
v = step[dd['low']]
|
||||||
|
if value == 'heart_rate':
|
||||||
|
if v<100:
|
||||||
|
v = '{v} \%'.format(v=v)
|
||||||
|
else:
|
||||||
|
v = v-100
|
||||||
|
v = '{v}'.format(v=v)
|
||||||
|
l = '{v}'.format(v=v)
|
||||||
|
if dd['high']:
|
||||||
|
v = step[dd['high']]
|
||||||
|
if value == 'heart_rate':
|
||||||
|
if v<100:
|
||||||
|
v = '{v} \%'.format(v=v)
|
||||||
|
else:
|
||||||
|
v = v-100
|
||||||
|
v = '{v}'.format(v=v)
|
||||||
|
h = 'and {v}'.format(v=v)
|
||||||
|
|
||||||
|
target = '{t} {l} {h}'.format(
|
||||||
|
t = t,
|
||||||
|
l = l,
|
||||||
|
h = h,
|
||||||
|
)
|
||||||
|
if key == 'intensity':
|
||||||
|
intensity = '{v}'.format(v=value)
|
||||||
|
if key == 'repeat':
|
||||||
|
pass
|
||||||
|
if key == 'message_index':
|
||||||
|
nr = '{v}'.format(v=value)
|
||||||
|
if key == 'wkt_step_name':
|
||||||
|
name = '{v}'.format(v=value)
|
||||||
|
|
||||||
|
s = '{nr}: {name} {intensity} {duration} {target} {repeat}'.format(
|
||||||
|
nr = nr,
|
||||||
|
name = name,
|
||||||
|
intensity = intensity,
|
||||||
|
duration = duration,
|
||||||
|
target=target,
|
||||||
|
repeat = repeat,
|
||||||
|
)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
def ps_dict_get_description(d):
|
||||||
|
s = ''
|
||||||
|
steps = d['steps']
|
||||||
|
for step in steps:
|
||||||
|
s += step_to_string(step)
|
||||||
|
s += '\n'
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
class FitWorkoutSteps(object):
|
||||||
|
def __init__(self,readfile):
|
||||||
|
self.readfile = readfile
|
||||||
|
self.fitfile = FitFile(readfile, check_crc=False)
|
||||||
|
self.records = self.fitfile.messages
|
||||||
|
self.name = ''
|
||||||
|
self.sport = 'Custom'
|
||||||
|
# message 0 is file id
|
||||||
|
# message 1 must be workout description
|
||||||
|
m0 = self.records[0]
|
||||||
|
typ = m0.fields[0].value
|
||||||
|
if typ != 'workout':
|
||||||
|
raise TypeError("Wrong FIT file type")
|
||||||
|
|
||||||
|
steps = []
|
||||||
|
stepmessages = self.fitfile.get_messages('workout_step')
|
||||||
|
|
||||||
|
for msg in stepmessages:
|
||||||
|
if msg.name == 'workout_step':
|
||||||
|
step = {}
|
||||||
|
for field in msg.fields:
|
||||||
|
ff = field.as_dict()
|
||||||
|
step[ff['name']] = ff['value']
|
||||||
|
steps.append(step)
|
||||||
|
|
||||||
|
for msg in self.fitfile.get_messages('workout'):
|
||||||
|
if msg.name == 'workout':
|
||||||
|
for field in msg.fields:
|
||||||
|
ff = field.as_dict()
|
||||||
|
if ff['name'] == 'wkt_name':
|
||||||
|
self.name = ff['value']
|
||||||
|
if ff['name'] == 'sport':
|
||||||
|
self.sport = ff['value']
|
||||||
|
|
||||||
|
|
||||||
|
self.steps = steps
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
d = self.get_dict()
|
||||||
|
|
||||||
|
return json.dumps(d)
|
||||||
|
|
||||||
|
def get_dict(self):
|
||||||
|
d = {}
|
||||||
|
d['filename'] = self.readfile
|
||||||
|
d['name'] = self.name
|
||||||
|
d['steps'] = self.steps
|
||||||
|
d['sport'] = self.sport
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def get_description(self):
|
||||||
|
s = ''
|
||||||
|
for step in self.steps:
|
||||||
|
s += step_to_string(step)
|
||||||
|
s += '\n'
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
def checkscores(r,macrocycles):
|
def checkscores(r,macrocycles):
|
||||||
for m in macrocycles:
|
for m in macrocycles:
|
||||||
createmesofillers(m)
|
createmesofillers(m)
|
||||||
@@ -1474,7 +1648,7 @@ def default_class(r,w,race):
|
|||||||
boatclass = 'water'
|
boatclass = 'water'
|
||||||
else:
|
else:
|
||||||
boatclass = 'rower'
|
boatclass = 'rower'
|
||||||
|
|
||||||
boattype = '1x'
|
boattype = '1x'
|
||||||
adaptiveclass = 'None'
|
adaptiveclass = 'None'
|
||||||
weightclass = 'hwt'
|
weightclass = 'hwt'
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from __future__ import print_function
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from rowers.views.statements import *
|
from rowers.views.statements import *
|
||||||
|
from rowingdata import trainingparser
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@permission_required('plannedsession.view_session',fn=get_session_by_pk,raise_exception=True)
|
@permission_required('plannedsession.view_session',fn=get_session_by_pk,raise_exception=True)
|
||||||
@@ -438,6 +439,9 @@ def plannedsession_create_view(request,
|
|||||||
comment = cd['comment']
|
comment = cd['comment']
|
||||||
course = cd['course']
|
course = cd['course']
|
||||||
name = cd['name']
|
name = cd['name']
|
||||||
|
interval_string = cd['interval_string']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if sessionunit == 'min':
|
if sessionunit == 'min':
|
||||||
sessionmode = 'time'
|
sessionmode = 'time'
|
||||||
@@ -460,6 +464,13 @@ def plannedsession_create_view(request,
|
|||||||
|
|
||||||
ps.save()
|
ps.save()
|
||||||
|
|
||||||
|
if interval_string:
|
||||||
|
dct = trainingparser.parsetodict(interval_string)
|
||||||
|
dct = trainingparser.tofitdict(dct)
|
||||||
|
txt = ps_dict_get_description(dct)
|
||||||
|
ps.comment += '\n'+txt
|
||||||
|
ps.save()
|
||||||
|
|
||||||
add_rower_session(r,ps)
|
add_rower_session(r,ps)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user