diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 7d12f7f7..183ffcb9 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -999,13 +999,31 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', maxhr = np.nan_to_num(maxhr) averagehr = np.nan_to_num(averagehr) + duplicate = False + + t = datetime.datetime.strptime(duration,"%H:%M:%S.%f") + delta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second) + + workoutenddatetime = workoutstartdatetime+delta + # check for duplicate start times and duration - ws = Workout.objects.filter(startdatetime=workoutstartdatetime, - distance=totaldist, - user=r) - if (len(ws) != 0): - message = "Warning: This workout probably already exists in the database" - privacy = 'hidden' + ws = Workout.objects.filter(user=r,date=workoutdate,duplicate=False).exclude( + startdatetime__gt=workoutenddatetime + ) + + ws2 = [] + + for ww in ws: + t = ww.duration + delta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second) + enddatetime = ww.startdatetime+delta + if enddatetime > workoutstartdatetime: + ws2.append(ww) + + + if (len(ws2) != 0): + message = "Warning: This workout overlaps with an existing one and was marked as a duplicate" + duplicate = True w = Workout(user=r, name=title, date=workoutdate, @@ -1014,6 +1032,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', duration=duration, distance=totaldist, weightcategory=r.weightcategory, starttime=workoutstarttime, + duplicate=duplicate, workoutsource=workoutsource, rankingpiece=rankingpiece, forceunit=forceunit, diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 5d61220e..c08ef90d 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -237,8 +237,6 @@ def interactive_boxchart(datadf,fieldname,extratitle=''): def interactive_activitychart(workouts,startdate,enddate,stack='type'): - if len(workouts) == 0: - return "","" dates = [] dates_sorting = [] @@ -316,7 +314,10 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type'): label = CatAttr(columns=['date'], sort=False), xlabel='Date', ylabel='Time', - title='Activity', + title='Activity {d1} to {d2}'.format( + d1 = startdate.strftime("%Y-%m-%d"), + d2 = enddate.strftime("%Y-%m-%d"), + ), stack=stack, plot_width=350, plot_height=250, diff --git a/rowers/models.py b/rowers/models.py index f628078f..dfa1726a 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -2134,6 +2134,7 @@ class Workout(models.Model): privacy = models.CharField(default='visible',max_length=30, choices=privacychoices) rankingpiece = models.BooleanField(default=False,verbose_name='Ranking Piece') + duplicate = models.BooleanField(default=False,verbose_name='Duplicate Workout') def __unicode__(self): @@ -2181,7 +2182,42 @@ def auto_delete_file_on_delete(sender, instance, **kwargs): if instance.csvfilename+'.gz': if os.path.isfile(instance.csvfilename+'.gz'): os.remove(instance.csvfilename+'.gz') - + +@receiver(models.signals.post_delete,sender=Workout) +def update_duplicates_on_delete(sender, instance, **kwargs): + if instance.id: + + duplicates = Workout.objects.filter( + user=instance.user,date=instance.date, + duplicate=True) + + for d in duplicates: + t = d.duration + delta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second) + workoutenddatetime = d.startdatetime+delta + ws = Workout.objects.filter( + user=d.user,date=d.date, + ).exclude( + pk__in=[instance.pk,d.pk] + ).exclude( + startdatetime__gt=workoutenddatetime + ) + + + ws2 = [] + + for ww in ws: + t = ww.duration + delta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second) + enddatetime = ww.startdatetime+delta + if enddatetime > d.startdatetime: + ws2.append(ww) + + if len(ws2) == 0: + d.duplicate=False + d.save() + + # Delete stroke data from the database when a workout is deleted @receiver(models.signals.post_delete,sender=Workout) def auto_delete_strokedata_on_delete(sender, instance, **kwargs): @@ -2404,7 +2440,7 @@ class WorkoutForm(ModelForm): # duration = forms.TimeInput(format='%H:%M:%S.%f') class Meta: model = Workout - fields = ['name','date','starttime','timezone','duration','distance','workouttype','boattype','weightcategory','notes','rankingpiece'] + fields = ['name','date','starttime','timezone','duration','distance','workouttype','boattype','weightcategory','notes','rankingpiece','duplicate'] widgets = { 'date': AdminDateWidget(), 'notes': forms.Textarea, diff --git a/rowers/views.py b/rowers/views.py index 283703fc..e5997a68 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -3380,6 +3380,11 @@ def addmanual_view(request): rankingpiece = form.cleaned_data['rankingpiece'] except KeyError: rankingpiece = False + + try: + duplicate = form.cleaned_data['duplicate'] + except KeyError: + duplicate = False if private: privacy = 'private' @@ -3403,6 +3408,7 @@ def addmanual_view(request): avghr=avghr, rankingpiece=rankingpiece, avgpwr=avgpwr, + duplicate=duplicate, avgspm=avgspm, title = name, notes=notes, @@ -6748,6 +6754,7 @@ def workouts_view(request,message='',successmessage='', enddate = startdate startdate = s + startdatestring = startdate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d') @@ -6763,6 +6770,10 @@ def workouts_view(request,message='',successmessage='', except ValueError: activity_enddate = enddate + g_startdate = activity_startdate + g_enddate = activity_enddate + + if teamid: try: theteam = Team.objects.get(id=teamid) @@ -6779,6 +6790,7 @@ def workouts_view(request,message='',successmessage='', team=theteam, startdatetime__gte=activity_startdate, startdatetime__lte=activity_enddate, + duplicate=False, privacy='visible').order_by("-date", "-starttime") elif theteam.viewing == 'coachonly': workouts = Workout.objects.filter( @@ -6790,6 +6802,7 @@ def workouts_view(request,message='',successmessage='', team=theteam,user=r, startdatetime__gte=activity_startdate, enddatetime__lte=activity_enddate, + duplicate=False, privacy='visible').order_by("-startdatetime") @@ -6805,6 +6818,7 @@ def workouts_view(request,message='',successmessage='', user=r, startdatetime__gte=activity_startdate, startdatetime__lte=activity_enddate, + duplicate=False, privacy='visible').order_by("-startdatetime") else: theteam = None @@ -6814,9 +6828,18 @@ def workouts_view(request,message='',successmessage='', startdatetime__lte=enddate).order_by("-date", "-starttime") g_workouts = Workout.objects.filter( user=r, + duplicate=False, startdatetime__gte=activity_startdate, startdatetime__lte=activity_enddate).order_by("-startdatetime") + + if len(g_workouts) == 0: + g_workouts = Workout.objects.filter( + user=r, + startdatetime__gte=timezone.now()-timedelta(days=15)).order_by("-startdatetime") + g_enddate = timezone.now() + g_startdate = (timezone.now()-timedelta(days=15)) + if rankingonly: workouts = workouts.exclude(rankingpiece=False) @@ -6854,9 +6877,10 @@ def workouts_view(request,message='',successmessage='', else: stack='type' + script,div = interactive_activitychart(g_workouts, - activity_startdate, - activity_enddate, + g_startdate, + g_enddate, stack=stack) messages.info(request,successmessage) @@ -9853,6 +9877,11 @@ def workout_edit_view(request,id=0,message="",successmessage=""): except KeyError: rankingpiece =- Workout.objects.get(id=id).rankingpiece + try: + duplicate = form.cleaned_data['duplicate'] + except KeyError: + duplicate = Workout.objects.get(id=id).duplicate + if private: privacy = 'private' else: @@ -9892,6 +9921,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""): row.duration = duration row.distance = distance row.boattype = boattype + row.duplicate = duplicate row.privacy = privacy row.rankingpiece = rankingpiece row.timezone = thetimezone