Merge branch 'develop' into feature/charts-microservice
This commit is contained in:
@@ -926,6 +926,164 @@ def interactive_histoall(theworkouts, histoparam, includereststrokes,
|
|||||||
|
|
||||||
|
|
||||||
def course_map(course):
|
def course_map(course):
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
latmean, lonmean, coordinates = course_coord_center(course)
|
||||||
|
if course.with_cn_nav_waypoints:
|
||||||
|
latmean, lonmean, coordinates = course_coord_crewnerd_navigation(course)
|
||||||
|
lat_min, lat_max, long_min, long_max = course_coord_maxmin(course)
|
||||||
|
|
||||||
|
coordinates = course_spline(coordinates)
|
||||||
|
|
||||||
|
scoordinates = "["
|
||||||
|
|
||||||
|
for index, row in coordinates.iterrows():
|
||||||
|
scoordinates += """[{x},{y}],
|
||||||
|
""".format(
|
||||||
|
x=row['latitude'],
|
||||||
|
y=row['longitude']
|
||||||
|
)
|
||||||
|
|
||||||
|
scoordinates += "]"
|
||||||
|
|
||||||
|
polygons = GeoPolygon.objects.filter(
|
||||||
|
course=course).order_by("order_in_course")
|
||||||
|
|
||||||
|
plabels = ''
|
||||||
|
|
||||||
|
for p in polygons:
|
||||||
|
coords = polygon_coord_center(p)
|
||||||
|
|
||||||
|
plabels += """
|
||||||
|
var marker = L.marker([{latbegin}, {longbegin}]).addTo(mymap);
|
||||||
|
marker.bindPopup("<b>{name}</b>");
|
||||||
|
|
||||||
|
""".format(
|
||||||
|
latbegin=coords[0],
|
||||||
|
longbegin=coords[1],
|
||||||
|
name=p.name
|
||||||
|
)
|
||||||
|
|
||||||
|
pcoordinates = """[
|
||||||
|
"""
|
||||||
|
|
||||||
|
for p in polygons:
|
||||||
|
pcoordinates += """[
|
||||||
|
["""
|
||||||
|
|
||||||
|
points = GeoPoint.objects.filter(polygon=p).order_by("order_in_poly")
|
||||||
|
|
||||||
|
for pt in points:
|
||||||
|
pcoordinates += "[{x},{y}],".format(
|
||||||
|
x=pt.latitude,
|
||||||
|
y=pt.longitude
|
||||||
|
)
|
||||||
|
|
||||||
|
# remove last comma
|
||||||
|
pcoordinates = pcoordinates[:-1]
|
||||||
|
pcoordinates += """]
|
||||||
|
],
|
||||||
|
"""
|
||||||
|
|
||||||
|
pcoordinates += """
|
||||||
|
]"""
|
||||||
|
|
||||||
|
script = """
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
var streets = L.tileLayer(
|
||||||
|
'https://api.mapbox.com/styles/v1/{{id}}/tiles/{{z}}/{{x}}/{{y}}?access_token={{accessToken}}', {{
|
||||||
|
attribution: '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> <strong><a href="https://www.mapbox.com/map-feedback/" target="_blank">Improve this map</a></strong>',
|
||||||
|
tileSize: 512,
|
||||||
|
maxZoom: 18,
|
||||||
|
zoomOffset: -1,
|
||||||
|
id: 'mapbox/streets-v11',
|
||||||
|
accessToken: 'pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA'
|
||||||
|
}}
|
||||||
|
),
|
||||||
|
|
||||||
|
satellite = L.tileLayer(
|
||||||
|
'https://api.mapbox.com/styles/v1/{{id}}/tiles/{{z}}/{{x}}/{{y}}?access_token={{accessToken}}', {{
|
||||||
|
attribution: '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> <strong><a href="https://www.mapbox.com/map-feedback/" target="_blank">Improve this map</a></strong>',
|
||||||
|
tileSize: 512,
|
||||||
|
maxZoom: 18,
|
||||||
|
zoomOffset: -1,
|
||||||
|
id: 'mapbox/satellite-v9',
|
||||||
|
accessToken: 'pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA'
|
||||||
|
}}
|
||||||
|
),
|
||||||
|
|
||||||
|
outdoors = L.tileLayer(
|
||||||
|
'https://api.mapbox.com/styles/v1/{{id}}/tiles/{{z}}/{{x}}/{{y}}?access_token={{accessToken}}', {{
|
||||||
|
attribution: '© <a href="https://www.mapbox.com/about/maps/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> <strong><a href="https://www.mapbox.com/map-feedback/" target="_blank">Improve this map</a></strong>',
|
||||||
|
tileSize: 512,
|
||||||
|
maxZoom: 18,
|
||||||
|
zoomOffset: -1,
|
||||||
|
id: 'mapbox/outdoors-v11',
|
||||||
|
accessToken: 'pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA'
|
||||||
|
}}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var mymap = L.map('map_canvas_{id}', {{
|
||||||
|
center: [{latmean}, {lonmean}],
|
||||||
|
zoom: 13,
|
||||||
|
layers: [outdoors]
|
||||||
|
}}).setView([{latmean},{lonmean}], 13);
|
||||||
|
|
||||||
|
var navionics = new JNC.Leaflet.NavionicsOverlay({{
|
||||||
|
navKey: 'Navionics_webapi_03205',
|
||||||
|
chartType: JNC.NAVIONICS_CHARTS.NAUTICAL,
|
||||||
|
isTransparent: true,
|
||||||
|
zIndex: 1
|
||||||
|
}});
|
||||||
|
|
||||||
|
|
||||||
|
var osmUrl2='http://tiles.openseamap.org/seamark/{{z}}/{{x}}/{{y}}.png';
|
||||||
|
var osmUrl='http://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png';
|
||||||
|
|
||||||
|
|
||||||
|
//create two TileLayer
|
||||||
|
var nautical=new L.TileLayer(osmUrl,{{
|
||||||
|
maxZoom:18}});
|
||||||
|
|
||||||
|
|
||||||
|
L.control.layers({{
|
||||||
|
"Streets": streets,
|
||||||
|
"Satellite": satellite,
|
||||||
|
"Outdoors": outdoors,
|
||||||
|
"Nautical": nautical,
|
||||||
|
}},{{
|
||||||
|
"Navionics":navionics,
|
||||||
|
}}).addTo(mymap);
|
||||||
|
|
||||||
|
var latlongs = {scoordinates}
|
||||||
|
var polyline = L.polyline(latlongs, {{color:'red'}}).addTo(mymap)
|
||||||
|
mymap.fitBounds(polyline.getBounds())
|
||||||
|
|
||||||
|
var platlongs = {pcoordinates}
|
||||||
|
var polygons = L.polygon(platlongs, {{color:'blue'}}).addTo(mymap)
|
||||||
|
|
||||||
|
{plabels}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
""".format(
|
||||||
|
id=course.id,
|
||||||
|
latmean=latmean,
|
||||||
|
lonmean=lonmean,
|
||||||
|
scoordinates=scoordinates,
|
||||||
|
pcoordinates=pcoordinates,
|
||||||
|
plabels=plabels
|
||||||
|
)
|
||||||
|
|
||||||
|
div = """
|
||||||
|
<div id="map_canvas_{id}" style="width: 100%; height: 400px; margin:0; padding:0;grid-gap:0;"></div>
|
||||||
|
""".format(
|
||||||
|
id=course.id,
|
||||||
|
)
|
||||||
|
>>>>>>> develop
|
||||||
|
|
||||||
course_dict = GeoCourseSerializer(course).data
|
course_dict = GeoCourseSerializer(course).data
|
||||||
|
|
||||||
|
|||||||
@@ -4158,6 +4158,7 @@ class IndoorVirtualRaceResult(models.Model):
|
|||||||
|
|
||||||
class CourseTestResult(models.Model):
|
class CourseTestResult(models.Model):
|
||||||
userid = models.IntegerField(default=0)
|
userid = models.IntegerField(default=0)
|
||||||
|
courseid = models.IntegerField(default=0)
|
||||||
workoutid = models.IntegerField(null=True)
|
workoutid = models.IntegerField(null=True)
|
||||||
plannedsession = models.ForeignKey(
|
plannedsession = models.ForeignKey(
|
||||||
PlannedSession, on_delete=models.CASCADE)
|
PlannedSession, on_delete=models.CASCADE)
|
||||||
@@ -4167,6 +4168,13 @@ class CourseTestResult(models.Model):
|
|||||||
startsecond = models.FloatField(default=0)
|
startsecond = models.FloatField(default=0)
|
||||||
endsecond = models.FloatField(default=0)
|
endsecond = models.FloatField(default=0)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.userid == 0:
|
||||||
|
w = Workout.objects.get(id=self.workoutid)
|
||||||
|
self.userid = w.user.id
|
||||||
|
|
||||||
|
super(CourseTestResult, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class IndoorVirtualRaceResultForm(ModelForm):
|
class IndoorVirtualRaceResultForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -1149,9 +1149,11 @@ def handle_check_race_course(self,
|
|||||||
record.duration = totaltime_sec_to_string(coursetimeseconds)
|
record.duration = totaltime_sec_to_string(coursetimeseconds)
|
||||||
record.distance = int(coursemeters)
|
record.distance = int(coursemeters)
|
||||||
record.workoutid = workoutid
|
record.workoutid = workoutid
|
||||||
|
record.courseid = courseid
|
||||||
record.startsecond = startsecond
|
record.startsecond = startsecond
|
||||||
record.endsecond = endsecond
|
record.endsecond = endsecond
|
||||||
record.points = points
|
record.points = points
|
||||||
|
record.coursecompleted = 1
|
||||||
record.save()
|
record.save()
|
||||||
|
|
||||||
if summary: # pragma: no cover
|
if summary: # pragma: no cover
|
||||||
@@ -1178,7 +1180,6 @@ def handle_check_race_course(self,
|
|||||||
workout.summary = summary
|
workout.summary = summary
|
||||||
workout.save()
|
workout.save()
|
||||||
|
|
||||||
|
|
||||||
if successemail: # pragma: no cover
|
if successemail: # pragma: no cover
|
||||||
handle_sendemail_coursesucceed(
|
handle_sendemail_coursesucceed(
|
||||||
useremail, userfirstname, logfile, workoutid
|
useremail, userfirstname, logfile, workoutid
|
||||||
|
|||||||
@@ -137,6 +137,35 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if ownrecords %}
|
||||||
|
<li class="grid_4">
|
||||||
|
<h2>Own (Private) Results</h2>
|
||||||
|
<p>
|
||||||
|
<table class="listtable shortpadded">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Time</th>
|
||||||
|
<th>Distance</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for record in ownrecords %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ record.duration |durationprint:"%H:%M:%S.%f" }}</td>
|
||||||
|
<td>{{ record.distance }} m</td>
|
||||||
|
<td>{{ record.workoutid|workoutdate }}</td>
|
||||||
|
<td>
|
||||||
|
<a title="Details" href="/rowers/workout/{{ record.workoutid|encode }}/view/">
|
||||||
|
<i class="fas fa-search-plus fa-fw"></i></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
105
rowers/templates/courses_challenges.html
Normal file
105
rowers/templates/courses_challenges.html
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
{% load leaflet_tags %}
|
||||||
|
|
||||||
|
{% block meta %}
|
||||||
|
{% leaflet_js %}
|
||||||
|
{% leaflet_css %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block title %}Rowsandall Virtual Challenges{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script type='text/javascript'
|
||||||
|
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_4">
|
||||||
|
<h1>Courses you might like</h1>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<a href="/rowers/list-courses/">All Courses</a>
|
||||||
|
</p>
|
||||||
|
<a href="/rowers/list-courses/?liked=true">Courses I like</a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
{% for course in coursesdicts %}
|
||||||
|
<li class="rounder">
|
||||||
|
<a href="/rowers/courses/{{ course.course.id }}/">
|
||||||
|
<h2>{{ course.course.name }}</h2>
|
||||||
|
</a>
|
||||||
|
<p>{{ course.course.country }}</p>
|
||||||
|
<p>{{ course.course.distance }}m</p>
|
||||||
|
<div class="mapdiv" id="{{ course.course.id }}">
|
||||||
|
{{ course.div|safe}}
|
||||||
|
{{ course.script|safe}}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
<li class="grid_4">
|
||||||
|
<h1>Interesting Challenges</h1>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<a href="/rowers/virtualevents/">All Active Challenges</a>
|
||||||
|
</p>
|
||||||
|
<a href="/rowers/virtualevents/?nearby=true">Nearby Challenges</a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
{% for challenge in challengesdicts %}
|
||||||
|
<li class="rounder">
|
||||||
|
<a href="/rowers/virtualevent/{{ challenge.challenge.id }}/">
|
||||||
|
<h2>{{ challenge.challenge.name }}</h2>
|
||||||
|
</a>
|
||||||
|
<p>{{ challenge.challenge.startdate|date:"Y-m-d" }}
|
||||||
|
{{ challenge.challenge.start_time|time:"H:i e" }}
|
||||||
|
to
|
||||||
|
{{ challenge.challenge.enddate|date:"Y-m-d" }}
|
||||||
|
{{ challenge.challenge.end_time|time:"H:i e" }}
|
||||||
|
({{ challenge.challenge.timezone }})</p>
|
||||||
|
<p>{% if challenge.challenge.sessiontype == 'fastest_time' %}
|
||||||
|
Time Challenge: To be rowed on the water
|
||||||
|
{% elif challenge.challenge.sessiontype == 'fastest_distance' %}
|
||||||
|
Distance Challenge: To be rowed on the water
|
||||||
|
{% elif challenge.challenge.sessiontype != 'race' %}
|
||||||
|
Indoor Race: To be rowed on a Concept2 ergometer
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% if challenge.challenge.sessiontype == 'fastest_time' %}
|
||||||
|
<div class="vignet">
|
||||||
|
<img src="/static/img/sculler.png"
|
||||||
|
alt="Marked Course">
|
||||||
|
</div>
|
||||||
|
{% elif challenge.challenge.sessiontype == 'fastest_distance' %}
|
||||||
|
<div class="vignet">
|
||||||
|
<img src="/static/img/sculler.png"
|
||||||
|
alt="Marked Course">
|
||||||
|
</div>
|
||||||
|
{% elif challenge.challenge.sessiontype != 'race' %}
|
||||||
|
<div class="vignet">
|
||||||
|
<img src="/static/img/domca.png"
|
||||||
|
alt="Marked Course">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
<div class="mapdiv" id="{{ challenge.challenge.id }}">
|
||||||
|
{{ challenge.div|safe}}
|
||||||
|
{{ challenge.script|safe}}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% include 'menu_racing.html' %}
|
||||||
|
{% endblock %}
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
</li>
|
</li>
|
||||||
{% if coursescript %}
|
{% if coursescript %}
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<h2>Course</h2>
|
<h2><a href="/rowers/courses/{{ plannedsession.course.id }}">{{ plannedsession.course.name }}</h2>
|
||||||
{{ coursediv|safe }}
|
{{ coursediv|safe }}
|
||||||
|
|
||||||
{{ coursescript|safe }}
|
{{ coursescript|safe }}
|
||||||
|
|||||||
@@ -311,6 +311,8 @@ urlpatterns = [
|
|||||||
name='workouts_view'),
|
name='workouts_view'),
|
||||||
re_path(r'^list-workouts/user/(?P<userid>\d+)/$', views.workouts_view,
|
re_path(r'^list-workouts/user/(?P<userid>\d+)/$', views.workouts_view,
|
||||||
name='workouts_view'),
|
name='workouts_view'),
|
||||||
|
re_path(r'^courses/$', views.courses_challenges_view,
|
||||||
|
name='courses_challenges_view'),
|
||||||
re_path(r'^virtualevents/$', views.virtualevents_view,
|
re_path(r'^virtualevents/$', views.virtualevents_view,
|
||||||
name='virtualevents_view'),
|
name='virtualevents_view'),
|
||||||
re_path(r'^virtualevent/createchoice/$', TemplateView.as_view(
|
re_path(r'^virtualevent/createchoice/$', TemplateView.as_view(
|
||||||
|
|||||||
@@ -410,12 +410,15 @@ def trendflexdata(workouts, options, userid=0):
|
|||||||
except (ValueError, AttributeError): # pragma: no cover
|
except (ValueError, AttributeError): # pragma: no cover
|
||||||
return ('', 'Error: not enough data')
|
return ('', 'Error: not enough data')
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
|
try:
|
||||||
bins = np.arange(datadf['days ago'].min()-binsize,
|
bins = np.arange(datadf['days ago'].min()-binsize,
|
||||||
datadf['days ago'].max()+binsize,
|
datadf['days ago'].max()+binsize,
|
||||||
binsize,
|
binsize,
|
||||||
)
|
)
|
||||||
groups = datadf.groupby(pd.cut(datadf['days ago'], bins,
|
groups = datadf.groupby(pd.cut(datadf['days ago'], bins,
|
||||||
labels=False))
|
labels=False))
|
||||||
|
except (ValueError, AttributeError): # pragma: no cover
|
||||||
|
return ('', 'Error: not enough data')
|
||||||
|
|
||||||
xvalues = []
|
xvalues = []
|
||||||
yvalues = []
|
yvalues = []
|
||||||
|
|||||||
@@ -2332,7 +2332,6 @@ def plannedsession_view(request, id=0, userid=0):
|
|||||||
if ps.sessiontype == 'coursetest': # pragma: no cover
|
if ps.sessiontype == 'coursetest': # pragma: no cover
|
||||||
vs = CourseTestResult.objects.filter(plannedsession=ps,
|
vs = CourseTestResult.objects.filter(plannedsession=ps,
|
||||||
workoutid=w.id)
|
workoutid=w.id)
|
||||||
|
|
||||||
if vs:
|
if vs:
|
||||||
for record in vs:
|
for record in vs:
|
||||||
if record.workoutid == w.id:
|
if record.workoutid == w.id:
|
||||||
|
|||||||
@@ -8,10 +8,99 @@ from django import forms
|
|||||||
from rowers.plannedsessions import timefield_to_seconds_duration
|
from rowers.plannedsessions import timefield_to_seconds_duration
|
||||||
|
|
||||||
from rowers.courses import getnearestraces, getnearestcourses,coursetokml, coursestokml
|
from rowers.courses import getnearestraces, getnearestcourses,coursetokml, coursestokml
|
||||||
|
from random import sample
|
||||||
|
|
||||||
|
# landing page for challenges & courses
|
||||||
|
def courses_challenges_view(request):
|
||||||
|
r = getrower(request.user)
|
||||||
|
g = GeoIP2()
|
||||||
|
|
||||||
|
ip = request.META.get('HTTP_X_REAL_IP', '1.1.1.1')
|
||||||
|
try:
|
||||||
|
lat_lon = g.lat_lon(ip)
|
||||||
|
city = g.city(ip)
|
||||||
|
except: # pragma: no cover
|
||||||
|
lat_lon = None
|
||||||
|
city = {
|
||||||
|
'city': '',
|
||||||
|
'country_name': '',
|
||||||
|
'time_zone': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
courses = GeoCourse.objects.all().order_by("country", "name", "distance")
|
||||||
|
nearby_courses = getnearestcourses(lat_lon, courses, whatisnear=2000)
|
||||||
|
liked_courses = GeoCourse.objects.filter(followers=r)
|
||||||
|
courses = GeoCourse.objects.filter(id__in=[course.id for course in nearby_courses]) | liked_courses
|
||||||
|
|
||||||
|
if courses.count() >= 3:
|
||||||
|
courses = sample(list(courses),3)
|
||||||
|
else:
|
||||||
|
courses = GeoCourse.objects.all().order_by("country", "name", "distance")
|
||||||
|
|
||||||
|
coursesdicts = []
|
||||||
|
for course in courses:
|
||||||
|
script, div = course_map(course)
|
||||||
|
coursesdicts.append({
|
||||||
|
'course': course,
|
||||||
|
'script': script,
|
||||||
|
'div': div,
|
||||||
|
})
|
||||||
|
|
||||||
|
allchallenges = VirtualRace.objects.all().order_by("-startdate")
|
||||||
|
totalnrchallenges = allchallenges.count()
|
||||||
|
challenges = VirtualRace.objects.filter(startdate__gte=timezone.now())
|
||||||
|
challenges2 = VirtualRace.objects.filter(startdate__lte=timezone.now(),
|
||||||
|
evaluation_closure__gte=timezone.now()-datetime.timedelta(days=3))
|
||||||
|
|
||||||
|
challenges = challenges | challenges2
|
||||||
|
count = 3
|
||||||
|
if totalnrchallenges > count:
|
||||||
|
allchallenges = list(allchallenges)
|
||||||
|
while len(challenges) < count:
|
||||||
|
try:
|
||||||
|
challenges = list(challenges)+sample(allchallenges, count-len(challenges))
|
||||||
|
except ValueError:
|
||||||
|
count = count-1
|
||||||
|
challenges = list(set(challenges))
|
||||||
|
else:
|
||||||
|
challenges = VirtualRace.objects.all()
|
||||||
|
count = challenges.count()
|
||||||
|
|
||||||
|
challenges = sample(list(challenges),count)
|
||||||
|
|
||||||
|
challengesdicts = []
|
||||||
|
for challenge in challenges:
|
||||||
|
script = ''
|
||||||
|
div = ''
|
||||||
|
if challenge.course:
|
||||||
|
script, div = course_map(challenge.course)
|
||||||
|
|
||||||
|
challengesdicts.append(
|
||||||
|
{
|
||||||
|
'script': script,
|
||||||
|
'div': div,
|
||||||
|
'challenge': challenge,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
breadcrumbs = [
|
||||||
|
{
|
||||||
|
'url': reverse('courses_challenges_view'),
|
||||||
|
'name': 'Courses and Challenges'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
return render(request, "courses_challenges.html",
|
||||||
|
{
|
||||||
|
'coursesdicts': coursesdicts,
|
||||||
|
'rower': r,
|
||||||
|
'challengesdicts': challengesdicts,
|
||||||
|
'breadcrumbs': breadcrumbs,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
# List Courses
|
# List Courses
|
||||||
|
|
||||||
|
|
||||||
def courses_view(request):
|
def courses_view(request):
|
||||||
r = getrower(request.user)
|
r = getrower(request.user)
|
||||||
g = GeoIP2()
|
g = GeoIP2()
|
||||||
@@ -280,6 +369,13 @@ def course_view(request, id=0):
|
|||||||
workoutid__isnull=False,
|
workoutid__isnull=False,
|
||||||
coursecompleted=True).order_by("duration", "-distance")
|
coursecompleted=True).order_by("duration", "-distance")
|
||||||
|
|
||||||
|
# get own training results
|
||||||
|
ownrecords = CourseTestResult.objects.filter(
|
||||||
|
courseid = course.id,
|
||||||
|
userid = r.id,
|
||||||
|
coursecompleted=True
|
||||||
|
).order_by("duration", "-distance")
|
||||||
|
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
notsharing = Rower.objects.filter(
|
notsharing = Rower.objects.filter(
|
||||||
share_course_results=False).exclude(id=r.id)
|
share_course_results=False).exclude(id=r.id)
|
||||||
@@ -371,6 +467,7 @@ def course_view(request, id=0):
|
|||||||
'mapdiv': div,
|
'mapdiv': div,
|
||||||
'nosessions': False,
|
'nosessions': False,
|
||||||
'records': records,
|
'records': records,
|
||||||
|
'ownrecords': ownrecords,
|
||||||
'rower': r,
|
'rower': r,
|
||||||
'form': form,
|
'form': form,
|
||||||
'onlyme': onlyme,
|
'onlyme': onlyme,
|
||||||
|
|||||||
@@ -206,8 +206,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li id="nav-racing">
|
<li id="nav-racing">
|
||||||
<a href="/rowers/virtualevents/">
|
<a href="/rowers/courses/">
|
||||||
<i class="fas fa-flag-checkered"></i> Challenges
|
<i class="fas fa-flag-checkered"></i> Challenges, Courses
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li id="nav-analysis">
|
<li id="nav-analysis">
|
||||||
|
|||||||
Reference in New Issue
Block a user