working MPV
This commit is contained in:
@@ -63,18 +63,22 @@ def getnearestraces(lat_lon,races,whatisnear=150):
|
||||
|
||||
return races
|
||||
|
||||
def getnearestcourses(lat_lon,courses,whatisnear=150):
|
||||
def getnearestcourses(lat_lon,courses,whatisnear=150,strict=False):
|
||||
print(lat_lon,whatisnear)
|
||||
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
|
||||
elif strict:
|
||||
courses = newlist
|
||||
else:
|
||||
orders = [(c.id,howfaris(lat_lon,c)) for c in courses]
|
||||
orders = sorted(orders,key = lambda tup:tup[1])
|
||||
|
||||
@@ -1472,17 +1472,21 @@ class RaceResultFilterForm(forms.Form):
|
||||
entrycategory = forms.MultipleChoiceField(
|
||||
choices = [],
|
||||
label = 'Groups',
|
||||
widget=forms.CheckboxSelectMultiple()
|
||||
widget=forms.CheckboxSelectMultiple(),
|
||||
required=False,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if 'records' in kwargs:
|
||||
records = kwargs.pop('records',None)
|
||||
groups = kwargs.pop('groups',None)
|
||||
|
||||
|
||||
|
||||
super(RaceResultFilterForm,self).__init__(*args,**kwargs)
|
||||
|
||||
if records:
|
||||
# group
|
||||
if groups:
|
||||
thecategories = [record.entrycategory for record in records]
|
||||
thecategories = list(set(thecategories))
|
||||
if len(thecategories) <= 1:
|
||||
@@ -1496,6 +1500,8 @@ class RaceResultFilterForm(forms.Form):
|
||||
)
|
||||
self.fields['entrycategory'].choices = categorychoices
|
||||
self.fields['entrycategory'].initial = [cat[0] for cat in categorychoices]
|
||||
else:
|
||||
del self.fields['entrycategory']
|
||||
|
||||
# sex
|
||||
thesexes = [record.sex for record in records]
|
||||
|
||||
@@ -66,7 +66,7 @@ from rowers.courses import (
|
||||
)
|
||||
|
||||
from rowers import mytypes
|
||||
from rowers.models import course_spline
|
||||
from rowers.models import course_spline,VirtualRaceResult
|
||||
|
||||
import datetime
|
||||
import math
|
||||
@@ -2419,47 +2419,185 @@ def course_map(course):
|
||||
|
||||
return script,div
|
||||
|
||||
def leaflet_chart(lat,lon,name=""):
|
||||
if lat.empty or lon.empty: # pragma: no cover
|
||||
return [0,"invalid coordinate data"]
|
||||
|
||||
def get_map_script_course(
|
||||
latmean,
|
||||
lonmean,
|
||||
latbegin,
|
||||
latend,
|
||||
longbegin,
|
||||
longend,
|
||||
scoordinates,
|
||||
course,
|
||||
):
|
||||
latmean,lonmean,coordinates = course_coord_center(course)
|
||||
lat_min, lat_max, long_min, long_max = course_coord_maxmin(course)
|
||||
|
||||
# Throw out 0,0
|
||||
df = pd.DataFrame({
|
||||
'lat':lat,
|
||||
'lon':lon
|
||||
})
|
||||
|
||||
df = df.replace(0,np.nan)
|
||||
df = df.loc[(df!=0).any(axis=1)]
|
||||
df.fillna(method='bfill',axis=0,inplace=True)
|
||||
df.fillna(method='ffill',axis=0,inplace=True)
|
||||
lat = df['lat']
|
||||
lon = df['lon']
|
||||
if lat.empty or lon.empty: # pragma: no cover
|
||||
return [0,"invalid coordinate data"]
|
||||
|
||||
latmean = lat.mean()
|
||||
lonmean = lon.mean()
|
||||
|
||||
latbegin = lat[lat.index[0]]
|
||||
longbegin = lon[lon.index[0]]
|
||||
latend = lat[lat.index[-1]]
|
||||
longend = lon[lon.index[-1]]
|
||||
|
||||
coordinates = zip(lat,lon)
|
||||
coordinates = course_spline(coordinates)
|
||||
|
||||
scoordinates = "["
|
||||
|
||||
for x,y in coordinates:
|
||||
for index,row in coordinates.iterrows():
|
||||
scoordinates += """[{x},{y}],
|
||||
""".format(
|
||||
x=x,
|
||||
y=y
|
||||
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', {{
|
||||
center: [{latmean}, {lonmean}],
|
||||
zoom: 13,
|
||||
layers: [streets, satellite]
|
||||
}}).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}
|
||||
|
||||
|
||||
|
||||
var latlongs = {scoordinates}
|
||||
var polyline = L.polyline(latlongs, {{color:'red'}}).addTo(mymap)
|
||||
mymap.fitBounds(polyline.getBounds())
|
||||
|
||||
</script>
|
||||
""".format(
|
||||
latmean=latmean,
|
||||
lonmean=lonmean,
|
||||
latbegin = latbegin,
|
||||
latend=latend,
|
||||
longbegin=longbegin,
|
||||
longend=longend,
|
||||
scoordinates=scoordinates,
|
||||
pcoordinates=pcoordinates,
|
||||
plabels=plabels
|
||||
)
|
||||
|
||||
return script
|
||||
|
||||
|
||||
def get_map_script(
|
||||
latmean,
|
||||
lonmean,
|
||||
latbegin,
|
||||
latend,
|
||||
longbegin,
|
||||
longend,
|
||||
scoordinates,
|
||||
):
|
||||
script = """
|
||||
<script>
|
||||
|
||||
@@ -2551,6 +2689,73 @@ def leaflet_chart(lat,lon,name=""):
|
||||
scoordinates=scoordinates,
|
||||
)
|
||||
|
||||
return script
|
||||
|
||||
def leaflet_chart(lat,lon,name="",raceresult=0):
|
||||
if lat.empty or lon.empty: # pragma: no cover
|
||||
return [0,"invalid coordinate data"]
|
||||
|
||||
|
||||
# Throw out 0,0
|
||||
df = pd.DataFrame({
|
||||
'lat':lat,
|
||||
'lon':lon
|
||||
})
|
||||
|
||||
df = df.replace(0,np.nan)
|
||||
df = df.loc[(df!=0).any(axis=1)]
|
||||
df.fillna(method='bfill',axis=0,inplace=True)
|
||||
df.fillna(method='ffill',axis=0,inplace=True)
|
||||
lat = df['lat']
|
||||
lon = df['lon']
|
||||
if lat.empty or lon.empty: # pragma: no cover
|
||||
return [0,"invalid coordinate data"]
|
||||
|
||||
latmean = lat.mean()
|
||||
lonmean = lon.mean()
|
||||
|
||||
latbegin = lat[lat.index[0]]
|
||||
longbegin = lon[lon.index[0]]
|
||||
latend = lat[lat.index[-1]]
|
||||
longend = lon[lon.index[-1]]
|
||||
|
||||
coordinates = zip(lat,lon)
|
||||
|
||||
scoordinates = "["
|
||||
|
||||
for x,y in coordinates:
|
||||
scoordinates += """[{x},{y}],
|
||||
""".format(
|
||||
x=x,
|
||||
y=y
|
||||
)
|
||||
|
||||
scoordinates += "]"
|
||||
|
||||
if raceresult == 0:
|
||||
script = get_map_script(
|
||||
latmean,
|
||||
lonmean,
|
||||
latbegin,
|
||||
latend,
|
||||
longbegin,
|
||||
longend,
|
||||
scoordinates,
|
||||
)
|
||||
else:
|
||||
record = VirtualRaceResult.objects.get(id=raceresult)
|
||||
course = record.course
|
||||
script = get_map_script_course(
|
||||
latmean,
|
||||
lonmean,
|
||||
latbegin,
|
||||
latend,
|
||||
longbegin,
|
||||
longend,
|
||||
scoordinates,
|
||||
course,
|
||||
)
|
||||
|
||||
div = """
|
||||
<div id="map_canvas" style="width: 100%; height: 400px;"><p> </p></div>
|
||||
"""
|
||||
|
||||
@@ -3473,6 +3473,10 @@ class VirtualRaceResult(models.Model):
|
||||
|
||||
return True
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.race and not self.course:
|
||||
self.course = self.race.course
|
||||
return super(VirtualRaceResult, self).save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
rr = Rower.objects.get(id=self.userid)
|
||||
|
||||
@@ -43,6 +43,71 @@
|
||||
{{ mapscript|safe }}
|
||||
</div>
|
||||
</li>
|
||||
{% if records %}
|
||||
<li class="grid_4">
|
||||
<h2>Course Results</h2>
|
||||
<table class="listtable shortpadded">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Boat</th>
|
||||
<th>Class</th>
|
||||
<th>Age</th>
|
||||
<th>Gender</th>
|
||||
<th>Weight Category</th>
|
||||
<th>Adaptive</th>
|
||||
<th>Time</th>
|
||||
<th>Distance</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for record in records %}
|
||||
<tr>
|
||||
<td>{{ record.username }}</td>
|
||||
<td>{{ record.boattype }}</td>
|
||||
<td>{{ record.boatclass }}</td>
|
||||
<td>{{ record.age }}</td>
|
||||
<td>{{ record.sex }}</td>
|
||||
<td>{{ record.weightcategory }}</td>
|
||||
<td>
|
||||
{% if record.adaptiveclass == 'None' %}
|
||||
|
||||
{% else %}
|
||||
{{ record.adaptiveclass }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<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/entry/{{ record.id }}/">
|
||||
<i class="fas fa-search-plus fa-fw"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if form %}
|
||||
<li class="grid_4">
|
||||
|
||||
<p>
|
||||
<h2>Filter Results</h2>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
<form id="result_filter_form", method="post">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
</table>
|
||||
|
||||
{% csrf_token %}
|
||||
<input type="submit" value="Submit">
|
||||
</p>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -36,11 +36,7 @@
|
||||
<tr>
|
||||
<td> {{ course.country }} </td>
|
||||
<td>
|
||||
{% if course.manager.user == user %}
|
||||
<a href="/rowers/courses/{{ course.id }}/edit/">{{ course.name }}</a>
|
||||
{% else %}
|
||||
<a href="/rowers/courses/{{ course.id }}/">{{ course.name }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ course.distance }} m
|
||||
|
||||
@@ -43,6 +43,14 @@ from django.template.defaultfilters import stringfilter
|
||||
|
||||
from six import string_types
|
||||
|
||||
@register.filter
|
||||
def workoutdate(id):
|
||||
try:
|
||||
w = Workout.objects.get(id=id)
|
||||
return w.date
|
||||
except Workout.DoesNotExist:
|
||||
return 'unknown'
|
||||
|
||||
@register.filter
|
||||
def isfollower(user,id):
|
||||
|
||||
|
||||
@@ -226,6 +226,61 @@ def course_view(request,id=0):
|
||||
|
||||
script,div = course_map(course)
|
||||
|
||||
# get results
|
||||
records = VirtualRaceResult.objects.filter(
|
||||
course=course,
|
||||
workoutid__isnull=False,
|
||||
coursecompleted=True).order_by("duration","-distance")
|
||||
|
||||
form = RaceResultFilterForm(records=records,groups=False)
|
||||
if request.method == 'POST':
|
||||
form = RaceResultFilterForm(request.POST,records=records,groups=False)
|
||||
if form.is_valid():
|
||||
cd = form.cleaned_data
|
||||
try:
|
||||
sex = cd['sex']
|
||||
except KeyError:
|
||||
sex = ['female','male','mixed']
|
||||
|
||||
try:
|
||||
boattype = cd['boattype']
|
||||
except KeyError:
|
||||
boattype = mytypes.waterboattype
|
||||
|
||||
try:
|
||||
boatclass = cd['boatclass']
|
||||
except KeyError:
|
||||
boatclass = [t for t in mytypes.otwtypes]
|
||||
|
||||
age_min = cd['age_min']
|
||||
age_max = cd['age_max']
|
||||
|
||||
try:
|
||||
weightcategory = cd['weightcategory']
|
||||
except KeyError:
|
||||
weightcategory = ['hwt','lwt']
|
||||
|
||||
try:
|
||||
adaptiveclass = cd['adaptiveclass']
|
||||
except KeyError:
|
||||
adaptiveclass = ['None','PR1','PR2','PR3','FES']
|
||||
|
||||
print(age_min,age_max)
|
||||
|
||||
records = VirtualRaceResult.objects.filter(
|
||||
course=course,
|
||||
workoutid__isnull=False,
|
||||
coursecompleted=True,
|
||||
weightcategory__in=weightcategory,
|
||||
sex__in=sex,
|
||||
age__gte=age_min,
|
||||
age__lte=age_max,
|
||||
boatclass__in=boatclass,
|
||||
boattype__in=boattype,
|
||||
adaptiveclass__in=adaptiveclass,
|
||||
).order_by("duration","-distance")
|
||||
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url': reverse('virtualevents_view'),
|
||||
@@ -249,7 +304,9 @@ def course_view(request,id=0):
|
||||
'mapscript':script,
|
||||
'mapdiv':div,
|
||||
'nosessions':False,
|
||||
'records':records,
|
||||
'rower':r,
|
||||
'form':form,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -2374,7 +2374,7 @@ def workout_view(request,id=0,raceresult=0,sessionresult=0,nocourseraceresult=0)
|
||||
else:
|
||||
latitudes = rowdata.df[' latitude']
|
||||
longitudes = rowdata.df[' longitude']
|
||||
mapscript,mapdiv = leaflet_chart(latitudes,longitudes,row.name,)
|
||||
mapscript,mapdiv = leaflet_chart(latitudes,longitudes,row.name,raceresult=raceresult)
|
||||
|
||||
|
||||
else:
|
||||
@@ -6163,9 +6163,11 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
||||
courseselectform = CourseSelectForm()
|
||||
has_latlon,lat_mean,lon_mean = dataprep.workout_has_latlon(row.id)
|
||||
if has_latlon:
|
||||
courses = getnearestcourses([lat_mean,lon_mean],GeoCourse.objects.all(),whatisnear=25)
|
||||
courses = getnearestcourses([lat_mean,lon_mean],GeoCourse.objects.all(),whatisnear=25,
|
||||
strict=True)
|
||||
courseselectform = CourseSelectForm(choices=courses)
|
||||
|
||||
|
||||
powerupdateform = PowerIntervalUpdateForm(initial=data)
|
||||
|
||||
if request.method == 'POST' and "course" in request.POST:
|
||||
|
||||
Reference in New Issue
Block a user