from django import forms from rowers.models import Workout from rowers.rows import validate_file_extension,must_be_csv 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 import dataprep import datetime # 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 files class DocumentsForm(forms.Form): filetypechoices = ( ('csv' , 'Painsled iOS CSV'), ('tcx' , 'TCX'), ('tcxnohr' , 'TCX No HR'), ('rp' , 'RowPro CSV'), ('speedcoach' , 'SpeedCoach GPS CSV'), ('speedcoach2' , 'SpeedCoach GPS 2 CSV'), ('ergdata' , 'ErgData CSV'), ('ergstick' , 'ErgStick CSV'), ('painsleddesktop' , 'Painsled Desktop CSV'), ('zip','Zipped file'), ) title = forms.CharField(required=False) file = forms.FileField(required=True, validators=[validate_file_extension]) workouttype = forms.ChoiceField(required=True, choices=Workout.workouttypes, initial='rower') notes = forms.CharField(required=False, widget=forms.Textarea) class Meta: fields = ['title','file','workouttype','fileformat'] # The form to indicate additional actions to be performed immediately # after a successful upload class UploadOptionsForm(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') upload_to_C2 = forms.BooleanField(initial=False,required=False, label='Upload to Concept2 logbook') upload_to_Strava = forms.BooleanField(initial=False,required=False, label='Upload to Strava') upload_to_SportTracks = forms.BooleanField(initial=False,required=False, label='Upload to SportTracks') upload_to_RunKeeper = forms.BooleanField(initial=False,required=False, label='Upload to RunKeeper') upload_to_MapMyFitness = forms.BooleanField(initial=False, required=False, label='Upload to MapMyFitness') upload_to_TrainingPeaks = forms.BooleanField(initial=False, required=False, label='Upload 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') 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 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.IntegerField(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)), label='Start Date') enddate = forms.DateField(initial=timezone.now(), widget=SelectDateWidget(years=range(1990,2050)), label='End Date') class Meta: fields = ['startdate','enddate'] # 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'] # 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 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') # This form sets options for the summary stats page class StatsOptionsForm(forms.Form): includereststrokes = forms.BooleanField(initial=False,label='Include Rest Strokes',required=False) water = forms.BooleanField(initial=False,required=False) rower = forms.BooleanField(initial=True,required=False) dynamic = forms.BooleanField(initial=True,required=False) slides = forms.BooleanField(initial=True,required=False) skierg = forms.BooleanField(initial=False,required=False) paddle = forms.BooleanField(initial=False,required=False) snow = forms.BooleanField(initial=False,required=False) other = forms.BooleanField(initial=False,required=False) class WorkoutMultipleCompareForm(forms.Form): workouts = forms.ModelMultipleChoiceField(queryset=Workout.objects.all(), widget=forms.CheckboxSelectMultiple()) 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') 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 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