non functional mockup stage
This commit is contained in:
@@ -22,6 +22,74 @@ import xml.etree.ElementTree as et
|
|||||||
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
|
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
|
||||||
|
# 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,whatisnear=150):
|
||||||
|
newlist = []
|
||||||
|
counter = 0
|
||||||
|
for race in races:
|
||||||
|
if race.course is None: # pragma: no cover
|
||||||
|
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:]: # pragma: no cover
|
||||||
|
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,whatisnear=150):
|
||||||
|
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: # pragma: no cover
|
||||||
|
ids.append(id)
|
||||||
|
|
||||||
|
for id in ids:
|
||||||
|
newlist.append(GeoCourse.objects.get(id=id))
|
||||||
|
courses = newlist
|
||||||
|
|
||||||
|
return courses
|
||||||
|
|
||||||
|
|
||||||
def prettify(elem):
|
def prettify(elem):
|
||||||
"""Return a pretty-printed XML string for the Element.
|
"""Return a pretty-printed XML string for the Element.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -309,6 +309,20 @@ def get_latlon_time(id):
|
|||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
def workout_has_latlon(id):
|
||||||
|
latitude, longitude = get_latlon(id)
|
||||||
|
latmean = latitude.mean()
|
||||||
|
lonmean = longitude.mean()
|
||||||
|
|
||||||
|
if latmean == 0 and lonmean == 0:
|
||||||
|
return False,latmean,lonmean
|
||||||
|
|
||||||
|
if latitude.std() > 0 and longitude.std() > 0:
|
||||||
|
return True, latmean,lonmean
|
||||||
|
|
||||||
|
return False, latmean,lonmean
|
||||||
|
|
||||||
|
|
||||||
def workout_summary_to_df(
|
def workout_summary_to_df(
|
||||||
rower,
|
rower,
|
||||||
startdate=datetime.datetime(1970,1,1),
|
startdate=datetime.datetime(1970,1,1),
|
||||||
|
|||||||
@@ -1128,27 +1128,28 @@ class PlanSelectForm(forms.Form):
|
|||||||
"price","shortname"
|
"price","shortname"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CourseSelectForm(forms.Form):
|
class CourseSelectForm(forms.Form):
|
||||||
course = forms.ModelChoiceField(queryset=GeoCourse.objects.filter())
|
course = forms.ModelChoiceField(queryset=GeoCourse.objects.filter())
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs): # pragma: no cover
|
def __init__(self, *args, **kwargs): # pragma: no cover
|
||||||
course = kwargs.pop('course',None)
|
course = kwargs.pop('course',None)
|
||||||
manager = kwargs.pop('manager',None)
|
manager = kwargs.pop('manager',None)
|
||||||
|
choices = kwargs.pop('choices',[])
|
||||||
super(CourseSelectForm,self).__init__(*args,**kwargs)
|
super(CourseSelectForm,self).__init__(*args,**kwargs)
|
||||||
|
if len(choices)>0:
|
||||||
|
self.fields['course'].queryset = GeoCourse.objects.filter(id__in=[c.id for c in choices])
|
||||||
if course is not None:
|
if course is not None:
|
||||||
d_min = 0.5*course.distance
|
d_min = 0.5*course.distance
|
||||||
d_max = 2*course.distance
|
d_max = 2*course.distance
|
||||||
country = course.country
|
country = course.country
|
||||||
countries = ['unknown',country]
|
countries = ['unknown',country]
|
||||||
print(countries)
|
|
||||||
self.fields['course'].queryset = self.fields['course'].queryset.filter(
|
self.fields['course'].queryset = self.fields['course'].queryset.filter(
|
||||||
distance__gt = d_min,distance__lt = d_max,
|
distance__gt = d_min,distance__lt = d_max,
|
||||||
country__in = countries
|
country__in = countries
|
||||||
).exclude(id=course.id)
|
).exclude(id=course.id)
|
||||||
if manager is not None:
|
if manager is not None:
|
||||||
self.fields['course'].queryset = self.fields['course'].queryset.filter(manager=manager)
|
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(
|
||||||
|
|||||||
@@ -3408,7 +3408,8 @@ class VirtualRaceResult(models.Model):
|
|||||||
verbose_name="Adaptive Class")
|
verbose_name="Adaptive Class")
|
||||||
skillclass = models.CharField(default="Open",max_length=50,
|
skillclass = models.CharField(default="Open",max_length=50,
|
||||||
verbose_name="Skill Class")
|
verbose_name="Skill Class")
|
||||||
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE,related_name='entries')
|
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE,related_name='entries',
|
||||||
|
blank=True,null=True)
|
||||||
duration = models.TimeField(default=datetime.time(1,0))
|
duration = models.TimeField(default=datetime.time(1,0))
|
||||||
distance = models.IntegerField(default=0)
|
distance = models.IntegerField(default=0)
|
||||||
points = models.FloatField(default=0)
|
points = models.FloatField(default=0)
|
||||||
@@ -3448,6 +3449,10 @@ class VirtualRaceResult(models.Model):
|
|||||||
return False
|
return False
|
||||||
if self.skillclass != other.skillclass:
|
if self.skillclass != other.skillclass:
|
||||||
return False
|
return False
|
||||||
|
if self.race is None and other.race is not None:
|
||||||
|
return False
|
||||||
|
if self.rae is not None and other.race is None:
|
||||||
|
return False
|
||||||
if self.race != other.race:
|
if self.race != other.race:
|
||||||
return False
|
return False
|
||||||
if self.boatclass != other.boatclass:
|
if self.boatclass != other.boatclass:
|
||||||
@@ -3522,7 +3527,7 @@ class IndoorVirtualRaceResult(models.Model):
|
|||||||
verbose_name="Adaptive Class")
|
verbose_name="Adaptive Class")
|
||||||
skillclass = models.CharField(default="Open",max_length=50,
|
skillclass = models.CharField(default="Open",max_length=50,
|
||||||
verbose_name="Skill Class")
|
verbose_name="Skill Class")
|
||||||
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE)
|
race = models.ForeignKey(VirtualRace,on_delete=models.CASCADE,null=True,blank=True)
|
||||||
duration = models.TimeField(default=datetime.time(1,0))
|
duration = models.TimeField(default=datetime.time(1,0))
|
||||||
distance = models.IntegerField(default=0)
|
distance = models.IntegerField(default=0)
|
||||||
referencespeed = models.FloatField(default=5.0)
|
referencespeed = models.FloatField(default=5.0)
|
||||||
@@ -3554,6 +3559,10 @@ class IndoorVirtualRaceResult(models.Model):
|
|||||||
endsecond = models.FloatField(default=0)
|
endsecond = models.FloatField(default=0)
|
||||||
|
|
||||||
def isduplicate(self,other): # pragma: no cover
|
def isduplicate(self,other): # pragma: no cover
|
||||||
|
if self.race is None and other.race is not None:
|
||||||
|
return False
|
||||||
|
if self.race is not None and other.race is None:
|
||||||
|
return False
|
||||||
if self.userid != other.userid:
|
if self.userid != other.userid:
|
||||||
return False
|
return False
|
||||||
if self.weightcategory != other.weightcategory:
|
if self.weightcategory != other.weightcategory:
|
||||||
|
|||||||
@@ -158,7 +158,7 @@
|
|||||||
|
|
||||||
<p>A typical interval is described as "<b>10min/5min</b>", with the work part before the "<b>/</b>" and the rest part after it. A zero rest can be omitted, so a single 1000m piece could be described either as "<b>1km</b>" or "<b>1000m</b>". The basic units can be combined with "<b>+</b>" and "<b>Nx</b>". You can use parentheses as in the example below.</p>
|
<p>A typical interval is described as "<b>10min/5min</b>", with the work part before the "<b>/</b>" and the rest part after it. A zero rest can be omitted, so a single 1000m piece could be described either as "<b>1km</b>" or "<b>1000m</b>". The basic units can be combined with "<b>+</b>" and "<b>Nx</b>". You can use parentheses as in the example below.</p>
|
||||||
|
|
||||||
<p>Here are a few examples.</p>
|
<p>Here are a few examples</p>
|
||||||
<table class="listtable" width=100%>
|
<table class="listtable" width=100%>
|
||||||
<tr>
|
<tr>
|
||||||
<td>8x500m/2min</td><td>8 times 500m with 2 minutes rest</td>
|
<td>8x500m/2min</td><td>8 times 500m with 2 minutes rest</td>
|
||||||
@@ -182,6 +182,23 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
|
{% if courses %}
|
||||||
|
<li>
|
||||||
|
<h1>Interval by Course</h1>
|
||||||
|
<p>
|
||||||
|
This functionality allows you to record a time on a set course that you've rowed during the workout.
|
||||||
|
The summary will be updated to show time on course, and you can compare this with other
|
||||||
|
attempts.
|
||||||
|
</p>
|
||||||
|
<form ecntype="multipart/form-data" method="post">
|
||||||
|
<table>
|
||||||
|
{{ courseselectform.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<input class="button" type="submit" value="Select Course">
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -11,72 +11,7 @@ from django.contrib.gis.geoip2 import GeoIP2
|
|||||||
from django import forms
|
from django import forms
|
||||||
from rowers.plannedsessions import timefield_to_seconds_duration
|
from rowers.plannedsessions import timefield_to_seconds_duration
|
||||||
|
|
||||||
# distance of course from lat_lon in km
|
from rowers.courses import getnearestraces, getnearestcourses
|
||||||
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: # pragma: no cover
|
|
||||||
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:]: # pragma: no cover
|
|
||||||
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: # pragma: no cover
|
|
||||||
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):
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from urllib.parse import urlparse, parse_qs
|
|||||||
from json.decoder import JSONDecodeError
|
from json.decoder import JSONDecodeError
|
||||||
|
|
||||||
import ruptures as rpt
|
import ruptures as rpt
|
||||||
|
from rowers.courses import getnearestraces, getnearestcourses
|
||||||
|
|
||||||
def default(o): # pragma: no cover
|
def default(o): # pragma: no cover
|
||||||
if isinstance(o, numpy.int64): return int(o)
|
if isinstance(o, numpy.int64): return int(o)
|
||||||
@@ -6157,7 +6158,13 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
data['selector'] = 'pace'
|
data['selector'] = 'pace'
|
||||||
powerorpace = 'pace'
|
powerorpace = 'pace'
|
||||||
|
|
||||||
|
# looking for courses
|
||||||
|
courses = []
|
||||||
|
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)
|
||||||
|
courseselectform = CourseSelectForm(choices=courses)
|
||||||
|
|
||||||
powerupdateform = PowerIntervalUpdateForm(initial=data)
|
powerupdateform = PowerIntervalUpdateForm(initial=data)
|
||||||
|
|
||||||
@@ -6490,6 +6497,8 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
'intervalstring':s,
|
'intervalstring':s,
|
||||||
'savebutton':savebutton,
|
'savebutton':savebutton,
|
||||||
'formvalues':formvalues,
|
'formvalues':formvalues,
|
||||||
|
'courses':courses,
|
||||||
|
'courseselectform':courseselectform,
|
||||||
})
|
})
|
||||||
|
|
||||||
class VideoDelete(DeleteView):
|
class VideoDelete(DeleteView):
|
||||||
|
|||||||
Reference in New Issue
Block a user