992 lines
35 KiB
Python
992 lines
35 KiB
Python
from django import forms
|
|
from django.contrib.admin.widgets import FilteredSelectMultiple
|
|
from rowers.models import Workout,Rower,Team,PlannedSession,GeoCourse
|
|
from rowers.rows import validate_file_extension,must_be_csv,validate_image_extension,validate_kml
|
|
from django.contrib.auth.forms import UserCreationForm
|
|
from django.contrib.auth.models import User
|
|
from django.contrib.admin.widgets import AdminDateWidget
|
|
from django.forms.extras.widgets import SelectDateWidget
|
|
from django.utils import timezone,translation
|
|
from django.forms import ModelForm, Select
|
|
import dataprep
|
|
import types
|
|
import datetime
|
|
from django.forms import formset_factory
|
|
from utils import landingpages
|
|
from metrics import axes
|
|
|
|
|
|
# login form
|
|
class LoginForm(forms.Form):
|
|
username = forms.CharField()
|
|
password = forms.CharField(widget=forms.PasswordInput())
|
|
|
|
# simple form for Contact page. Sends email to info@rowsandall.com
|
|
class EmailForm(forms.Form):
|
|
firstname = forms.CharField(max_length=255)
|
|
lastname = forms.CharField(max_length=255)
|
|
email = forms.EmailField()
|
|
subject = forms.CharField(max_length=255)
|
|
botcheck = forms.CharField(max_length=5)
|
|
message = forms.CharField()
|
|
|
|
|
|
|
|
# Upload the CrewNerd Summary CSV
|
|
class CNsummaryForm(forms.Form):
|
|
file = forms.FileField(required=True,validators=[must_be_csv])
|
|
|
|
# The little window to type '4x2000m/500m' to update the workout summary
|
|
class SummaryStringForm(forms.Form):
|
|
intervalstring = forms.CharField(max_length=255,label='Workout Description')
|
|
|
|
# little window to type a Team invitation code
|
|
class TeamInviteCodeForm(forms.Form):
|
|
code = forms.CharField(max_length=10,label='Team Code',
|
|
)
|
|
|
|
# Used for testing the POST API for StrokeData
|
|
class StrokeDataForm(forms.Form):
|
|
strokedata = forms.CharField(label='payload',widget=forms.Textarea)
|
|
|
|
# The form used for uploading images
|
|
class ImageForm(forms.Form):
|
|
file = forms.FileField(required=False,
|
|
validators=[validate_image_extension])
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
from django.forms.widgets import HiddenInput
|
|
super(ImageForm, self).__init__(*args, **kwargs)
|
|
|
|
|
|
# The form used for uploading images
|
|
class CourseForm(forms.Form):
|
|
name = forms.CharField(max_length=150,label='Course Name')
|
|
file = forms.FileField(required=False,
|
|
validators=[validate_kml])
|
|
notes = forms.CharField(required=False,
|
|
max_length=200,label='Course Notes',
|
|
widget=forms.Textarea)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
from django.forms.widgets import HiddenInput
|
|
super(CourseForm, self).__init__(*args, **kwargs)
|
|
|
|
|
|
# The form used for uploading files
|
|
class DocumentsForm(forms.Form):
|
|
title = forms.CharField(required=False)
|
|
file = forms.FileField(required=False,
|
|
validators=[validate_file_extension])
|
|
|
|
workouttype = forms.ChoiceField(required=True,
|
|
choices=Workout.workouttypes)
|
|
|
|
boattype = forms.ChoiceField(required=True,
|
|
choices=types.boattypes,
|
|
label = "Boat Type")
|
|
|
|
|
|
notes = forms.CharField(required=False,
|
|
widget=forms.Textarea)
|
|
|
|
offline = forms.BooleanField(initial=False,required=False,
|
|
label='Process in Background')
|
|
class Meta:
|
|
fields = ['title','file','workouttype','boattype','fileformat','offline']
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
from django.forms.widgets import HiddenInput
|
|
super(DocumentsForm, self).__init__(*args, **kwargs)
|
|
# self.fields['offline'].widget = HiddenInput()
|
|
|
|
from utils import (
|
|
workflowleftpanel,workflowmiddlepanel,
|
|
defaultleft,defaultmiddle
|
|
)
|
|
|
|
|
|
# Form to change Workflow page layout
|
|
class WorkFlowLeftPanelForm(forms.Form):
|
|
panels = defaultleft
|
|
|
|
leftpanel = forms.MultipleChoiceField(
|
|
label='',
|
|
choices=workflowleftpanel,
|
|
initial=panels,
|
|
widget=FilteredSelectMultiple(
|
|
('elements'),
|
|
False
|
|
)
|
|
)
|
|
|
|
class Media:
|
|
css = {
|
|
'all':['admin/css/widgets.css',]
|
|
# 'css/uid-manage-form.css'],
|
|
}
|
|
js = ['/admin/jsi18n/']
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
if 'instance' in kwargs:
|
|
r = kwargs.pop('instance')
|
|
panels = r.workflowleftpanel
|
|
self.base_fields['leftpanel'].initial=panels
|
|
else:
|
|
panels = defaultleft
|
|
|
|
|
|
super(WorkFlowLeftPanelForm,self).__init__(*args, **kwargs)
|
|
|
|
|
|
class WorkFlowMiddlePanelForm(forms.Form):
|
|
panels = defaultmiddle
|
|
|
|
|
|
middlepanel = forms.MultipleChoiceField(
|
|
label='',
|
|
choices=workflowmiddlepanel,
|
|
initial=panels,
|
|
widget=FilteredSelectMultiple(
|
|
('elements'),
|
|
False
|
|
)
|
|
)
|
|
|
|
class Media:
|
|
css = {
|
|
'all':['admin/css/widgets.css',]
|
|
# 'css/uid-manage-form.css'],
|
|
}
|
|
js = ['/admin/jsi18n/']
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
if 'instance' in kwargs:
|
|
r = kwargs.pop('instance')
|
|
panels = r.workflowmiddlepanel
|
|
self.base_fields['middlepanel'].initial=panels
|
|
else:
|
|
panels = defaultmiddle
|
|
|
|
super(WorkFlowMiddlePanelForm,self).__init__(*args, **kwargs)
|
|
|
|
class WorkFlowLeftPanelElement(forms.Form):
|
|
panelchoices = tuple(list(workflowleftpanel)+[('None','None')])
|
|
|
|
panel = forms.ChoiceField(
|
|
label='',
|
|
choices=panelchoices,
|
|
initial='None',
|
|
)
|
|
|
|
class WorkFlowMiddlePanelElement(forms.Form):
|
|
panelchoices = tuple(list(workflowmiddlepanel)+[('None','None')])
|
|
|
|
panel = forms.ChoiceField(
|
|
label='',
|
|
choices=panelchoices,
|
|
initial='None',
|
|
)
|
|
|
|
|
|
# The form to indicate additional actions to be performed immediately
|
|
# after a successful upload
|
|
|
|
nextpages = list(landingpages)
|
|
nextpages.append(('workout_upload_view','Upload Another File'))
|
|
nextpages = tuple(nextpages)
|
|
|
|
class LandingPageForm(forms.Form):
|
|
landingpage = forms.ChoiceField(choices=nextpages,
|
|
initial='workout_edit_view',
|
|
label='After Upload, go to')
|
|
|
|
class UploadOptionsForm(forms.Form):
|
|
plotchoices = (
|
|
('timeplot','Time Plot'),
|
|
('distanceplot','Distance Plot'),
|
|
('pieplot','Heart Rate Pie Chart'),
|
|
)
|
|
make_plot = forms.BooleanField(initial=False,required=False)
|
|
plottype = forms.ChoiceField(required=False,
|
|
choices=plotchoices,
|
|
initial='timeplot',
|
|
label='Plot Type')
|
|
upload_to_C2 = forms.BooleanField(initial=False,required=False,
|
|
label='Export to Concept2 logbook')
|
|
upload_to_Strava = forms.BooleanField(initial=False,required=False,
|
|
label='Export to Strava')
|
|
upload_to_SportTracks = forms.BooleanField(initial=False,required=False,
|
|
label='Export to SportTracks')
|
|
upload_to_RunKeeper = forms.BooleanField(initial=False,required=False,
|
|
label='Export to RunKeeper')
|
|
upload_to_MapMyFitness = forms.BooleanField(initial=False,
|
|
required=False,
|
|
label='Export to MapMyFitness')
|
|
upload_to_TrainingPeaks = forms.BooleanField(initial=False,
|
|
required=False,
|
|
label='Export to TrainingPeaks')
|
|
# do_physics = forms.BooleanField(initial=False,required=False,label='Power Estimate (OTW)')
|
|
makeprivate = forms.BooleanField(initial=False,required=False,
|
|
label='Make Workout Private')
|
|
|
|
landingpage = forms.ChoiceField(choices=nextpages,
|
|
initial='workout_edit_view',
|
|
label='After Upload, go to')
|
|
|
|
class Meta:
|
|
fields = ['make_plot','plottype','upload_toc2','makeprivate']
|
|
|
|
# The form to indicate additional actions to be performed immediately
|
|
# after a successful upload. This version allows the Team manager to select
|
|
# a team member
|
|
class TeamUploadOptionsForm(forms.Form):
|
|
plotchoices = (
|
|
('timeplot','Time Plot'),
|
|
('distanceplot','Distance Plot'),
|
|
('pieplot','Pie Chart'),
|
|
)
|
|
make_plot = forms.BooleanField(initial=False,required=False)
|
|
plottype = forms.ChoiceField(required=False,
|
|
choices=plotchoices,
|
|
initial='timeplot',
|
|
label='Plot Type')
|
|
|
|
class Meta:
|
|
fields = ['make_plot','plottype']
|
|
|
|
# This form is used on the Workout Split page
|
|
class WorkoutSplitForm(forms.Form):
|
|
splitchoices = (
|
|
('keep original','Keep Original'),
|
|
('keep first','Keep First Part'),
|
|
('keep second','Keep Second Part'),
|
|
('firstprivate','Set First Part Private'),
|
|
('secondprivate','Set Second Part Private'),
|
|
('originalprivate','Set Original Private'),
|
|
)
|
|
splittime = forms.TimeField(input_formats=['%H:%M:%S.%f',
|
|
'%H:%M:%S',
|
|
'%H:%M:%S',
|
|
'%M:%S.%f',
|
|
'%M:%S',
|
|
'%M'],
|
|
label = 'Split Time')
|
|
splitmode = forms.MultipleChoiceField(
|
|
initial=['keep original',
|
|
'keep first',
|
|
'keep second',
|
|
'firstprivate',
|
|
'secondprivate'],
|
|
label='Split Mode',
|
|
choices=splitchoices,
|
|
widget = forms.CheckboxSelectMultiple())
|
|
|
|
# This form is used on the Analysis page to add a custom distance/time
|
|
# trial and predict the pace
|
|
class PredictedPieceForm(forms.Form):
|
|
unitchoices = (
|
|
('t','minutes'),
|
|
('d','meters'),
|
|
)
|
|
pieceunit = forms.ChoiceField(required=True,choices=unitchoices,
|
|
initial='t',label='Unit')
|
|
value = forms.FloatField(initial=10,label='Value')
|
|
|
|
class Meta:
|
|
fields = ['value','pieceunit']
|
|
|
|
# On the Geeky side, to update stream information for river dwellers
|
|
class UpdateStreamForm(forms.Form):
|
|
unitchoices = (
|
|
('m','m/s'),
|
|
('f','foot/s'),
|
|
('k','knots'),
|
|
('p','pace difference (sec/500m)'),
|
|
)
|
|
dist1 = forms.FloatField(initial=0,label = 'Distance 1')
|
|
dist2 = forms.FloatField(initial=1000,label = 'Distance 2')
|
|
stream1 = forms.FloatField(initial=0,label = 'Stream velocity 1')
|
|
stream2 = forms.FloatField(initial=0,label = 'Stream velocity 2')
|
|
streamunit = forms.ChoiceField(required=True,
|
|
choices=unitchoices,
|
|
initial='m',
|
|
label='Unit')
|
|
|
|
class Meta:
|
|
fields = ['dist1','dist2','stream1', 'stream2','streamunit']
|
|
|
|
# add wind information to your workout
|
|
class UpdateWindForm(forms.Form):
|
|
unitchoices = (
|
|
('m','m/s'),
|
|
('k','knots'),
|
|
('b','beaufort'),
|
|
('kmh','km/h'),
|
|
('mph','miles/hour'),
|
|
)
|
|
dist1 = forms.FloatField(initial=0,label = 'Distance 1')
|
|
dist2 = forms.FloatField(initial=1000,label = 'Distance 2')
|
|
vwind1 = forms.FloatField(initial=0,required=False,label = 'Wind Speed 1')
|
|
vwind2 = forms.FloatField(initial=0,required=False,label = 'Wind Speed 2')
|
|
windunit = forms.ChoiceField(required=True,
|
|
choices=unitchoices,
|
|
initial='m',
|
|
label='Unit')
|
|
winddirection1 = forms.IntegerField(initial=0,required=False,
|
|
label = 'Wind Direction 1')
|
|
winddirection2 = forms.IntegerField(initial=0,required=False,
|
|
label = 'Wind Direction 2')
|
|
|
|
class Meta:
|
|
fields = ['dist1','dist2',
|
|
'vwind1','vwind2',
|
|
'windunit',
|
|
'winddirection1','winddirection2']
|
|
|
|
# Form to select a data range to show workouts from a certain time period
|
|
class DateRangeForm(forms.Form):
|
|
startdate = forms.DateField(
|
|
initial=timezone.now()-datetime.timedelta(days=365),
|
|
# widget=SelectDateWidget(years=range(1990,2050)),
|
|
widget=AdminDateWidget(),
|
|
label='Start Date')
|
|
enddate = forms.DateField(
|
|
initial=timezone.now(),
|
|
widget=AdminDateWidget(),
|
|
label='End Date')
|
|
|
|
class Meta:
|
|
fields = ['startdate','enddate']
|
|
|
|
class FitnessMetricForm(forms.Form):
|
|
startdate = forms.DateField(
|
|
initial=timezone.now()-datetime.timedelta(days=365),
|
|
# widget=SelectDateWidget(years=range(1990,2050)),
|
|
widget=AdminDateWidget(),
|
|
label='Start Date')
|
|
enddate = forms.DateField(
|
|
initial=timezone.now(),
|
|
widget=AdminDateWidget(),
|
|
label='End Date')
|
|
|
|
modechoices = (
|
|
('rower','indoor rower'),
|
|
('water','on the water')
|
|
)
|
|
|
|
mode = forms.ChoiceField(required=True,
|
|
choices=modechoices,
|
|
initial='rower',
|
|
label='Workout Mode'
|
|
)
|
|
|
|
class Meta:
|
|
fields = ['startdate','enddate','mode']
|
|
|
|
class SessionDateShiftForm(forms.Form):
|
|
shiftstartdate = forms.DateField(
|
|
initial=timezone.now(),
|
|
widget=AdminDateWidget(),
|
|
label='Shift to start on')
|
|
|
|
class Meta:
|
|
fields = ['shiftstartdate']
|
|
|
|
# Form used to select workouts for the past N days
|
|
class DeltaDaysForm(forms.Form):
|
|
deltadays = forms.IntegerField(initial=7,required=False,label='')
|
|
|
|
class RegistrationForm(UserCreationForm):
|
|
"""
|
|
Form for registering a new user account.
|
|
Validates that the requested username is not already in use, and
|
|
requires the password to be entered twice to catch typos.
|
|
Subclasses should feel free to add any additional validation they
|
|
need, but should avoid defining a ``save()`` method -- the actual
|
|
saving of collected user data is delegated to the active
|
|
registration backend.
|
|
"""
|
|
required_css_class = 'required'
|
|
email = forms.EmailField(label="E-mail")
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = ("username", "first_name", "last_name", "email", "password1", "password2")
|
|
|
|
class RegistrationFormTermsOfService(RegistrationForm):
|
|
"""
|
|
Subclass of ``RegistrationForm`` which adds a required checkbox
|
|
for agreeing to a site's Terms of Service.
|
|
"""
|
|
tos = forms.BooleanField(widget=forms.CheckboxInput,
|
|
label='I have read and agree to the Terms of Service',
|
|
error_messages={'required': "You must agree to the terms to register"})
|
|
|
|
|
|
|
|
class RegistrationFormUniqueEmail(RegistrationFormTermsOfService):
|
|
"""
|
|
Subclass of ``RegistrationFormTermsOfService`` which enforces uniqueness of
|
|
email addresses.
|
|
"""
|
|
def clean_email(self):
|
|
"""
|
|
Validate that the supplied email address is unique for the
|
|
site.
|
|
"""
|
|
if User.objects.filter(email__iexact=self.cleaned_data['email']):
|
|
raise forms.ValidationError("This email address is already in use. Please supply a different email address.")
|
|
return self.cleaned_data['email']
|
|
|
|
class RegistrationFormSex(RegistrationFormUniqueEmail):
|
|
sexcategories = (
|
|
('female','female'),
|
|
('male','male'),
|
|
('not specified','not specified'),
|
|
)
|
|
|
|
weightcategories = (
|
|
('hwt','heavy-weight'),
|
|
('lwt','light-weight'),
|
|
)
|
|
|
|
thisyear = timezone.now().year
|
|
|
|
birthdate = forms.DateTimeField(
|
|
widget=SelectDateWidget(years=range(1900,thisyear)),
|
|
initial = datetime.date(year=1970,
|
|
month=4,
|
|
day=15))
|
|
|
|
def clean_birthdate(self):
|
|
dob = self.cleaned_data['birthdate']
|
|
age = (timezone.now() - dob).days/365
|
|
if age < 16:
|
|
raise forms.ValidationError('Must be at least 16 years old to register')
|
|
|
|
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.
|
|
class MyTimeField(forms.TimeField):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(MyTimeField, self).__init__(*args, **kwargs)
|
|
supports_microseconds = True
|
|
|
|
# Form used to automatically define intervals by pace or power
|
|
class PowerIntervalUpdateForm(forms.Form):
|
|
selectorchoices = (
|
|
('power','Power'),
|
|
('pace','Pace'),
|
|
('work','Work per Stroke'),
|
|
)
|
|
|
|
pace = forms.DurationField(required=False,label='Pace (/500m)')
|
|
power = forms.IntegerField(required=False,label='Power (W)')
|
|
work = forms.IntegerField(required=False,label='Work per Stroke (J)')
|
|
selector = forms.ChoiceField(choices=selectorchoices,
|
|
required=True,
|
|
initial='power',
|
|
label='Use')
|
|
|
|
# Form used to update interval stats
|
|
class IntervalUpdateForm(forms.Form):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
typechoices = (
|
|
(1,'single time'),
|
|
(2,'single distance'),
|
|
(3,'rest (time based)'),
|
|
(3,'rest (distance based)'),
|
|
(4,'work (time based)'),
|
|
(5,'work (distance based)'),
|
|
)
|
|
aantal = int(kwargs.pop('aantal'))
|
|
super(IntervalUpdateForm, self).__init__(*args, **kwargs)
|
|
|
|
for i in range(aantal):
|
|
self.fields['intervalt_%s' % i] = forms.DurationField(label='Time '+str(i+1))
|
|
self.fields['intervald_%s' % i] = forms.IntegerField(label='Distance '+str(i+1))
|
|
self.fields['type_%s' % i] = forms.ChoiceField(choices=typechoices,
|
|
required=True,
|
|
initial=4,
|
|
label = 'Type '+str(i+1))
|
|
self.fields['intervalt_%s' % i].widget.attrs['style'] = 'width:76px; height: 16px;'
|
|
self.fields['intervald_%s' % i].widget.attrs['style'] = 'width:76px; height: 16px;'
|
|
self.fields['type_%s' % i].widget.attrs['style'] = 'width:156px; height: 22px;'
|
|
self.fields['intervald_%s' % i].widget = forms.TimeInput(format='%H:%M:%S.%f')
|
|
|
|
boattypes = types.boattypes
|
|
workouttypes = types.workouttypes
|
|
ww = list(workouttypes)
|
|
ww.append(tuple(('all','All')))
|
|
workouttypes = tuple(ww)
|
|
|
|
# form to select modality and boat type for trend flex
|
|
class TrendFlexModalForm(forms.Form):
|
|
modality = forms.ChoiceField(choices=workouttypes,
|
|
label='Workout Type',
|
|
initial='all')
|
|
waterboattype = forms.MultipleChoiceField(choices=boattypes,
|
|
label='Water Boat Type',
|
|
initial = types.waterboattype)
|
|
rankingonly = forms.BooleanField(initial=False,
|
|
label='Only Ranking Pieces',
|
|
required=False)
|
|
|
|
|
|
# This form sets options for the summary stats page
|
|
class StatsOptionsForm(forms.Form):
|
|
includereststrokes = forms.BooleanField(initial=False,label='Include Rest Strokes',required=False)
|
|
rankingonly = forms.BooleanField(initial=False,
|
|
label='Only Ranking Pieces',required=False)
|
|
water = forms.BooleanField(initial=False,required=False)
|
|
waterboattype = forms.MultipleChoiceField(choices=boattypes,
|
|
label='Water Boat Type',
|
|
widget=forms.CheckboxSelectMultiple(),
|
|
initial = types.waterboattype)
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(StatsOptionsForm, self).__init__(*args,**kwargs)
|
|
|
|
for type in types.checktypes:
|
|
self.fields[type] = forms.BooleanField(initial=True,required=False)
|
|
|
|
|
|
class CourseSelectForm(forms.Form):
|
|
course = forms.ModelChoiceField(queryset=GeoCourse.objects.all())
|
|
|
|
class WorkoutMultipleCompareForm(forms.Form):
|
|
workouts = forms.ModelMultipleChoiceField(queryset=Workout.objects.all(),
|
|
widget=forms.CheckboxSelectMultiple())
|
|
|
|
class PlannedSessionMultipleCloneForm(forms.Form):
|
|
plannedsessions = forms.ModelMultipleChoiceField(
|
|
queryset=PlannedSession.objects.all(),
|
|
widget=forms.CheckboxSelectMultiple(),
|
|
label='Planned Sessions'
|
|
)
|
|
|
|
from rowers.metrics import axlabels
|
|
|
|
formaxlabels = axlabels.copy()
|
|
formaxlabels.pop('None')
|
|
parchoices = list(sorted(formaxlabels.items(), key = lambda x:x[1]))
|
|
|
|
|
|
class BoxPlotChoiceForm(forms.Form):
|
|
yparam = forms.ChoiceField(choices=parchoices,initial='spm',
|
|
label='Metric')
|
|
spmmin = forms.FloatField(initial=15,
|
|
required=False,label = 'Min SPM')
|
|
spmmax = forms.FloatField(initial=55,
|
|
required=False,label = 'Max SPM')
|
|
workmin = forms.FloatField(initial=0,
|
|
required=False,label = 'Min Work per Stroke')
|
|
workmax = forms.FloatField(initial=1500,
|
|
required=False,label = 'Max Work per Stroke')
|
|
|
|
includereststrokes = forms.BooleanField(initial=False,
|
|
required=False,
|
|
label='Include Rest Strokes')
|
|
|
|
grouplabels = axlabels.copy()
|
|
grouplabels['date'] = 'Date'
|
|
grouplabels['workoutid'] = 'Workout'
|
|
grouplabels.pop('None')
|
|
grouplabels.pop('time')
|
|
groupchoices = list(sorted(grouplabels.items(), key = lambda x:x[1]))
|
|
formaxlabelsmultiflex = formaxlabels.copy()
|
|
formaxlabelsmultiflex.pop('time')
|
|
formaxlabelsmultiflex.pop('distance')
|
|
formaxlabelsmultiflex['workoutid'] = 'Workout'
|
|
parchoicesmultiflex = list(sorted(formaxlabelsmultiflex.items(), key = lambda x:x[1]))
|
|
|
|
from utils import palettes
|
|
|
|
palettechoices = tuple((p,p) for p in palettes.keys())
|
|
|
|
|
|
class MultiFlexChoiceForm(forms.Form):
|
|
xparam = forms.ChoiceField(choices=parchoicesmultiflex,
|
|
initial='hr',
|
|
label='X axis')
|
|
yparam = forms.ChoiceField(choices=parchoicesmultiflex,
|
|
initial='pace',
|
|
label='Y axis')
|
|
groupby = forms.ChoiceField(choices=groupchoices,initial='spm',
|
|
label='Group By')
|
|
binsize = forms.FloatField(initial=1,required=False,label = 'Bin Size')
|
|
spmmin = forms.FloatField(initial=15,
|
|
required=False,label = 'Min SPM')
|
|
spmmax = forms.FloatField(initial=55,
|
|
required=False,label = 'Max SPM')
|
|
workmin = forms.FloatField(initial=0,
|
|
required=False,label = 'Min Work per Stroke')
|
|
workmax = forms.FloatField(initial=1500,
|
|
required=False,label = 'Max Work per Stroke')
|
|
ploterrorbars = forms.BooleanField(initial=False,
|
|
required=False,
|
|
label='Plot Error Bars')
|
|
includereststrokes = forms.BooleanField(initial=False,
|
|
required=False,
|
|
label='Include Rest Strokes')
|
|
palette = forms.ChoiceField(choices=palettechoices,
|
|
label = 'Color Scheme',
|
|
initial='monochrome_blue')
|
|
|
|
class ChartParamChoiceForm(forms.Form):
|
|
plotchoices = (
|
|
('line','Line Plot'),
|
|
('scatter','Scatter Plot'),
|
|
)
|
|
xparam = forms.ChoiceField(choices=parchoices,initial='distance')
|
|
yparam = forms.ChoiceField(choices=parchoices,initial='hr')
|
|
plottype = forms.ChoiceField(choices=plotchoices,initial='scatter')
|
|
teamid = forms.IntegerField(widget=forms.HiddenInput())
|
|
|
|
formaxlabels.pop('time')
|
|
metricchoices = list(sorted(formaxlabels.items(), key = lambda x:x[1]))
|
|
|
|
class WorkoutJoinParamForm(forms.Form):
|
|
workout_name = forms.CharField(required = True, initial = 'Joined Workout')
|
|
set_private = forms.BooleanField(initial=False, required = False)
|
|
|
|
class FusionMetricChoiceForm(ModelForm):
|
|
class Meta:
|
|
model = Workout
|
|
fields = []
|
|
|
|
posneg = (
|
|
('pos','Workout 2 starts after Workout 1'),
|
|
('neg','Workout 2 starts before Workout 1'),
|
|
)
|
|
columns = forms.MultipleChoiceField(choices=metricchoices,
|
|
initial=[],
|
|
widget=forms.CheckboxSelectMultiple())
|
|
posneg = forms.ChoiceField(choices=posneg,initial='pos')
|
|
offset = forms.DurationField(label='Time Offset',initial=datetime.timedelta())
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(FusionMetricChoiceForm, self).__init__(*args, **kwargs)
|
|
formaxlabels2 = formaxlabels.copy()
|
|
# need to add code to remove "empty" fields
|
|
|
|
if self.instance.id is not None:
|
|
id = self.instance.id
|
|
df = dataprep.getrowdata_db(id=id)[0]
|
|
|
|
labeldict = {key:value for key,value in self.fields['columns'].choices}
|
|
|
|
for label in labeldict:
|
|
if df.ix[:,label].std() == 0:
|
|
try:
|
|
formaxlabels2.pop(label)
|
|
except KeyError:
|
|
pass
|
|
|
|
metricchoices = list(sorted(formaxlabels2.items(), key = lambda x:x[1]))
|
|
self.fields['columns'].choices = metricchoices
|
|
|
|
class PlannedSessionSelectForm(forms.Form):
|
|
|
|
def __init__(self, sessionchoices, *args, **kwargs):
|
|
initialsession = kwargs.pop('initialsession',None)
|
|
super(PlannedSessionSelectForm, self).__init__(*args,**kwargs)
|
|
|
|
self.fields['plannedsession'] = forms.ChoiceField(
|
|
label='Sessions',
|
|
choices = sessionchoices,
|
|
widget = forms.RadioSelect,
|
|
initial=initialsession
|
|
)
|
|
|
|
|
|
class WorkoutSessionSelectForm(forms.Form):
|
|
|
|
def __init__(self, workoutdata, *args, **kwargs):
|
|
|
|
super(WorkoutSessionSelectForm, self).__init__(*args, **kwargs)
|
|
|
|
self.fields['workouts'] = forms.MultipleChoiceField(
|
|
label='Workouts',
|
|
choices = workoutdata['choices'],
|
|
initial=workoutdata['initial'],
|
|
widget = forms.CheckboxSelectMultiple,
|
|
)
|
|
|
|
|
|
|
|
class RaceResultFilterForm(forms.Form):
|
|
boatclasses = (type for type in types.workouttypes if type[0] in types.otwtypes)
|
|
boatclassinitial = [t for t in types.otwtypes]
|
|
sexchoices = (
|
|
('female','Female'),
|
|
('male','Male'),
|
|
('mixed','Mixed'),
|
|
)
|
|
|
|
weightcategories = (
|
|
('hwt','heavy-weight'),
|
|
('lwt','light-weight'),
|
|
)
|
|
|
|
|
|
sex = forms.MultipleChoiceField(
|
|
choices=sexchoices,
|
|
initial=['male','female','mixed'],
|
|
label='Gender',
|
|
widget=forms.CheckboxSelectMultiple())
|
|
|
|
boatclass = forms.MultipleChoiceField(
|
|
choices=boatclasses,
|
|
initial=boatclassinitial,
|
|
label='Boat Class',
|
|
widget=forms.CheckboxSelectMultiple())
|
|
|
|
boattype = forms.MultipleChoiceField(
|
|
choices=boattypes,
|
|
label='Boat Type',
|
|
initial=types.waterboattype,
|
|
widget=forms.CheckboxSelectMultiple())
|
|
|
|
age_min = forms.IntegerField(label='Min Age',initial=16)
|
|
age_max = forms.IntegerField(label='Max Age',initial=100)
|
|
|
|
weightcategory = forms.MultipleChoiceField(
|
|
choices=weightcategories,
|
|
label='Weight Category',
|
|
initial=['hwt','lwt'],
|
|
widget=forms.CheckboxSelectMultiple())
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
if 'records' in kwargs:
|
|
records = kwargs.pop('records',None)
|
|
|
|
super(RaceResultFilterForm,self).__init__(*args,**kwargs)
|
|
|
|
if records:
|
|
# sex
|
|
thesexes = [record.sex for record in records]
|
|
thesexes = list(set(thesexes))
|
|
|
|
if len(thesexes)<= 1:
|
|
del self.fields['sex']
|
|
else:
|
|
sexchoices = []
|
|
for choice in self.fields['sex'].choices:
|
|
if choice[0] in thesexes:
|
|
sexchoices.append(choice)
|
|
self.fields['sex'].choices = sexchoices
|
|
|
|
# boatclass
|
|
theboatclasses = [record.boatclass for record in records]
|
|
theboatclasses = list(set(theboatclasses))
|
|
|
|
if len(theboatclasses)<= 1:
|
|
del self.fields['boatclass']
|
|
else:
|
|
boatclasschoices = []
|
|
for choice in self.fields['boatclass'].choices:
|
|
if choice[0] in theboatclasses:
|
|
boatclasschoices.append(choice)
|
|
self.fields['boatclass'].choices = boatclasschoices
|
|
|
|
# boattype
|
|
theboattypees = [record.boattype for record in records]
|
|
theboattypees = list(set(theboattypees))
|
|
|
|
if len(theboattypees)<= 1:
|
|
del self.fields['boattype']
|
|
else:
|
|
boattypechoices = []
|
|
for choice in self.fields['boattype'].choices:
|
|
if choice[0] in theboattypees:
|
|
boattypechoices.append(choice)
|
|
self.fields['boattype'].choices = boattypechoices
|
|
|
|
# weightcategory
|
|
theweightcategoryes = [record.weightcategory for record in records]
|
|
theweightcategoryes = list(set(theweightcategoryes))
|
|
|
|
if len(theweightcategoryes)<= 1:
|
|
del self.fields['weightcategory']
|
|
else:
|
|
weightcategorychoices = []
|
|
for choice in self.fields['weightcategory'].choices:
|
|
if choice[0] in theweightcategoryes:
|
|
weightcategorychoices.append(choice)
|
|
self.fields['weightcategory'].choices = weightcategorychoices
|
|
|
|
class WorkoutRaceSelectForm(forms.Form):
|
|
# evaluate_after = forms.TimeField(
|
|
# input_formats=['%H:%M:%S.%f',
|
|
# '%H:%M:%S',
|
|
# '%H:%M:%S',
|
|
# '%M:%S.%f',
|
|
# '%M:%S',
|
|
# '%M'],
|
|
# label = 'Only Evaluate After:',
|
|
# required=False)
|
|
|
|
def __init__(self, workoutdata,entries, *args, **kwargs):
|
|
|
|
super(WorkoutRaceSelectForm, self).__init__(*args, **kwargs)
|
|
|
|
self.fields['workouts'] = forms.ChoiceField(
|
|
label='Workouts',
|
|
choices = workoutdata['choices'],
|
|
initial=workoutdata['initial'],
|
|
widget=forms.RadioSelect,
|
|
)
|
|
|
|
self.fields['record'] = forms.ChoiceField(
|
|
label = 'Entry',
|
|
choices = entries['choices'],
|
|
initial = entries['initial'],
|
|
)
|
|
|
|
# self.fields['evaluate_after'] =
|
|
|
|
class PlannedSessionTeamForm(forms.Form):
|
|
team = forms.ModelMultipleChoiceField(
|
|
queryset=Team.objects.all(),
|
|
required=False,
|
|
widget=forms.CheckboxSelectMultiple())
|
|
|
|
def __init__(self, user, *args, **kwargs):
|
|
super(PlannedSessionTeamForm,self).__init__(*args, **kwargs)
|
|
|
|
self.fields['team'].queryset = Team.objects.filter(manager=user)
|
|
|
|
|
|
class PlannedSessionTeamMemberForm(forms.Form):
|
|
members = forms.ModelMultipleChoiceField(
|
|
queryset=Rower.objects.all(),
|
|
widget=forms.CheckboxSelectMultiple())
|
|
|
|
def __init__(self, thesession, *args, **kwargs):
|
|
super(PlannedSessionTeamMemberForm,self).__init__(*args,**kwargs)
|
|
|
|
self.fields['members'].queryset = thesession.rower.all()
|
|
|
|
from rowers.models import VirtualRace,GeoCourse
|
|
|
|
def get_countries():
|
|
try:
|
|
countries = VirtualRace.objects.order_by('country').values_list('country').distinct()
|
|
countries = tuple([(c[0],c[0]) for c in countries])
|
|
countries = countries+(('All','All'),)
|
|
except:
|
|
countries = (('All','All'))
|
|
return countries
|
|
|
|
|
|
|
|
class VirtualRaceSelectForm(forms.Form):
|
|
regattatypechoices = (
|
|
('upcoming','Upcoming Races'),
|
|
('ongoing','Ongoing Races'),
|
|
('previous','Previous Races'),
|
|
('my','My Races'),
|
|
('all','All Races'),
|
|
)
|
|
|
|
regattatype = forms.ChoiceField(
|
|
label='Type',
|
|
choices = regattatypechoices,
|
|
initial = 'upcoming',
|
|
)
|
|
|
|
country = forms.ChoiceField(
|
|
label='Country',
|
|
choices = get_countries()
|
|
)
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super(VirtualRaceSelectForm, self).__init__(*args, **kwargs)
|
|
self.fields['country'] = forms.ChoiceField(
|
|
choices = get_countries(),initial='All'
|
|
)
|
|
|
|
class FlexOptionsForm(forms.Form):
|
|
includereststrokes = forms.BooleanField(initial=True, required = False,
|
|
label='Include Rest Strokes')
|
|
plotchoices = (
|
|
('line','Line Plot'),
|
|
('scatter','Scatter Plot'),
|
|
)
|
|
plottype = forms.ChoiceField(choices=plotchoices,initial='scatter',
|
|
label='Chart Type')
|
|
|
|
|
|
class FlexAxesForm(forms.Form):
|
|
axchoices = (
|
|
(ax[0],ax[1]) for ax in axes if ax[0] not in ['cumdist','None']
|
|
)
|
|
|
|
|
|
yaxchoices = (
|
|
(ax[0], ax[1]) for ax in axes if ax[0] not in ['cumdist','distance','time']
|
|
)
|
|
|
|
yaxchoices2 = (
|
|
(ax[0], ax[1]) for ax in axes if ax[0] not in ['cumdist','distance','time']
|
|
)
|
|
|
|
|
|
xaxis = forms.ChoiceField(
|
|
choices=axchoices,label='X-Axis',required=True)
|
|
yaxis1 = forms.ChoiceField(
|
|
choices=yaxchoices,label='Left Axis',required=True)
|
|
yaxis2 = forms.ChoiceField(
|
|
choices=yaxchoices2,label='Right Axis',required=True)
|
|
|
|
def __init__(self,request,*args,**kwargs):
|
|
super(FlexAxesForm, self).__init__(*args, **kwargs)
|
|
|
|
rower = Rower.objects.get(user=request.user)
|
|
|
|
axchoicespro = (
|
|
('',ax[1]) if ax[4] == 'pro' and ax[0] else (ax[0],ax[1]) for ax in axes
|
|
)
|
|
|
|
axchoicesbasicx = []
|
|
axchoicesbasicy = []
|
|
|
|
for ax in axes:
|
|
if ax[4] != 'pro' and ax[0] != 'cumdist':
|
|
if ax[0] != 'None':
|
|
axchoicesbasicx.insert(0,(ax[0],ax[1]))
|
|
if ax[0] not in ['cumdist','distance','time']:
|
|
axchoicesbasicy.insert(0,(ax[0],ax[1]))
|
|
else:
|
|
if ax[0] != 'None':
|
|
axchoicesbasicx.insert(0,('None',ax[1]+' (PRO)'))
|
|
if ax[0] not in ['cumdist','distance','time']:
|
|
axchoicesbasicy.insert(0,('None',ax[1]+' (PRO)'))
|
|
|
|
|
|
if rower.rowerplan == 'basic':
|
|
self.fields['xaxis'].choices = axchoicesbasicx
|
|
self.fields['yaxis1'].choices = axchoicesbasicy
|
|
self.fields['yaxis2'].choices = axchoicesbasicy
|
|
|
|
|
|
|
|
|