Private
Public Access
1
0

Merge branch 'develop' into feature/garmin

This commit is contained in:
Sander Roosendaal
2020-07-04 06:56:27 +02:00
11 changed files with 207 additions and 23 deletions

View File

@@ -947,7 +947,26 @@ class PlanSelectForm(forms.Form):
class CourseSelectForm(forms.Form): class CourseSelectForm(forms.Form):
course = forms.ModelChoiceField(queryset=GeoCourse.objects.all()) course = forms.ModelChoiceField(queryset=GeoCourse.objects.filter())
def __init__(self, *args, **kwargs):
course = kwargs.pop('course',None)
manager = kwargs.pop('manager',None)
super(CourseSelectForm,self).__init__(*args,**kwargs)
if course is not None:
print('aap',course)
d_min = 0.5*course.distance
d_max = 2*course.distance
country = course.country
countries = ['unknown',country]
print(countries)
self.fields['course'].queryset = self.fields['course'].queryset.filter(
distance__gt = d_min,distance__lt = d_max,
country__in = countries
).exclude(id=course.id)
if manager is not None:
self.fields['course'].queryset = self.fields['course'].queryset.filter(manager=manager)
print(self.fields['course'].queryset)
class WorkoutSingleSelectForm(forms.Form): class WorkoutSingleSelectForm(forms.Form):
workout = forms.ModelChoiceField( workout = forms.ModelChoiceField(

View File

@@ -1868,7 +1868,7 @@ def course_map(course):
var mymap = L.map('map_canvas', {{ var mymap = L.map('map_canvas', {{
center: [{latmean}, {lonmean}], center: [{latmean}, {lonmean}],
zoom: 13, zoom: 13,
layers: [streets, satellite] layers: [outdoors]
}}).setView([{latmean},{lonmean}], 13); }}).setView([{latmean},{lonmean}], 13);
var navionics = new JNC.Leaflet.NavionicsOverlay({{ var navionics = new JNC.Leaflet.NavionicsOverlay({{
@@ -2076,7 +2076,7 @@ def leaflet_chart_compare(course,workoutids,labeldict={},startenddict={}):
'time':time-time[0], 'time':time-time[0],
}) })
data.append(df) data.append(df)
except Workout.DoesNotExist: except (Workout.DoesNotExist,KeyError):
pass pass

View File

@@ -25,7 +25,8 @@ import re
import pytz import pytz
from django_countries.fields import CountryField from django_countries.fields import CountryField
from scipy.interpolate import splprep, splev, CubicSpline from scipy.interpolate import splprep, splev, CubicSpline,interp1d
import numpy as np import numpy as np
import shutil import shutil
@@ -438,8 +439,10 @@ def course_spline(coordinates):
tnew = np.linspace(0,1,100) tnew = np.linspace(0,1,100)
try: try:
latnew = CubicSpline(t,latitudes,bc_type='clamped')(tnew) #latnew = CubicSpline(t,latitudes,bc_type='not-a-knot')(tnew)
lonnew = CubicSpline(t,longitudes,bc_type='clamped')(tnew) #lonnew = CubicSpline(t,longitudes,bc_type='not-a-knot')(tnew)
latnew = interp1d(t,latitudes)(tnew)
lonnew = interp1d(t,longitudes)(tnew)
except ValueError: except ValueError:
latnew = latitudes latnew = latitudes
lonnew = longitudes lonnew = longitudes
@@ -1225,6 +1228,7 @@ class GeoCourse(models.Model):
name = models.CharField(max_length=150,blank=True) name = models.CharField(max_length=150,blank=True)
country = models.CharField(max_length=150,blank=True) country = models.CharField(max_length=150,blank=True)
notes = models.CharField(blank=True,max_length=200,verbose_name='Course Notes') notes = models.CharField(blank=True,max_length=200,verbose_name='Course Notes')
def __str__(self): def __str__(self):
name = self.name name = self.name
country = self.country country = self.country
@@ -1240,6 +1244,10 @@ class GeoCourse(models.Model):
d = d, d = d,
) )
@property
def coord(self):
return course_coord_center(self)
class GeoCourseEditForm(ModelForm): class GeoCourseEditForm(ModelForm):
class Meta: class Meta:
model = GeoCourse model = GeoCourse

View File

@@ -1400,7 +1400,7 @@ def default_class(r,w,race):
agemin__lt=age,agemax__gt=age agemin__lt=age,agemax__gt=age
).order_by( ).order_by(
"agemax","-agemin","boattype","sex", "agemax","-agemin","boattype","sex",
"weightcategory","referencespeed") "weightclass","referencespeed")
if standards.count()==0: if standards.count()==0:
# boolean, boattype, boatclass, adaptiveclass, weightclass, sex, coursestandard, # boolean, boattype, boatclass, adaptiveclass, weightclass, sex, coursestandard,

