diff --git a/rowers/templates/course_view.html b/rowers/templates/course_view.html
index decc0089..4a610e83 100644
--- a/rowers/templates/course_view.html
+++ b/rowers/templates/course_view.html
@@ -111,6 +111,15 @@
+ {% if workoutid %}
+
+
+ Suggested Workout: {{ workoutid|getworkoutname }}
+
Measure time on course
+
+
+
+ {% endif %}
{% if form %}
@@ -136,6 +145,16 @@
{% endif %}
+ {% else %}
+ {% if workoutid %}
+
+
+ Suggested Workout: {{ workoutid|getworkoutname }}
+
Measure time on course
+
+
+
+ {% endif %}
{% endif %}
{% if ownrecords %}
diff --git a/rowers/templates/workout_form.html b/rowers/templates/workout_form.html
index ac019062..98034e21 100644
--- a/rowers/templates/workout_form.html
+++ b/rowers/templates/workout_form.html
@@ -213,6 +213,18 @@
{% endif %}
+ {% if suggested_courses %}
+
+ Suggested Measured Courses
+ {% for course in suggested_courses %}
+
+ {{ course }}
+
See course
+
Measure time on course
+
+ {% endfor %}
+
+{% endif %}
{% for graph in graphs %}
diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py
index 2d4af95e..60a97c29 100644
--- a/rowers/templatetags/rowerfilters.py
+++ b/rowers/templatetags/rowerfilters.py
@@ -48,6 +48,16 @@ from six import string_types
register = template.Library()
+@register.filter
+def getworkoutname(id):
+ try:
+ w = Workout.objects.get(id=encoder.decode_hex(id))
+ return w
+ except Workout.DoesNotExist:
+ return ''
+
+ return ''
+
@register.filter
def workoutdate(id): # pragma: no cover
try:
@@ -56,6 +66,8 @@ def workoutdate(id): # pragma: no cover
except Workout.DoesNotExist:
return 'unknown'
+ return 'unknown'
+
@register.filter
def usermessages(rower):
try:
diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz
index 96de0892..5cf8d9a4 100644
Binary files a/rowers/tests/testdata/testdata.tcx.gz and b/rowers/tests/testdata/testdata.tcx.gz differ
diff --git a/rowers/urls.py b/rowers/urls.py
index afe89f63..18b28d66 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -366,6 +366,8 @@ urlpatterns = [
views.course_follow_view, name='course_follow_view'),
re_path(r'^courses/(?P\d+)/unfollow/',
views.course_unfollow_view, name='course_unfollow_view'),
+ re_path(r'^courses/(?P\d+)/workout/(?P\b[0-9A-Fa-f]+\b)',
+ views.course_view, name='course_view'),
re_path(r'^standards/upload/$', views.standards_upload_view,
name='standards_upload_view'),
re_path(r'^standards/upload/(?P\d+)/$',
@@ -385,6 +387,8 @@ urlpatterns = [
re_path(
r'^user-analysis-select/(?P\w.*)/team/(?P\d+)/workout/(?P\b[0-9A-Fa-f]+\b)/$',
views.analysis_new, name='analysis_new'),
+ re_path(r'workout/(?P\b[0-9A-Fa-f]+\b)/submit/(?P\d+)/$',
+ views.workout_submit_course_view, name='workout_submit_course_view'),
re_path(r'^workouts-dupes-select/user/(?P\d+)/$',
views.workouts_duplicates_select_view, name='workouts_duplicates_select_view'),
re_path(r'^workouts-dupes-select/$',
diff --git a/rowers/views/racesviews.py b/rowers/views/racesviews.py
index 006de323..c233a985 100644
--- a/rowers/views/racesviews.py
+++ b/rowers/views/racesviews.py
@@ -356,7 +356,7 @@ def course_unfollow_view(request, id=0):
url = reverse("courses_view")
return HttpResponseRedirect(url)
-def course_view(request, id=0):
+def course_view(request, id=0, workoutid=0):
try:
course = GeoCourse.objects.get(id=id)
except GeoCourse.DoesNotExist: # pragma: no cover
@@ -477,6 +477,7 @@ def course_view(request, id=0):
'rower': r,
'form': form,
'onlyme': onlyme,
+ 'workoutid': workoutid,
}
)
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index 73719594..fe0724b3 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -4540,24 +4540,13 @@ def workout_edit_view(request, id=0, message="", successmessage=""):
hascoordinates = 1
courses = []
- if rowdata != 0:
- try:
- latitude = rowdata.df[' latitude']
- longitude = rowdata.df[' longitude']
- if not latitude.std(): # pragma: no cover
- hascoordinates = 0
- if not longitude.std():
- hascoordinates = 0
- except (KeyError, AttributeError):
- hascoordinates = 0
-
- else: # pragma: no cover
- hascoordinates = 0
+ suggested_courses = []
+ has_latlon, lat_mean, lon_mean = dataprep.workout_has_latlon(row.id)
mapscript = ""
mapdiv = ""
- if hascoordinates:
+ if has_latlon:
try:
mapscript, mapdiv = leaflet_chart(
rowdata.df[' latitude'],
@@ -4570,6 +4559,12 @@ def workout_edit_view(request, id=0, message="", successmessage=""):
workoutid=row.id, userid=row.user.user.id, coursecompleted=True)
if records.count() > 0: # pragma: no cover
courses = list(set([record.course for record in records]))
+ suggested_courses = getnearestcourses([lat_mean, lon_mean], GeoCourse.objects.all(), whatisnear=25,
+ strict=True)
+
+ suggested_courses = list(set(courses) ^ set(suggested_courses))
+
+
breadcrumbs = [
{
@@ -4608,6 +4603,7 @@ def workout_edit_view(request, id=0, message="", successmessage=""):
'mapdiv': mapdiv,
'rower': r,
'courses': courses,
+ 'suggested_courses': suggested_courses,
})
@@ -6102,8 +6098,71 @@ def workout_fusion_view(request, id1=0, id2=1):
'workout2': w2,
})
-# See attached courses
+# See attached courses / attaching courses
+@login_required()
+@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)
+def workout_submit_course_view(request, id, courseid):
+ row = get_workout_by_opaqueid(request, id)
+ r = getrower(request.user)
+ try:
+ course = GeoCourse.objects.get(id=courseid)
+ except GeoCourse.DoesNotExist:
+ url = reverse('workout_edit_view', kwargs={'id': encoder.encode_hex(row.id)})
+ return HttpResponseRedirect(url)
+
+ # got a course
+ records = VirtualRaceResult.objects.filter(
+ userid = r.id,
+ course=course,
+ workoutid=row.id
+ )
+ if records:
+ record = records[0]
+ else:
+ # create record
+ record = VirtualRaceResult(
+ userid=r.id,
+ username=r.user.first_name+' '+r.user.last_name,
+ workoutid=row.id,
+ weightcategory=r.weightcategory,
+ adaptiveclass=r.adaptiveclass,
+ course=course,
+ distance=course.distance,
+ boatclass=row.workouttype,
+ boattype=row.boattype,
+ sex=r.sex,
+ age=calculate_age(r.birthdate),
+ )
+ record.save()
+
+ job = myqueue(
+ queuehigh,
+ handle_check_race_course,
+ row.csvfilename,
+ row.id,
+ course.id,
+ record.id,
+ r.user.email,
+ r.user.first_name,
+ summary=True,
+ successemail=True,
+ )
+
+ try:
+ request.session['async_tasks'] += [
+ (job.id, 'check_race_course')]
+ except KeyError: # pragma: no cover
+ request.session['async_tasks'] = [
+ (job.id, 'check_race_course')]
+
+ messages.info(request, 'We are checking your time on the course in the background." \
+ " You will receive an email when the check is complete." \
+ " You can check the status here')
+
+ url = reverse('workout_edit_view', kwargs={'id': encoder.encode_hex(row.id)})
+ return HttpResponseRedirect(url)
+
@login_required()
@permission_required('workout.change_workout', fn=get_workout_by_opaqueid, raise_exception=True)