diff --git a/rowers/models.py b/rowers/models.py index c0718c93..022e2d96 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -20,6 +20,7 @@ from datetimewidget.widgets import DateTimeWidget from django.contrib.admin.widgets import AdminDateWidget,AdminTimeWidget,AdminSplitDateTime from django.core.validators import validate_email import os +import json import twitter import re import pytz @@ -31,6 +32,8 @@ import numpy as np import shutil +from rowingdata import trainingparser + from django.conf import settings from sqlalchemy import create_engine import sqlalchemy as sa @@ -478,7 +481,8 @@ class TeamRequest(models.Model): from rowers.utils import ( workflowleftpanel,workflowmiddlepanel, - defaultleft,defaultmiddle,landingpages + defaultleft,defaultmiddle,landingpages, + steps_read_fit ) from rowers.utils import geo_distance @@ -2279,7 +2283,7 @@ class PlannedSession(models.Model): is_template = models.BooleanField(default=False) fitfile = models.FileField(blank=True,null=True) - json_string = models.TextField(max_length=10000,default=None,blank=True,null=True) + steps_json = models.TextField(max_length=10000,default=None,blank=True,null=True) interval_string = models.TextField(max_length=1000,default=None,blank=True,null=True, verbose_name='Interval String (optional)') @@ -2309,6 +2313,15 @@ class PlannedSession(models.Model): "You must be a Self-Coach user or higher to create a planned session" ) + # interval string + if self.interval_string: + dct = trainingparser.parsetodict(interval_string) + dct = [item for item in dct if item['value'] != 0] + dct = trainingparser.tofitdict(dct) + ps.steps_json = json.dumps(dct) + + + # sort units if self.sessionmode == 'distance': @@ -2346,8 +2359,21 @@ class PlannedSession(models.Model): if self.preferreddate < self.startdate: self.preferreddate = self.startdate + super(PlannedSession,self).save(*args, **kwargs) + # read file + if self.fitfile: + if self.fitfile.name == 'False': + self.fitfile = None + else: + steps = steps_read_fit(settings.MEDIA_ROOT+'/'+self.fitfile.name) + self.steps_json = json.dumps(steps) + + super(PlannedSession,self).save(*args, **kwargs) + + + from django.core.validators import RegexValidator,validate_email class StandardCollection(models.Model): @@ -2515,7 +2541,8 @@ class PlannedSessionForm(ModelForm): 'startdate': AdminDateWidget(), 'enddate': AdminDateWidget(), 'preferreddate': AdminDateWidget(), - 'interval_string': forms.Textarea(attrs={'rows':2,'cols':50}) + 'interval_string': forms.Textarea(attrs={'rows':2,'cols':50}), + #'sessiontype': forms.Select(attrs={'style':'width:50px'}) } def __init__(self,*args,**kwargs): diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index ae06c6ed..66698eaa 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -16,8 +16,7 @@ from django.conf import settings import pytz from dateutil import parser from rowers.utils import myqueue,calculate_age,totaltime_sec_to_string - -from fitparse import FitFile +from rowers.rows import handle_uploaded_file import re import django_rq @@ -190,42 +189,17 @@ def ps_dict_get_description(d): 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' + def __init__(self,json_string,name='',sport='Custom'): + self.json = json_string + self.steps = json.loads(json_string) + + self.name = name + self.sport = sport # 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() @@ -233,13 +207,7 @@ class FitWorkoutSteps(object): 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 + return self.steps def get_description(self): @@ -1155,7 +1123,14 @@ def update_plannedsession(ps,cd): if attr == 'comment': value.replace("\r\n", " "); value.replace("\n", " "); - setattr(ps, attr, value) + if attr != 'fitfile': + setattr(ps, attr, value) + + if cd['fitfile']: + f = cd['fitfile'] + filename, path_and_filename = handle_uploaded_file(f) + ps.fitfile.name = filename + ps.save() diff --git a/rowers/serializers.py b/rowers/serializers.py index 27b7e3ae..5ef818ad 100644 --- a/rowers/serializers.py +++ b/rowers/serializers.py @@ -147,7 +147,7 @@ class PlannedSessionSerializer(serializers.ModelSerializer): 'course', 'approximate_distance', 'approximate_duration', - 'json_string', + 'steps_json', 'fitfile' ) diff --git a/rowers/templates/plannedsession_multicreate.html b/rowers/templates/plannedsession_multicreate.html index 581e8a85..66c761be 100644 --- a/rowers/templates/plannedsession_multicreate.html +++ b/rowers/templates/plannedsession_multicreate.html @@ -91,7 +91,7 @@ - + @@ -169,9 +169,9 @@ } }); - - + + }); diff --git a/rowers/templates/plannedsessioncreate.html b/rowers/templates/plannedsessioncreate.html index 1c881598..4f5b52ef 100644 --- a/rowers/templates/plannedsessioncreate.html +++ b/rowers/templates/plannedsessioncreate.html @@ -40,7 +40,7 @@ {{ form.as_table }} {% csrf_token %} - +
diff --git a/rowers/templates/plannedsessionedit.html b/rowers/templates/plannedsessionedit.html index 9e1cf82d..f5e04af5 100644 --- a/rowers/templates/plannedsessionedit.html +++ b/rowers/templates/plannedsessionedit.html @@ -50,13 +50,13 @@

