Merge branch 'feature/restapi' into develop
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,31 @@ from pandas import DataFrame,Series
|
||||
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import itertools
|
||||
|
||||
from django.conf import settings
|
||||
from sqlalchemy import create_engine
|
||||
import sqlalchemy as sa
|
||||
|
||||
user = settings.DATABASES['default']['USER']
|
||||
password = settings.DATABASES['default']['PASSWORD']
|
||||
database_name = settings.DATABASES['default']['NAME']
|
||||
host = settings.DATABASES['default']['HOST']
|
||||
port = settings.DATABASES['default']['PORT']
|
||||
|
||||
database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
|
||||
user=user,
|
||||
password=password,
|
||||
database_name=database_name,
|
||||
host=host,
|
||||
port=port,
|
||||
)
|
||||
|
||||
if settings.DEBUG or user=='':
|
||||
# database_url = 'sqlite:///db.sqlite3'
|
||||
database_url = 'sqlite:///'+database_name
|
||||
|
||||
engine = create_engine(database_url, echo=False)
|
||||
|
||||
from scipy.signal import savgol_filter
|
||||
|
||||
@@ -59,6 +84,55 @@ def rdata(file,rower=rrower()):
|
||||
|
||||
return res
|
||||
|
||||
def delete_strokedata(id):
|
||||
query = sa.text('DELETE FROM strokedata WHERE workoutid={id};'.format(
|
||||
id=id,
|
||||
))
|
||||
with engine.connect() as conn, conn.begin():
|
||||
try:
|
||||
result = conn.execute(query)
|
||||
except:
|
||||
print "Database Locked"
|
||||
|
||||
def testdata(time,distance,pace,spm):
|
||||
t1 = np.issubdtype(time,np.number)
|
||||
t2 = np.issubdtype(distance,np.number)
|
||||
t3 = np.issubdtype(pace,np.number)
|
||||
t4 = np.issubdtype(spm,np.number)
|
||||
|
||||
return t1 and t2 and t3 and t4
|
||||
|
||||
def getrowdata_db(id=0):
|
||||
data = read_df_sql(id)
|
||||
data['pace'] = data['pace']/1.0e6
|
||||
data['ergpace'] = data['ergpace']/1.0e6
|
||||
data['nowindpace'] = data['nowindpace']/1.0e6
|
||||
data['time'] = data['time']/1.0e6
|
||||
data['x_right'] = data['x_right']/1.0e6
|
||||
if data.empty:
|
||||
rowdata,row = getrowdata(id=id)
|
||||
if rowdata:
|
||||
data = dataprep(rowdata.df,id=id,bands=True,barchart=True,otwpower=True)
|
||||
else:
|
||||
data = pd.DataFrame() # returning empty dataframe
|
||||
else:
|
||||
row = Workout.objects.get(id=id)
|
||||
|
||||
return data,row
|
||||
|
||||
def getsmallrowdata_db(columns,ids=[]):
|
||||
prepmultipledata(ids)
|
||||
data = read_cols_df_sql(ids,columns)
|
||||
for column in columns:
|
||||
if column == 'time':
|
||||
data['time'] = data['time']/1.0e6
|
||||
if column == 'pace':
|
||||
data['pace'] = data['pace']/1.0e6
|
||||
if column == 'pace':
|
||||
data['pace'] = data['pace']/1.0e6
|
||||
|
||||
return data
|
||||
|
||||
def getrowdata(id=0):
|
||||
|
||||
# check if valid ID exists (workout exists)
|
||||
@@ -80,6 +154,56 @@ def getrowdata(id=0):
|
||||
return rowdata,row
|
||||
|
||||
|
||||
def prepmultipledata(ids,verbose=False):
|
||||
query = sa.text('SELECT DISTINCT workoutid FROM strokedata')
|
||||
with engine.connect() as conn, conn.begin():
|
||||
res = conn.execute(query)
|
||||
res = list(itertools.chain.from_iterable(res.fetchall()))
|
||||
|
||||
res = list(set(ids)-set(res))
|
||||
for id in res:
|
||||
rowdata,row = getrowdata(id=id)
|
||||
if verbose:
|
||||
print id
|
||||
if rowdata:
|
||||
data = dataprep(rowdata.df,id=id,bands=True,barchart=True,otwpower=True)
|
||||
return res
|
||||
|
||||
def read_cols_df_sql(ids,columns):
|
||||
columns = list(columns)+['distance','spm']
|
||||
columns = [x for x in columns if x != 'None']
|
||||
columns = list(set(columns))
|
||||
cls = ''
|
||||
for column in columns:
|
||||
cls += column+', '
|
||||
cls = cls[:-2]
|
||||
if len(ids) == 0:
|
||||
query = sa.text('SELECT {columns} FROM strokedata WHERE workoutid=0'.format(
|
||||
columns = cls,
|
||||
))
|
||||
elif len(ids) == 1:
|
||||
query = sa.text('SELECT {columns} FROM strokedata WHERE workoutid={id}'.format(
|
||||
id = ids[0],
|
||||
columns = cls,
|
||||
))
|
||||
else:
|
||||
query = sa.text('SELECT {columns} FROM strokedata WHERE workoutid IN {ids}'.format(
|
||||
columns = cls,
|
||||
ids = tuple(ids),
|
||||
))
|
||||
|
||||
df = pd.read_sql_query(query,engine)
|
||||
return df
|
||||
|
||||
|
||||
def read_df_sql(id):
|
||||
df = pd.read_sql_query(sa.text('SELECT * FROM strokedata WHERE workoutid={id}'.format(
|
||||
id=id)), engine)
|
||||
return df
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def smalldataprep(therows,xparam,yparam1,yparam2):
|
||||
df = pd.DataFrame()
|
||||
@@ -110,8 +234,7 @@ def smalldataprep(therows,xparam,yparam1,yparam2):
|
||||
return df
|
||||
|
||||
|
||||
|
||||
def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
|
||||
def dataprep(rowdatadf,id=0,bands=False,barchart=False,otwpower=False):
|
||||
rowdatadf.set_index([range(len(rowdatadf))],inplace=True)
|
||||
t = rowdatadf.ix[:,'TimeStamp (sec)']
|
||||
t = pd.Series(t-rowdatadf.ix[0,'TimeStamp (sec)'])
|
||||
@@ -127,8 +250,11 @@ def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
|
||||
power = rowdatadf.ix[:,' Power (watts)']
|
||||
averageforce = rowdatadf.ix[:,' AverageDriveForce (lbs)']
|
||||
drivelength = rowdatadf.ix[:,' DriveLength (meters)']
|
||||
|
||||
|
||||
try:
|
||||
workoutstate = rowdatadf.ix[:,' WorkoutState']
|
||||
except KeyError:
|
||||
workoutstate = 0*hr
|
||||
|
||||
peakforce = rowdatadf.ix[:,' PeakDriveForce (lbs)']
|
||||
|
||||
forceratio = averageforce/peakforce
|
||||
@@ -175,6 +301,7 @@ def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
|
||||
fpace = nicepaceformat(p2),
|
||||
driveenergy=driveenergy,
|
||||
power=power,
|
||||
workoutstate=workoutstate,
|
||||
averageforce=averageforce,
|
||||
drivelength=drivelength,
|
||||
peakforce=peakforce,
|
||||
@@ -228,5 +355,11 @@ def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
|
||||
|
||||
data = data.replace([-np.inf,np.inf],np.nan)
|
||||
data = data.fillna(method='ffill')
|
||||
|
||||
|
||||
# write data if id given
|
||||
if id != 0:
|
||||
data['workoutid'] = id
|
||||
with engine.connect() as conn, conn.begin():
|
||||
data.to_sql('strokedata',engine,if_exists='append',index=False)
|
||||
|
||||
return data
|
||||
|
||||
@@ -27,6 +27,10 @@ class CNsummaryForm(forms.Form):
|
||||
class SummaryStringForm(forms.Form):
|
||||
intervalstring = forms.CharField(max_length=255,label='Workout Description')
|
||||
|
||||
class StrokeDataForm(forms.Form):
|
||||
strokedata = forms.CharField(label='payload',
|
||||
widget=forms.Textarea)
|
||||
|
||||
class DocumentsForm(forms.Form):
|
||||
filetypechoices = (
|
||||
('csv' , 'Painsled iOS CSV'),
|
||||
|
||||
@@ -70,14 +70,14 @@ from rowers.dataprep import timedeltaconv
|
||||
def interactive_histoall(theworkouts):
|
||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
||||
|
||||
therows = []
|
||||
for workout in theworkouts:
|
||||
f1 = workout.csvfilename
|
||||
rowdata = rdata(f1)
|
||||
if rowdata != 0:
|
||||
therows.append(rowdata)
|
||||
|
||||
histopwr = histodata(therows)
|
||||
ids = [w.id for w in theworkouts]
|
||||
|
||||
rowdata = dataprep.getsmallrowdata_db(['power'],ids=ids)
|
||||
|
||||
histopwr = rowdata['power'].values
|
||||
if len(histopwr) == 0:
|
||||
return "","CSV file not found","",""
|
||||
|
||||
# throw out nans
|
||||
histopwr = histopwr[~np.isinf(histopwr)]
|
||||
histopwr = histopwr[histopwr > 25]
|
||||
@@ -496,18 +496,15 @@ def interactive_chart(id=0,promember=0):
|
||||
else:
|
||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
||||
|
||||
rowdata,row = dataprep.getrowdata(id=id)
|
||||
if rowdata == 0:
|
||||
|
||||
datadf,row = dataprep.getrowdata_db(id=id)
|
||||
if datadf.empty:
|
||||
return "","CSV Data File Not Found"
|
||||
|
||||
datadf = dataprep.dataprep(rowdata.df)
|
||||
|
||||
source = ColumnDataSource(
|
||||
datadf
|
||||
)
|
||||
|
||||
|
||||
|
||||
plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
|
||||
plot_width=400,
|
||||
plot_height=400,
|
||||
@@ -554,10 +551,10 @@ def interactive_chart(id=0,promember=0):
|
||||
|
||||
hover.mode = 'mouse'
|
||||
|
||||
plot.extra_y_ranges = {"hr": Range1d(start=100,end=200)}
|
||||
plot.extra_y_ranges = {"hrax": Range1d(start=100,end=200)}
|
||||
plot.line('time','hr',source=source,color="red",
|
||||
y_range_name="hr", legend="Heart Rate")
|
||||
plot.add_layout(LinearAxis(y_range_name="hr",axis_label="HR"),'right')
|
||||
y_range_name="hrax", legend="Heart Rate")
|
||||
plot.add_layout(LinearAxis(y_range_name="hrax",axis_label="HR"),'right')
|
||||
|
||||
plot.legend.location = "bottom_right"
|
||||
|
||||
@@ -570,8 +567,10 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
|
||||
yparam1='power',
|
||||
yparam2='spm'):
|
||||
|
||||
datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2)
|
||||
|
||||
# datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2)
|
||||
ids = [w.id for w in theworkouts]
|
||||
datadf = dataprep.getsmallrowdata_db([xparam,yparam1,yparam2],ids=ids)
|
||||
|
||||
axlabels = {
|
||||
'time': 'Time',
|
||||
'distance': 'Distance (m)',
|
||||
@@ -666,6 +665,7 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
|
||||
else:
|
||||
datadf['yname2'] = yparam1
|
||||
|
||||
|
||||
source = ColumnDataSource(
|
||||
datadf
|
||||
)
|
||||
@@ -678,7 +678,7 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
|
||||
if (promember==1):
|
||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair'
|
||||
else:
|
||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair'
|
||||
|
||||
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
|
||||
tools=TOOLS,
|
||||
@@ -862,384 +862,6 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
|
||||
return [script,div,js_resources,css_resources]
|
||||
|
||||
|
||||
def interactive_cum_flex_chart(theworkouts,promember=0,
|
||||
xparam='spm',
|
||||
yparam1='power',
|
||||
yparam2='hr',
|
||||
):
|
||||
|
||||
|
||||
therows = []
|
||||
for workout in theworkouts:
|
||||
f1 = workout.csvfilename
|
||||
rowdata = rdata(f1)
|
||||
if rowdata != 0:
|
||||
therows.append(rowdata.df)
|
||||
|
||||
datadf = pd.concat(therows)
|
||||
|
||||
axlabels = {
|
||||
'time': 'Time',
|
||||
'distance': 'Distance (m)',
|
||||
'hr': 'Heart Rate (bpm)',
|
||||
'spm': 'Stroke Rate (spm)',
|
||||
'pace': 'Pace (/500m)',
|
||||
'power': 'Power (Watt)',
|
||||
'averageforce': 'Average Drive Force (lbs)',
|
||||
'drivelength': 'Drive Length (m)',
|
||||
'peakforce': 'Peak Drive Force (lbs)',
|
||||
'forceratio': 'Average/Peak Drive Force Ratio',
|
||||
'driveenergy': 'Work per Stroke (J)',
|
||||
'drivespeed': 'Drive Speed (m/s)',
|
||||
'None': '',
|
||||
}
|
||||
|
||||
yparamname1 = axlabels[yparam1]
|
||||
yparamname2 = axlabels[yparam2]
|
||||
|
||||
yaxminima = {
|
||||
'hr':100,
|
||||
'spm':15,
|
||||
'pace': 1.0e3*210,
|
||||
'power': 0,
|
||||
'averageforce': 0,
|
||||
'peakforce': 0,
|
||||
'forceratio':0,
|
||||
'drivelength':0.5,
|
||||
'driveenergy': 0,
|
||||
'drivespeed': 0,
|
||||
}
|
||||
|
||||
yaxmaxima = {
|
||||
'hr':200,
|
||||
'spm':45,
|
||||
'pace':1.0e3*90,
|
||||
'power': 600,
|
||||
'averageforce':200,
|
||||
'peakforce':400,
|
||||
'forceratio':1,
|
||||
'drivelength':2.0,
|
||||
'driveenergy': 1000,
|
||||
'drivespeed':4,
|
||||
}
|
||||
|
||||
|
||||
datadf = dataprep.dataprep(datadf)
|
||||
|
||||
if yparam1 != 'pace' and yparam1 != 'time':
|
||||
datadf = datadf[datadf[yparam1] > 0]
|
||||
elif yparam1 == 'time':
|
||||
datadf = datadf[datadf['timesecs'] > 0]
|
||||
else:
|
||||
datadf = datadf[datadf['pseconds']>0]
|
||||
|
||||
if xparam != 'time' and xparam != 'pace':
|
||||
datadf = datadf[datadf[xparam] > 0]
|
||||
elif xparam == 'time':
|
||||
datadf = datadf[datadf['timesecs']>0]
|
||||
else:
|
||||
datadf = datadf[datadf['pseconds']>0]
|
||||
|
||||
if yparam2 != 'None':
|
||||
datadf = datadf[datadf[yparam2] > 0]
|
||||
|
||||
# check if dataframe not empty
|
||||
if datadf.empty:
|
||||
return ['','<p>No non-zero data in selection</p>','','']
|
||||
|
||||
|
||||
datadf['x1'] = datadf.ix[:,xparam]
|
||||
tseconds = datadf.ix[:,'timesecs']
|
||||
|
||||
|
||||
datadf['y1'] = datadf.ix[:,yparam1]
|
||||
if yparam2 != 'None':
|
||||
datadf['y2'] = datadf.ix[:,yparam2]
|
||||
else:
|
||||
datadf['y2'] = datadf['y1']
|
||||
|
||||
|
||||
if xparam=='time':
|
||||
xaxmax = tseconds.max()
|
||||
xaxmin = tseconds.min()
|
||||
xaxmax = 1.0e3*xaxmax
|
||||
xaxmin = 1.0e3*xaxmin
|
||||
elif xparam=='distance':
|
||||
xaxmax = datadf['x1'].max()
|
||||
xaxmin = datadf['x1'].min()
|
||||
else:
|
||||
xaxmax = yaxmaxima[xparam]
|
||||
xaxmin = yaxminima[xparam]
|
||||
|
||||
# average values
|
||||
if xparam != 'time':
|
||||
x1mean = datadf['x1'].mean()
|
||||
else:
|
||||
x1mean = 0
|
||||
|
||||
y1mean = datadf['y1'].mean()
|
||||
y2mean = datadf['y2'].mean()
|
||||
|
||||
if xparam != 'time':
|
||||
xvals = pd.Series(xaxmin+np.arange(100)*(xaxmax-xaxmin)/100.)
|
||||
else:
|
||||
xvals = pd.Series(np.arange(100))
|
||||
|
||||
x_axis_type = 'linear'
|
||||
y_axis_type = 'linear'
|
||||
if xparam == 'time':
|
||||
x_axis_type = 'datetime'
|
||||
|
||||
if yparam1 == 'pace':
|
||||
y_axis_type = 'datetime'
|
||||
y1mean = datadf.ix[:,'pseconds'].mean()
|
||||
|
||||
datadf['xname'] = xparam
|
||||
datadf['yname1'] = yparam1
|
||||
if yparam2 != 'None':
|
||||
datadf['yname2'] = yparam2
|
||||
else:
|
||||
datadf['yname2'] = yparam1
|
||||
|
||||
source = ColumnDataSource(
|
||||
datadf
|
||||
)
|
||||
|
||||
source2 = ColumnDataSource(
|
||||
datadf.copy()
|
||||
)
|
||||
|
||||
# Add hover to this comma-separated string and see what changes
|
||||
if (promember==1):
|
||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
||||
else:
|
||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
||||
|
||||
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
|
||||
tools=TOOLS,
|
||||
toolbar_location="above",
|
||||
toolbar_sticky=False)
|
||||
|
||||
x1means = Span(location=x1mean,dimension='height',line_color='green',
|
||||
line_dash=[6,6], line_width=2)
|
||||
|
||||
y1means = Span(location=y1mean,dimension='width',line_color='blue',
|
||||
line_dash=[6,6],line_width=2)
|
||||
y2means = y1means
|
||||
|
||||
xlabel = Label(x=370,y=130,x_units='screen',y_units='screen',
|
||||
text=xparam+": {x1mean:6.2f}".format(x1mean=x1mean),
|
||||
background_fill_alpha=.7,
|
||||
text_color='green',
|
||||
)
|
||||
|
||||
if (xparam != 'time') and (xparam != 'distance'):
|
||||
plot.add_layout(x1means)
|
||||
plot.add_layout(xlabel)
|
||||
|
||||
plot.add_layout(y1means)
|
||||
|
||||
y1label = Label(x=370,y=100,x_units='screen',y_units='screen',
|
||||
text=yparam1+": {y1mean:6.2f}".format(y1mean=y1mean),
|
||||
background_fill_alpha=.7,
|
||||
text_color='blue',
|
||||
)
|
||||
if yparam1 != 'time' and yparam1 != 'pace':
|
||||
plot.add_layout(y1label)
|
||||
|
||||
y2label = y1label
|
||||
plot.circle('x1','y1',source=source2,fill_alpha=0.3,line_color=None,
|
||||
legend=yparamname1,
|
||||
)
|
||||
|
||||
plot.xaxis.axis_label = axlabels[xparam]
|
||||
plot.yaxis.axis_label = axlabels[yparam1]
|
||||
|
||||
|
||||
yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1])
|
||||
plot.y_range = yrange1
|
||||
|
||||
if (xparam != 'time') and (xparam != 'distance'):
|
||||
xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam])
|
||||
plot.x_range = xrange1
|
||||
|
||||
if xparam == 'time':
|
||||
xrange1 = Range1d(start=xaxmin,end=xaxmax)
|
||||
plot.x_range = xrange1
|
||||
plot.xaxis[0].formatter = DatetimeTickFormatter(
|
||||
hours = ["%H"],
|
||||
minutes = ["%M"],
|
||||
seconds = ["%S"],
|
||||
days = ["0"],
|
||||
months = [""],
|
||||
years = [""]
|
||||
)
|
||||
|
||||
|
||||
|
||||
if yparam1 == 'pace':
|
||||
plot.yaxis[0].formatter = DatetimeTickFormatter(
|
||||
seconds = ["%S"],
|
||||
minutes = ["%M"]
|
||||
)
|
||||
|
||||
if yparam2 != 'None':
|
||||
yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2])
|
||||
plot.extra_y_ranges = {"yax2": yrange2}
|
||||
|
||||
plot.circle('x1','y2',color="red",y_range_name="yax2",
|
||||
legend=yparamname2,
|
||||
source=source2,fill_alpha=0.3,line_color=None)
|
||||
|
||||
plot.add_layout(LinearAxis(y_range_name="yax2",
|
||||
axis_label=axlabels[yparam2]),'right')
|
||||
|
||||
y2means = Span(location=y2mean,dimension='width',line_color='red',
|
||||
line_dash=[6,6],line_width=2,y_range_name="yax2")
|
||||
|
||||
|
||||
plot.add_layout(y2means)
|
||||
y2label = Label(x=370,y=70,x_units='screen',y_units='screen',
|
||||
text=yparam2+": {y2mean:6.2f}".format(y2mean=y2mean),
|
||||
background_fill_alpha=.7,
|
||||
text_color='red',
|
||||
)
|
||||
if yparam2 != 'pace' and yparam2 != 'time':
|
||||
plot.add_layout(y2label)
|
||||
|
||||
hover = plot.select(dict(type=HoverTool))
|
||||
|
||||
|
||||
hover.tooltips = OrderedDict([
|
||||
('Time','@ftime'),
|
||||
('Pace','@fpace'),
|
||||
('HR','@hr{int}'),
|
||||
('SPM','@spm{1.1}'),
|
||||
('Power','@power{int}'),
|
||||
])
|
||||
|
||||
hover.mode = 'mouse'
|
||||
|
||||
callback = CustomJS(args = dict(source=source,source2=source2,
|
||||
x1means=x1means,
|
||||
y1means=y1means,
|
||||
y1label=y1label,
|
||||
y2label=y2label,
|
||||
xlabel=xlabel,
|
||||
y2means=y2means), code="""
|
||||
var data = source.data
|
||||
var data2 = source2.data
|
||||
var x1 = data['x1']
|
||||
var y1 = data['y1']
|
||||
var y2 = data['y2']
|
||||
var spm1 = data['spm']
|
||||
var time1 = data['time']
|
||||
var pace1 = data['pace']
|
||||
var hr1 = data['hr']
|
||||
var distance1 = data['distance']
|
||||
var power1 = data['power']
|
||||
var xname = data['xname'][0]
|
||||
var yname1 = data['yname1'][0]
|
||||
var yname2 = data['yname2'][0]
|
||||
|
||||
var minspm = minspm.value
|
||||
var maxspm = maxspm.value
|
||||
var mindist = mindist.value
|
||||
var maxdist = maxdist.value
|
||||
var xm = 0
|
||||
var ym1 = 0
|
||||
var ym2 = 0
|
||||
|
||||
data2['x1'] = []
|
||||
data2['y1'] = []
|
||||
data2['y2'] = []
|
||||
data2['spm'] = []
|
||||
data2['time'] = []
|
||||
data2['pace'] = []
|
||||
data2['hr'] = []
|
||||
data2['distance'] = []
|
||||
data2['power'] = []
|
||||
data2['x1mean'] = []
|
||||
data2['y1mean'] = []
|
||||
data2['y2mean'] = []
|
||||
data2['xvals'] = []
|
||||
data2['y1vals'] = []
|
||||
data2['y2vals'] = []
|
||||
|
||||
for (i=0; i<x1.length; i++) {
|
||||
if (spm1[i]>=minspm && spm1[i]<=maxspm) {
|
||||
if (distance1[i]>=mindist && distance1[i]<=maxdist) {
|
||||
data2['x1'].push(x1[i])
|
||||
data2['y1'].push(y1[i])
|
||||
data2['y2'].push(y2[i])
|
||||
data2['spm'].push(spm1[i])
|
||||
data2['time'].push(time1[i])
|
||||
data2['pace'].push(pace1[i])
|
||||
data2['hr'].push(hr1[i])
|
||||
data2['distance'].push(distance1[i])
|
||||
data2['power'].push(power1[i])
|
||||
|
||||
xm += x1[i]
|
||||
ym1 += y1[i]
|
||||
ym2 += y2[i]
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xm /= data2['x1'].length
|
||||
ym1 /= data2['x1'].length
|
||||
ym2 /= data2['x1'].length
|
||||
|
||||
data2['x1mean'] = [xm,xm]
|
||||
data2['y1mean'] = [ym1,ym1]
|
||||
data2['y2mean'] = [ym2,ym2]
|
||||
x1means.location = xm
|
||||
y1means.location = ym1
|
||||
y2means.location = ym2
|
||||
y1label.text = yname1+': '+ym1.toFixed(2)
|
||||
y2label.text = yname2+': '+ym2.toFixed(2)
|
||||
xlabel.text = xname+': '+xm.toFixed(2)
|
||||
|
||||
source2.trigger('change');
|
||||
""")
|
||||
|
||||
slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1,
|
||||
title="Min SPM",callback=callback)
|
||||
callback.args["minspm"] = slider_spm_min
|
||||
|
||||
|
||||
slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1,
|
||||
title="Max SPM",callback=callback)
|
||||
callback.args["maxspm"] = slider_spm_max
|
||||
|
||||
distmax = 100+100*int(datadf['distance'].max()/100.)
|
||||
|
||||
slider_dist_min = Slider(start=0,end=distmax,value=0,step=1,
|
||||
title="Min Distance",callback=callback)
|
||||
callback.args["mindist"] = slider_dist_min
|
||||
|
||||
slider_dist_max = Slider(start=0,end=distmax,value=distmax,
|
||||
step=1,
|
||||
title="Max Distance",callback=callback)
|
||||
callback.args["maxdist"] = slider_dist_max
|
||||
|
||||
layout = layoutrow([layoutcolumn([slider_spm_min,
|
||||
slider_spm_max,
|
||||
slider_dist_min,
|
||||
slider_dist_max,
|
||||
],
|
||||
),
|
||||
plot])
|
||||
|
||||
script, div = components(layout)
|
||||
js_resources = INLINE.render_js()
|
||||
css_resources = INLINE.render_css()
|
||||
|
||||
|
||||
|
||||
return [script,div,js_resources,css_resources]
|
||||
|
||||
|
||||
|
||||
def interactive_flex_chart2(id=0,promember=0,
|
||||
@@ -1292,8 +914,8 @@ def interactive_flex_chart2(id=0,promember=0,
|
||||
'drivespeed':4,
|
||||
}
|
||||
|
||||
rowdata,row = dataprep.getrowdata(id=id)
|
||||
if rowdata == 0:
|
||||
rowdata,row = dataprep.getrowdata_db(id=id)
|
||||
if rowdata.empty:
|
||||
return "","CSV Data File Not Found"
|
||||
|
||||
workoutstateswork = [1,4,5,8,9,6,7]
|
||||
@@ -1302,16 +924,10 @@ def interactive_flex_chart2(id=0,promember=0,
|
||||
|
||||
if workstrokesonly:
|
||||
try:
|
||||
rowdata.df = rowdata.df[~rowdata.df[' WorkoutState'].isin(workoutstatesrest)]
|
||||
rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
rowdata = dataprep.dataprep(rowdata.df)
|
||||
|
||||
|
||||
# get user
|
||||
# u = User.objects.get(id=row.user.id)
|
||||
|
||||
rowdata['x1'] = rowdata.ix[:,xparam]
|
||||
|
||||
rowdata['y1'] = rowdata.ix[:,yparam1]
|
||||
@@ -1634,15 +1250,10 @@ def interactive_flex_chart2(id=0,promember=0,
|
||||
|
||||
def interactive_bar_chart(id=0,promember=0):
|
||||
# check if valid ID exists (workout exists)
|
||||
rowdata,row = dataprep.getrowdata(id=id)
|
||||
if rowdata == 0:
|
||||
rowdata,row = dataprep.getrowdata_db(id=id)
|
||||
if rowdata.empty:
|
||||
return "","CSV Data File Not Found"
|
||||
|
||||
rowdata = dataprep.dataprep(rowdata.df,bands=True,barchart=True)
|
||||
|
||||
|
||||
|
||||
|
||||
# Add hover to this comma-separated string and see what changes
|
||||
if (promember==1):
|
||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
||||
@@ -1653,8 +1264,6 @@ def interactive_bar_chart(id=0,promember=0):
|
||||
rowdata
|
||||
)
|
||||
|
||||
|
||||
|
||||
plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
|
||||
toolbar_sticky=False,
|
||||
plot_width=920,
|
||||
@@ -1751,19 +1360,14 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
|
||||
|
||||
|
||||
# check if valid ID exists (workout exists)
|
||||
rowdata1,row1 = dataprep.getrowdata(id=id1)
|
||||
rowdata2,row2 = dataprep.getrowdata(id=id2)
|
||||
if rowdata1 == 0:
|
||||
rowdata1,row1 = dataprep.getrowdata_db(id=id1)
|
||||
rowdata2,row2 = dataprep.getrowdata_db(id=id2)
|
||||
if rowdata1.empty:
|
||||
return "","CSV Data File Not Found"
|
||||
|
||||
if rowdata2 == 0:
|
||||
if rowdata2.empty:
|
||||
return "","CSV Data File Not Found"
|
||||
|
||||
rowdata1 = dataprep.dataprep(rowdata1.df)
|
||||
rowdata2 = dataprep.dataprep(rowdata2.df)
|
||||
|
||||
|
||||
|
||||
x1 = rowdata1.ix[:,xparam]
|
||||
x2 = rowdata2.ix[:,xparam]
|
||||
|
||||
@@ -1899,12 +1503,10 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
|
||||
|
||||
def interactive_otw_advanced_pace_chart(id=0,promember=0):
|
||||
# check if valid ID exists (workout exists)
|
||||
rowdata,row = dataprep.getrowdata(id=id)
|
||||
if rowdata == 0:
|
||||
rowdata,row = dataprep.getrowdata_db(id=id)
|
||||
if rowdata.empty:
|
||||
return "","CSV Data File Not Found"
|
||||
|
||||
rowdata = dataprep.dataprep(rowdata.df,otwpower=True)
|
||||
|
||||
# Add hover to this comma-separated string and see what changes
|
||||
if (promember==1):
|
||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
||||
|
||||
@@ -9,8 +9,31 @@ from django.forms.widgets import SplitDateTimeWidget
|
||||
from datetimewidget.widgets import DateTimeWidget
|
||||
import os
|
||||
|
||||
# Create your models here.
|
||||
from django.conf import settings
|
||||
from sqlalchemy import create_engine
|
||||
import sqlalchemy as sa
|
||||
from sqlite3 import OperationalError
|
||||
|
||||
user = settings.DATABASES['default']['USER']
|
||||
password = settings.DATABASES['default']['PASSWORD']
|
||||
database_name = settings.DATABASES['default']['NAME']
|
||||
host = settings.DATABASES['default']['HOST']
|
||||
port = settings.DATABASES['default']['PORT']
|
||||
|
||||
database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
|
||||
user=user,
|
||||
password=password,
|
||||
database_name=database_name,
|
||||
host=host,
|
||||
port=port,
|
||||
)
|
||||
|
||||
if settings.DEBUG or user=='':
|
||||
database_url = 'sqlite:///db.sqlite3'
|
||||
|
||||
engine = create_engine(database_url, echo=False)
|
||||
|
||||
# Create your models here.
|
||||
class Team(models.Model):
|
||||
name = models.CharField(max_length=150)
|
||||
notes = models.CharField(blank=True,max_length=200)
|
||||
@@ -120,7 +143,54 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
|
||||
if os.path.isfile(instance.csvfilename):
|
||||
os.remove(instance.csvfilename)
|
||||
|
||||
@receiver(models.signals.post_delete,sender=Workout)
|
||||
def auto_delete_strokedata_on_delete(sender, instance, **kwargs):
|
||||
if instance.id:
|
||||
query = sa.text('DELETE FROM strokedata WHERE workoutid={id};'.format(
|
||||
id=instance.id,
|
||||
))
|
||||
with engine.connect() as conn, conn.begin():
|
||||
try:
|
||||
result = conn.execute(query)
|
||||
except:
|
||||
print "Database Locked"
|
||||
|
||||
class StrokeData(models.Model):
|
||||
class Meta:
|
||||
db_table = 'strokedata'
|
||||
|
||||
workoutid = models.IntegerField(null=True)
|
||||
time = models.TimeField(null=True)
|
||||
timesecs = models.FloatField(null=True)
|
||||
hr = models.IntegerField(null=True)
|
||||
pace = models.TimeField(null=True)
|
||||
workoutstate = models.IntegerField(null=True,default=1)
|
||||
pseconds = models.FloatField(null=True)
|
||||
spm = models.FloatField(null=True)
|
||||
cumdist = models.FloatField(null=True)
|
||||
ftime = models.CharField(max_length=30)
|
||||
fpace = models.CharField(max_length=30)
|
||||
driveenergy = models.FloatField(null=True)
|
||||
power = models.FloatField(null=True)
|
||||
averageforce = models.FloatField(null=True)
|
||||
drivelength = models.FloatField(null=True)
|
||||
peakforce = models.FloatField(null=True)
|
||||
forceratio = models.FloatField(null=True)
|
||||
distance = models.FloatField(null=True)
|
||||
drivespeed = models.FloatField(null=True)
|
||||
hr_ut2 = models.IntegerField(null=True)
|
||||
hr_ut1 = models.IntegerField(null=True)
|
||||
hr_at = models.IntegerField(null=True)
|
||||
hr_tr = models.IntegerField(null=True)
|
||||
hr_an = models.IntegerField(null=True)
|
||||
hr_max = models.IntegerField(null=True)
|
||||
hr_bottom = models.IntegerField(null=True)
|
||||
x_right = models.FloatField(null=True)
|
||||
ergpace = models.TimeField(null=True)
|
||||
nowindpace = models.TimeField(null=True)
|
||||
equivergpower = models.FloatField(null=True)
|
||||
fergpace = models.CharField(max_length=30)
|
||||
fnowindpace = models.CharField(max_length=30)
|
||||
|
||||
class GraphImage(models.Model):
|
||||
filename = models.CharField(default='',max_length=150,blank=True,null=True)
|
||||
|
||||
280
rowers/ownapistuff.py
Normal file
280
rowers/ownapistuff.py
Normal file
@@ -0,0 +1,280 @@
|
||||
# Python
|
||||
import oauth2 as oauth
|
||||
import cgi
|
||||
import requests
|
||||
import requests.auth
|
||||
import json
|
||||
from django.utils import timezone
|
||||
from datetime import datetime
|
||||
import numpy as np
|
||||
from dateutil import parser
|
||||
import time
|
||||
import math
|
||||
from math import sin,cos,atan2,sqrt
|
||||
|
||||
import urllib
|
||||
import c2stuff
|
||||
|
||||
# Django
|
||||
from django.shortcuts import render_to_response
|
||||
from django.http import HttpResponseRedirect, HttpResponse,JsonResponse
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
# Project
|
||||
# from .models import Profile
|
||||
from rowingdata import rowingdata
|
||||
import pandas as pd
|
||||
from rowers.models import Rower,Workout
|
||||
|
||||
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, SPORTTRACKS_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI
|
||||
|
||||
TEST_CLIENT_ID = "1"
|
||||
TEST_CLIENT_SECRET = "aapnootmies"
|
||||
|
||||
TEST_REDIRECT_URI = "http://localhost:8000/rowers/test_callback"
|
||||
|
||||
def custom_exception_handler(exc,message):
|
||||
|
||||
response = {
|
||||
"errors": [
|
||||
{
|
||||
"code": str(exc),
|
||||
"detail": message,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
res = HttpResponse(message)
|
||||
res.status_code = 401
|
||||
res.json = json.dumps(response)
|
||||
|
||||
return res
|
||||
|
||||
def do_refresh_token(refreshtoken):
|
||||
client_auth = requests.auth.HTTPBasicAuth(TEST_CLIENT_ID, TEST_CLIENT_SECRET)
|
||||
post_data = {"grant_type": "refresh_token",
|
||||
"client_secret": TEST_CLIENT_SECRET,
|
||||
"client_id":TEST_CLIENT_ID,
|
||||
"refresh_token": refreshtoken,
|
||||
}
|
||||
headers = {'user-agent': 'sanderroosendaal',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'}
|
||||
|
||||
url = "http://localhost:8000/rowers/o/token"
|
||||
|
||||
response = requests.post(url,
|
||||
data=json.dumps(post_data),
|
||||
headers=headers)
|
||||
|
||||
token_json = response.json()
|
||||
thetoken = token_json['access_token']
|
||||
expires_in = token_json['expires_in']
|
||||
try:
|
||||
refresh_token = token_json['refresh_token']
|
||||
except KeyError:
|
||||
refresh_token = refreshtoken
|
||||
|
||||
return [thetoken,expires_in,refresh_token]
|
||||
|
||||
|
||||
def get_token(code):
|
||||
client_auth = requests.auth.HTTPBasicAuth(TEST_CLIENT_ID, TEST_CLIENT_SECRET)
|
||||
post_data = {"grant_type": "authorization_code",
|
||||
"code": code,
|
||||
"redirect_uri": TEST_REDIRECT_URI,
|
||||
"client_secret": TEST_CLIENT_SECRET,
|
||||
"client_id":TEST_CLIENT_ID,
|
||||
}
|
||||
headers = {'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'}
|
||||
|
||||
url = "http://localhost:8000/rowers/o/token/"
|
||||
|
||||
|
||||
response = requests.post(url,
|
||||
data=json.dumps(post_data),
|
||||
headers=headers)
|
||||
|
||||
print response.text
|
||||
token_json = response.json()
|
||||
thetoken = token_json['access_token']
|
||||
expires_in = token_json['expires_in']
|
||||
refresh_token = token_json['refresh_token']
|
||||
|
||||
return [thetoken,expires_in,refresh_token]
|
||||
|
||||
def make_authorization_url(request):
|
||||
# Generate a random string for the state parameter
|
||||
# Save it for use later to prevent xsrf attacks
|
||||
from uuid import uuid4
|
||||
state = str(uuid4())
|
||||
|
||||
params = {"client_id": TEST_CLIENT_ID,
|
||||
"response_type": "code",
|
||||
"redirect_uri": TEST_REDIRECT_URI,
|
||||
"scope":"write",
|
||||
"state":state}
|
||||
|
||||
|
||||
import urllib
|
||||
url = "http://localhost:8000/rowers/o/authorize" +urllib.urlencode(params)
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
def rower_ownapi_token_refresh(user):
|
||||
r = Rower.objects.get(user=user)
|
||||
res = do_refresh_token(r.ownapirefreshtoken)
|
||||
access_token = res[0]
|
||||
expires_in = res[1]
|
||||
refresh_token = res[2]
|
||||
expirydatetime = timezone.now()+timedelta(seconds=expires_in)
|
||||
|
||||
r = Rower.objects.get(user=user)
|
||||
r.ownapitoken = access_token
|
||||
r.tokenexpirydate = expirydatetime
|
||||
r.ownapirefreshtoken = refresh_token
|
||||
|
||||
r.save()
|
||||
return r.ownapitoken
|
||||
|
||||
def get_ownapi_workout_list(user):
|
||||
r = Rower.objects.get(user=user)
|
||||
if (r.ownapitoken == '') or (r.ownapitoken is None):
|
||||
s = "Token doesn't exist. Need to authorize"
|
||||
return custom_exception_handler(401,s)
|
||||
elif (timezone.now()>r.ownapitokenexpirydate):
|
||||
s = "Token expired. Needs to refresh."
|
||||
return custom_exception_handler(401,s)
|
||||
else:
|
||||
# ready to fetch. Hurray
|
||||
authorizationstring = str('Bearer ' + r.ownapitoken)
|
||||
headers = {'Authorization': authorizationstring,
|
||||
'user-agent': 'sanderroosendaal',
|
||||
'Content-Type': 'application/json'}
|
||||
url = "https://api.ownapi.mobi/api/v2/fitnessActivities"
|
||||
s = requests.get(url,headers=headers)
|
||||
|
||||
return s
|
||||
|
||||
|
||||
def get_ownapi_workout(user,ownapiid):
|
||||
r = Rower.objects.get(user=user)
|
||||
if (r.ownapitoken == '') or (r.ownapitoken is None):
|
||||
return custom_exception_handler(401,s)
|
||||
s = "Token doesn't exist. Need to authorize"
|
||||
elif (timezone.now()>r.ownapitokenexpirydate):
|
||||
s = "Token expired. Needs to refresh."
|
||||
return custom_exception_handler(401,s)
|
||||
else:
|
||||
# ready to fetch. Hurray
|
||||
authorizationstring = str('Bearer ' + r.ownapitoken)
|
||||
headers = {'Authorization': authorizationstring,
|
||||
'user-agent': 'sanderroosendaal',
|
||||
'Content-Type': 'application/json'}
|
||||
url = "https://api.ownapi.mobi/api/v2/fitnessActivities/"+str(ownapiid)
|
||||
s = requests.get(url,headers=headers)
|
||||
|
||||
return s
|
||||
|
||||
def createownapiworkoutdata(w):
|
||||
filename = w.csvfilename
|
||||
row = rowingdata(filename)
|
||||
averagehr = int(row.df[' HRCur (bpm)'].mean())
|
||||
maxhr = int(row.df[' HRCur (bpm)'].max())
|
||||
|
||||
# adding diff, trying to see if this is valid
|
||||
t = row.df.ix[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)']
|
||||
t[0] = t[1]
|
||||
d = row.df.ix[:,'cum_dist'].values
|
||||
d[0] = d[1]
|
||||
t = t.astype(int)
|
||||
d = d.astype(int)
|
||||
spm = row.df[' Cadence (stokes/min)'].astype(int)
|
||||
spm[0] = spm[1]
|
||||
hr = row.df[' HRCur (bpm)'].astype(int)
|
||||
|
||||
haslatlon=1
|
||||
|
||||
try:
|
||||
lat = row.df[' latitude'].values
|
||||
lon = row.df[' longitude'].values
|
||||
except KeyError:
|
||||
haslatlon = 0
|
||||
|
||||
haspower = 1
|
||||
try:
|
||||
power = row.df[' Power (watts)'].values
|
||||
except KeyError:
|
||||
haspower = 0
|
||||
|
||||
locdata = []
|
||||
hrdata = []
|
||||
spmdata = []
|
||||
distancedata = []
|
||||
powerdata = []
|
||||
|
||||
for i in range(len(t)):
|
||||
hrdata.append(t[i])
|
||||
hrdata.append(hr[i])
|
||||
distancedata.append(t[i])
|
||||
distancedata.append(d[i])
|
||||
spmdata.append(t[i])
|
||||
spmdata.append(spm[i])
|
||||
if haslatlon:
|
||||
locdata.append(t[i])
|
||||
locdata.append([lat[i],lon[i]])
|
||||
if haspower:
|
||||
powerdata.append(t[i])
|
||||
powerdata.append(power[i])
|
||||
|
||||
|
||||
if haslatlon:
|
||||
data = {
|
||||
"type": "Rowing",
|
||||
"name": w.name,
|
||||
# "start_time": str(w.date)+"T"+str(w.starttime)+"Z",
|
||||
"start_time": w.startdatetime.isoformat(),
|
||||
"total_distance": int(w.distance),
|
||||
"duration": int(max(t)),
|
||||
"notes": w.notes,
|
||||
"avg_heartrate": averagehr,
|
||||
"max_heartrate": maxhr,
|
||||
"location": locdata,
|
||||
"distance": distancedata,
|
||||
"cadence": spmdata,
|
||||
"heartrate": hrdata,
|
||||
}
|
||||
else:
|
||||
data = {
|
||||
"type": "Rowing",
|
||||
"name": w.name,
|
||||
# "start_time": str(w.date)+"T"+str(w.starttime)+"Z",
|
||||
"start_time": w.startdatetime.isoformat(),
|
||||
"total_distance": int(w.distance),
|
||||
"duration": int(max(t)),
|
||||
"notes": w.notes,
|
||||
"avg_heartrate": averagehr,
|
||||
"max_heartrate": maxhr,
|
||||
"distance": distancedata,
|
||||
"cadence": spmdata,
|
||||
"heartrate": hrdata,
|
||||
}
|
||||
|
||||
if haspower:
|
||||
data['power'] = powerdata
|
||||
|
||||
return data
|
||||
|
||||
def getidfromresponse(response):
|
||||
t = json.loads(response.text)
|
||||
uri = t['uris'][0]
|
||||
id = uri[len(uri)-13:len(uri)-5]
|
||||
|
||||
return int(id)
|
||||
|
||||
|
||||
21
rowers/permissions.py
Normal file
21
rowers/permissions.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from rest_framework import permissions
|
||||
from rowers.models import Rower
|
||||
|
||||
class IsOwnerOrReadOnly(permissions.BasePermission):
|
||||
"""
|
||||
Custom permission to only allow owners of an object to edit it.
|
||||
"""
|
||||
|
||||
def has_object_permission(self, request, view, obj):
|
||||
# Read permissions are allowed to any request,
|
||||
# so we'll always allow GET, HEAD or OPTIONS requests.
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
return True
|
||||
|
||||
# Write permissions are only allowed to the owner of the snippet.
|
||||
return obj.owner == request.user
|
||||
|
||||
class IsOwnerOrNot(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj):
|
||||
r = Rower.objects.get(user=request.user)
|
||||
return (obj.user == r)
|
||||
105
rowers/serializers.py
Normal file
105
rowers/serializers.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from rest_framework import serializers
|
||||
from rowers.models import Workout,Rower
|
||||
|
||||
import datetime
|
||||
|
||||
# Serializers define the API representation.
|
||||
class RowerSerializer(serializers.HyperlinkedModelSerializer):
|
||||
class Meta:
|
||||
model = Rower
|
||||
fields = (
|
||||
'weightcategory',
|
||||
'max',
|
||||
'rest',
|
||||
'ut2',
|
||||
'ut1',
|
||||
'at',
|
||||
'tr',
|
||||
'an',
|
||||
'ftp',
|
||||
)
|
||||
|
||||
|
||||
class WorkoutSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Workout
|
||||
fields = (
|
||||
'id',
|
||||
'name',
|
||||
'date',
|
||||
'workouttype',
|
||||
'starttime',
|
||||
'distance',
|
||||
'duration',
|
||||
'averagehr',
|
||||
'maxhr',
|
||||
'notes',
|
||||
'summary',
|
||||
)
|
||||
|
||||
def create(self, validated_data):
|
||||
r = Rower.objects.get(user=self.context['request'].user)
|
||||
d = validated_data['date']
|
||||
t = validated_data['starttime']
|
||||
rowdatetime = datetime.datetime(d.year,
|
||||
d.month,
|
||||
d.day,
|
||||
t.hour,
|
||||
t.minute,
|
||||
t.second)
|
||||
w = Workout(user=r,
|
||||
name=validated_data['name'],
|
||||
date=validated_data['date'],
|
||||
workouttype=validated_data['workouttype'],
|
||||
duration=validated_data['duration'],
|
||||
distance=validated_data['distance'],
|
||||
weightcategory=r.weightcategory,
|
||||
starttime=validated_data['starttime'],
|
||||
csvfilename='',
|
||||
notes=validated_data['notes'],
|
||||
uploadedtoc2=0,
|
||||
summary=validated_data['summary'],
|
||||
averagehr=validated_data['averagehr'],
|
||||
maxhr=validated_data['maxhr'],
|
||||
startdatetime=rowdatetime)
|
||||
w.save()
|
||||
return w
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
d = validated_data['date']
|
||||
t = validated_data['starttime']
|
||||
rowdatetime = datetime.datetime(d.year,
|
||||
d.month,
|
||||
d.day,
|
||||
t.hour,
|
||||
t.minute,
|
||||
t.second)
|
||||
|
||||
|
||||
instance.name=validated_data['name']
|
||||
instance.date=validated_data['date']
|
||||
instance.workouttype=validated_data['workouttype']
|
||||
instance.duration=validated_data['duration']
|
||||
instance.distance=validated_data['distance']
|
||||
instance.starttime=validated_data['starttime']
|
||||
instance.notes=validated_data['notes']
|
||||
instance.summary=validated_data['summary']
|
||||
instance.averagehr=validated_data['averagehr']
|
||||
instance.maxhr=validated_data['maxhr']
|
||||
instance.startdatetime=rowdatetime
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
class StrokeDataSerializer(serializers.Serializer):
|
||||
workoutid = serializers.IntegerField
|
||||
strokedata = serializers.JSONField
|
||||
|
||||
def create(self, validated_data):
|
||||
"""
|
||||
Create and enter a new set of stroke data into the DB
|
||||
"""
|
||||
|
||||
# do something
|
||||
print "fake serializer"
|
||||
return 1
|
||||
|
||||
25
rowers/templates/strokedata_form.html
Normal file
25
rowers/templates/strokedata_form.html
Normal file
@@ -0,0 +1,25 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Change Rower {% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if form.errors %}
|
||||
<p style="color: red;">
|
||||
Please correct the error{{ form.errors|pluralize }} below.
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="grid_12 alpha">
|
||||
<h1>Stroke Data for workout {{ id }}</h1>
|
||||
|
||||
<form enctype="multipart/form-data" action="/rowers/api/workouts/{{ id }}/strokedata" method="post">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
</table>
|
||||
{% csrf_token %}
|
||||
<div class="grid_2 prefix_2 suffix_2">
|
||||
<input class="button green" type="submit" value="POST">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
1
rowers/testdata/strokedata.txt
vendored
Normal file
1
rowers/testdata/strokedata.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
from django.test import TestCase, Client
|
||||
from django.test import TestCase, Client,override_settings
|
||||
from django.test.client import RequestFactory
|
||||
from .views import checkworkoutuser,c2_open
|
||||
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
|
||||
@@ -24,6 +24,11 @@ import numpy as np
|
||||
from rowers import urls
|
||||
from rowers.views import error500_view,error404_view,error400_view,error403_view
|
||||
|
||||
from dataprep import delete_strokedata
|
||||
|
||||
|
||||
|
||||
|
||||
class DjangoTestCase(TestCase, MockTestCase):
|
||||
def _pre_setup(self):
|
||||
MockTestCase.setUp(self)
|
||||
@@ -33,6 +38,7 @@ class DjangoTestCase(TestCase, MockTestCase):
|
||||
def _post_teardown(self):
|
||||
TestCase._post_teardown(self)
|
||||
MockTestCase.tearDown(self)
|
||||
delete_strokedata(1)
|
||||
|
||||
# Create your tests here.
|
||||
|
||||
@@ -149,6 +155,7 @@ class STObjects(DjangoTestCase):
|
||||
|
||||
class TestErrorPages(TestCase):
|
||||
def test_error_handlers(self):
|
||||
|
||||
self.assertTrue(urls.handler404.endswith('.error404_view'))
|
||||
self.assertTrue(urls.handler500.endswith('.error500_view'))
|
||||
factory = RequestFactory()
|
||||
@@ -315,13 +322,12 @@ class DataTest(TestCase):
|
||||
|
||||
form = DocumentsForm(form_data,file_data)
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
|
||||
f.close()
|
||||
|
||||
u = User.objects.get(username='john')
|
||||
r = Rower.objects.get(user=u)
|
||||
|
||||
|
||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
||||
hrut1=r.ut1,hrat=r.at,
|
||||
hrtr=r.tr,hran=r.an,ftp=r.ftp)
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
from django.conf import settings
|
||||
from django.conf.urls import url, include
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from models import Workout,Rower
|
||||
|
||||
from rest_framework import routers, serializers, viewsets,permissions
|
||||
from rest_framework.urlpatterns import format_suffix_patterns
|
||||
|
||||
from . import views
|
||||
from django.contrib.auth import views as auth_views
|
||||
@@ -8,6 +14,20 @@ from django.conf.urls import (
|
||||
handler400, handler403, handler404, handler500,
|
||||
)
|
||||
|
||||
from rowers.permissions import IsOwnerOrNot,IsOwnerOrReadOnly
|
||||
from rowers.serializers import WorkoutSerializer,RowerSerializer
|
||||
|
||||
class WorkoutViewSet(viewsets.ModelViewSet):
|
||||
queryset = Workout.objects.all().order_by("-date", "-starttime")
|
||||
serializer_class = WorkoutSerializer
|
||||
permission_classes = (IsOwnerOrNot,)
|
||||
|
||||
|
||||
# Routers provide an easy way of automatically determining the URL conf.
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'api/workouts',WorkoutViewSet)
|
||||
#router.register(r'api/rower',RowerViewSet)
|
||||
|
||||
handler500 = 'views.error500_view'
|
||||
handler404 = 'views.error404_view'
|
||||
handler400 = 'views.error400_view'
|
||||
@@ -16,6 +36,11 @@ handler403 = 'views.error403_view'
|
||||
urlpatterns = [
|
||||
# url(r'^password_change/$',auth_views.password_change),
|
||||
# url(r'^password_change_done/$',auth_views.password_change_done),
|
||||
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
|
||||
url(r'^', include(router.urls)),
|
||||
url(r'^api-docs$', views.schema_view),
|
||||
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
url(r'^api/workouts/(\d+)/strokedata$',views.strokedatajson),
|
||||
url(r'^testbokeh$',views.testbokeh),
|
||||
url(r'^500/$', TemplateView.as_view(template_name='500.html'),name='500'),
|
||||
url(r'^404/$', TemplateView.as_view(template_name='404.html'),name='404'),
|
||||
@@ -138,6 +163,8 @@ urlpatterns = [
|
||||
url(r'^workout/(?P<id>\d+)/flexchart$',views.workout_flexchart3_view),
|
||||
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>\w+.*)/(?P<plottype>\w+.*)$',views.workout_comparison_view2),
|
||||
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>\w+.*)/$',views.workout_comparison_view2),
|
||||
url(r'^test\_callback',views.rower_process_testcallback),
|
||||
url(r'^workout/(\d+)/test\_strokedata$',views.strokedataform),
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
@@ -146,3 +173,5 @@ if settings.DEBUG:
|
||||
url(r'^testreverse/$',views.test_reverse_view),
|
||||
url(r'^c2listug/$',views.c2listdebug_view),
|
||||
]
|
||||
|
||||
#urlpatterns = format_suffix_patterns(urlpatterns)
|
||||
|
||||
224
rowers/views.py
224
rowers/views.py
@@ -15,7 +15,7 @@ from django.utils import timezone,translation
|
||||
from django.core.mail import send_mail, BadHeaderError
|
||||
from rowers.forms import EmailForm, RegistrationForm, RegistrationFormTermsOfService,RegistrationFormUniqueEmail,CNsummaryForm,UpdateWindForm,UpdateStreamForm
|
||||
from rowers.forms import PredictedPieceForm,DateRangeForm,DeltaDaysForm
|
||||
from rowers.forms import SummaryStringForm,IntervalUpdateForm
|
||||
from rowers.forms import SummaryStringForm,IntervalUpdateForm,StrokeDataForm
|
||||
from rowers.models import Workout, User, Rower, WorkoutForm
|
||||
from rowers.models import RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm
|
||||
import StringIO
|
||||
@@ -29,10 +29,14 @@ from c2stuff import C2NoTokenError
|
||||
from iso8601 import ParseError
|
||||
import stravastuff
|
||||
import sporttracksstuff
|
||||
import ownapistuff
|
||||
from ownapistuff import TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_REDIRECT_URI
|
||||
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET
|
||||
from rowsandall_app.settings import SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI, SPORTTRACKS_CLIENT_SECRET
|
||||
import requests
|
||||
import json
|
||||
from rest_framework.renderers import JSONRenderer
|
||||
from rest_framework.parsers import JSONParser
|
||||
from rowsandall_app.rows import handle_uploaded_file
|
||||
from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv
|
||||
from rowers.tasks import handle_sendemail_unrecognized
|
||||
@@ -64,6 +68,16 @@ queue = django_rq.get_queue('default')
|
||||
queuelow = django_rq.get_queue('low')
|
||||
queuehigh = django_rq.get_queue('low')
|
||||
|
||||
from rest_framework_swagger.views import get_swagger_view
|
||||
from rest_framework.renderers import JSONRenderer
|
||||
from rest_framework.parsers import JSONParser
|
||||
from rest_framework.response import Response
|
||||
from rowers.serializers import RowerSerializer,WorkoutSerializer
|
||||
from rest_framework import status,permissions,generics
|
||||
from rest_framework.decorators import api_view
|
||||
|
||||
from permissions import IsOwnerOrNot
|
||||
|
||||
import plots
|
||||
import mailprocessing
|
||||
|
||||
@@ -77,6 +91,10 @@ USER_LANGUAGE = 'en-US'
|
||||
|
||||
from interactiveplots import *
|
||||
|
||||
schema_view = get_swagger_view(title='Rowsandall API (Unstable)')
|
||||
|
||||
|
||||
|
||||
def error500_view(request):
|
||||
response = render_to_response('500.html', {},
|
||||
context_instance = RequestContext(request))
|
||||
@@ -1153,6 +1171,7 @@ def rower_process_stravacallback(request):
|
||||
return imports_view(request,successmessage=successmessage)
|
||||
|
||||
|
||||
|
||||
@login_required()
|
||||
def rower_process_sporttrackscallback(request):
|
||||
code = request.GET['code']
|
||||
@@ -1174,6 +1193,26 @@ def rower_process_sporttrackscallback(request):
|
||||
successmessage = "Tokens stored. Good to go"
|
||||
return imports_view(request,successmessage=successmessage)
|
||||
|
||||
@login_required()
|
||||
def rower_process_testcallback(request):
|
||||
code = request.GET['code']
|
||||
res = ownapistuff.get_token(code)
|
||||
|
||||
|
||||
access_token = res[0]
|
||||
expires_in = res[1]
|
||||
refresh_token = res[2]
|
||||
expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)
|
||||
|
||||
text = "Access Token:\n"
|
||||
text += access_token
|
||||
|
||||
text += "\n\nRefresh Token:\n"
|
||||
text += refresh_token
|
||||
|
||||
return HttpResponse(text)
|
||||
|
||||
|
||||
@login_required()
|
||||
def histo_all(request,theuser=0):
|
||||
promember=0
|
||||
@@ -1867,7 +1906,7 @@ def workouts_view(request,message='',successmessage='',
|
||||
'enddate':enddate,
|
||||
})
|
||||
except Rower.DoesNotExist:
|
||||
return HttpResponse("Admin has no rower instance")
|
||||
return HttpResponse("User has no rower instance")
|
||||
|
||||
@user_passes_test(promember,login_url="/login")
|
||||
def workout_comparison_list(request,id=0,message='',successmessage='',
|
||||
@@ -1942,7 +1981,7 @@ def workout_comparison_list(request,id=0,message='',successmessage='',
|
||||
'enddate':enddate,
|
||||
})
|
||||
except Rower.DoesNotExist:
|
||||
return HttpResponse("Admin has no rower instance")
|
||||
return HttpResponse("User has no rower instance")
|
||||
|
||||
def workout_view(request,id=0):
|
||||
try:
|
||||
@@ -2859,17 +2898,16 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
||||
u = request.user
|
||||
r = Rower.objects.get(user=u)
|
||||
|
||||
res = interactive_chart(id)
|
||||
script = res[0]
|
||||
div = res[1]
|
||||
|
||||
rowdata = rdata(f1)
|
||||
hascoordinates = 1
|
||||
try:
|
||||
latitude = rowdata.df[' latitude']
|
||||
except KeyError:
|
||||
hascoordinates = 0
|
||||
|
||||
if rowdata != 0:
|
||||
try:
|
||||
latitude = rowdata.df[' latitude']
|
||||
except KeyError,AttributeError:
|
||||
hascoordinates = 0
|
||||
else:
|
||||
hascoordinates = 0
|
||||
|
||||
if hascoordinates:
|
||||
res = googlemap_chart(rowdata.df[' latitude'],
|
||||
rowdata.df[' longitude'],
|
||||
@@ -2892,8 +2930,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
||||
'gmscript': gmscript,
|
||||
'gmdiv': gmdiv,
|
||||
})
|
||||
# 'interactiveplot':script,
|
||||
# 'the_div':div})
|
||||
|
||||
else:
|
||||
return render(request, 'workout_form.html',
|
||||
{'form':form,
|
||||
@@ -2905,8 +2942,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
||||
'gmscript': gmscript,
|
||||
'gmdiv': gmdiv,
|
||||
})
|
||||
# 'interactiveplot':script,
|
||||
# 'the_div':div})
|
||||
|
||||
|
||||
except Workout.DoesNotExist:
|
||||
form = WorkoutForm(
|
||||
@@ -3644,6 +3680,8 @@ def workout_upload_view(request,message=""):
|
||||
startdatetime=workoutstartdatetime)
|
||||
|
||||
w.save()
|
||||
# put stroke data in database
|
||||
res = dataprep.dataprep(row.df,id=w.id,bands=True,barchart=True,otwpower=True)
|
||||
|
||||
# Make Plot
|
||||
if (make_plot):
|
||||
@@ -3716,7 +3754,7 @@ def workout_upload_view(request,message=""):
|
||||
'user-agent': 'sanderroosendaal',
|
||||
'Content-Type': 'application/json'}
|
||||
import urllib
|
||||
url = "https://log.concept2.com/api/users/%s/results" % (c2userid)
|
||||
url = "httpvs://log.concept2.com/api/users/%s/results" % (c2userid)
|
||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
||||
|
||||
# response = c2stuff.workout_c2_upload(request.user,w)
|
||||
@@ -4077,7 +4115,7 @@ def dashboard_view(request,message="",successmessage=""):
|
||||
'successmessage':successmessage})
|
||||
|
||||
except Rower.DoesNotExist:
|
||||
return HttpResponse("Admin has no rower instance")
|
||||
return HttpResponse("User has no rower instance")
|
||||
|
||||
|
||||
@login_required()
|
||||
@@ -4104,7 +4142,7 @@ def graphs_view(request):
|
||||
{'graphs1': g[0:5],
|
||||
'graphs2': g[5:10]})
|
||||
except Rower.DoesNotExist:
|
||||
return HttpResponse("Admin has no rower instance")
|
||||
return HttpResponse("User has no rower instance")
|
||||
|
||||
|
||||
def graph_show_view(request,id):
|
||||
@@ -4435,4 +4473,150 @@ def rower_edit_view(request,message=""):
|
||||
except Rower.DoesNotExist:
|
||||
return HttpResponse("This user doesn't exist")
|
||||
|
||||
|
||||
class JSONResponse(HttpResponse):
|
||||
def __init__(self, data, **kwargs):
|
||||
content = JSONRenderer().render(data)
|
||||
kwargs['content_type'] = 'application/json'
|
||||
super(JSONResponse, self).__init__(content, **kwargs)
|
||||
|
||||
def totimestamp(dt, epoch=datetime.datetime(1970,1,1,tzinfo=tz('UTC'))):
|
||||
td = dt - epoch
|
||||
# return td.total_seconds()
|
||||
return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
|
||||
|
||||
def trydf(df,aantal,column):
|
||||
try:
|
||||
s = df[column]
|
||||
if len(s) != aantal:
|
||||
return np.zeros(aantal)
|
||||
if not np.issubdtype(s,np.number):
|
||||
return np.zeros(aantal)
|
||||
except KeyError:
|
||||
s = np.zeros(aantal)
|
||||
|
||||
return s
|
||||
|
||||
@login_required()
|
||||
def strokedataform(request,id=0):
|
||||
if request.method == 'GET':
|
||||
form = StrokeDataForm()
|
||||
return render(request, 'strokedata_form.html',
|
||||
{
|
||||
'form':form,
|
||||
'id':id,
|
||||
})
|
||||
elif request.method == 'POST':
|
||||
form = StrokeDataForm()
|
||||
|
||||
return render(request, 'strokedata_form.html',
|
||||
{
|
||||
'form':form,
|
||||
'id':id,
|
||||
})
|
||||
|
||||
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
@csrf_exempt
|
||||
@login_required()
|
||||
def strokedatajson(request,id):
|
||||
try:
|
||||
row = Workout.objects.get(id=id)
|
||||
if (checkworkoutuser(request.user,row)==False):
|
||||
return HttpResponse("Permission error")
|
||||
except Workout.DoesNotExist:
|
||||
return HttpResponse("Workout doesn't exist")
|
||||
try:
|
||||
id = int(id)
|
||||
except ValueError:
|
||||
return HttpResponse("Not a valid workout number")
|
||||
|
||||
|
||||
if request.method == 'GET':
|
||||
columns = ['spm','timesecs','hr','pseconds','power','distance']
|
||||
datadf = dataprep.getsmallrowdata_db(columns,ids=[id])
|
||||
return JSONResponse(datadf)
|
||||
|
||||
if request.method == 'POST':
|
||||
checkdata,r = dataprep.getrowdata_db(id=row.id)
|
||||
if not checkdata.empty:
|
||||
return "Not OK 1"
|
||||
# strokedata = request.POST['strokedata']
|
||||
print request.body
|
||||
received_json_data = json.loads(request.body)
|
||||
# checking/validating and cleaning
|
||||
try:
|
||||
strokedata = json.loads(received_json_data['strokedata'])
|
||||
except:
|
||||
return HttpResponse("Not OK 2")
|
||||
|
||||
df = pd.DataFrame(strokedata)
|
||||
df.index = df.index.astype(int)
|
||||
df.sort_index(inplace=True)
|
||||
# time, hr, pace, spm, power, drivelength, distance, drivespeed, dragfactor, strokerecoverytime, averagedriveforce, peakdriveforce, lapidx
|
||||
time = df['timesecs']
|
||||
aantal = len(time)
|
||||
pace = df['pseconds']
|
||||
if len(pace) != aantal:
|
||||
return "Not OK"
|
||||
distance = df['distance']
|
||||
if len(distance) != aantal:
|
||||
return "Not OK 3"
|
||||
|
||||
spm = df['spm']
|
||||
if len(spm) != aantal:
|
||||
return "Not OK 4"
|
||||
|
||||
res = dataprep.testdata(time,distance,pace,spm)
|
||||
if not res:
|
||||
return HttpResponse("Not OK 5")
|
||||
|
||||
power = trydf(df,aantal,'power')
|
||||
drivelength = trydf(df,aantal,'drivelength')
|
||||
drivespeed = trydf(df,aantal,'drivespeed')
|
||||
dragfactor = trydf(df,aantal,'dragfactor')
|
||||
drivetime = trydf(df,aantal,'drivetime')
|
||||
strokerecoverytime = trydf(df,aantal,'strokerecoverytime')
|
||||
averagedriveforce = trydf(df,aantal,'averagedriveforce')
|
||||
peakdriveforce = trydf(df,aantal,'peakdriveforce')
|
||||
lapidx = trydf(df,aantal,'lapidx')
|
||||
hr = trydf(df,aantal,'hr')
|
||||
|
||||
starttime = totimestamp(row.startdatetime)+time
|
||||
unixtime = starttime+time
|
||||
|
||||
data = pd.DataFrame({'TimeStamp (sec)':unixtime,
|
||||
' Horizontal (meters)': distance,
|
||||
' Cadence (stokes/min)':spm,
|
||||
' HRCur (bpm)':hr,
|
||||
' DragFactor':dragfactor,
|
||||
' Stroke500mPace (sec/500m)':pace,
|
||||
' Power (watts)':power,
|
||||
' DriveLength (meters)':drivelength,
|
||||
' DriveTime (ms)':drivetime,
|
||||
' StrokeRecoveryTime (ms)':strokerecoverytime,
|
||||
' AverageDriveForce (lbs)':averagedriveforce,
|
||||
' PeakDriveForce (lbs)':peakdriveforce,
|
||||
' lapIdx':lapidx,
|
||||
' ElapsedTime (sec)':time,
|
||||
})
|
||||
|
||||
|
||||
timestr = row.startdatetime.strftime("%Y%m%d-%H%M%S")
|
||||
csvfilename ='media/Import_'+timestr+'.csv'
|
||||
|
||||
res = data.to_csv(csvfilename,index_label='index')
|
||||
row.csvfilename = csvfilename
|
||||
row.save()
|
||||
|
||||
r = Rower.objects.get(user=request.user)
|
||||
|
||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
||||
hrut1=r.ut1,hrat=r.at,
|
||||
hrtr=r.tr,hran=r.an,ftp=r.ftp)
|
||||
rowdata = rdata(row.csvfilename,rower=rr).df
|
||||
|
||||
datadf = dataprep.dataprep(rowdata,id=row.id,bands=True,barchart=True,otwpower=True)
|
||||
# mangling
|
||||
|
||||
#
|
||||
return HttpResponse("OK")
|
||||
|
||||
@@ -47,16 +47,28 @@ INSTALLED_APPS = [
|
||||
'translation_manager',
|
||||
'debug_toolbar',
|
||||
'django_mailbox',
|
||||
'rest_framework',
|
||||
'rest_framework_swagger',
|
||||
'oauth2_provider',
|
||||
'corsheaders',
|
||||
]
|
||||
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'oauth2_provider.backends.OAuth2Backend',
|
||||
# Uncomment following if you want to access the admin
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = [
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'oauth2_provider.middleware.OAuth2TokenMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'debug_toolbar.middleware.DebugToolbarMiddleware',
|
||||
@@ -86,6 +98,8 @@ TEMPLATES = [
|
||||
]
|
||||
|
||||
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
|
||||
WSGI_APPLICATION = 'rowsandall_app.wsgi.application'
|
||||
|
||||
|
||||
@@ -230,5 +244,26 @@ EMAIL_USE_TLS = True
|
||||
FORECAST_IO_KEY = "bc8196fbd89f11375c7dfc8aa6323c72"
|
||||
GMAPIKEY = "AIzaSyAgu1w9QSthaGPMLp8y9JedPoMc9sfEgJ8"
|
||||
|
||||
# test
|
||||
# OAUTH2
|
||||
|
||||
OAUTH2_PROVIDER = {
|
||||
# this is the list of available scopes
|
||||
'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'}
|
||||
}
|
||||
|
||||
|
||||
# REST Framework
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
# Use Django's standard `django.contrib.auth` permissions,
|
||||
# or allow read-only access for unauthenticated users.
|
||||
'DEFAULT_PERMISSION_CLASSES': [
|
||||
'rest_framework.permissions.IsAuthenticated'
|
||||
],
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
|
||||
),
|
||||
'PAGE_SIZE': 20,
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ from rowers import views as rowersviews
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^admin/', admin.site.urls),
|
||||
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
# url('^', include('django.contrib.auth.urls')),
|
||||
url(r'^$',rootview),
|
||||
url(r'^version/$',version),
|
||||
|
||||
Reference in New Issue
Block a user