View File

@@ -450,6 +450,8 @@ def handle_check_race_course(self,
t = time.localtime() t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
f.write('\n') f.write('\n')
f.write('Course id {n}, Record id {m}'.format(n=courseid,m=recordid))
f.write('\n')
f.write(timestamp) f.write(timestamp)
f.write(' ') f.write(' ')
f.write('Found {n} entrytimes'.format(n=len(entrytimes))) f.write('Found {n} entrytimes'.format(n=len(entrytimes)))

View File

@@ -30,13 +30,16 @@
<tr> <tr>
<th>Notes</th><td>{{ course.notes|linebreaks }}</td> <th>Notes</th><td>{{ course.notes|linebreaks }}</td>
</tr> </tr>
<tr>
<th>Manager</th><td>{{ course.manager }}</td>
</tr>
</table> </table>
</li> </li>
<li class="grid_2"> <li class="grid_2">
<div class="mapdiv"> <div class="mapdiv">
{{ mapdiv|safe }} {{ mapdiv|safe }}
{{ mapscript|safe }} {{ mapscript|safe }}
</div> </div>
</li> </li>

View File

@@ -45,7 +45,7 @@
<td> <td>
{{ course.distance }} m {{ course.distance }} m
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
@@ -64,6 +64,15 @@
<input type="submit" value="GO"></input> <input type="submit" value="GO"></input>
</form> </form>
</p> </p>
{% if location %}
<p>
<a href="/rowers/list-courses/?nearby=true">Filter courses closest to you</a>
{{ city }} {{ country_name }} {{ time_zone }}
</p>
<p>
<a href="/rowers/list-courses/">All courses</a>
</p>
{% endif %}
<p> <p>
<a href="/rowers/courses/upload/">Add Courses</a> <a href="/rowers/courses/upload/">Add Courses</a>
</p> </p>
@@ -79,7 +88,7 @@
{% endfor %} {% endfor %}
<p>&nbsp;</p> <p>&nbsp;</p>
{% endif %} {% endif %}
</li> </li>
<li class="grid_4"> <li class="grid_4">
@@ -89,27 +98,27 @@
test pieces and measure the time spent on the course (as opposed test pieces and measure the time spent on the course (as opposed
to the total duration of a workout). This allows you to row and rank to the total duration of a workout). This allows you to row and rank
marked courses. marked courses.
To create a course, you use <a href="https://www.google.com/earth/">Google Earth</a> To create a course, you use <a href="https://www.google.com/earth/">Google Earth</a>
to mark the start and finish lines using polygons. The process is identical to mark the start and finish lines using polygons. The process is identical
to creating custom courses for the to creating custom courses for the
<a href="http://performancephones.com/crewnerd/">CrewNerd</a> <a href="http://performancephones.com/crewnerd/">CrewNerd</a>
app. app.
</p> </p>
<p>CrewNerd has published a nice video tutorial of the process. <p>CrewNerd has published a nice video tutorial of the process.
<a href="https://youtu.be/whhWFmMJbhM">Click here</a> to see the video. The part <a href="https://youtu.be/whhWFmMJbhM">Click here</a> to see the video. The part
we're interested in starts at 2:05. we're interested in starts at 2:05.
</p> </p>
<p> <p>
In addition to start and finish areas, on rowsandall.com you can add additional In addition to start and finish areas, on rowsandall.com you can add additional
polygons to mark areas that you must pass (in that order). This allows for polygons to mark areas that you must pass (in that order). This allows for
courses with turns around buoys, respecting buoy lines, or respecting traffic courses with turns around buoys, respecting buoy lines, or respecting traffic
patterns on rivers and lakes. patterns on rivers and lakes.
</p> </p>
<p> <p>
<ul> <ul>
<li>Open Google Earth</li> <li>Open Google Earth</li>
@@ -126,7 +135,7 @@
<p>You are allowed to have multiple courses in one KML file. <p>You are allowed to have multiple courses in one KML file.
Your CrewNerd "courses.kml" file works out of the box</p> Your CrewNerd "courses.kml" file works out of the box</p>
<p>The site doesn't test for duplicate courses.</p> <p>The site doesn't test for duplicate courses.</p>
</li> </li>

View File

@@ -67,12 +67,22 @@
<p> <p>
<input name='form' class='green button' type='submit' value="Submit"> <input name='form' class='green button' type='submit' value="Submit">
</form> </form>
</p> </p>
</li>
<li class="grid_4"> <li class="grid_4">
<p>Click on the challenge name or on the Details button to see the challenge <p>Click on the challenge name or on the Details button to see the challenge
details (and manage your participation and results). Click on the details (and manage your participation and results). Click on the
course name to see the course details. course name to see the course details.
</p> </p>
{% if location %}
<p>
<a href="/rowers/virtualevents/?nearby=true">Challenges in your area</a>
{{ city }} {{ country_name }} {{ time_zone }}
</p>
<p>
<a href="/rowers/virtualevents/">All Challenges</a>
</p>
{% endif %}
</li> </li>
<li class="grid_4" id="racelist"> <li class="grid_4" id="racelist">

View File

@@ -7,11 +7,100 @@ from rowers.views.statements import *
from rowsandall_app.settings import SITE_URL from rowsandall_app.settings import SITE_URL
from rowers.scoring import * from rowers.scoring import *
from django.contrib.gis.geoip2 import GeoIP2
# distance of course from lat_lon in km
def howfaris(lat_lon,course):
coords = course.coord
distance = geo_distance(lat_lon[0],lat_lon[1],coords[0],coords[1])[0]
return distance
whatisnear = 150
# get nearest races
def getnearestraces(lat_lon,races):
newlist = []
counter = 0
for race in races:
if race.course is None:
newlist.append(race)
else:
c = race.course
coords = c.coord
distance = howfaris(lat_lon,c)
if distance < whatisnear:
newlist.append(race)
counter += 1
if counter>0:
races = newlist
else:
courseraces = races.exclude(course__isnull=True)
orders = [(c.id,howfaris(lat_lon,c.course)) for c in courseraces]
orders = sorted(orders,key = lambda tup:tup[1])
ids = [id for id,distance in orders[0:4]]
for id, distance in orders[5:]:
if distance<whatisnear:
ids.append(id)
for id in ids:
newlist.append(VirtualRace.objects.get(id=id))
races = newlist
return races
def getnearestcourses(lat_lon,courses):
newlist = []
counter = 0
for c in courses:
coords = c.coord
distance = howfaris(lat_lon,c)
if distance < whatisnear:
newlist.append(c)
counter += 1
if counter>0:
courses = newlist
else:
orders = [(c.id,howfaris(lat_lon,c)) for c in courses]
orders = sorted(orders,key = lambda tup:tup[1])
ids = [id for id,distance in orders[0:4]]
for id, distance in orders[5:]:
if distance<whatisnear:
ids.append(id)
for id in ids:
newlist.append(GeoCourse.objects.get(id=id))
courses = newlist
return courses
# List Courses # List Courses
def courses_view(request): def courses_view(request):
r = getrower(request.user) 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:
lat_lon = None
city = {
'city': '',
'country_name': '',
'time_zone': '',
}
courses = GeoCourse.objects.all().order_by("country","name","distance")
nearby = request.GET.get('nearby')
if nearby and lat_lon is not None:
courses = getnearestcourses(lat_lon,courses)
courses = GeoCourse.objects.all().order_by("country","name")
# add search processing # add search processing
query = request.GET.get('q') query = request.GET.get('q')
@@ -34,6 +123,10 @@ def courses_view(request):
'active':'nav-racing', 'active':'nav-racing',
'searchform':searchform, 'searchform':searchform,
'rower':r, 'rower':r,
'location':lat_lon,
'city':city['city'],
'country_name': city['country_name'],
'time_zone':city['time_zone'],
}) })
# List Courses # List Courses
@@ -116,7 +209,7 @@ def course_replace_view(request,id=0):
r = getrower(request.user) r = getrower(request.user)
thecourses = GeoCourse.objects.filter(manager=r).exclude(id=id) #thecourses = GeoCourse.objects.filter(manager=r).exclude(id=id)
if request.method == 'POST': if request.method == 'POST':
form = CourseSelectForm(request.POST) form = CourseSelectForm(request.POST)
@@ -132,8 +225,8 @@ def course_replace_view(request,id=0):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:
form = CourseSelectForm() form = CourseSelectForm(course=course,manager=r)
form.fields["course"].queryset = thecourses #form.fields["course"].queryset = thecourses
script,div = course_map(course) script,div = course_map(course)
@@ -287,7 +380,12 @@ def standard_view(request,id=0):
r = getrower(request.user) r = getrower(request.user)
allower = ["-referencespeed","agemax","agemin","sex","name",
"referencespeed","-agemax","-agemin","-sex","-name"]
orderby = request.GET.get('order_by') orderby = request.GET.get('order_by')
if orderby not in allowed:
orderby = None
if orderby is not None: if orderby is not None:
standards = CourseStandard.objects.filter( standards = CourseStandard.objects.filter(
@@ -646,6 +744,19 @@ def virtualevents_view(request):
if request.is_ajax(): if request.is_ajax():
is_ajax = True is_ajax = True
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:
lat_lon = None
city = {
'city': '',
'country_name': '',
'time_zone': '',
}
# default races # default races
races1 = VirtualRace.objects.filter( races1 = VirtualRace.objects.filter(
startdate__gte=datetime.date.today(), startdate__gte=datetime.date.today(),
@@ -656,6 +767,8 @@ def virtualevents_view(request):
) )
races = (races1 | races2).order_by("startdate","start_time") races = (races1 | races2).order_by("startdate","start_time")
if len(races) == 0: if len(races) == 0:
@@ -718,10 +831,20 @@ def virtualevents_view(request):
else: else:
form = VirtualRaceSelectForm() form = VirtualRaceSelectForm()
nearby = request.GET.get('nearby')
if nearby and lat_lon is not None:
races = getnearestraces(lat_lon,races)
if is_ajax: if is_ajax:
return render(request,'racelist.html', return render(request,'racelist.html',
{ 'races':races, { 'races':races,
'rower':r, 'rower':r,
'location': lat_lon,
'city':city['city'],
'country_name': city['country_name'],
'time_zone':city['time_zone'],
}) })
breadcrumbs = [ breadcrumbs = [
@@ -737,6 +860,10 @@ def virtualevents_view(request):
'breadcrumbs':breadcrumbs, 'breadcrumbs':breadcrumbs,
'active':'nav-racing', 'active':'nav-racing',
'rower':r, 'rower':r,
'location': lat_lon,
'city':city['city'],
'country_name': city['country_name'],
'time_zone':city['time_zone'],
} }
) )
@@ -1208,7 +1335,11 @@ def virtualevent_view(request,id=0):
} }
] ]
allowed = ["duration","distance","-distance","points","-points","-duration","-distance"]
orderby = request.GET.get('order_by') orderby = request.GET.get('order_by')
if orderby not in allowed:
orderby = None
if orderby is not None: if orderby is not None:
try: try:
results = results.order_by(orderby) results = results.order_by(orderby)

View File

@@ -539,3 +539,5 @@ try:
except KeyError: except KeyError:
RECAPTCHA_SITE_KEY = '' RECAPTCHA_SITE_KEY = ''
RECAPTCHA_SITE_SECRET = '' RECAPTCHA_SITE_SECRET = ''
GEOIP_PATH = STATIC_ROOT

BIN
static/GeoLite2-City.mmdb Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 MiB