Merge branch 'develop' into feature/garmin
This commit is contained in:
@@ -947,7 +947,26 @@ class PlanSelectForm(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):
|
||||
workout = forms.ModelChoiceField(
|
||||
|
||||
@@ -1868,7 +1868,7 @@ def course_map(course):
|
||||
var mymap = L.map('map_canvas', {{
|
||||
center: [{latmean}, {lonmean}],
|
||||
zoom: 13,
|
||||
layers: [streets, satellite]
|
||||
layers: [outdoors]
|
||||
}}).setView([{latmean},{lonmean}], 13);
|
||||
|
||||
var navionics = new JNC.Leaflet.NavionicsOverlay({{
|
||||
@@ -2076,7 +2076,7 @@ def leaflet_chart_compare(course,workoutids,labeldict={},startenddict={}):
|
||||
'time':time-time[0],
|
||||
})
|
||||
data.append(df)
|
||||
except Workout.DoesNotExist:
|
||||
except (Workout.DoesNotExist,KeyError):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ import re
|
||||
import pytz
|
||||
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 shutil
|
||||
@@ -438,8 +439,10 @@ def course_spline(coordinates):
|
||||
tnew = np.linspace(0,1,100)
|
||||
|
||||
try:
|
||||
latnew = CubicSpline(t,latitudes,bc_type='clamped')(tnew)
|
||||
lonnew = CubicSpline(t,longitudes,bc_type='clamped')(tnew)
|
||||
#latnew = CubicSpline(t,latitudes,bc_type='not-a-knot')(tnew)
|
||||
#lonnew = CubicSpline(t,longitudes,bc_type='not-a-knot')(tnew)
|
||||
latnew = interp1d(t,latitudes)(tnew)
|
||||
lonnew = interp1d(t,longitudes)(tnew)
|
||||
except ValueError:
|
||||
latnew = latitudes
|
||||
lonnew = longitudes
|
||||
@@ -1225,6 +1228,7 @@ class GeoCourse(models.Model):
|
||||
name = 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')
|
||||
|
||||
def __str__(self):
|
||||
name = self.name
|
||||
country = self.country
|
||||
@@ -1240,6 +1244,10 @@ class GeoCourse(models.Model):
|
||||
d = d,
|
||||
)
|
||||
|
||||
@property
|
||||
def coord(self):
|
||||
return course_coord_center(self)
|
||||
|
||||
class GeoCourseEditForm(ModelForm):
|
||||
class Meta:
|
||||
model = GeoCourse
|
||||
|
||||
@@ -1400,7 +1400,7 @@ def default_class(r,w,race):
|
||||
agemin__lt=age,agemax__gt=age
|
||||
).order_by(
|
||||
"agemax","-agemin","boattype","sex",
|
||||
"weightcategory","referencespeed")
|
||||
"weightclass","referencespeed")
|
||||
|
||||
if standards.count()==0:
|
||||
# boolean, boattype, boatclass, adaptiveclass, weightclass, sex, coursestandard,
|
||||
|
||||
@@ -450,6 +450,8 @@ def handle_check_race_course(self,
|
||||
t = time.localtime()
|
||||
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
|
||||
f.write('\n')
|
||||
f.write('Course id {n}, Record id {m}'.format(n=courseid,m=recordid))
|
||||
f.write('\n')
|
||||
f.write(timestamp)
|
||||
f.write(' ')
|
||||
f.write('Found {n} entrytimes'.format(n=len(entrytimes)))
|
||||
|
||||
@@ -30,13 +30,16 @@
|
||||
<tr>
|
||||
<th>Notes</th><td>{{ course.notes|linebreaks }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Manager</th><td>{{ course.manager }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
<li class="grid_2">
|
||||
<div class="mapdiv">
|
||||
{{ mapdiv|safe }}
|
||||
|
||||
|
||||
|
||||
|
||||
{{ mapscript|safe }}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<td>
|
||||
{{ course.distance }} m
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
@@ -64,6 +64,15 @@
|
||||
<input type="submit" value="GO"></input>
|
||||
</form>
|
||||
</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>
|
||||
<a href="/rowers/courses/upload/">Add Courses</a>
|
||||
</p>
|
||||
@@ -79,7 +88,7 @@
|
||||
{% endfor %}
|
||||
<p> </p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class="grid_4">
|
||||
@@ -89,27 +98,27 @@
|
||||
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
|
||||
marked courses.
|
||||
|
||||
|
||||
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 creating custom courses for the
|
||||
<a href="http://performancephones.com/crewnerd/">CrewNerd</a>
|
||||
app.
|
||||
|
||||
app.
|
||||
|
||||
</p>
|
||||
|
||||
<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
|
||||
we're interested in starts at 2:05.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
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
|
||||
courses with turns around buoys, respecting buoy lines, or respecting traffic
|
||||
patterns on rivers and lakes.
|
||||
patterns on rivers and lakes.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>Open Google Earth</li>
|
||||
@@ -126,7 +135,7 @@
|
||||
|
||||
<p>You are allowed to have multiple courses in one KML file.
|
||||
Your CrewNerd "courses.kml" file works out of the box</p>
|
||||
|
||||
|
||||
<p>The site doesn't test for duplicate courses.</p>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -67,12 +67,22 @@
|
||||
<p>
|
||||
<input name='form' class='green button' type='submit' value="Submit">
|
||||
</form>
|
||||
</p>
|
||||
</p>
|
||||
</li>
|
||||
<li class="grid_4">
|
||||
<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
|
||||
course name to see the course details.
|
||||
</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 class="grid_4" id="racelist">
|
||||
|
||||
@@ -7,11 +7,100 @@ from rowers.views.statements import *
|
||||
from rowsandall_app.settings import SITE_URL
|
||||
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
|
||||
def courses_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:
|
||||
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
|
||||
query = request.GET.get('q')
|
||||
@@ -34,6 +123,10 @@ def courses_view(request):
|
||||
'active':'nav-racing',
|
||||
'searchform':searchform,
|
||||
'rower':r,
|
||||
'location':lat_lon,
|
||||
'city':city['city'],
|
||||
'country_name': city['country_name'],
|
||||
'time_zone':city['time_zone'],
|
||||
})
|
||||
|
||||
# List Courses
|
||||
@@ -116,7 +209,7 @@ def course_replace_view(request,id=0):
|
||||
|
||||
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':
|
||||
form = CourseSelectForm(request.POST)
|
||||
@@ -132,8 +225,8 @@ def course_replace_view(request,id=0):
|
||||
return HttpResponseRedirect(url)
|
||||
else:
|
||||
|
||||
form = CourseSelectForm()
|
||||
form.fields["course"].queryset = thecourses
|
||||
form = CourseSelectForm(course=course,manager=r)
|
||||
#form.fields["course"].queryset = thecourses
|
||||
|
||||
script,div = course_map(course)
|
||||
|
||||
@@ -287,7 +380,12 @@ def standard_view(request,id=0):
|
||||
|
||||
r = getrower(request.user)
|
||||
|
||||
allower = ["-referencespeed","agemax","agemin","sex","name",
|
||||
"referencespeed","-agemax","-agemin","-sex","-name"]
|
||||
|
||||
orderby = request.GET.get('order_by')
|
||||
if orderby not in allowed:
|
||||
orderby = None
|
||||
|
||||
if orderby is not None:
|
||||
standards = CourseStandard.objects.filter(
|
||||
@@ -646,6 +744,19 @@ def virtualevents_view(request):
|
||||
if request.is_ajax():
|
||||
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
|
||||
races1 = VirtualRace.objects.filter(
|
||||
startdate__gte=datetime.date.today(),
|
||||
@@ -656,6 +767,8 @@ def virtualevents_view(request):
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
races = (races1 | races2).order_by("startdate","start_time")
|
||||
|
||||
if len(races) == 0:
|
||||
@@ -718,10 +831,20 @@ def virtualevents_view(request):
|
||||
else:
|
||||
form = VirtualRaceSelectForm()
|
||||
|
||||
nearby = request.GET.get('nearby')
|
||||
|
||||
if nearby and lat_lon is not None:
|
||||
races = getnearestraces(lat_lon,races)
|
||||
|
||||
|
||||
if is_ajax:
|
||||
return render(request,'racelist.html',
|
||||
{ 'races':races,
|
||||
'rower':r,
|
||||
'location': lat_lon,
|
||||
'city':city['city'],
|
||||
'country_name': city['country_name'],
|
||||
'time_zone':city['time_zone'],
|
||||
})
|
||||
|
||||
breadcrumbs = [
|
||||
@@ -737,6 +860,10 @@ def virtualevents_view(request):
|
||||
'breadcrumbs':breadcrumbs,
|
||||
'active':'nav-racing',
|
||||
'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')
|
||||
if orderby not in allowed:
|
||||
orderby = None
|
||||
|
||||
if orderby is not None:
|
||||
try:
|
||||
results = results.order_by(orderby)
|
||||
|
||||
@@ -539,3 +539,5 @@ try:
|
||||
except KeyError:
|
||||
RECAPTCHA_SITE_KEY = ''
|
||||
RECAPTCHA_SITE_SECRET = ''
|
||||
|
||||
GEOIP_PATH = STATIC_ROOT
|
||||
|
||||
BIN
static/GeoLite2-City.mmdb
Normal file
BIN
static/GeoLite2-City.mmdb
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 MiB |
Reference in New Issue
Block a user