diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 827a9717..28bf84be 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -369,7 +369,7 @@ def workout_summary_to_df( return df -def resample(id, r, parent, overwrite='copy'): +def resample(id, r, parent, overwrite=False): data, row = getrowdata_db(id=id) messages = [] @@ -393,7 +393,7 @@ def resample(id, r, parent, overwrite='copy'): data['pace'] = data['pace'] / 1000. data['time'] = data['time'] / 1000. - if overwrite == 'overwrite': + if overwrite == True: # remove CP data try: cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=parent.id) diff --git a/rowers/forms.py b/rowers/forms.py index 0ebc5fb3..506f900f 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -67,13 +67,12 @@ class FlexibleDecimalField(forms.DecimalField): class ResampleForm(forms.Form): - resamplechoices = ( - ('overwrite', 'Overwrite Workout'), - ('copy', 'Create a Duplicate Workout') - ) - + # add resamplechoice field, the result is a True or False boolean, labels are "overwrite" and "create copy" resamplechoice = forms.ChoiceField( - initial='copy', choices=resamplechoices, label='Copy behavior') + required=True, + choices=((True, 'overwrite'), (False, 'create copy')), + label='Resample choice', + widget=forms.RadioSelect) class TrainingZonesForm(forms.Form): @@ -582,6 +581,11 @@ class UploadOptionsForm(forms.Form): races = VirtualRace.objects.filter( registration_closure__gt=timezone.now()) + # set upload_to_X based on r.X_auto_export + for field in ['C2', 'Strava', 'SportTracks', 'TrainingPeaks', 'Intervals']: + if getattr(r, field.lower()+'_auto_export') and r.rowerplan in ['pro', 'plan','coach']: + self.fields['upload_to_'+field].initial = True + registrations = IndoorVirtualRaceResult.objects.filter( race__in=races, userid=r.id) @@ -665,6 +669,10 @@ class TeamUploadOptionsForm(forms.Form): upload_to_TrainingPeaks = forms.BooleanField(initial=False, required=False, label='Export to TrainingPeaks') + + upload_to_Intervals = 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') diff --git a/rowers/integrations/intervals.py b/rowers/integrations/intervals.py index 4e0ac680..7db883ae 100644 --- a/rowers/integrations/intervals.py +++ b/rowers/integrations/intervals.py @@ -17,6 +17,7 @@ import os from uuid import uuid4 from django.utils import timezone from datetime import timedelta +import rowers.dataprep as dataprep from rowsandall_app.settings import ( INTERVALS_CLIENT_ID, INTERVALS_REDIRECT_URI, INTERVALS_CLIENT_SECRET, SITE_URL @@ -101,7 +102,16 @@ class IntervalsIntegration(SyncIntegration): def createworkoutdata(self, w, *args, **kwargs) -> str: dozip = kwargs.get('dozip', True) - filename = w.csvfilename + # resample if wanted by user, not tested + if w.user.intervals_resample_to_1s: + datadf, id, msgs = dataprep.resample( + w.id, w.user, w, overwrite=False + ) + w_resampled = Workout.objects.get(id=id) + filename = w_resampled.csvfilename + else: + w_resampled = None + filename = w.csvfilename try: row = rowingdata(csvfile=filename) except IOError: # pragma: no cover @@ -128,6 +138,8 @@ class IntervalsIntegration(SyncIntegration): except TypeError: newnotes = 'from'+w.workoutsource+' via rowsandall.com' + if w.user.intervals_resample_to_1s and w_resampled: + w_resampled.delete() row.exporttotcx(tcxfilename, notes=newnotes, sport=mytypes.intervalsmapping[w.workouttype]) if dozip: gzfilename = tcxfilename + '.gz' diff --git a/rowers/models.py b/rowers/models.py index f4715081..047d8d0a 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -1174,6 +1174,7 @@ class Rower(models.Model): c2_auto_import = models.BooleanField(default=False) intervals_auto_export = models.BooleanField(default=False) intervals_auto_import = models.BooleanField(default=False) + intervals_resample_to_1s = models.BooleanField(default=False, verbose_name='Resample to 1s on export') sporttrackstoken = models.CharField( default='', max_length=200, blank=True, null=True) sporttrackstokenexpirydate = models.DateTimeField(blank=True, null=True) @@ -4560,7 +4561,78 @@ class RowerExportForm(ModelForm): 'rp3_auto_import', 'intervals_auto_import', 'intervals_auto_export', + 'intervals_resample_to_1s' ] + +class RowerExportFormStrava(ModelForm): + class Meta: + model = Rower + fields = [ + 'stravaexportas', + 'strava_auto_export', + 'strava_auto_import', + 'strava_auto_delete', + ] + +class RowerExportFormIntervals(ModelForm): + class Meta: + model = Rower + fields = [ + 'intervals_auto_import', + 'intervals_auto_export', + 'intervals_resample_to_1s', + ] + +class RowerExportFormGarmin(ModelForm): + class Meta: + model = Rower + fields = [ + 'garminactivity', + ] + +class RowerExportFormPolar(ModelForm): + class Meta: + model = Rower + fields = [ + 'polar_auto_import', + ] + +class RowerExportFormConcept2(ModelForm): + class Meta: + model = Rower + fields = [ + 'c2_auto_export', + 'c2_auto_import', + ] + +class RowerExportFormSportTracks(ModelForm): + class Meta: + model = Rower + fields = [ + 'sporttracks_auto_export', + ] + +class RowerExportFormTrainingPeaks(ModelForm): + class Meta: + model = Rower + fields = [ + 'trainingpeaks_auto_export', + ] + +class RowerExportFormRP3(ModelForm): + class Meta: + model = Rower + fields = [ + 'rp3_auto_import', + ] + +class RowerExportFormNK(ModelForm): + class Meta: + model = Rower + fields = [ + 'nk_auto_import' + ] + # Simple form to set rower's Functional Threshold Power class SimpleRowerPowerForm(ModelForm): diff --git a/rowers/templates/rower_exportsettings.html b/rowers/templates/rower_exportsettings.html index b6aae035..13418d15 100644 --- a/rowers/templates/rower_exportsettings.html +++ b/rowers/templates/rower_exportsettings.html @@ -7,8 +7,10 @@ {% block main %}