Private
Public Access
1
0

Merge branch 'release/v5.29'

This commit is contained in:
Sander Roosendaal
2017-12-07 14:53:18 +01:00
7 changed files with 107 additions and 9 deletions
+6 -1
View File
@@ -32,7 +32,7 @@ from rowingdata import (
MysteryParser, BoatCoachOTWParser,QuiskeParser, MysteryParser, BoatCoachOTWParser,QuiskeParser,
painsledDesktopParser, speedcoachParser, ErgStickParser, painsledDesktopParser, speedcoachParser, ErgStickParser,
SpeedCoach2Parser, FITParser, fitsummarydata, SpeedCoach2Parser, FITParser, fitsummarydata,
make_cumvalues,cumcpdata, make_cumvalues,cumcpdata,ExcelTemplate,
summarydata, get_file_type, summarydata, get_file_type,
) )
@@ -996,6 +996,11 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
def parsenonpainsled(fileformat,f2,summary): def parsenonpainsled(fileformat,f2,summary):
# handle RowPro: # handle RowPro:
if (fileformat == 'xls'):
row = ExcelTemplate(f2)
hasrecognized = True
if (fileformat == 'rp'): if (fileformat == 'rp'):
row = RowProParser(f2) row = RowProParser(f2)
hasrecognized = True hasrecognized = True
+30
View File
@@ -356,6 +356,7 @@ class RegistrationFormTermsOfService(RegistrationForm):
error_messages={'required': "You must agree to the terms to register"}) error_messages={'required': "You must agree to the terms to register"})
class RegistrationFormUniqueEmail(RegistrationFormTermsOfService): class RegistrationFormUniqueEmail(RegistrationFormTermsOfService):
""" """
Subclass of ``RegistrationFormTermsOfService`` which enforces uniqueness of Subclass of ``RegistrationFormTermsOfService`` which enforces uniqueness of
@@ -370,6 +371,35 @@ class RegistrationFormUniqueEmail(RegistrationFormTermsOfService):
raise forms.ValidationError("This email address is already in use. Please supply a different email address.") raise forms.ValidationError("This email address is already in use. Please supply a different email address.")
return self.cleaned_data['email'] return self.cleaned_data['email']
class RegistrationFormSex(RegistrationFormUniqueEmail):
sexcategories = (
('female','female'),
('male','male'),
('not specified','not specified'),
)
weightcategories = (
('hwt','heavy-weight'),
('lwt','light-weight'),
)
birthdate = forms.DateTimeField(widget=SelectDateWidget(
years=range(timezone.now().year-100,timezone.now().year-10)),
initial = datetime.date(year=1970,
month=4,
day=15))
sex = forms.ChoiceField(required=True,
choices=sexcategories,
initial='not specified',
label='Sex')
weightcategory = forms.ChoiceField(label='Weight Category',
choices=weightcategories)
# def __init__(self, *args, **kwargs):
# self.fields['sex'].initial = 'not specified'
# Time field supporting microseconds. Not used, I believe. # Time field supporting microseconds. Not used, I believe.
class MyTimeField(forms.TimeField): class MyTimeField(forms.TimeField):
+15
View File
@@ -1,4 +1,5 @@
from utils import lbstoN from utils import lbstoN
import numpy as np
rowingmetrics = ( rowingmetrics = (
('time',{ ('time',{
@@ -301,3 +302,17 @@ dropping to 8m for race pace in the single.""",
This value should be fairly constant across all stroke rates.""", This value should be fairly constant across all stroke rates.""",
}, },
) )
def calc_trimp(df,sex,hrmax,hrmin):
if sex == 'male':
f = 1.92
else:
f = 1.67
dt = df['time'].diff()/6.e4
hrr = (df['hr']-hrmin)/(hrmax-hrmin)
trimpdata = dt*hrr*0.64*np.exp(f*hrr)
trimp = trimpdata.sum()
return trimp
+20 -1
View File
@@ -8,6 +8,7 @@ from django import forms
from django.forms import ModelForm from django.forms import ModelForm
from django.dispatch import receiver from django.dispatch import receiver
from django.forms.widgets import SplitDateTimeWidget from django.forms.widgets import SplitDateTimeWidget
from django.forms.extras.widgets import SelectDateWidget
from django.forms.formsets import BaseFormSet from django.forms.formsets import BaseFormSet
from datetimewidget.widgets import DateTimeWidget from datetimewidget.widgets import DateTimeWidget
from django.core.validators import validate_email from django.core.validators import validate_email
@@ -210,6 +211,12 @@ class Rower(models.Model):
('lwt','light-weight'), ('lwt','light-weight'),
) )
sexcategories = (
('male','male'),
('female','female'),
('not specified','not specified'),
)
stravatypes = ( stravatypes = (
('Ride','Ride'), ('Ride','Ride'),
('Kitesurf','Kitesurf'), ('Kitesurf','Kitesurf'),
@@ -257,6 +264,11 @@ class Rower(models.Model):
max_length=30, max_length=30,
choices=weightcategories) choices=weightcategories)
sex = models.CharField(default="not specified",
max_length=30,
choices=sexcategories)
birthdate = models.DateField(null=True,blank=True)
# Power Zone Data # Power Zone Data
ftp = models.IntegerField(default=226,verbose_name="Functional Threshold Power") ftp = models.IntegerField(default=226,verbose_name="Functional Threshold Power")
@@ -939,10 +951,17 @@ class RowerPowerZonesForm(ModelForm):
class AccountRowerForm(ModelForm): class AccountRowerForm(ModelForm):
class Meta: class Meta:
model = Rower model = Rower
fields = ['weightcategory','getemailnotifications', fields = ['sex','birthdate','weightcategory','getemailnotifications',
'defaulttimezone','showfavoritechartnotes', 'defaulttimezone','showfavoritechartnotes',
'defaultlandingpage'] 'defaultlandingpage']
widgets = {
'birthdate': SelectDateWidget(
years=range(
timezone.now().year-100,timezone.now().year-10)),
}
def clean_email(self): def clean_email(self):
email = self.cleaned_data.get('email') email = self.cleaned_data.get('email')
+1 -1
View File
@@ -50,7 +50,7 @@ def validate_file_extension(value):
ext = os.path.splitext(value.name)[1] ext = os.path.splitext(value.name)[1]
valid_extensions = ['.tcx','.csv','.TCX', valid_extensions = ['.tcx','.csv','.TCX',
'.CSV','.fit','.FIT','.zip','.ZIP', '.CSV','.fit','.FIT','.zip','.ZIP',
'.gz','.GZ'] '.gz','.GZ','.xls']
if not ext in valid_extensions: if not ext in valid_extensions:
raise ValidationError(u'File not supported!') raise ValidationError(u'File not supported!')
+3
View File
@@ -307,6 +307,9 @@ class NewUserRegistrationTest(TestCase):
'password1':'aapindewei2', 'password1':'aapindewei2',
'password2':'aapindewei2', 'password2':'aapindewei2',
'tos':True, 'tos':True,
'weightcategory':'hwt',
'sex':'male',
'birthdate':datetime.datetime(year=1970,month=4,day=2)
} }
form = RegistrationFormUniqueEmail(form_data) form = RegistrationFormUniqueEmail(form_data)
+31 -5
View File
@@ -44,7 +44,8 @@ from rowers.forms import (
SummaryStringForm,IntervalUpdateForm,StrokeDataForm, SummaryStringForm,IntervalUpdateForm,StrokeDataForm,
StatsOptionsForm,PredictedPieceForm,DateRangeForm,DeltaDaysForm, StatsOptionsForm,PredictedPieceForm,DateRangeForm,DeltaDaysForm,
EmailForm, RegistrationForm, RegistrationFormTermsOfService, EmailForm, RegistrationForm, RegistrationFormTermsOfService,
RegistrationFormUniqueEmail,CNsummaryForm,UpdateWindForm, RegistrationFormUniqueEmail,RegistrationFormSex,
CNsummaryForm,UpdateWindForm,
UpdateStreamForm,WorkoutMultipleCompareForm,ChartParamChoiceForm, UpdateStreamForm,WorkoutMultipleCompareForm,ChartParamChoiceForm,
FusionMetricChoiceForm,BoxPlotChoiceForm,MultiFlexChoiceForm, FusionMetricChoiceForm,BoxPlotChoiceForm,MultiFlexChoiceForm,
TrendFlexModalForm,WorkoutSplitForm,WorkoutJoinParamForm, TrendFlexModalForm,WorkoutSplitForm,WorkoutJoinParamForm,
@@ -58,6 +59,7 @@ from rowers.models import (
) )
from rowers.models import FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement from rowers.models import FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement
from rowers.metrics import rowingmetrics,defaultfavoritecharts from rowers.metrics import rowingmetrics,defaultfavoritecharts
from rowers import metrics
import rowers.uploads as uploads import rowers.uploads as uploads
from django.forms.formsets import formset_factory from django.forms.formsets import formset_factory
import StringIO import StringIO
@@ -772,20 +774,25 @@ def add_defaultfavorites(r):
# User registration # User registration
def rower_register_view(request): def rower_register_view(request):
if request.method == 'POST': if request.method == 'POST':
form = RegistrationFormUniqueEmail(request.POST) #form = RegistrationFormUniqueEmail(request.POST)
form = RegistrationFormSex(request.POST)
if form.is_valid(): if form.is_valid():
first_name = form.cleaned_data['first_name'] first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name'] last_name = form.cleaned_data['last_name']
email = form.cleaned_data['email'] email = form.cleaned_data['email']
password = form.cleaned_data['password1'] password = form.cleaned_data['password1']
username = form.cleaned_data['username'] username = form.cleaned_data['username']
sex = form.cleaned_data['sex']
birthdate = form.cleaned_data['birthdate']
weightcategory = form.cleaned_data['weightcategory']
theuser = User.objects.create_user(username,password=password) theuser = User.objects.create_user(username,password=password)
theuser.first_name = first_name theuser.first_name = first_name
theuser.last_name = last_name theuser.last_name = last_name
theuser.email = email theuser.email = email
theuser.save() theuser.save()
therower = Rower(user=theuser) therower = Rower(user=theuser,sex=sex,birthdate=birthdate,
weightcategory=weightcategory)
therower.save() therower.save()
@@ -843,7 +850,7 @@ Oh, one more thing. The site is currently in beta and is developing fast. Bear w
"registration_form.html", "registration_form.html",
{'form':form}) {'form':form})
else: else:
form = RegistrationFormUniqueEmail() form = RegistrationFormSex()
return render(request, return render(request,
"registration_form.html", "registration_form.html",
{'form':form,}) {'form':form,})
@@ -6878,9 +6885,15 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly)
if datadf.empty:
datadf,row = dataprep.getrowdata_db(id=id)
datadf = dataprep.clean_df_stats(datadf,workstrokesonly=False)
workstrokesonly=False
if datadf.empty: if datadf.empty:
return HttpResponse("CSV data file not found") return HttpResponse("CSV data file not found")
workoutstateswork = [1,4,5,8,9,6,7] workoutstateswork = [1,4,5,8,9,6,7]
workoutstatesrest = [3] workoutstatesrest = [3]
workoutstatetransition = [0,2,10,11,12,13] workoutstatetransition = [0,2,10,11,12,13]
@@ -6977,6 +6990,15 @@ def workout_stats_view(request,id=0,message="",successmessage=""):
except ZeroDivisionError,ValueError: except ZeroDivisionError,ValueError:
pass pass
# TRIMP
if datadf['hr'].mean() > 0 and r.sex != 'not specified':
trimp = metrics.calc_trimp(datadf,r.sex,r.max,r.rest)
trimp = int(trimp)
otherstats['trimp'] = {
'verbose_name': 'TRIMP',
'value': trimp,
'unit': 'minutes'
}
return render(request, return render(request,
'workoutstats.html', 'workoutstats.html',
@@ -7802,7 +7824,7 @@ def workout_comment_view(request,id=0):
url = url, url = url,
) )
if request.user != r.user: if request.user != r.user:
a_messages.info(r.user,message) a_messages.info(r.user,message.encode('ascii','ignore'))
res = myqueue(queuehigh, res = myqueue(queuehigh,
handle_sendemailnewcomment,r.user.first_name, handle_sendemailnewcomment,r.user.first_name,
@@ -10222,8 +10244,10 @@ def rower_edit_view(request,message=""):
first_name = ucd['first_name'] first_name = ucd['first_name']
last_name = ucd['last_name'] last_name = ucd['last_name']
email = ucd['email'] email = ucd['email']
sex = cd['sex']
defaultlandingpage = cd['defaultlandingpage'] defaultlandingpage = cd['defaultlandingpage']
weightcategory = cd['weightcategory'] weightcategory = cd['weightcategory']
birthdate = cd['birthdate']
showfavoritechartnotes = cd['showfavoritechartnotes'] showfavoritechartnotes = cd['showfavoritechartnotes']
getemailnotifications = cd['getemailnotifications'] getemailnotifications = cd['getemailnotifications']
defaulttimezone=cd['defaulttimezone'] defaulttimezone=cd['defaulttimezone']
@@ -10242,6 +10266,8 @@ def rower_edit_view(request,message=""):
r.getemailnotifications = getemailnotifications r.getemailnotifications = getemailnotifications
r.defaultlandingpage = defaultlandingpage r.defaultlandingpage = defaultlandingpage
r.showfavoritechartnotes = showfavoritechartnotes r.showfavoritechartnotes = showfavoritechartnotes
r.sex = sex
r.birthdate = birthdate
r.save() r.save()
form = RowerForm(instance=r) form = RowerForm(instance=r)
powerform = RowerPowerForm(instance=r) powerform = RowerPowerForm(instance=r)