{% csrf_token %}
- +

Delete Clone

- @@ -161,7 +161,7 @@ $(document).ready(function(){ var o = $("td #id_sessiontype").find(":selected").val(); - + if (o != 'coursetest') { $("td #id_course").hide(); $("th label[for='id_course']").hide(); @@ -257,7 +257,7 @@ } - ); + ); diff --git a/rowers/utils.py b/rowers/utils.py index c7573b69..dd0cb69f 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -14,6 +14,8 @@ import datetime import json +from fitparse import FitFile + from django.http import HttpResponse import requests @@ -540,3 +542,42 @@ def allsundays(startdate,enddate): while d<=enddate: yield d d += datetime.timedelta(days=7) + +def steps_read_fit(filename,name='',sport='Custom'): + fitfile = FitFile(filename,check_crc=False) + records = fitfile.messages + m0 = records[0] + typ = m0.fields[0].value + if typ != 'workout': + raise TypeError("Wrong FIT file type") + + steps = [] + stepmessages = fitfile.get_messages('workout_step') + + steps = [] + stepmessages = 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 fitfile.get_messages('workout'): + if msg.name == 'workout': + for field in msg.fields: + ff = field.as_dict() + if ff['name'] == 'wkt_name': + name = ff['value'] + if ff['name'] == 'sport': + sport = ff['value'] + + d = {} + d['filename'] = filename + d['name'] = name + d['steps'] = steps + d['sport'] = sport + + return d diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py index c9345637..11e4aa0a 100644 --- a/rowers/views/planviews.py +++ b/rowers/views/planviews.py @@ -441,6 +441,7 @@ def plannedsession_create_view(request, course = cd['course'] name = cd['name'] interval_string = cd['interval_string'] + fitfile = cd['fitfile'] @@ -467,25 +468,11 @@ def plannedsession_create_view(request, ps.save() - if interval_string: - dct = trainingparser.parsetodict(interval_string) - dct = [item for item in dct if item['value'] != 0] - dct = trainingparser.tofitdict(dct) - ps.json_string = json.dumps(dct) - - txt = ps_dict_get_description(dct) - ps.comment += '\n'+txt - ps.save() - - if sessioncreateform.cleaned_data['fitfile']: - f = sessioncreateform.cleaned_data['fitfile'] - filename, path_and_filename = handle_uploaded_file(f) - ps.fitfile.name = filename - structured_workout = FitWorkoutSteps(path_and_filename) - dct = structured_workout.get_dict() - ps.comment += '\n'+structured_workout.get_description() - ps.json_string = json.dumps(dct) - ps.save() + #if sessioncreateform.cleaned_data['fitfile']: + # f = sessioncreateform.cleaned_data['fitfile'] + # filename, path_and_filename = handle_uploaded_file(f) + # ps.fitfile.name = filename + # ps.save() add_rower_session(r,ps) @@ -759,7 +746,7 @@ def plannedsession_teamcreate_view(request, sessiontemplates = PlannedSession.objects.filter(manager=request.user,is_template=True) if request.method == 'POST': - sessioncreateform = PlannedSessionForm(request.POST) + sessioncreateform = PlannedSessionForm(request.POST, request.FILES) sessionteamselectform = PlannedSessionTeamForm( request.user,request.POST ) @@ -777,6 +764,9 @@ def plannedsession_teamcreate_view(request, comment = cd['comment'] course = cd['course'] name = cd['name'] + interval_string = cd['interval_string'] + fitfile = cd['fitfile'] + if sessionunit == 'min': sessionmode = 'time' @@ -795,6 +785,8 @@ def plannedsession_teamcreate_view(request, comment=comment, criterium=criterium, course=course, + interval_string=interval_string, + fitfile=fitfile, manager=request.user) ps.save() @@ -940,7 +932,7 @@ def plannedsession_teamedit_view(request, "preferreddate","startdate","enddate") if request.method == 'POST': - sessioncreateform = PlannedSessionForm(request.POST,instance=ps) + sessioncreateform = PlannedSessionForm(request.POST,request.FILES,instance=ps) sessionteamselectform = PlannedSessionTeamForm( request.user,request.POST ) @@ -1792,7 +1784,7 @@ def plannedsession_edit_view(request,id=0,userid=0): return HttpResponseRedirect(url) if request.method == 'POST': - sessioncreateform = PlannedSessionForm(request.POST,instance=ps) + sessioncreateform = PlannedSessionForm(request.POST, request.FILES,instance=ps) if sessioncreateform.is_valid(): cd = sessioncreateform.cleaned_data