Merge branch 'feature/cpnotifications' into develop
This commit is contained in:
@@ -36,13 +36,15 @@ import pandas as pd
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import itertools
|
import itertools
|
||||||
import math
|
import math
|
||||||
from tasks import handle_sendemail_unrecognized
|
from tasks import handle_sendemail_unrecognized,handle_sendemail_breakthrough
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import utils
|
||||||
|
import datautils
|
||||||
from utils import lbstoN
|
from utils import lbstoN
|
||||||
from scipy.interpolate import griddata
|
from scipy.interpolate import griddata
|
||||||
|
|
||||||
@@ -139,71 +141,6 @@ def filter_df(datadf,fieldname,value,largerthan=True):
|
|||||||
|
|
||||||
return datadf
|
return datadf
|
||||||
|
|
||||||
def getcp(dfgrouped,logarr):
|
|
||||||
delta = []
|
|
||||||
cpvalue = []
|
|
||||||
avgpower = {}
|
|
||||||
#avgpower[0] = 0
|
|
||||||
|
|
||||||
for id,group in dfgrouped:
|
|
||||||
tt = group['time'].copy()
|
|
||||||
ww = group['power'].copy()
|
|
||||||
|
|
||||||
tmax = tt.max()
|
|
||||||
newlen = int(tmax/2000.)
|
|
||||||
print newlen,len(ww)
|
|
||||||
newt = np.arange(newlen)*tmax/float(newlen)
|
|
||||||
neww = griddata(tt.values,
|
|
||||||
ww.values,
|
|
||||||
newt,method='linear',
|
|
||||||
rescale=True)
|
|
||||||
|
|
||||||
#tt = pd.Series(newt)
|
|
||||||
#ww = pd.Series(neww)
|
|
||||||
|
|
||||||
try:
|
|
||||||
avgpower[id] = int(ww.mean())
|
|
||||||
except ValueError:
|
|
||||||
avgpower[id] = '---'
|
|
||||||
if not np.isnan(ww.mean()):
|
|
||||||
length = len(ww)
|
|
||||||
dt = []
|
|
||||||
cpw = []
|
|
||||||
for i in range(length-2):
|
|
||||||
w_roll = ww.rolling(i+2).mean().dropna()
|
|
||||||
if len(w_roll):
|
|
||||||
# now goes with # data points - should be fixed seconds
|
|
||||||
indexmax = w_roll.idxmax(axis=1)
|
|
||||||
try:
|
|
||||||
t_0 = tt.ix[indexmax]
|
|
||||||
t_1 = tt.ix[indexmax-i]
|
|
||||||
deltat = 1.0e-3*(t_0-t_1)
|
|
||||||
wmax = w_roll.ix[indexmax]
|
|
||||||
if not np.isnan(deltat) and not np.isnan(wmax):
|
|
||||||
dt.append(deltat)
|
|
||||||
cpw.append(wmax)
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
dt = pd.Series(dt)
|
|
||||||
cpw = pd.Series(cpw)
|
|
||||||
|
|
||||||
|
|
||||||
cpvalues = griddata(dt.values,
|
|
||||||
cpw.values,
|
|
||||||
logarr,method='linear',
|
|
||||||
rescale=True)
|
|
||||||
|
|
||||||
for cpv in cpvalues:
|
|
||||||
cpvalue.append(cpv)
|
|
||||||
for d in logarr:
|
|
||||||
delta.append(d)
|
|
||||||
|
|
||||||
delta = pd.Series(delta,name='Delta')
|
|
||||||
cpvalue = pd.Series(cpvalue,name='CP')
|
|
||||||
return delta,cpvalue,avgpower
|
|
||||||
|
|
||||||
|
|
||||||
def df_resample(datadf):
|
def df_resample(datadf):
|
||||||
# time stamps must be in seconds
|
# time stamps must be in seconds
|
||||||
@@ -488,6 +425,12 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower',
|
|||||||
powerperc=powerperc,powerzones=r.powerzones)
|
powerperc=powerperc,powerzones=r.powerzones)
|
||||||
row = rdata(f2,rower=rr)
|
row = rdata(f2,rower=rr)
|
||||||
|
|
||||||
|
isbreakthrough = False
|
||||||
|
if workouttype == 'water':
|
||||||
|
delta,cpvalues,avgpower = datautils.getsinglecp(row.df)
|
||||||
|
if utils.isbreakthrough(delta,cpvalues,r.p0,r.p1,r.p2,r.p3):
|
||||||
|
isbreakthrough = True
|
||||||
|
|
||||||
dtavg = row.df['TimeStamp (sec)'].diff().mean()
|
dtavg = row.df['TimeStamp (sec)'].diff().mean()
|
||||||
|
|
||||||
if dtavg < 1:
|
if dtavg < 1:
|
||||||
@@ -643,6 +586,25 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower',
|
|||||||
|
|
||||||
w.save()
|
w.save()
|
||||||
|
|
||||||
|
# submit email task to send email about breakthrough workout
|
||||||
|
if isbreakthrough:
|
||||||
|
a_messages.info(r.user,'It looks like you have a new breakthrough workout')
|
||||||
|
if settings.DEBUG and r.getemailnotifications:
|
||||||
|
res = handle_sendemail_breakthrough.delay(w.id,r.user.email,
|
||||||
|
r.user.first_name,
|
||||||
|
r.user.last_name)
|
||||||
|
elif r.getemailnotifications:
|
||||||
|
try:
|
||||||
|
res = queuehigh.enqueue(
|
||||||
|
handle_sendemail_breakthrough(w.id,
|
||||||
|
r.user.email,
|
||||||
|
r.user.first_name,
|
||||||
|
r.user.last_name))
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
if privacy == 'visible':
|
if privacy == 'visible':
|
||||||
ts = Team.objects.filter(rower=r)
|
ts = Team.objects.filter(rower=r)
|
||||||
for t in ts:
|
for t in ts:
|
||||||
|
|||||||
109
rowers/datautils.py
Normal file
109
rowers/datautils.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from scipy.interpolate import griddata
|
||||||
|
|
||||||
|
def getsinglecp(df):
|
||||||
|
thesecs = df['TimeStamp (sec)'].max()-df['TimeStamp (sec)'].min()
|
||||||
|
if thesecs != 0:
|
||||||
|
maxt = 2*thesecs
|
||||||
|
else:
|
||||||
|
maxt = 1000.
|
||||||
|
|
||||||
|
maxlog10 = np.log10(maxt)
|
||||||
|
logarr = np.arange(50)*maxlog10/50.
|
||||||
|
logarr = [int(10.**(la)) for la in logarr]
|
||||||
|
logarr = pd.Series(logarr)
|
||||||
|
logarr.drop_duplicates(keep='first',inplace=True)
|
||||||
|
|
||||||
|
logarr = logarr.values
|
||||||
|
|
||||||
|
|
||||||
|
dfnew = pd.DataFrame({
|
||||||
|
'time':1000*(df['TimeStamp (sec)']-df.ix[0,'TimeStamp (sec)']),
|
||||||
|
'power':df[' Power (watts)']
|
||||||
|
})
|
||||||
|
|
||||||
|
dfnew['workoutid'] = 0
|
||||||
|
|
||||||
|
dfgrouped = dfnew.groupby(['workoutid'])
|
||||||
|
delta,cpvalue,avgpower = getcp(dfgrouped,logarr)
|
||||||
|
|
||||||
|
return delta,cpvalue,avgpower
|
||||||
|
|
||||||
|
def getcp(dfgrouped,logarr):
|
||||||
|
delta = []
|
||||||
|
cpvalue = []
|
||||||
|
avgpower = {}
|
||||||
|
#avgpower[0] = 0
|
||||||
|
|
||||||
|
for id,group in dfgrouped:
|
||||||
|
tt = group['time'].copy()
|
||||||
|
ww = group['power'].copy()
|
||||||
|
|
||||||
|
tmax = tt.max()
|
||||||
|
if tmax > 500000:
|
||||||
|
newlen = int(tmax/5000.)
|
||||||
|
else:
|
||||||
|
newlen = len(tt)
|
||||||
|
if newlen < len(tt):
|
||||||
|
newt = np.arange(newlen)*tmax/float(newlen)
|
||||||
|
ww = griddata(tt.values,
|
||||||
|
ww.values,
|
||||||
|
newt,method='linear',
|
||||||
|
rescale=True)
|
||||||
|
|
||||||
|
tt = pd.Series(newt)
|
||||||
|
ww = pd.Series(ww)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
avgpower[id] = int(ww.mean())
|
||||||
|
except ValueError:
|
||||||
|
avgpower[id] = '---'
|
||||||
|
if not np.isnan(ww.mean()):
|
||||||
|
length = len(ww)
|
||||||
|
dt = []
|
||||||
|
cpw = []
|
||||||
|
for i in xrange(length-2):
|
||||||
|
deltat,wmax = getmaxwattinterval(tt,ww,i)
|
||||||
|
if not np.isnan(deltat) and not np.isnan(wmax):
|
||||||
|
dt.append(deltat)
|
||||||
|
cpw.append(wmax)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dt = pd.Series(dt)
|
||||||
|
cpw = pd.Series(cpw)
|
||||||
|
if len(dt):
|
||||||
|
|
||||||
|
cpvalues = griddata(dt.values,
|
||||||
|
cpw.values,
|
||||||
|
logarr,method='linear',
|
||||||
|
rescale=True)
|
||||||
|
|
||||||
|
for cpv in cpvalues:
|
||||||
|
cpvalue.append(cpv)
|
||||||
|
for d in logarr:
|
||||||
|
delta.append(d)
|
||||||
|
|
||||||
|
delta = pd.Series(delta,name='Delta')
|
||||||
|
cpvalue = pd.Series(cpvalue,name='CP')
|
||||||
|
return delta,cpvalue,avgpower
|
||||||
|
|
||||||
|
def getmaxwattinterval(tt,ww,i):
|
||||||
|
w_roll = ww.rolling(i+2).mean().dropna()
|
||||||
|
if len(w_roll):
|
||||||
|
# now goes with # data points - should be fixed seconds
|
||||||
|
indexmax = w_roll.idxmax(axis=1)
|
||||||
|
try:
|
||||||
|
t_0 = tt.ix[indexmax]
|
||||||
|
t_1 = tt.ix[indexmax-i]
|
||||||
|
deltat = 1.0e-3*(t_0-t_1)
|
||||||
|
wmax = w_roll.ix[indexmax]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
wmax = 0
|
||||||
|
deltat = 0
|
||||||
|
|
||||||
|
return deltat,wmax
|
||||||
@@ -619,7 +619,7 @@ def interactive_otwcpchart(powerdf,promember=0):
|
|||||||
# there is no Paul's law for OTW
|
# there is no Paul's law for OTW
|
||||||
|
|
||||||
# Fit the data to thee parameter CP model
|
# Fit the data to thee parameter CP model
|
||||||
fitfunc = lambda pars,x: pars[0]/(1+(x/pars[2])) + pars[1]/(1+(x/pars[3]))
|
fitfunc = lambda pars,x: abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3])))
|
||||||
errfunc = lambda pars,x,y: fitfunc(pars,x)-y
|
errfunc = lambda pars,x,y: fitfunc(pars,x)-y
|
||||||
|
|
||||||
p0 = [500,350,10,8000]
|
p0 = [500,350,10,8000]
|
||||||
@@ -636,6 +636,7 @@ def interactive_otwcpchart(powerdf,promember=0):
|
|||||||
p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]]
|
p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]]
|
||||||
|
|
||||||
|
|
||||||
|
p1 = [abs(p) for p in p1]
|
||||||
fitt = pd.Series(10**(4*np.arange(100)/100.))
|
fitt = pd.Series(10**(4*np.arange(100)/100.))
|
||||||
|
|
||||||
fitpower = fitfunc(p1,fitt)
|
fitpower = fitfunc(p1,fitt)
|
||||||
|
|||||||
@@ -232,6 +232,9 @@ class Rower(models.Model):
|
|||||||
('hidden','Hidden'),
|
('hidden','Hidden'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
getemailnotifications = models.BooleanField(default=True,
|
||||||
|
verbose_name='Receive email notifications')
|
||||||
|
|
||||||
rowerplan = models.CharField(default='basic',max_length=30,
|
rowerplan = models.CharField(default='basic',max_length=30,
|
||||||
choices=plans)
|
choices=plans)
|
||||||
|
|
||||||
@@ -746,7 +749,7 @@ class RowerPowerZonesForm(ModelForm):
|
|||||||
class AccountRowerForm(ModelForm):
|
class AccountRowerForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Rower
|
model = Rower
|
||||||
fields = ['weightcategory']
|
fields = ['weightcategory','getemailnotifications']
|
||||||
|
|
||||||
class UserForm(ModelForm):
|
class UserForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ from rowers.dataprepnodjango import new_workout_from_file
|
|||||||
from django.core.mail import send_mail, BadHeaderError,EmailMessage
|
from django.core.mail import send_mail, BadHeaderError,EmailMessage
|
||||||
|
|
||||||
|
|
||||||
|
import datautils
|
||||||
|
import utils
|
||||||
|
|
||||||
# testing task
|
# testing task
|
||||||
@app.task
|
@app.task
|
||||||
@@ -47,6 +47,43 @@ def handle_new_workout_from_file(r,f2,
|
|||||||
return new_workout_from_file(r,f2,workouttype,
|
return new_workout_from_file(r,f2,workouttype,
|
||||||
title,makeprivate,notes)
|
title,makeprivate,notes)
|
||||||
|
|
||||||
|
# send email when a breakthrough workout is uploaded
|
||||||
|
@app.task
|
||||||
|
def handle_sendemail_breakthrough(workoutid,useremail,userfirstname,userlastname):
|
||||||
|
|
||||||
|
# send email with attachment
|
||||||
|
subject = "A breakthrough workout on rowsandall.com"
|
||||||
|
message = "Dear "+userfirstname+",\n"
|
||||||
|
message += "Congratulations! Your recent workout has been analyzed"
|
||||||
|
message += " by Rowsandall.com and it appears your fitness,"
|
||||||
|
message += " as measured by Critical Power, has improved!"
|
||||||
|
message += " Critical Power (CP) is the power that you can "
|
||||||
|
message += "sustain for a given duration. For more, see this "
|
||||||
|
message += " article in the analytics blog:\n\n"
|
||||||
|
message += " [link to article to be written]\n\n"
|
||||||
|
message += "Link to the workout http://rowsandall.com/rowers/workout/"
|
||||||
|
message += str(workoutid)
|
||||||
|
message +="/edit\n\n"
|
||||||
|
message +="To add the workout to your Ranking workouts and see the updated CP plot, click the following link:\n"
|
||||||
|
message += "http://rowsandall.com/rowers/workout/"
|
||||||
|
message += str(workoutid)
|
||||||
|
message += "/updatecp\n\n"
|
||||||
|
|
||||||
|
message += "To opt out of these email notifications, deselect the checkbox on your Profile page under Account Information.\n\n"
|
||||||
|
|
||||||
|
message += "Best Regards, the Rowsandall Team"
|
||||||
|
|
||||||
|
email = EmailMessage(subject, message,
|
||||||
|
'Rowsandall <info@rowsandall.com>',
|
||||||
|
[useremail])
|
||||||
|
|
||||||
|
|
||||||
|
res = email.send()
|
||||||
|
|
||||||
|
# remove tcx file
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
# send email to me when an unrecognized file is uploaded
|
# send email to me when an unrecognized file is uploaded
|
||||||
@app.task
|
@app.task
|
||||||
def handle_sendemail_unrecognized(unrecognizedfile,useremail):
|
def handle_sendemail_unrecognized(unrecognizedfile,useremail):
|
||||||
@@ -141,7 +178,7 @@ def handle_sendemailcsv(first_name,last_name,email,csvfile):
|
|||||||
# Calculate wind and stream corrections for OTW rowing
|
# Calculate wind and stream corrections for OTW rowing
|
||||||
@app.task
|
@app.task
|
||||||
def handle_otwsetpower(f1,boattype,weightvalue,
|
def handle_otwsetpower(f1,boattype,weightvalue,
|
||||||
first_name,last_name,email,workoutid,
|
first_name,last_name,email,workoutid,ps=[1,1,1,1],
|
||||||
debug=False):
|
debug=False):
|
||||||
try:
|
try:
|
||||||
rowdata = rdata(f1)
|
rowdata = rdata(f1)
|
||||||
@@ -183,6 +220,12 @@ def handle_otwsetpower(f1,boattype,weightvalue,
|
|||||||
rowdata.write_csv(f1,gzip=True)
|
rowdata.write_csv(f1,gzip=True)
|
||||||
update_strokedata(workoutid,rowdata.df,debug=debug)
|
update_strokedata(workoutid,rowdata.df,debug=debug)
|
||||||
|
|
||||||
|
delta,cpvalues,avgpower = datautils.getsinglecp(rowdata.df)
|
||||||
|
if utils.isbreakthrough(delta,cpvalues,ps[0],ps[1],ps[2],ps[3]):
|
||||||
|
handle_sendemail_breakthrough(workoutid,email,
|
||||||
|
first_name,
|
||||||
|
last_name)
|
||||||
|
|
||||||
# send email
|
# send email
|
||||||
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
||||||
subject = "Your Rowsandall OTW calculations are ready"
|
subject = "Your Rowsandall OTW calculations are ready"
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ class C2Objects(DjangoTestCase):
|
|||||||
u = User.objects.create_user('john',
|
u = User.objects.create_user('john',
|
||||||
'sander@ds.ds',
|
'sander@ds.ds',
|
||||||
'koeinsloot')
|
'koeinsloot')
|
||||||
|
u.first_name = 'John'
|
||||||
|
u.last_name = 'Sander'
|
||||||
|
u.save()
|
||||||
r = Rower.objects.create(user=u)
|
r = Rower.objects.create(user=u)
|
||||||
|
|
||||||
res = add_workout_from_strokedata(u,1,data,strokedata,source='c2')
|
res = add_workout_from_strokedata(u,1,data,strokedata,source='c2')
|
||||||
@@ -88,6 +91,9 @@ class C2Objects(DjangoTestCase):
|
|||||||
u = User.objects.create_user('john',
|
u = User.objects.create_user('john',
|
||||||
'sander@ds.ds',
|
'sander@ds.ds',
|
||||||
'koeinsloot')
|
'koeinsloot')
|
||||||
|
u.first_name = 'John'
|
||||||
|
u.last_name = 'Sander'
|
||||||
|
u.save()
|
||||||
r = Rower.objects.create(user=u)
|
r = Rower.objects.create(user=u)
|
||||||
|
|
||||||
res = add_workout_from_strokedata(u,1,data,strokedata,source='c2')
|
res = add_workout_from_strokedata(u,1,data,strokedata,source='c2')
|
||||||
@@ -162,6 +168,9 @@ class StravaObjects(DjangoTestCase):
|
|||||||
u = User.objects.create_user('john',
|
u = User.objects.create_user('john',
|
||||||
'sander@ds.ds',
|
'sander@ds.ds',
|
||||||
'koeinsloot')
|
'koeinsloot')
|
||||||
|
u.first_name = 'John'
|
||||||
|
u.last_name = 'Sander'
|
||||||
|
u.save()
|
||||||
r = Rower.objects.create(user=u)
|
r = Rower.objects.create(user=u)
|
||||||
|
|
||||||
res = add_workout_from_strokedata(u,1,workoutsummary,strokedata,
|
res = add_workout_from_strokedata(u,1,workoutsummary,strokedata,
|
||||||
@@ -235,6 +244,9 @@ class StravaObjects(DjangoTestCase):
|
|||||||
u = User.objects.create_user('john',
|
u = User.objects.create_user('john',
|
||||||
'sander@ds.ds',
|
'sander@ds.ds',
|
||||||
'koeinsloot')
|
'koeinsloot')
|
||||||
|
u.first_name = 'John'
|
||||||
|
u.last_name = 'Sander'
|
||||||
|
u.save()
|
||||||
r = Rower.objects.create(user=u)
|
r = Rower.objects.create(user=u)
|
||||||
|
|
||||||
res = add_workout_from_strokedata(u,1,workoutsummary,strokedata,
|
res = add_workout_from_strokedata(u,1,workoutsummary,strokedata,
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ urlpatterns = [
|
|||||||
url(r'^workout/compare/(?P<id>\d+)/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\w+.*)$',views.workout_comparison_list),
|
url(r'^workout/compare/(?P<id>\d+)/(?P<startdatestring>\d+-\d+-\d+)/(?P<enddatestring>\w+.*)$',views.workout_comparison_list),
|
||||||
url(r'^workout/(?P<id>\d+)/edit$',views.workout_edit_view),
|
url(r'^workout/(?P<id>\d+)/edit$',views.workout_edit_view),
|
||||||
url(r'^workout/(?P<id>\d+)/setprivate$',views.workout_setprivate_view),
|
url(r'^workout/(?P<id>\d+)/setprivate$',views.workout_setprivate_view),
|
||||||
|
url(r'^workout/(?P<id>\d+)/updatecp$',views.workout_update_cp_view),
|
||||||
url(r'^workout/(?P<id>\d+)/makepublic$',views.workout_makepublic_view),
|
url(r'^workout/(?P<id>\d+)/makepublic$',views.workout_makepublic_view),
|
||||||
url(r'^workout/(?P<id>\d+)/geeky$',views.workout_geeky_view),
|
url(r'^workout/(?P<id>\d+)/geeky$',views.workout_geeky_view),
|
||||||
url(r'^workout/(?P<id>\d+)/advanced$',views.workout_advanced_view),
|
url(r'^workout/(?P<id>\d+)/advanced$',views.workout_advanced_view),
|
||||||
|
|||||||
@@ -74,3 +74,13 @@ def geo_distance(lat1,lon1,lat2,lon2):
|
|||||||
bearing = math.degrees(tc1)
|
bearing = math.degrees(tc1)
|
||||||
|
|
||||||
return [distance,bearing]
|
return [distance,bearing]
|
||||||
|
|
||||||
|
|
||||||
|
def isbreakthrough(delta,cpvalues,p0,p1,p2,p3):
|
||||||
|
|
||||||
|
pwr = p0/(1+delta/p2)
|
||||||
|
pwr += p1/(1+delta/p3)
|
||||||
|
|
||||||
|
res = np.sum(cpvalues>pwr)
|
||||||
|
|
||||||
|
return res>1
|
||||||
|
|||||||
@@ -274,6 +274,8 @@ from utils import (
|
|||||||
str2bool
|
str2bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import datautils
|
||||||
|
|
||||||
from rowers.models import checkworkoutuser
|
from rowers.models import checkworkoutuser
|
||||||
|
|
||||||
# Check if a user is a Coach member
|
# Check if a user is a Coach member
|
||||||
@@ -343,6 +345,10 @@ def rower_register_view(request):
|
|||||||
response = dataprep.new_workout_from_file(therower,f2,
|
response = dataprep.new_workout_from_file(therower,f2,
|
||||||
title='New User Sample Data',
|
title='New User Sample Data',
|
||||||
notes='This is an example workout to get you started')
|
notes='This is an example workout to get you started')
|
||||||
|
newworkoutid = response[0]
|
||||||
|
w = Workout.objects.get(id=newworkoutid)
|
||||||
|
w.startdatetime = timezone.now()
|
||||||
|
w.save()
|
||||||
|
|
||||||
# Create and send email
|
# Create and send email
|
||||||
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
|
||||||
@@ -2774,6 +2780,27 @@ def rankings_view(request,theuser=0,
|
|||||||
'teams':get_my_teams(request.user),
|
'teams':get_my_teams(request.user),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
|
||||||
|
def workout_update_cp_view(request,id=0):
|
||||||
|
try:
|
||||||
|
row = Workout.objects.get(id=id)
|
||||||
|
except Workout.DoesNotExist:
|
||||||
|
raise Http404("Workout doesn't exist")
|
||||||
|
|
||||||
|
if (checkworkoutuser(request.user,row)==False):
|
||||||
|
message = "You are not allowed to edit this workout"
|
||||||
|
messages.error(request,message)
|
||||||
|
url = reverse(workouts_view)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
row.rankingpiece = True
|
||||||
|
row.save()
|
||||||
|
|
||||||
|
url = reverse(otwrankings_view)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
# Show ranking distances including predicted paces
|
# Show ranking distances including predicted paces
|
||||||
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
|
@user_passes_test(ispromember,login_url="/",redirect_field_name=None)
|
||||||
def otwrankings_view(request,theuser=0,
|
def otwrankings_view(request,theuser=0,
|
||||||
@@ -2915,7 +2942,7 @@ def otwrankings_view(request,theuser=0,
|
|||||||
|
|
||||||
|
|
||||||
dfgrouped = df.groupby(['workoutid'])
|
dfgrouped = df.groupby(['workoutid'])
|
||||||
delta,cpvalue,avgpower = dataprep.getcp(dfgrouped,logarr)
|
delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr)
|
||||||
|
|
||||||
|
|
||||||
powerdf = pd.DataFrame({
|
powerdf = pd.DataFrame({
|
||||||
@@ -7409,7 +7436,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
iunits = []
|
iunits = []
|
||||||
itypes = []
|
itypes = []
|
||||||
iresults = []
|
iresults = []
|
||||||
for i in range(nrintervals):
|
for i in xrange(nrintervals):
|
||||||
try:
|
try:
|
||||||
t = datetime.datetime.strptime(request.POST['intervalt_%s' % i],"%H:%M:%S.%f")
|
t = datetime.datetime.strptime(request.POST['intervalt_%s' % i],"%H:%M:%S.%f")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -7462,7 +7489,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
iunits = []
|
iunits = []
|
||||||
itypes = []
|
itypes = []
|
||||||
iresults = []
|
iresults = []
|
||||||
for i in range(nrintervals):
|
for i in xrange(nrintervals):
|
||||||
t = cd['intervalt_%s' % i]
|
t = cd['intervalt_%s' % i]
|
||||||
timesecs = t.total_seconds()
|
timesecs = t.total_seconds()
|
||||||
itime += [timesecs]
|
itime += [timesecs]
|
||||||
@@ -7496,7 +7523,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
form = SummaryStringForm()
|
form = SummaryStringForm()
|
||||||
|
|
||||||
initial = {}
|
initial = {}
|
||||||
for i in range(nrintervals):
|
for i in xrange(nrintervals):
|
||||||
initial['intervald_%s' % i] = idist[i]
|
initial['intervald_%s' % i] = idist[i]
|
||||||
initial['intervalt_%s' % i] = get_time(itime[i])
|
initial['intervalt_%s' % i] = get_time(itime[i])
|
||||||
initial['type_%s' % i] = itype[i]
|
initial['type_%s' % i] = itype[i]
|
||||||
@@ -7775,6 +7802,7 @@ def rower_edit_view(request,message=""):
|
|||||||
last_name = ucd['last_name']
|
last_name = ucd['last_name']
|
||||||
email = ucd['email']
|
email = ucd['email']
|
||||||
weightcategory = cd['weightcategory']
|
weightcategory = cd['weightcategory']
|
||||||
|
getemailnotifications = cd['getemailnotifications']
|
||||||
u = request.user
|
u = request.user
|
||||||
if len(first_name):
|
if len(first_name):
|
||||||
u.first_name = first_name
|
u.first_name = first_name
|
||||||
@@ -7784,6 +7812,7 @@ def rower_edit_view(request,message=""):
|
|||||||
u.save()
|
u.save()
|
||||||
r = getrower(u)
|
r = getrower(u)
|
||||||
r.weightcategory = weightcategory
|
r.weightcategory = weightcategory
|
||||||
|
r.getemailnotifications = getemailnotifications
|
||||||
r.save()
|
r.save()
|
||||||
form = RowerForm(instance=r)
|
form = RowerForm(instance=r)
|
||||||
powerform = RowerPowerForm(instance=r)
|
powerform = RowerPowerForm(instance=r)
|
||||||
|
|||||||
BIN
rowsanda_107501
BIN
rowsanda_107501
Binary file not shown.
@@ -54,7 +54,6 @@ INSTALLED_APPS = [
|
|||||||
'django_rq',
|
'django_rq',
|
||||||
'django_rq_dashboard',
|
'django_rq_dashboard',
|
||||||
'translation_manager',
|
'translation_manager',
|
||||||
# 'debug_toolbar',
|
|
||||||
'django_mailbox',
|
'django_mailbox',
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'rest_framework_swagger',
|
'rest_framework_swagger',
|
||||||
@@ -90,7 +89,6 @@ MIDDLEWARE_CLASSES = [
|
|||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'async_messages.middleware.AsyncMiddleware',
|
'async_messages.middleware.AsyncMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
# 'debug_toolbar.middleware.DebugToolbarMiddleware',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'rowsandall_app.urls'
|
ROOT_URLCONF = 'rowsandall_app.urls'
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ TEMPLATES[0]['OPTIONS']['debug'] = DEBUG
|
|||||||
|
|
||||||
ALLOWED_HOSTS = ['localhost']
|
ALLOWED_HOSTS = ['localhost']
|
||||||
|
|
||||||
|
INSTALLED_APPS += ['debug_toolbar',]
|
||||||
|
|
||||||
|
MIDDLEWARE_CLASSES += ['debug_toolbar.middleware.DebugToolbarMiddleware',]
|
||||||
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
|
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
|
||||||
|
|||||||
Reference in New Issue
Block a user