Private
Public Access
1
0

Merge branch 'feature/magicintervals' into develop

This commit is contained in:
Sander Roosendaal
2021-05-28 10:24:01 +02:00
4 changed files with 106 additions and 50 deletions
-1
View File
@@ -468,7 +468,6 @@ def getfastest(df,thevalue,mode='distance'):
starttime = griddata(restime,starttimes,[thevalue*60*1000],method='linear',rescale=True) starttime = griddata(restime,starttimes,[thevalue*60*1000],method='linear',rescale=True)
duration = griddata(restime,restime,[thevalue*60*1000],method='linear',rescale=True) duration = griddata(restime,restime,[thevalue*60*1000],method='linear',rescale=True)
endtime = starttime+duration endtime = starttime+duration
print(distance,starttime,endtime )
return distance[0],starttime[0]/1000.,endtime[0]/1000. return distance[0],starttime[0]/1000.,endtime[0]/1000.
return 0 # pragma: no cover return 0 # pragma: no cover
+68 -49
View File
@@ -41,24 +41,75 @@
title="Jump to following workout"><em>Next</em></a> title="Jump to following workout"><em>Next</em></a>
{% endif %} {% endif %}
</p> </p>
<p>
<table width=100%>
<tr>
<th>Name</th><td>{{ workout.name }}</td>
</tr><tr>
<th>Distance:</th><td>{{ workout.distance }}m</td>
</tr><tr>
<th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td>
</tr><tr>
<th>Public link to this workout</th>
<td>
<a href="/rowers/workout/{{ workout.id|encode }}/">https://rowsandall.com/rowers/workout/{{ workout.id|encode }}</a>
<td>
</tr>
</table>
</p>
<h1>Edit Workout Interval Data</h1> <h1>Edit Workout Interval Data</h1>
<ul class="main-content"> <ul class="main-content">
<li class="grid_2"> <li class="grid_2">
<table width=100%> <h1>Updated Summary</h1>
<tr> <form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id|encode }}/editintervals/" method="post">
<th>Name</th><td>{{ workout.name }}</td> {% csrf_token %}
</tr><tr> <input type="hidden" name="{{ savebutton }}" value="{{ intervalstring }}">
<th>Distance:</th><td>{{ workout.distance }}m</td> <input type="hidden" name="nrintervals" value={{ nrintervals }}>
</tr><tr> {% for key,value in formvalues.items %}
<th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td> <input type="hidden" name="{{ key }}" value="{{ value|safe }}">
</tr><tr> {% endfor %}
<th>Public link to this workout</th> <p>
<td> <input type="submit" value="Save">
<a href="/rowers/workout/{{ workout.id|encode }}/">https://rowsandall.com/rowers/workout/{{ workout.id|encode }}</a> </p>
<td> <span>
</tr> <a href="">Reset to last saved</a>
</table> &nbsp;
<a href="/rowers/workout/{{ workout.id|encode }}/restore/">Restore Original data</a>
</span>
</form>
<p>
<pre>
{{ intervalstats }}
</pre>
</p>
</li>
<li class="grid_2">
<script src="https://cdn.pydata.org/bokeh/release/bokeh-2.2.3.min.js"></script>
<script async="true" type="text/javascript">
Bokeh.set_log_level("info");
</script>
{{ interactiveplot |safe }}
{{ the_div |safe }}
</li>
<li class="grid_2">
<h1>Feeling lucky?</h1>
<p>This new, experimental feature tries to find intervals by looking for patterns in the data. It does not
autodetect rest and work intervals yet. The resulting "interval string" is copied to the Interval Shorthand
section below, where you can edit it.
<form enctype="multipart/form-data" method="post">
<input type="hidden" name="ruptures" value="ruptures">
<table width=100%>
{{ ruptureform.as_table }}
</table>
{% csrf_token %}
<input class="button" type="submit" value="I'm feeling lucky">
</form>
</p>
</li>
<li class="grid_2">
<h1>Interval Shorthand</h1> <h1>Interval Shorthand</h1>
<p> <p>
See the how-to <a href="#howto">at the bottom of this page</a> for details on how to use this form. See the how-to <a href="#howto">at the bottom of this page</a> for details on how to use this form.
@@ -70,6 +121,8 @@
{% csrf_token %} {% csrf_token %}
<input class="button" type="submit" value="Update"> <input class="button" type="submit" value="Update">
</form> </form>
</li>
<li class="grid_2">
<h1>Intervals by Power/Pace</h1> <h1>Intervals by Power/Pace</h1>
<p>With this form, you can specify a power or pace level. Everything faster/harder than the <p>With this form, you can specify a power or pace level. Everything faster/harder than the
@@ -92,40 +145,6 @@
<input class="button" type="submit" value="Submit"> <input class="button" type="submit" value="Submit">
</form> </form>
</li> </li>
<li class="grid_2">
<script src="https://cdn.pydata.org/bokeh/release/bokeh-2.2.3.min.js"></script>
<script async="true" type="text/javascript">
Bokeh.set_log_level("info");
</script>
{{ interactiveplot |safe }}
{{ the_div |safe }}
</li>
<li class="grid_2">
<h1>Updated Summary</h1>
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id|encode }}/editintervals/" method="post">
{% csrf_token %}
<input type="hidden" name="{{ savebutton }}" value="{{ intervalstring }}">
<input type="hidden" name="nrintervals" value={{ nrintervals }}>
{% for key,value in formvalues.items %}
<input type="hidden" name="{{ key }}" value="{{ value|safe }}">
{% endfor %}
<p>
<input type="submit" value="Save">
</p>
<span>
<a href="">Reset to last saved</a>
&nbsp;
<a href="/rowers/workout/{{ workout.id|encode }}/restore/">Restore Original data</a>
</span>
</form>
<p>
<pre>
{{ intervalstats }}
</pre>
</p>
</li>
<li class="grid_2"> <li class="grid_2">
<h1 id="howto">Interval Shorthand How-To</h1> <h1 id="howto">Interval Shorthand How-To</h1>
<p>This is a quick way to enter the intervals using a special mini-language.</p> <p>This is a quick way to enter the intervals using a special mini-language.</p>
Binary file not shown.
+38
View File
@@ -18,6 +18,8 @@ from rowers.utils import intervals_to_string
from urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
from json.decoder import JSONDecodeError from json.decoder import JSONDecodeError
import ruptures as rpt
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)
if isinstance(o, numpy.int32): return int(o) if isinstance(o, numpy.int32): return int(o)
@@ -6144,6 +6146,42 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
powerupdateform = PowerIntervalUpdateForm(initial=data) powerupdateform = PowerIntervalUpdateForm(initial=data)
# feeling lucky / ruptures
if request.method == 'POST' and "ruptures" in request.POST:
df = pd.DataFrame({
'spm':rowdata.df[' Cadence (stokes/min)'],
'power':rowdata.df[' Power (watts)'],
'v':rowdata.df[' AverageBoatSpeed (m/s)']
})
algo = rpt.Pelt(model="rbf").fit(df.values)
result = algo.predict(pen=10)
df['time'] = rowdata.df['TimeStamp (sec)'].values
timeprev = int(df['time'].values[0])
timenext = int(df['time'].values[result[0]])
s = '{delta}sec'.format(delta=timenext-timeprev)
for i in range(len(result)-1):
timeprev = int(df['time'].values[result[i]-1])
timenext = int(df['time'].values[result[i+1]-1])
interval = '+{delta}sec'.format(delta=timenext-timeprev)
s += interval
try:
rowdata.updateinterval_string(s)
except:
messages.error(request,"Nope, you were not lucky")
intervalstats = rowdata.allstats()
itime, idist, itype = rowdata.intervalstats_values()
nrintervals = len(idist)
savebutton = 'savestringform'
intervalString = s
form = SummaryStringForm(initial={'intervalstring':intervalString})
# We have submitted the mini language interpreter # We have submitted the mini language interpreter
if request.method == 'POST' and "intervalstring" in request.POST: if request.method == 'POST' and "intervalstring" in request.POST:
form = SummaryStringForm(request.POST) form = SummaryStringForm(request.POST)