Merge branch 'release/v5.6'
This commit is contained in:
@@ -295,6 +295,12 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True,
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
mask = datadf['efficiency'] > 200.
|
||||||
|
datadf.loc[mask, 'efficiency'] = np.nan
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mask = datadf['spm'] < 10
|
mask = datadf['spm'] < 10
|
||||||
datadf.loc[mask, 'spm'] = np.nan
|
datadf.loc[mask, 'spm'] = np.nan
|
||||||
@@ -509,6 +515,23 @@ def paceformatsecs(values):
|
|||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
def fitnessmetric_to_sql(m,table='powertimefitnessmetric',debug=False):
|
||||||
|
engine = create_engine(database_url, echo=False)
|
||||||
|
columns = ', '.join(m.keys())
|
||||||
|
placeholders = ", ".join(["?"] * len(m))
|
||||||
|
|
||||||
|
query = "INSERT into %s ( %s ) Values (%s)" % (table, columns, placeholders)
|
||||||
|
|
||||||
|
values = tuple(m[key] for key in m.keys())
|
||||||
|
with engine.connect() as conn, conn.begin():
|
||||||
|
result = conn.execute(query,values)
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
engine.dispose()
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
def getcpdata_sql(rower_id,table='cpdata'):
|
def getcpdata_sql(rower_id,table='cpdata'):
|
||||||
engine = create_engine(database_url, echo=False)
|
engine = create_engine(database_url, echo=False)
|
||||||
query = sa.text('SELECT * from {table} WHERE user={rower_id};'.format(
|
query = sa.text('SELECT * from {table} WHERE user={rower_id};'.format(
|
||||||
|
|||||||
@@ -495,6 +495,26 @@ def getsmallrowdata_db(columns,ids=[],debug=False):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def fitnessmetric_to_sql(m,table='powertimefitnessmetric',debug=False):
|
||||||
|
if debug:
|
||||||
|
engine = create_engine(database_url_debug, echo=False)
|
||||||
|
else:
|
||||||
|
engine = create_engine(database_url, echo=False)
|
||||||
|
|
||||||
|
columns = ', '.join(m.keys())
|
||||||
|
placeholders = ", ".join(["?"] * len(m))
|
||||||
|
|
||||||
|
query = "INSERT into %s ( %s ) Values (%s)" % (table, columns, placeholders)
|
||||||
|
|
||||||
|
values = tuple(m[key] for key in m.keys())
|
||||||
|
with engine.connect() as conn, conn.begin():
|
||||||
|
result = conn.execute(query,values)
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
engine.dispose()
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+102
-2
@@ -107,7 +107,104 @@ def getsinglecp(df):
|
|||||||
|
|
||||||
return delta,cpvalue,avgpower
|
return delta,cpvalue,avgpower
|
||||||
|
|
||||||
|
def getcp_new(dfgrouped,logarr):
|
||||||
|
delta = []
|
||||||
|
cpvalue = []
|
||||||
|
avgpower = {}
|
||||||
|
|
||||||
|
|
||||||
|
for id, group in dfgrouped:
|
||||||
|
tt = group['time'].copy()
|
||||||
|
|
||||||
|
ww = group['power'].copy()
|
||||||
|
|
||||||
|
try:
|
||||||
|
avgpower[id] = int(ww.mean())
|
||||||
|
except ValueError:
|
||||||
|
avgpower[id] = '---'
|
||||||
|
|
||||||
|
tmax = tt.max()
|
||||||
|
|
||||||
|
if tmax > 500000:
|
||||||
|
newlen = int(tmax/2000.)
|
||||||
|
newt = np.arange(newlen)*tmax/float(newlen)
|
||||||
|
deltat = newt[1]-newt[0]
|
||||||
|
else:
|
||||||
|
newt = np.arange(0,tmax,10.)
|
||||||
|
deltat = 10.
|
||||||
|
|
||||||
|
ww = griddata(tt.values,
|
||||||
|
ww.values,
|
||||||
|
newt,method='linear',
|
||||||
|
rescale=True)
|
||||||
|
|
||||||
|
tt = pd.Series(newt)
|
||||||
|
ww = pd.Series(ww)
|
||||||
|
|
||||||
|
G = pd.Series(ww.cumsum())
|
||||||
|
G = pd.concat([pd.Series([0]),G])
|
||||||
|
|
||||||
|
h = np.mgrid[0:len(tt)+1:1,0:len(tt)+1:1]
|
||||||
|
|
||||||
|
distances = pd.DataFrame(h[1]-h[0])
|
||||||
|
|
||||||
|
ones = 1+np.zeros(len(G))
|
||||||
|
|
||||||
|
Ghor = np.outer(ones,G)
|
||||||
|
Gver = np.outer(G,ones)
|
||||||
|
|
||||||
|
Gdif = Ghor - Gver
|
||||||
|
|
||||||
|
Gdif = np.tril(Gdif.T).T
|
||||||
|
|
||||||
|
Gdif = pd.DataFrame(Gdif)
|
||||||
|
|
||||||
|
F = Gdif/distances
|
||||||
|
|
||||||
|
F.fillna(inplace=True,method='ffill',axis=1)
|
||||||
|
F.fillna(inplace=True,value=0)
|
||||||
|
|
||||||
|
restime = []
|
||||||
|
power = []
|
||||||
|
|
||||||
|
for i in np.arange(0,len(tt)+1,1):
|
||||||
|
restime.append(deltat*i)
|
||||||
|
cp = np.diag(F,i).max()
|
||||||
|
power.append(cp)
|
||||||
|
|
||||||
|
power[0] = power[1]
|
||||||
|
|
||||||
|
restime = np.array(restime)
|
||||||
|
power = np.array(power)
|
||||||
|
|
||||||
|
|
||||||
|
#power[0] = power[1]
|
||||||
|
|
||||||
|
cpvalues = griddata(restime,power,
|
||||||
|
logarr,method='linear', fill_value=0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for cpv in cpvalues:
|
||||||
|
cpvalue.append(cpv)
|
||||||
|
for d in logarr:
|
||||||
|
delta.append(d)
|
||||||
|
|
||||||
|
df = pd.DataFrame({
|
||||||
|
'delta':delta,
|
||||||
|
'cpvalue':cpvalue
|
||||||
|
})
|
||||||
|
|
||||||
|
df.dropna(axis=0, how='any',inplace=True)
|
||||||
|
df = df.sort_values(['delta','cp'], ascending=[1, 0])
|
||||||
|
df = df.drop_duplicates(subset='Delta', keep='first')
|
||||||
|
|
||||||
|
delta = df['delta']
|
||||||
|
cpvalue = df['cpvalue']
|
||||||
|
|
||||||
|
return delta,cpvalue,avgpower
|
||||||
|
|
||||||
|
|
||||||
def getcp(dfgrouped,logarr):
|
def getcp(dfgrouped,logarr):
|
||||||
delta = []
|
delta = []
|
||||||
cpvalue = []
|
cpvalue = []
|
||||||
@@ -165,7 +262,9 @@ def getcp(dfgrouped,logarr):
|
|||||||
cpvalue.append(cpv)
|
cpvalue.append(cpv)
|
||||||
for d in logarr:
|
for d in logarr:
|
||||||
delta.append(d)
|
delta.append(d)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
delta = pd.Series(delta,name='Delta')
|
delta = pd.Series(delta,name='Delta')
|
||||||
cpvalue = pd.Series(cpvalue,name='CP')
|
cpvalue = pd.Series(cpvalue,name='CP')
|
||||||
|
|
||||||
@@ -201,7 +300,8 @@ def getmaxwattinterval(tt,ww,i):
|
|||||||
wmax = 0
|
wmax = 0
|
||||||
deltat = 0
|
deltat = 0
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
wmax = 0
|
||||||
|
deltat = 0
|
||||||
else:
|
else:
|
||||||
wmax = 0
|
wmax = 0
|
||||||
deltat = 0
|
deltat = 0
|
||||||
|
|||||||
+2
-2
@@ -65,7 +65,7 @@ rowingmetrics = (
|
|||||||
'null':True,
|
'null':True,
|
||||||
'verbose_name': 'Average Drive Force (N)',
|
'verbose_name': 'Average Drive Force (N)',
|
||||||
'ax_min': 0,
|
'ax_min': 0,
|
||||||
'ax_max': 900,
|
'ax_max': 1200,
|
||||||
'mode':'both',
|
'mode':'both',
|
||||||
'type': 'pro'}),
|
'type': 'pro'}),
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ rowingmetrics = (
|
|||||||
'null':True,
|
'null':True,
|
||||||
'verbose_name': 'Peak Drive Force (N)',
|
'verbose_name': 'Peak Drive Force (N)',
|
||||||
'ax_min': 0,
|
'ax_min': 0,
|
||||||
'ax_max': 900,
|
'ax_max': 1500,
|
||||||
'mode':'both',
|
'mode':'both',
|
||||||
'type': 'pro'}),
|
'type': 'pro'}),
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
from django.utils import timezone
|
||||||
|
from rowers.models import Workout, PowerTimeFitnessMetric, Rower
|
||||||
|
import datetime
|
||||||
|
from utils import myqueue
|
||||||
|
import django_rq
|
||||||
|
queue = django_rq.get_queue('default')
|
||||||
|
from rowers.tasks import handle_updatefitnessmetric
|
||||||
|
|
||||||
|
def getrower(user):
|
||||||
|
try:
|
||||||
|
r = Rower.objects.get(user=user)
|
||||||
|
except Rower.DoesNotExist:
|
||||||
|
r = Rower(user=user)
|
||||||
|
r.save()
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
def do_update(user,mode='rower',days=42):
|
||||||
|
r = getrower(user)
|
||||||
|
|
||||||
|
startdate = timezone.now()-datetime.timedelta(days=days)
|
||||||
|
|
||||||
|
# test if not something already done
|
||||||
|
now_date = timezone.now().strftime('%Y-%m-%d')
|
||||||
|
ms = PowerTimeFitnessMetric.objects.filter(
|
||||||
|
user=user,
|
||||||
|
workoutmode=mode)
|
||||||
|
|
||||||
|
if len(ms) == 0:
|
||||||
|
max_workout_id = 0
|
||||||
|
last_update_date = '1972-01-01'
|
||||||
|
else:
|
||||||
|
max_workout_id = max([m.last_workout for m in ms])
|
||||||
|
last_update_date = max([m.date.strftime('%Y-%m-%d') for m in ms])
|
||||||
|
|
||||||
|
if mode == 'rower':
|
||||||
|
workouts = Workout.objects.filter(
|
||||||
|
user=r,
|
||||||
|
workouttype__in=['rower','dynamic','slides'],
|
||||||
|
startdatetime__gte=startdate)
|
||||||
|
else:
|
||||||
|
workouts = Workout.objects.filter(
|
||||||
|
user=r,
|
||||||
|
workouttype__in=['water','coastal'],
|
||||||
|
startdatetime__gte=startdate)
|
||||||
|
|
||||||
|
theids = [int(w.id) for w in workouts]
|
||||||
|
try:
|
||||||
|
max_id = max(theids)
|
||||||
|
except ValueError:
|
||||||
|
max_id = 0
|
||||||
|
|
||||||
|
if last_update_date < now_date and max_workout_id < max_id:
|
||||||
|
job = myqueue(queue,
|
||||||
|
handle_updatefitnessmetric,
|
||||||
|
user.id,mode,theids,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
class PowerTimeFitnessMetricMiddleWare(object):
|
||||||
|
def process_request(self, request):
|
||||||
|
# Code to be executed before the view is called
|
||||||
|
if request.user.is_authenticated():
|
||||||
|
result = do_update(request.user,mode='rower')
|
||||||
|
result = do_update(request.user,mode='water')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -241,6 +241,23 @@ class CalcAgePerformance(models.Model):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'calcagegrouprecords'
|
db_table = 'calcagegrouprecords'
|
||||||
|
|
||||||
|
class PowerTimeFitnessMetric(models.Model):
|
||||||
|
modechoices = (
|
||||||
|
('rower','Rower'),
|
||||||
|
('water','On the water')
|
||||||
|
)
|
||||||
|
|
||||||
|
date = models.DateField(default=timezone.now)
|
||||||
|
last_workout = models.IntegerField(default=0)
|
||||||
|
user = models.ForeignKey(User)
|
||||||
|
PowerFourMin = models.FloatField(default=0)
|
||||||
|
PowerTwoK = models.FloatField(default=0)
|
||||||
|
PowerOneHour = models.FloatField(default=0)
|
||||||
|
workoutmode = models.CharField(default='rower',choices=modechoices,
|
||||||
|
max_length=40)
|
||||||
|
class Meta:
|
||||||
|
db_table = 'powertimefitnessmetric'
|
||||||
|
|
||||||
class C2WorldClassAgePerformance(models.Model):
|
class C2WorldClassAgePerformance(models.Model):
|
||||||
weightcategories = (
|
weightcategories = (
|
||||||
|
|||||||
+78
-1
@@ -25,13 +25,14 @@ from rowsandall_app.settings import PROGRESS_CACHE_SECRET
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from django_rq import job
|
from django_rq import job
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from utils import deserialize_list
|
from utils import deserialize_list
|
||||||
|
|
||||||
from rowers.dataprepnodjango import (
|
from rowers.dataprepnodjango import (
|
||||||
update_strokedata, new_workout_from_file,
|
update_strokedata, new_workout_from_file,
|
||||||
getsmallrowdata_db, updatecpdata_sql,
|
getsmallrowdata_db, updatecpdata_sql,
|
||||||
update_agegroup_db,
|
update_agegroup_db,fitnessmetric_to_sql
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.core.mail import send_mail, EmailMessage
|
from django.core.mail import send_mail, EmailMessage
|
||||||
@@ -612,6 +613,82 @@ def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs):
|
|||||||
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@app.task
|
||||||
|
def handle_updatefitnessmetric(user_id,mode,workoutids,debug=False,
|
||||||
|
**kwargs):
|
||||||
|
|
||||||
|
columns = ['power','workoutid','time']
|
||||||
|
df = getsmallrowdata_db(columns,ids=workoutids,debug=debug)
|
||||||
|
df.dropna(inplace=True,axis=0)
|
||||||
|
|
||||||
|
if df.empty:
|
||||||
|
# change this
|
||||||
|
return 2
|
||||||
|
|
||||||
|
# df is not empty. We continue
|
||||||
|
dfgrouped = df.groupby(['workoutid'])
|
||||||
|
maxt = 1.05*df['time'].max()/1000.
|
||||||
|
|
||||||
|
logarr = datautils.getlogarr(maxt)
|
||||||
|
|
||||||
|
delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr)
|
||||||
|
|
||||||
|
powerdf = pd.DataFrame({
|
||||||
|
'Delta':delta,
|
||||||
|
'CP':cpvalue,
|
||||||
|
})
|
||||||
|
|
||||||
|
powerdf = powerdf[powerdf['CP']>0]
|
||||||
|
powerdf.dropna(axis=0,inplace=True)
|
||||||
|
powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True)
|
||||||
|
powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True)
|
||||||
|
|
||||||
|
p1,fitt,fitpower,ratio = datautils.cpfit(powerdf)
|
||||||
|
# This is code duplication from datautils -- correct asap
|
||||||
|
fitfunc = lambda pars,x: abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3])))
|
||||||
|
|
||||||
|
powerfourmin = fitfunc(p1,240.)
|
||||||
|
powerhour = fitfunc(p1,3600.)
|
||||||
|
|
||||||
|
# 2k power
|
||||||
|
velofourmin = (powerfourmin/2.8)**(1./3.)
|
||||||
|
dfourmin = 240.*velofourmin
|
||||||
|
dratio = 2000./dfourmin
|
||||||
|
pacefourmin = 500./velofourmin
|
||||||
|
|
||||||
|
# assume 5 sec per doubling drop
|
||||||
|
pace2k = pacefourmin + 5.*np.log10(dratio)/np.log10(2.)
|
||||||
|
velo2k = 500./pace2k
|
||||||
|
t2k = 2000./velo2k
|
||||||
|
pwr2k = fitfunc(p1,t2k)
|
||||||
|
velo2 = (pwr2k/2.8)**(1./3.)
|
||||||
|
if np.isnan(velo2) or velo2 <= 0:
|
||||||
|
velo2 = 1.0
|
||||||
|
|
||||||
|
t2 = 2000./velo2
|
||||||
|
|
||||||
|
pwr2k = fitfunc(p1,t2)
|
||||||
|
|
||||||
|
velo3 = (pwr2k/2.8)**(1./3.)
|
||||||
|
|
||||||
|
t3 = 2000./velo3
|
||||||
|
|
||||||
|
power2k = fitfunc(p1,t3)
|
||||||
|
|
||||||
|
|
||||||
|
mdict = {
|
||||||
|
'user_id': user_id,
|
||||||
|
'PowerFourMin': powerfourmin,
|
||||||
|
'PowerTwoK': power2k,
|
||||||
|
'PowerOneHour': powerhour,
|
||||||
|
'workoutmode': mode,
|
||||||
|
'last_workout': max(workoutids),
|
||||||
|
'date': timezone.now().strftime('%Y-%m-%d'),
|
||||||
|
}
|
||||||
|
|
||||||
|
result = fitnessmetric_to_sql(mdict,debug=debug)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
@app.task
|
@app.task
|
||||||
def handle_updatecp(rower_id,workoutids,debug=False,table='cpdata',**kwargs):
|
def handle_updatecp(rower_id,workoutids,debug=False,table='cpdata',**kwargs):
|
||||||
|
|||||||
@@ -133,8 +133,7 @@
|
|||||||
</td>
|
</td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td>
|
<td>
|
||||||
<a href={% url rower.defaultlandingpage
|
<a href={% url rower.defaultlandingpage id=workout.id %}>No Name
|
||||||
id=workout.id %}>No Name
|
|
||||||
</a></td>
|
</a></td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@@ -125,6 +125,9 @@ urlpatterns = [
|
|||||||
url(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)$',views.agegroupcpview),
|
url(r'^agegroupcp/(?P<age>\d+)/(?P<normalize>\d+)$',views.agegroupcpview),
|
||||||
url(r'^ajax_agegroup/(?P<age>\d+)/(?P<weightcategory>\w+.*)/(?P<sex>\w+.*)/(?P<userid>\d+)$',
|
url(r'^ajax_agegroup/(?P<age>\d+)/(?P<weightcategory>\w+.*)/(?P<sex>\w+.*)/(?P<userid>\d+)$',
|
||||||
views.ajax_agegrouprecords),
|
views.ajax_agegrouprecords),
|
||||||
|
url(r'^updatefitness/(?P<mode>\w+.*)/(?P<days>\d+)$',views.fitness_metric_view),
|
||||||
|
url(r'^updatefitness/(?P<mode>\w+.*)$',views.fitness_metric_view),
|
||||||
|
url(r'^updatefitness$',views.fitness_metric_view),
|
||||||
url(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<distance>\d+)m$',
|
url(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<distance>\d+)m$',
|
||||||
views.agegrouprecordview),
|
views.agegrouprecordview),
|
||||||
url(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<duration>\d+)min$',
|
url(r'^agegrouprecords/(?P<sex>\w+.*)/(?P<weightcategory>\w+.*)/(?P<duration>\d+)min$',
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ landingpages = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
workflowmiddlepanel = (
|
workflowmiddlepanel = (
|
||||||
('panel_statcharts.html','Static Charts'),
|
('panel_statcharts.html','Static Charts'),
|
||||||
('flexthumbnails.html','Flex Charts'),
|
('flexthumbnails.html','Flex Charts'),
|
||||||
|
|||||||
+79
-7
@@ -56,7 +56,7 @@ from rowers.models import (
|
|||||||
RowerPowerZonesForm,AccountRowerForm,UserForm,StrokeData,
|
RowerPowerZonesForm,AccountRowerForm,UserForm,StrokeData,
|
||||||
Team,TeamForm,TeamInviteForm,TeamInvite,TeamRequest,
|
Team,TeamForm,TeamInviteForm,TeamInvite,TeamRequest,
|
||||||
WorkoutComment,WorkoutCommentForm,RowerExportForm,
|
WorkoutComment,WorkoutCommentForm,RowerExportForm,
|
||||||
CalcAgePerformance
|
CalcAgePerformance,PowerTimeFitnessMetric,
|
||||||
)
|
)
|
||||||
from rowers.models import FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement
|
from rowers.models import FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement
|
||||||
from rowers.metrics import rowingmetrics,defaultfavoritecharts
|
from rowers.metrics import rowingmetrics,defaultfavoritecharts
|
||||||
@@ -109,7 +109,8 @@ from rowers.tasks import (
|
|||||||
handle_sendemail_unrecognized,handle_sendemailnewcomment,
|
handle_sendemail_unrecognized,handle_sendemailnewcomment,
|
||||||
handle_sendemailnewresponse, handle_updatedps,
|
handle_sendemailnewresponse, handle_updatedps,
|
||||||
handle_updatecp,long_test_task,long_test_task2,
|
handle_updatecp,long_test_task,long_test_task2,
|
||||||
handle_zip_file,handle_getagegrouprecords
|
handle_zip_file,handle_getagegrouprecords,
|
||||||
|
handle_updatefitnessmetric
|
||||||
)
|
)
|
||||||
|
|
||||||
from scipy.signal import savgol_filter
|
from scipy.signal import savgol_filter
|
||||||
@@ -159,6 +160,20 @@ class JSONResponse(HttpResponse):
|
|||||||
kwargs['content_type'] = 'application/json'
|
kwargs['content_type'] = 'application/json'
|
||||||
super(JSONResponse, self).__init__(content, **kwargs)
|
super(JSONResponse, self).__init__(content, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def getrower(user):
|
||||||
|
try:
|
||||||
|
r = Rower.objects.get(user=user)
|
||||||
|
except Rower.DoesNotExist:
|
||||||
|
r = Rower(user=user)
|
||||||
|
r.save()
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getvalue(data):
|
def getvalue(data):
|
||||||
perc = 0
|
perc = 0
|
||||||
total = 1
|
total = 1
|
||||||
@@ -238,6 +253,7 @@ from io import BytesIO
|
|||||||
from scipy.special import lambertw
|
from scipy.special import lambertw
|
||||||
|
|
||||||
from dataprep import timedeltaconv
|
from dataprep import timedeltaconv
|
||||||
|
from dataprep import getsmallrowdata_db
|
||||||
|
|
||||||
from scipy.interpolate import griddata
|
from scipy.interpolate import griddata
|
||||||
|
|
||||||
@@ -736,6 +752,8 @@ def iscoachmember(user):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getrower(user):
|
def getrower(user):
|
||||||
try:
|
try:
|
||||||
r = Rower.objects.get(user=user)
|
r = Rower.objects.get(user=user)
|
||||||
@@ -745,6 +763,8 @@ def getrower(user):
|
|||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check if a user is a Pro member
|
# Check if a user is a Pro member
|
||||||
def ispromember(user):
|
def ispromember(user):
|
||||||
if not user.is_anonymous():
|
if not user.is_anonymous():
|
||||||
@@ -3206,6 +3226,46 @@ def addmanual_view(request):
|
|||||||
{'form':form,
|
{'form':form,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def fitness_metric_view(request,mode='rower',days=42):
|
||||||
|
r = getrower(request.user)
|
||||||
|
startdate = timezone.now()-datetime.timedelta(days=days)
|
||||||
|
|
||||||
|
# test if not something already done
|
||||||
|
ms = PowerTimeFitnessMetric.objects.filter(user=request.user)
|
||||||
|
max_workout_id = max([m.last_workout for m in ms])
|
||||||
|
last_update_date = max([m.date.strftime('%Y-%m-%d') for m in ms])
|
||||||
|
|
||||||
|
|
||||||
|
now_date = timezone.now().strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
|
||||||
|
if mode == 'rower':
|
||||||
|
workouts = Workout.objects.filter(
|
||||||
|
user=r,
|
||||||
|
workouttype__in=['rower','dynamic','slides'],
|
||||||
|
startdatetime__gte=startdate)
|
||||||
|
else:
|
||||||
|
workouts = Workout.objects.filter(
|
||||||
|
user=r,
|
||||||
|
workouttype__in=['water','coastal'],
|
||||||
|
startdatetime__gte=startdate)
|
||||||
|
|
||||||
|
theids = [int(w.id) for w in workouts]
|
||||||
|
max_id = max(theids)
|
||||||
|
|
||||||
|
if last_update_date >= now_date or max_workout_id >= max_id:
|
||||||
|
return HttpResponse("already done today or no new workouts")
|
||||||
|
|
||||||
|
|
||||||
|
job = myqueue(queue,
|
||||||
|
handle_updatefitnessmetric,
|
||||||
|
request.user.id,mode,theids,
|
||||||
|
)
|
||||||
|
|
||||||
|
return HttpResponse("job queued")
|
||||||
|
|
||||||
|
|
||||||
# Show ranking distances including predicted paces
|
# Show ranking distances including predicted paces
|
||||||
@login_required()
|
@login_required()
|
||||||
def rankings_view(request,theuser=0,
|
def rankings_view(request,theuser=0,
|
||||||
@@ -4104,8 +4164,11 @@ def otwrankings_view(request,theuser=0,
|
|||||||
remove_asynctask(request,task['id'])
|
remove_asynctask(request,task['id'])
|
||||||
elif 'fail' in task['status'].lower():
|
elif 'fail' in task['status'].lower():
|
||||||
runningjob = 0
|
runningjob = 0
|
||||||
remove_asynctask(request,task[id])
|
try:
|
||||||
messages.error(request,'Oh, your task failed')
|
remove_asynctask(request,task[id])
|
||||||
|
messages.error(request,'Oh, your task failed')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
elif 'started' in task['status'].lower():
|
elif 'started' in task['status'].lower():
|
||||||
messages.info(request,'Busy updating CP chart data')
|
messages.info(request,'Busy updating CP chart data')
|
||||||
runningjob = 1
|
runningjob = 1
|
||||||
@@ -4356,8 +4419,11 @@ def oterankings_view(request,theuser=0,
|
|||||||
remove_asynctask(request,task['id'])
|
remove_asynctask(request,task['id'])
|
||||||
elif 'fail' in task['status'].lower():
|
elif 'fail' in task['status'].lower():
|
||||||
runningjob = 0
|
runningjob = 0
|
||||||
remove_asynctask(request,task['id'])
|
try:
|
||||||
messages.error(request,'Oh, your task failed')
|
remove_asynctask(request,task[id])
|
||||||
|
messages.error(request,'Oh, your task failed')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
elif 'started' in task['status'].lower():
|
elif 'started' in task['status'].lower():
|
||||||
messages.info(request,'Busy updating CP chart data')
|
messages.info(request,'Busy updating CP chart data')
|
||||||
runningjob = 1
|
runningjob = 1
|
||||||
@@ -10176,7 +10242,13 @@ def workout_split_view(request,id=id):
|
|||||||
else:
|
else:
|
||||||
url = reverse(workouts_view)
|
url = reverse(workouts_view)
|
||||||
|
|
||||||
qdict = {'q':row.name}
|
rowname = row.name
|
||||||
|
if isinstance(rowname,unicode):
|
||||||
|
rowname = rowname.encode('utf8')
|
||||||
|
elif isinstance(rowname, str):
|
||||||
|
rowname = rowname.decode('utf8')
|
||||||
|
|
||||||
|
qdict = {'q':rowname}
|
||||||
url+='?'+urllib.urlencode(qdict)
|
url+='?'+urllib.urlencode(qdict)
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ MIDDLEWARE_CLASSES = [
|
|||||||
'async_messages.middleware.AsyncMiddleware',
|
'async_messages.middleware.AsyncMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'tz_detect.middleware.TimezoneMiddleware',
|
'tz_detect.middleware.TimezoneMiddleware',
|
||||||
|
'rowers.middleware.PowerTimeFitnessMetricMiddleWare',
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'rowsandall_app.urls'
|
ROOT_URLCONF = 'rowsandall_app.urls'
|
||||||
|
|||||||
Reference in New Issue
Block a user