From de16a237fcb131d397906919cdb6e0bb365d2f84 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 11 Nov 2024 11:43:18 +0100 Subject: [PATCH] improving course compare --- rowers/courses.py | 15 +++++++++ rowers/courseutils.py | 1 - rowers/models.py | 12 +++++++ rowers/templates/mapcompare.html | 1 + rowers/tests/testdata/testdata.tcx.gz | Bin 4001 -> 4000 bytes rowers/views/workoutviews.py | 45 +++++++++++++++++++++----- 6 files changed, 65 insertions(+), 9 deletions(-) diff --git a/rowers/courses.py b/rowers/courses.py index 3e9fa947..43a3b8ea 100644 --- a/rowers/courses.py +++ b/rowers/courses.py @@ -36,6 +36,21 @@ from rowers.models import VirtualRace # distance of course from lat_lon in km +def pass_start(df, course): + if df.empty: + return False + + def f(x): + return coordinate_in_path(x[' latitude'], x[' longitude'], p) + + + polygons = course.polygons.all() + p = polygon_to_path(polygons[0]) + + inpolygon = df.apply(lambda row:f(row), axis=1).copy() + + return inpolygon.any() + def howfaris(lat_lon, course): coords = course.coord diff --git a/rowers/courseutils.py b/rowers/courseutils.py index c60f0034..c4422cc6 100644 --- a/rowers/courseutils.py +++ b/rowers/courseutils.py @@ -14,7 +14,6 @@ class InvalidTrajectoryError(Exception): def __str__(self): # pragma: no cover return repr(self.value) - def time_in_path(df, p, maxmin='max', getall=False, name='unknown', logfile=None): if df.empty: # pragma: no cover diff --git a/rowers/models.py b/rowers/models.py index 4b40e835..5ddc51dc 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -3727,6 +3727,18 @@ class Workout(models.Model): elif self.workouttype in mytypes.otetypes and self.boattype in mytypes.boattypes: self.boattype = 'static' + records = VirtualRaceResult.objects.filter(workoutid=self.pk) + for record in records: + record.boattype = self.boattype + record.boatclass = self.workouttype + record.save() + + records = IndoorVirtualRaceResult.objects.filter(workoutid=self.pk) + for record in records: + record.boattype = self.boattype + record.boatclass = self.workouttype + record.save() + super(Workout, self).save(*args, **kwargs) def __str__(self): diff --git a/rowers/templates/mapcompare.html b/rowers/templates/mapcompare.html index 49fad21f..76e3b1d0 100644 --- a/rowers/templates/mapcompare.html +++ b/rowers/templates/mapcompare.html @@ -21,6 +21,7 @@

+ {{ dateform.as_table }} {% for competitor in competitors %} {% if competitor in selected_users %} {{ competitor }}
diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 332f949c52fa08af9afeeef9fecb351ddba6275a..10ac57e0053895fe2cf8d8bafa2392f0bbc1b8e2 100644 GIT binary patch literal 4000 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 GfB^su2}V-@ literal 4001 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 H#DD<+*l9w4 diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index a254c816..d42782c8 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -13,6 +13,7 @@ from json.decoder import JSONDecodeError import ruptures as rpt from rowers.courses import getnearestcourses +from rowers.courses import pass_start from pandas.errors import IntCastingNaNError def default(o): # pragma: no cover @@ -1337,6 +1338,18 @@ def course_mapcompare_view(request, id=0): except GeoCourse.DoesNotExist: # pragma: no cover raise Http404("Course does not exist") + startdate = request.GET.get('startdate', None) + enddate = request.GET.get('enddate', None) + if startdate: + startdate = iso8601.parse_date(startdate) + else: + startdate = timezone.now()-datetime.timedelta(days=30) + + if enddate: + enddate = iso8601.parse_date(enddate) + else: + enddate = timezone.now()+datetime.timedelta(days=1) + focususer = encoder.decode_hex(request.GET.get('user',None)) if focususer: try: @@ -1380,7 +1393,12 @@ def course_mapcompare_view(request, id=0): selected_users = Rower.objects.filter(id__in=selected_ids) - workoutids = [result.workoutid for result in results] + #workoutids = [result.workoutid for result in results] + workoutids = [] + for result in results: + w = Workout.objects.get(id=result.workoutid) + if w.startdatetime >= startdate and w.startdatetime <= enddate: + workoutids.append(result.workoutid) startenddict = {} @@ -1388,14 +1406,8 @@ def course_mapcompare_view(request, id=0): startenddict[result.workoutid] = (result.startsecond, result.endsecond) if len(workoutids) == 0: # pragma: no cover - url = reverse('course_view', - kwargs={ - 'id': course.id, - }) - messages.info(request, 'There are no results to display') - return HttpResponseRedirect(url) workouts = [] for id in workoutids: @@ -1412,6 +1424,11 @@ def course_mapcompare_view(request, id=0): labeldict=labeldict, startenddict=startenddict) + dateform = DateRangeForm(initial={ + 'startdate':startdate, + 'enddate':enddate, + }) + breadcrumbs = [ { 'url': reverse('courses_view'), @@ -1447,6 +1464,7 @@ def course_mapcompare_view(request, id=0): 'teams': [], 'competitors': competitors, 'selected_users': selected_users, + 'dateform': dateform, }) @@ -4602,7 +4620,12 @@ def workout_edit_view(request, id=0, message="", successmessage=""): strict=True) suggested_courses = list(set(courses) ^ set(suggested_courses)) - + s2 = [] + for c in suggested_courses: + if pass_start(rowdata.df, c): + s2.append(c) + + suggested_courses = s2 breadcrumbs = [ @@ -4712,6 +4735,12 @@ def workout_map_view(request, id=0): strict=True) suggested_courses = list(set(courses) ^ set(suggested_courses)) + s2 = [] + for c in suggested_courses: + if pass_start(rowdata.df, c): + s2.append(c) + + suggested_courses = s2 return render(request, 'map_view.html',