Private
Public Access
1
0

working MPV

This commit is contained in:
Sander Roosendaal
2021-10-08 16:24:58 +02:00
parent b497449846
commit e604350e23
9 changed files with 401 additions and 54 deletions

View File

@@ -63,18 +63,22 @@ def getnearestraces(lat_lon,races,whatisnear=150):
return races return races
def getnearestcourses(lat_lon,courses,whatisnear=150): def getnearestcourses(lat_lon,courses,whatisnear=150,strict=False):
print(lat_lon,whatisnear)
newlist = [] newlist = []
counter = 0 counter = 0
for c in courses: for c in courses:
coords = c.coord coords = c.coord
distance = howfaris(lat_lon,c) distance = howfaris(lat_lon,c)
if distance < whatisnear: if distance < whatisnear:
newlist.append(c) newlist.append(c)
counter += 1 counter += 1
if counter>0: if counter>0:
courses = newlist courses = newlist
elif strict:
courses = newlist
else: else:
orders = [(c.id,howfaris(lat_lon,c)) for c in courses] orders = [(c.id,howfaris(lat_lon,c)) for c in courses]
orders = sorted(orders,key = lambda tup:tup[1]) orders = sorted(orders,key = lambda tup:tup[1])

View File

@@ -1472,17 +1472,21 @@ class RaceResultFilterForm(forms.Form):
entrycategory = forms.MultipleChoiceField( entrycategory = forms.MultipleChoiceField(
choices = [], choices = [],
label = 'Groups', label = 'Groups',
widget=forms.CheckboxSelectMultiple() widget=forms.CheckboxSelectMultiple(),
required=False,
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if 'records' in kwargs:
records = kwargs.pop('records',None) records = kwargs.pop('records',None)
groups = kwargs.pop('groups',None)
super(RaceResultFilterForm,self).__init__(*args,**kwargs) super(RaceResultFilterForm,self).__init__(*args,**kwargs)
if records: if records:
# group # group
if groups:
thecategories = [record.entrycategory for record in records] thecategories = [record.entrycategory for record in records]
thecategories = list(set(thecategories)) thecategories = list(set(thecategories))
if len(thecategories) <= 1: if len(thecategories) <= 1:
@@ -1496,6 +1500,8 @@ class RaceResultFilterForm(forms.Form):
) )
self.fields['entrycategory'].choices = categorychoices self.fields['entrycategory'].choices = categorychoices
self.fields['entrycategory'].initial = [cat[0] for cat in categorychoices] self.fields['entrycategory'].initial = [cat[0] for cat in categorychoices]
else:
del self.fields['entrycategory']
# sex # sex
thesexes = [record.sex for record in records] thesexes = [record.sex for record in records]

View File

@@ -66,7 +66,7 @@ from rowers.courses import (
) )
from rowers import mytypes from rowers import mytypes
from rowers.models import course_spline from rowers.models import course_spline,VirtualRaceResult
import datetime import datetime
import math import math
@@ -2419,47 +2419,185 @@ def course_map(course):
return script,div 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 coordinates = course_spline(coordinates)
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 = "[" scoordinates = "["
for x,y in coordinates: for index,row in coordinates.iterrows():
scoordinates += """[{x},{y}], scoordinates += """[{x},{y}],
""".format( """.format(
x=x, x=row['latitude'],
y=y y=row['longitude']
) )
scoordinates +="]" 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 = """
<script> <script>
@@ -2551,6 +2689,73 @@ def leaflet_chart(lat,lon,name=""):
scoordinates=scoordinates, 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 = """
<div id="map_canvas" style="width: 100%; height: 400px;"><p>&nbsp;</p></div> <div id="map_canvas" style="width: 100%; height: 400px;"><p>&nbsp;</p></div>
""" """

View File

@@ -3473,6 +3473,10 @@ class VirtualRaceResult(models.Model):
return True 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): def __str__(self):
rr = Rower.objects.get(id=self.userid) rr = Rower.objects.get(id=self.userid)

View File

@@ -43,6 +43,71 @@
{{ mapscript|safe }} {{ mapscript|safe }}
</div> </div>
</li> </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' %}
&nbsp;
{% 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> </ul>
{% endblock %} {% endblock %}

View File

@@ -36,11 +36,7 @@
<tr> <tr>
<td> {{ course.country }} </td> <td> {{ course.country }} </td>
<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> <a href="/rowers/courses/{{ course.id }}/">{{ course.name }}</a>
{% endif %}
</td> </td>
<td> <td>
{{ course.distance }} m {{ course.distance }} m

View File

@@ -43,6 +43,14 @@ from django.template.defaultfilters import stringfilter
from six import string_types 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 @register.filter
def isfollower(user,id): def isfollower(user,id):

View File

@@ -226,6 +226,61 @@ def course_view(request,id=0):
script,div = course_map(course) 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 = [ breadcrumbs = [
{ {
'url': reverse('virtualevents_view'), 'url': reverse('virtualevents_view'),
@@ -249,7 +304,9 @@ def course_view(request,id=0):
'mapscript':script, 'mapscript':script,
'mapdiv':div, 'mapdiv':div,
'nosessions':False, 'nosessions':False,
'records':records,
'rower':r, 'rower':r,
'form':form,
} }
) )

View File

@@ -2374,7 +2374,7 @@ def workout_view(request,id=0,raceresult=0,sessionresult=0,nocourseraceresult=0)
else: else:
latitudes = rowdata.df[' latitude'] latitudes = rowdata.df[' latitude']
longitudes = rowdata.df[' longitude'] longitudes = rowdata.df[' longitude']
mapscript,mapdiv = leaflet_chart(latitudes,longitudes,row.name,) mapscript,mapdiv = leaflet_chart(latitudes,longitudes,row.name,raceresult=raceresult)
else: else:
@@ -6163,9 +6163,11 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
courseselectform = CourseSelectForm() courseselectform = CourseSelectForm()
has_latlon,lat_mean,lon_mean = dataprep.workout_has_latlon(row.id) has_latlon,lat_mean,lon_mean = dataprep.workout_has_latlon(row.id)
if has_latlon: 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) courseselectform = CourseSelectForm(choices=courses)
powerupdateform = PowerIntervalUpdateForm(initial=data) powerupdateform = PowerIntervalUpdateForm(initial=data)
if request.method == 'POST' and "course" in request.POST: if request.method == 'POST' and "course" in request.POST: