Merge branch 'feature/mergeworkoutcreation' into develop
This commit is contained in:
@@ -447,7 +447,6 @@ def get_username(access_token):
|
|||||||
|
|
||||||
me_json = response.json()
|
me_json = response.json()
|
||||||
|
|
||||||
|
|
||||||
return me_json['data']['username']
|
return me_json['data']['username']
|
||||||
|
|
||||||
# Get user id, having access token
|
# Get user id, having access token
|
||||||
@@ -463,9 +462,12 @@ def get_userid(access_token):
|
|||||||
|
|
||||||
|
|
||||||
me_json = response.json()
|
me_json = response.json()
|
||||||
|
try:
|
||||||
|
res = me_json['data']['id']
|
||||||
return me_json['data']['id']
|
except KeyError:
|
||||||
|
res = 0
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
# For debugging purposes
|
# For debugging purposes
|
||||||
def process_callback(request):
|
def process_callback(request):
|
||||||
@@ -515,16 +517,19 @@ def workout_c2_upload(user,w):
|
|||||||
def rower_c2_token_refresh(user):
|
def rower_c2_token_refresh(user):
|
||||||
r = Rower.objects.get(user=user)
|
r = Rower.objects.get(user=user)
|
||||||
res = do_refresh_token(r.c2refreshtoken)
|
res = do_refresh_token(r.c2refreshtoken)
|
||||||
access_token = res[0]
|
if res[0]:
|
||||||
expires_in = res[1]
|
access_token = res[0]
|
||||||
refresh_token = res[2]
|
expires_in = res[1]
|
||||||
expirydatetime = timezone.now()+timedelta(seconds=expires_in)
|
refresh_token = res[2]
|
||||||
|
expirydatetime = timezone.now()+timedelta(seconds=expires_in)
|
||||||
|
|
||||||
r = Rower.objects.get(user=user)
|
r = Rower.objects.get(user=user)
|
||||||
r.c2token = access_token
|
r.c2token = access_token
|
||||||
r.tokenexpirydate = expirydatetime
|
r.tokenexpirydate = expirydatetime
|
||||||
r.c2refreshtoken = refresh_token
|
r.c2refreshtoken = refresh_token
|
||||||
|
|
||||||
r.save()
|
r.save()
|
||||||
return r.c2token
|
return r.c2token
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from celery import Celery
|
|||||||
# on Windows, so I use Celery on my notebook.
|
# on Windows, so I use Celery on my notebook.
|
||||||
|
|
||||||
# set the default Django settings module for the 'celery' program.
|
# set the default Django settings module for the 'celery' program.
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rowsandall_app.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rowsandall_app.settings_dev')
|
||||||
|
|
||||||
from django.conf import settings # noqa
|
from django.conf import settings # noqa
|
||||||
|
|
||||||
@@ -25,6 +25,8 @@ app.config_from_object('django.conf:settings')
|
|||||||
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
||||||
|
|
||||||
|
|
||||||
|
database_url = 'sqlite:///db.sqlite3'
|
||||||
|
|
||||||
@app.task(bind=True)
|
@app.task(bind=True)
|
||||||
def debug_task(self):
|
def debug_task(self):
|
||||||
print('Request: {0!r}'.format(self.request))
|
print('Request: {0!r}'.format(self.request))
|
||||||
|
|||||||
@@ -15,11 +15,25 @@ from pytz import timezone as tz,utc
|
|||||||
|
|
||||||
from django.utils.timezone import get_current_timezone
|
from django.utils.timezone import get_current_timezone
|
||||||
thetimezone = get_current_timezone()
|
thetimezone = get_current_timezone()
|
||||||
|
from rowingdata import (
|
||||||
|
TCXParser,RowProParser,ErgDataParser,TCXParserNoHR,
|
||||||
|
BoatCoachParser,RowPerfectParser,BoatCoachAdvancedParser,
|
||||||
|
MysteryParser,
|
||||||
|
painsledDesktopParser,speedcoachParser,ErgStickParser,
|
||||||
|
SpeedCoach2Parser,FITParser,fitsummarydata,
|
||||||
|
make_cumvalues,
|
||||||
|
summarydata,get_file_type,
|
||||||
|
)
|
||||||
|
|
||||||
|
from rowers.models import Team
|
||||||
|
|
||||||
|
import os
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
from tasks import handle_sendemail_unrecognized
|
||||||
|
|
||||||
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
|
||||||
@@ -205,115 +219,55 @@ def timedeltaconv(x):
|
|||||||
|
|
||||||
return dt
|
return dt
|
||||||
|
|
||||||
# Create new workout from file and store it in the database
|
# Processes painsled CSV file to database
|
||||||
# This routine should be used everywhere in views.py and mailprocessing.py
|
def save_workout_database(f2,r,dosmooth=True,workouttype='rower',
|
||||||
# Currently there is code duplication
|
dosummary=True,title='Workout',
|
||||||
def new_workout_from_file(r,f2,
|
notes='',totaldist=0,totaltime=0):
|
||||||
workouttype='rower',
|
message = None
|
||||||
title='Workout',
|
powerperc = 100*np.array([r.pw_ut2,
|
||||||
notes=''):
|
r.pw_ut1,
|
||||||
|
r.pw_at,
|
||||||
fileformat = get_file_type(f2)
|
r.pw_tr,r.pw_an])/r.ftp
|
||||||
summary = ''
|
|
||||||
# handle non-Painsled
|
|
||||||
if (fileformat != 'csv'):
|
|
||||||
# handle RowPro:
|
|
||||||
if (fileformat == 'rp'):
|
|
||||||
row = RowProParser(f2)
|
|
||||||
# handle TCX
|
|
||||||
if (fileformat == 'tcx'):
|
|
||||||
row = TCXParser(f2)
|
|
||||||
|
|
||||||
# handle Mystery
|
|
||||||
if (fileformat == 'mystery'):
|
|
||||||
row = MysteryParser(f2)
|
|
||||||
|
|
||||||
# handle TCX no HR
|
|
||||||
if (fileformat == 'tcxnohr'):
|
|
||||||
row = TCXParserNoHR(f2)
|
|
||||||
|
|
||||||
# handle ErgData
|
|
||||||
if (fileformat == 'ergdata'):
|
|
||||||
row = ErgDataParser(f2)
|
|
||||||
|
|
||||||
# handle BoatCoach
|
|
||||||
if (fileformat == 'boatcoach'):
|
|
||||||
row = BoatCoachParser(f2)
|
|
||||||
|
|
||||||
# handle painsled desktop
|
|
||||||
if (fileformat == 'painsleddesktop'):
|
|
||||||
row = painsledDesktopParser(f2)
|
|
||||||
|
|
||||||
# handle speed coach GPS
|
|
||||||
if (fileformat == 'speedcoach'):
|
|
||||||
row = speedcoachParser(f2)
|
|
||||||
|
|
||||||
# handle speed coach GPS 2
|
|
||||||
if (fileformat == 'speedcoach2'):
|
|
||||||
row = SpeedCoach2Parser(f2)
|
|
||||||
summary = row.allstats()
|
|
||||||
|
|
||||||
|
|
||||||
# handle ErgStick
|
|
||||||
if (fileformat == 'ergstick'):
|
|
||||||
row = ErgStickParser(f2)
|
|
||||||
|
|
||||||
# handle FIT
|
|
||||||
if (fileformat == 'fit'):
|
|
||||||
row = FITParser(f2)
|
|
||||||
s = fitsummarydata(f2)
|
|
||||||
s.setsummary()
|
|
||||||
summary = s.summarytext
|
|
||||||
|
|
||||||
|
|
||||||
f_to_be_deleted = f2
|
|
||||||
# should delete file
|
|
||||||
f2 = f2[:-4]+'o.csv'
|
|
||||||
row.write_csv(f2,gzip=True)
|
|
||||||
|
|
||||||
#os.remove(f2)
|
|
||||||
try:
|
|
||||||
os.remove(f_to_be_deleted)
|
|
||||||
except:
|
|
||||||
os.remove(f_to_be_deleted+'.gz')
|
|
||||||
|
|
||||||
# make workout and put in database
|
# make workout and put in database
|
||||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
||||||
hrut1=r.ut1,hrat=r.at,
|
hrut1=r.ut1,hrat=r.at,
|
||||||
hrtr=r.tr,hran=r.an,ftp=r.ftp)
|
hrtr=r.tr,hran=r.an,ftp=r.ftp,
|
||||||
|
powerperc=powerperc,powerzones=r.powerzones)
|
||||||
row = rdata(f2,rower=rr)
|
row = rdata(f2,rower=rr)
|
||||||
if row == 0:
|
if row == 0:
|
||||||
return HttpResponse("Error: CSV Data File Not Found")
|
return (0,'Error: CSV data file not found')
|
||||||
|
|
||||||
# auto smoothing
|
if dosmooth:
|
||||||
pace = row.df[' Stroke500mPace (sec/500m)'].values
|
# auto smoothing
|
||||||
velo = 500./pace
|
pace = row.df[' Stroke500mPace (sec/500m)'].values
|
||||||
|
velo = 500./pace
|
||||||
|
|
||||||
f = row.df['TimeStamp (sec)'].diff().mean()
|
f = row.df['TimeStamp (sec)'].diff().mean()
|
||||||
windowsize = 2*(int(10./(f)))+1
|
windowsize = 2*(int(10./(f)))+1
|
||||||
if not 'originalvelo' in row.df:
|
if not 'originalvelo' in row.df:
|
||||||
row.df['originalvelo'] = velo
|
row.df['originalvelo'] = velo
|
||||||
|
|
||||||
if windowsize > 3 and windowsize<len(velo):
|
if windowsize > 3 and windowsize<len(velo):
|
||||||
velo2 = savgol_filter(velo,windowsize,3)
|
velo2 = savgol_filter(velo,windowsize,3)
|
||||||
else:
|
else:
|
||||||
velo2 = velo
|
velo2 = velo
|
||||||
|
|
||||||
velo3 = pd.Series(velo2)
|
velo3 = pd.Series(velo2)
|
||||||
velo3 = velo3.replace([-np.inf,np.inf],np.nan)
|
velo3 = velo3.replace([-np.inf,np.inf],np.nan)
|
||||||
velo3 = velo3.fillna(method='ffill')
|
velo3 = velo3.fillna(method='ffill')
|
||||||
|
|
||||||
pace2 = 500./abs(velo3)
|
pace2 = 500./abs(velo3)
|
||||||
|
|
||||||
|
row.df[' Stroke500mPace (sec/500m)'] = pace2
|
||||||
|
|
||||||
row.df[' Stroke500mPace (sec/500m)'] = pace2
|
row.df = row.df.fillna(0)
|
||||||
|
|
||||||
row.df = row.df.fillna(0)
|
row.write_csv(f2,gzip=True)
|
||||||
|
try:
|
||||||
row.write_csv(f2,gzip=True)
|
os.remove(f2)
|
||||||
try:
|
except:
|
||||||
os.remove(f2)
|
pass
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# recalculate power data
|
# recalculate power data
|
||||||
if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides':
|
if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides':
|
||||||
@@ -323,24 +277,32 @@ def new_workout_from_file(r,f2,
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if fileformat != 'fit' and summary == '':
|
|
||||||
summary = row.summary()
|
|
||||||
summary += '\n'
|
|
||||||
summary += row.intervalstats_painsled()
|
|
||||||
|
|
||||||
averagehr = row.df[' HRCur (bpm)'].mean()
|
averagehr = row.df[' HRCur (bpm)'].mean()
|
||||||
maxhr = row.df[' HRCur (bpm)'].max()
|
maxhr = row.df[' HRCur (bpm)'].max()
|
||||||
|
|
||||||
totaldist = row.df['cum_dist'].max()
|
if totaldist == 0:
|
||||||
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
|
totaldist = row.df['cum_dist'].max()
|
||||||
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
|
if totaltime == 0:
|
||||||
|
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
|
||||||
|
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
hours = int(totaltime/3600.)
|
hours = int(totaltime/3600.)
|
||||||
|
if hours>23:
|
||||||
|
message = 'Warning: The workout duration was longer than 23 hours'
|
||||||
|
hours = 23
|
||||||
|
|
||||||
minutes = int((totaltime - 3600.*hours)/60.)
|
minutes = int((totaltime - 3600.*hours)/60.)
|
||||||
seconds = int(totaltime - 3600.*hours - 60.*minutes)
|
seconds = int(totaltime - 3600.*hours - 60.*minutes)
|
||||||
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
|
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
|
||||||
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
|
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
|
||||||
|
|
||||||
|
if dosummary:
|
||||||
|
summary = row.summary()
|
||||||
|
summary += '\n'
|
||||||
|
summary += row.intervalstats()
|
||||||
|
|
||||||
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
|
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
|
||||||
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
|
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
|
||||||
workoutstartdatetime = thetimezone.localize(row.rowdatetime).astimezone(utc)
|
workoutstartdatetime = thetimezone.localize(row.rowdatetime).astimezone(utc)
|
||||||
@@ -360,11 +322,152 @@ def new_workout_from_file(r,f2,
|
|||||||
maxhr=maxhr,averagehr=averagehr,
|
maxhr=maxhr,averagehr=averagehr,
|
||||||
startdatetime=workoutstartdatetime)
|
startdatetime=workoutstartdatetime)
|
||||||
|
|
||||||
w.save()
|
|
||||||
# put stroke data in database
|
|
||||||
res = dataprep(row.df,id=w.id,bands=True,barchart=True,otwpower=True,empower=True)
|
|
||||||
|
|
||||||
return True
|
w.save()
|
||||||
|
|
||||||
|
ts = Team.objects.filter(rower=r)
|
||||||
|
|
||||||
|
for t in ts:
|
||||||
|
w.team.add(t)
|
||||||
|
|
||||||
|
# put stroke data in database
|
||||||
|
res = dataprep(row.df,id=w.id,bands=True,
|
||||||
|
barchart=True,otwpower=True,empower=True)
|
||||||
|
|
||||||
|
return (w.id,message)
|
||||||
|
|
||||||
|
def handle_nonpainsled(f2,fileformat,summary=''):
|
||||||
|
# handle RowPro:
|
||||||
|
if (fileformat == 'rp'):
|
||||||
|
row = RowProParser(f2)
|
||||||
|
# handle TCX
|
||||||
|
if (fileformat == 'tcx'):
|
||||||
|
row = TCXParser(f2)
|
||||||
|
|
||||||
|
# handle Mystery
|
||||||
|
if (fileformat == 'mystery'):
|
||||||
|
row = MysteryParser(f2)
|
||||||
|
|
||||||
|
# handle TCX no HR
|
||||||
|
if (fileformat == 'tcxnohr'):
|
||||||
|
row = TCXParserNoHR(f2)
|
||||||
|
|
||||||
|
# handle RowPerfect
|
||||||
|
if (fileformat == 'rowperfect3'):
|
||||||
|
row = RowPerfectParser(f2)
|
||||||
|
|
||||||
|
# handle ErgData
|
||||||
|
if (fileformat == 'ergdata'):
|
||||||
|
row = ErgDataParser(f2)
|
||||||
|
|
||||||
|
# handle Mike
|
||||||
|
if (fileformat == 'bcmike'):
|
||||||
|
row = BoatCoachAdvancedParser(f2)
|
||||||
|
|
||||||
|
# handle BoatCoach
|
||||||
|
if (fileformat == 'boatcoach'):
|
||||||
|
row = BoatCoachParser(f2)
|
||||||
|
|
||||||
|
# handle painsled desktop
|
||||||
|
if (fileformat == 'painsleddesktop'):
|
||||||
|
row = painsledDesktopParser(f2)
|
||||||
|
|
||||||
|
# handle speed coach GPS
|
||||||
|
if (fileformat == 'speedcoach'):
|
||||||
|
row = speedcoachParser(f2)
|
||||||
|
|
||||||
|
# handle speed coach GPS 2
|
||||||
|
if (fileformat == 'speedcoach2'):
|
||||||
|
row = SpeedCoach2Parser(f2)
|
||||||
|
try:
|
||||||
|
summary = row.allstats()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# handle ErgStick
|
||||||
|
if (fileformat == 'ergstick'):
|
||||||
|
row = ErgStickParser(f2)
|
||||||
|
|
||||||
|
# handle FIT
|
||||||
|
if (fileformat == 'fit'):
|
||||||
|
row = FITParser(f2)
|
||||||
|
s = fitsummarydata(f2)
|
||||||
|
s.setsummary()
|
||||||
|
summary = s.summarytext
|
||||||
|
|
||||||
|
|
||||||
|
f_to_be_deleted = f2
|
||||||
|
# should delete file
|
||||||
|
f2 = f2[:-4]+'o.csv'
|
||||||
|
row.write_csv(f2,gzip=True)
|
||||||
|
|
||||||
|
#os.remove(f2)
|
||||||
|
try:
|
||||||
|
os.remove(f_to_be_deleted)
|
||||||
|
except:
|
||||||
|
os.remove(f_to_be_deleted+'.gz')
|
||||||
|
|
||||||
|
return (f2,summary)
|
||||||
|
|
||||||
|
# Create new workout from file and store it in the database
|
||||||
|
# This routine should be used everywhere in views.py and mailprocessing.py
|
||||||
|
# Currently there is code duplication
|
||||||
|
def new_workout_from_file(r,f2,
|
||||||
|
workouttype='rower',
|
||||||
|
title='Workout',
|
||||||
|
notes=''):
|
||||||
|
message = None
|
||||||
|
fileformat = get_file_type(f2)
|
||||||
|
summary = ''
|
||||||
|
if len(fileformat)==3 and fileformat[0]=='zip':
|
||||||
|
f_to_be_deleted = f2
|
||||||
|
with zipfile.ZipFile(f2) as z:
|
||||||
|
# for now, we're getting only the first file
|
||||||
|
# from the NK zip file (issue #69 on bitbucket)
|
||||||
|
f2 = z.extract(z.namelist()[0],path='media/')
|
||||||
|
fileformat = fileformat[2]
|
||||||
|
os.remove(f_to_be_deleted)
|
||||||
|
|
||||||
|
# Some people try to upload Concept2 logbook summaries
|
||||||
|
if fileformat == 'c2log':
|
||||||
|
os.remove(f2)
|
||||||
|
message = "This C2 logbook summary does not contain stroke data. Please download the Export Stroke Data file from the workout details on the C2 logbook."
|
||||||
|
return (0,message)
|
||||||
|
|
||||||
|
# Some people try to upload RowPro summary logs
|
||||||
|
if fileformat == 'rowprolog':
|
||||||
|
os.remove(f2)
|
||||||
|
message = "This RowPro logbook summary does not contain stroke data. Please use the Stroke Data CSV file for the individual workout in your log."
|
||||||
|
return (0,message)
|
||||||
|
|
||||||
|
# Sometimes people try an unsupported file type.
|
||||||
|
# Send an email to info@rowsandall.com with the file attached
|
||||||
|
# for me to check if it is a bug, or a new file type
|
||||||
|
# worth supporting
|
||||||
|
if fileformat == 'unknown':
|
||||||
|
message = "We couldn't recognize the file type"
|
||||||
|
if settings.DEBUG:
|
||||||
|
res = handle_sendemail_unrecognized.delay(f2,
|
||||||
|
request.user.email)
|
||||||
|
|
||||||
|
else:
|
||||||
|
res = queuehigh.enqueue(handle_sendemail_unrecognized,
|
||||||
|
f2,request.user.email)
|
||||||
|
return (0,'message')
|
||||||
|
|
||||||
|
# handle non-Painsled by converting it to painsled compatible CSV
|
||||||
|
if (fileformat != 'csv'):
|
||||||
|
f2,summary = handle_nonpainsled(f2,fileformat,summary=summary)
|
||||||
|
|
||||||
|
|
||||||
|
dosummary = (fileformat != 'fit')
|
||||||
|
id,message = save_workout_database(f2,r,
|
||||||
|
workouttype=workouttype,
|
||||||
|
dosummary=dosummary,
|
||||||
|
title=title)
|
||||||
|
|
||||||
|
return (id,message)
|
||||||
|
|
||||||
# Compare the data from the CSV file and the database
|
# Compare the data from the CSV file and the database
|
||||||
# Currently only calculates number of strokes. To be expanded with
|
# Currently only calculates number of strokes. To be expanded with
|
||||||
|
|||||||
@@ -32,10 +32,14 @@ class CNsummaryForm(forms.Form):
|
|||||||
class SummaryStringForm(forms.Form):
|
class SummaryStringForm(forms.Form):
|
||||||
intervalstring = forms.CharField(max_length=255,label='Workout Description')
|
intervalstring = forms.CharField(max_length=255,label='Workout Description')
|
||||||
|
|
||||||
|
# little window to type a Team invitation code
|
||||||
|
class TeamInviteCodeForm(forms.Form):
|
||||||
|
code = forms.CharField(max_length=10,label='Team Code',
|
||||||
|
)
|
||||||
|
|
||||||
# Used for testing the POST API for StrokeData
|
# Used for testing the POST API for StrokeData
|
||||||
class StrokeDataForm(forms.Form):
|
class StrokeDataForm(forms.Form):
|
||||||
strokedata = forms.CharField(label='payload',
|
strokedata = forms.CharField(label='payload',widget=forms.Textarea)
|
||||||
widget=forms.Textarea)
|
|
||||||
|
|
||||||
# The form used for uploading files
|
# The form used for uploading files
|
||||||
class DocumentsForm(forms.Form):
|
class DocumentsForm(forms.Form):
|
||||||
|
|||||||
@@ -159,15 +159,19 @@ def processattachments_debug():
|
|||||||
# Need to move the code to a subroutine used both in views.py and here
|
# Need to move the code to a subroutine used both in views.py and here
|
||||||
def make_new_workout_from_email(rr,f2,name,cntr=0):
|
def make_new_workout_from_email(rr,f2,name,cntr=0):
|
||||||
workouttype = 'rower'
|
workouttype = 'rower'
|
||||||
f2 = f2.name
|
|
||||||
fileformat = get_file_type('media/'+f2)
|
try:
|
||||||
|
f2 = f2.name
|
||||||
|
fileformat = get_file_type('media/'+f2)
|
||||||
|
except IOError:
|
||||||
|
f2 = f2.name+'.gz'
|
||||||
|
fileformat = get_file_type('media/'+f2)
|
||||||
|
|
||||||
if len(fileformat)==3 and fileformat[0]=='zip':
|
if len(fileformat)==3 and fileformat[0]=='zip':
|
||||||
f_to_be_deleted = f2
|
f_to_be_deleted = f2
|
||||||
with zipfile.ZipFile('media/'+f2) as z:
|
with zipfile.ZipFile('media/'+f2) as z:
|
||||||
f2 = z.extract(z.namelist()[0],path='media/')[6:]
|
f2 = z.extract(z.namelist()[0],path='media/')[6:]
|
||||||
fileformat = fileformat[2]
|
fileformat = fileformat[2]
|
||||||
print f2
|
|
||||||
|
|
||||||
if fileformat == 'unknown':
|
if fileformat == 'unknown':
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
@@ -182,149 +186,42 @@ def make_new_workout_from_email(rr,f2,name,cntr=0):
|
|||||||
|
|
||||||
summary = ''
|
summary = ''
|
||||||
# handle non-Painsled
|
# handle non-Painsled
|
||||||
if (fileformat != 'csv'):
|
if fileformat != 'csv':
|
||||||
# handle RowPro:
|
f3,summary = dataprep.handle_nonpainsled('media/'+f2,fileformat,summary)
|
||||||
if (fileformat == 'rp'):
|
else:
|
||||||
row = RowProParser('media/'+f2)
|
f3 = 'media/'+f2
|
||||||
|
|
||||||
# handle TCX
|
|
||||||
if (fileformat == 'tcx'):
|
|
||||||
row = TCXParser('media/'+f2)
|
|
||||||
|
|
||||||
# handle Mystery
|
|
||||||
if (fileformat == 'mystery'):
|
|
||||||
row = MysteryParser('media/'+f2)
|
|
||||||
|
|
||||||
# handle TCX no HR
|
|
||||||
if (fileformat == 'tcxnohr'):
|
|
||||||
row = TCXParserNoHR('media/'+f2)
|
|
||||||
|
|
||||||
# handle ErgData
|
|
||||||
if (fileformat == 'ergdata'):
|
|
||||||
row = ErgDataParser('media/'+f2)
|
|
||||||
|
|
||||||
# handle BoatCoach
|
|
||||||
if (fileformat == 'boatcoach'):
|
|
||||||
row = BoatCoachParser('media/'+f2)
|
|
||||||
|
|
||||||
# handle painsled desktop
|
|
||||||
if (fileformat == 'painsleddesktop'):
|
|
||||||
row = painsledDesktopParser('media/'+f2)
|
|
||||||
|
|
||||||
# handle speed coach GPS
|
|
||||||
if (fileformat == 'speedcoach'):
|
|
||||||
row = speedcoachParser('media/'+f2)
|
|
||||||
|
|
||||||
# handle speed coach GPS 2
|
|
||||||
if (fileformat == 'speedcoach2'):
|
|
||||||
row = SpeedCoach2Parser('media/'+f2)
|
|
||||||
|
|
||||||
# handle ErgStick
|
|
||||||
if (fileformat == 'ergstick'):
|
|
||||||
row = ErgStickParser('media/'+f2)
|
|
||||||
|
|
||||||
# handle FIT
|
|
||||||
if (fileformat == 'fit'):
|
|
||||||
row = FITParser('media/'+f2)
|
|
||||||
s = fitsummarydata('media/'+f2)
|
|
||||||
s.setsummary()
|
|
||||||
summary = s.summarytext
|
|
||||||
|
|
||||||
timestr = time.strftime("%Y%m%d-%H%M%S")
|
|
||||||
filename = timestr+str(cntr)+'o.csv'
|
|
||||||
row.write_csv('media/'+filename,gzip=True)
|
|
||||||
f2 = filename
|
|
||||||
|
|
||||||
# make workout and put in database
|
# make workout and put in database
|
||||||
#r = rrower(hrmax=rr.max,hrut2=rr.ut2,
|
#r = rrower(hrmax=rr.max,hrut2=rr.ut2,
|
||||||
# hrut1=rr.ut1,hrat=rr.at,
|
# hrut1=rr.ut1,hrat=rr.at,
|
||||||
# hrtr=rr.tr,hran=rr.an,ftp=r.ftp)
|
# hrtr=rr.tr,hran=rr.an,ftp=r.ftp)
|
||||||
row = rdata('media/'+f2) #,rower=r)
|
row = rdata(f3) #,rower=r)
|
||||||
if row == 0:
|
if row == 0:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
# change filename
|
# change filename
|
||||||
if f2[:5] != 'media':
|
if f2[:5] != 'media':
|
||||||
timestr = time.strftime("%Y%m%d-%H%M%S")
|
timestr = time.strftime("%Y%m%d-%H%M%S")
|
||||||
f2 = 'media/'+timestr+str(cntr)+'o.csv'
|
f2 = 'media/'+timestr+str(cntr)+'o.csv'
|
||||||
|
|
||||||
# auto smoothing
|
|
||||||
pace = row.df[' Stroke500mPace (sec/500m)'].values
|
|
||||||
velo = 500./pace
|
|
||||||
|
|
||||||
f = row.df['TimeStamp (sec)'].diff().mean()
|
|
||||||
windowsize = 2*(int(10./(f)))+1
|
|
||||||
|
|
||||||
if not 'originalvelo' in row.df:
|
|
||||||
row.df['originalvelo'] = velo
|
|
||||||
|
|
||||||
if windowsize > 3:
|
|
||||||
velo2 = savgol_filter(velo,windowsize,3)
|
|
||||||
else:
|
|
||||||
velo2 = velo
|
|
||||||
|
|
||||||
pace2 = 500./abs(velo2)
|
|
||||||
row.df[' Stroke500mPace (sec/500m)'] = pace2
|
|
||||||
|
|
||||||
row.df = row.df.fillna(0)
|
|
||||||
|
|
||||||
row.write_csv(f2,gzip=True)
|
row.write_csv(f2,gzip=True)
|
||||||
|
dosummary = (fileformat != 'fit')
|
||||||
|
|
||||||
# recalculate power data
|
|
||||||
if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides':
|
|
||||||
try:
|
|
||||||
row.erg_recalculatepower()
|
|
||||||
# row.spm_fromtimestamps()
|
|
||||||
row.write_csv(f2,gzip=True)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if fileformat != 'fit':
|
|
||||||
summary = row.summary()
|
|
||||||
summary += '\n'
|
|
||||||
summary += row.intervalstats_painsled()
|
|
||||||
|
|
||||||
averagehr = row.df[' HRCur (bpm)'].mean()
|
|
||||||
maxhr = row.df[' HRCur (bpm)'].max()
|
|
||||||
|
|
||||||
totaldist = row.df['cum_dist'].max()
|
|
||||||
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
|
|
||||||
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
|
|
||||||
|
|
||||||
|
|
||||||
hours = int(totaltime/3600.)
|
|
||||||
minutes = int((totaltime - 3600.*hours)/60.)
|
|
||||||
seconds = int(totaltime - 3600.*hours - 60.*minutes)
|
|
||||||
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
|
|
||||||
|
|
||||||
|
|
||||||
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
|
|
||||||
|
|
||||||
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
|
|
||||||
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
|
|
||||||
|
|
||||||
notes = 'imported through email'
|
|
||||||
if name == '':
|
if name == '':
|
||||||
name = 'imported through email'
|
name = 'imported through email'
|
||||||
|
|
||||||
w = Workout(user=rr,name=name,date=workoutdate,
|
id,message = dataprep.save_workout_database(f2,rr,
|
||||||
workouttype=workouttype,
|
workouttype=workouttype,
|
||||||
duration=duration,distance=totaldist,
|
dosummary=dosummary,
|
||||||
weightcategory=rr.weightcategory,
|
title=name,
|
||||||
starttime=workoutstarttime,
|
notes='imported through email')
|
||||||
csvfilename=f2,notes=notes,summary=summary,
|
|
||||||
maxhr=maxhr,averagehr=averagehr,
|
|
||||||
startdatetime=row.rowdatetime)
|
|
||||||
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
# put stroke data in database
|
return id
|
||||||
res = dataprep.dataprep(row.df,id=w.id,
|
|
||||||
bands=True,barchart=True,
|
|
||||||
otwpower=True,empower=True)
|
|
||||||
|
|
||||||
|
|
||||||
return w.id
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ from rowsandall_app.settings import BASE_DIR
|
|||||||
from rowingdata import rower as rrower
|
from rowingdata import rower as rrower
|
||||||
from rowingdata import main as rmain
|
from rowingdata import main as rmain
|
||||||
from rowingdata import rowingdata as rrdata
|
from rowingdata import rowingdata as rrdata
|
||||||
from rowingdata import TCXParser,RowProParser,ErgDataParser,TCXParserNoHR
|
|
||||||
from rowingdata import MysteryParser
|
|
||||||
from rowingdata import painsledDesktopParser,speedcoachParser,ErgStickParser
|
|
||||||
from rowingdata import SpeedCoach2Parser,FITParser,fitsummarydata
|
|
||||||
from rowingdata import make_cumvalues
|
from rowingdata import make_cumvalues
|
||||||
from rowingdata import summarydata,get_file_type
|
from rowingdata import summarydata,get_file_type
|
||||||
|
|
||||||
|
|||||||
@@ -377,9 +377,14 @@ class Workout(models.Model):
|
|||||||
date = self.date
|
date = self.date
|
||||||
name = self.name
|
name = self.name
|
||||||
|
|
||||||
str = date.strftime('%Y-%m-%d')+'_'+name
|
try:
|
||||||
|
stri = date.strftime('%Y-%m-%d')+'_'+name
|
||||||
|
except AttributeError:
|
||||||
|
stri = str(date)+'_'+name
|
||||||
|
|
||||||
|
|
||||||
return str
|
|
||||||
|
return stri
|
||||||
|
|
||||||
# delete files belonging to workout instance
|
# delete files belonging to workout instance
|
||||||
# related GraphImage objects should be deleted automatically
|
# related GraphImage objects should be deleted automatically
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ from rowers.tasks import (
|
|||||||
inviteduration = 14 # days
|
inviteduration = 14 # days
|
||||||
|
|
||||||
def update_team(t,name,manager,private,notes):
|
def update_team(t,name,manager,private,notes):
|
||||||
|
if t.manager != manager:
|
||||||
|
return (0,'You are not the manager of this team')
|
||||||
try:
|
try:
|
||||||
t.name = name
|
t.name = name
|
||||||
t.manager = manager
|
t.manager = manager
|
||||||
|
|||||||
@@ -100,7 +100,25 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h3>Manual code redeem</h3>
|
||||||
|
<div class="grid_4 alpha">
|
||||||
|
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
|
||||||
|
{% if form.errors %}
|
||||||
|
<p style\"color: red;">
|
||||||
|
Please correct the error{{ form.errors|pluralize }} below.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% csrf_token %}
|
||||||
|
<table>
|
||||||
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="formbutton" class="grid_1 suffix_1 omega">
|
||||||
|
<input class="button green" type="submit" value="Submit">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p> </p>
|
<p> </p>
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ urlpatterns = [
|
|||||||
url(r'^workout/(?P<id>\d+)/export/c/(?P<message>\w+.*)/s/(?P<successmessage>\w+.*)$',views.workout_edit_view),
|
url(r'^workout/(?P<id>\d+)/export/c/(?P<message>\w+.*)/s/(?P<successmessage>\w+.*)$',views.workout_edit_view),
|
||||||
url(r'^workout/(?P<id>\d+)/edit/c/(?P<message>.+.*)$',views.workout_edit_view),
|
url(r'^workout/(?P<id>\d+)/edit/c/(?P<message>.+.*)$',views.workout_edit_view),
|
||||||
url(r'^workout/(?P<id>\d+)/edit/s/(?P<successmessage>.+.*)$',views.workout_edit_view),
|
url(r'^workout/(?P<id>\d+)/edit/s/(?P<successmessage>.+.*)$',views.workout_edit_view),
|
||||||
url(r'^workout/(\d+)/edit$',views.workout_edit_view),
|
url(r'^workout/(?P<id>\d+)/edit$',views.workout_edit_view),
|
||||||
url(r'^workout/(?P<id>\d+)/advanced/c/(?P<message>.+.*)$',views.workout_advanced_view),
|
url(r'^workout/(?P<id>\d+)/advanced/c/(?P<message>.+.*)$',views.workout_advanced_view),
|
||||||
url(r'^workout/(?P<id>\d+)/advanced/s/(?P<successmessage>.+.*)$',views.workout_advanced_view),
|
url(r'^workout/(?P<id>\d+)/advanced/s/(?P<successmessage>.+.*)$',views.workout_advanced_view),
|
||||||
url(r'^workout/(?P<id>\d+)/geeky$',views.workout_geeky_view),
|
url(r'^workout/(?P<id>\d+)/geeky$',views.workout_geeky_view),
|
||||||
|
|||||||
585
rowers/views.py
585
rowers/views.py
@@ -67,13 +67,8 @@ from shutil import copyfile
|
|||||||
from rowingdata import rower as rrower
|
from rowingdata import rower as rrower
|
||||||
from rowingdata import main as rmain
|
from rowingdata import main as rmain
|
||||||
from rowingdata import rowingdata as rrdata
|
from rowingdata import rowingdata as rrdata
|
||||||
from rowingdata import TCXParser,RowProParser,ErgDataParser,TCXParserNoHR
|
|
||||||
from rowingdata import BoatCoachParser,RowPerfectParser,BoatCoachAdvancedParser
|
|
||||||
from rowingdata import MysteryParser
|
|
||||||
from rowingdata import painsledDesktopParser,speedcoachParser,ErgStickParser
|
|
||||||
from rowingdata import SpeedCoach2Parser,FITParser,fitsummarydata
|
|
||||||
from rowingdata import make_cumvalues
|
from rowingdata import make_cumvalues
|
||||||
from rowingdata import summarydata,get_file_type
|
from rowingdata import summarydata
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
@@ -451,69 +446,27 @@ def add_workout_from_strokedata(user,importid,data,strokedata,
|
|||||||
compression='gzip')
|
compression='gzip')
|
||||||
|
|
||||||
|
|
||||||
# make workout
|
|
||||||
powerperc = 100*np.array([r.pw_ut2,
|
|
||||||
r.pw_ut1,
|
|
||||||
r.pw_at,
|
|
||||||
r.pw_tr,r.pw_an])/r.ftp
|
|
||||||
|
|
||||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
|
||||||
hrut1=r.ut1,hrat=r.at,
|
|
||||||
hrtr=r.tr,hran=r.an,ftp=r.ftp,
|
|
||||||
powerperc=powerperc,
|
|
||||||
powerzones=r.powerzones,
|
|
||||||
)
|
|
||||||
row = rdata(csvfilename,rower=rr)
|
|
||||||
|
|
||||||
averagehr = row.df[' HRCur (bpm)'].mean()
|
|
||||||
maxhr = row.df[' HRCur (bpm)'].max()
|
|
||||||
totaldist = row.df['cum_dist'].max()
|
|
||||||
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
|
|
||||||
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
|
|
||||||
|
|
||||||
# with Concept2
|
# with Concept2
|
||||||
if source=='c2':
|
if source=='c2':
|
||||||
try:
|
try:
|
||||||
totaldist = data['distance']
|
totaldist = data['distance']
|
||||||
totaltime = data['time']/10.
|
totaltime = data['time']/10.
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
totaldist = 0
|
||||||
|
totaltime = 0
|
||||||
|
else:
|
||||||
|
totaldist = 0
|
||||||
|
totaltime = 0
|
||||||
|
|
||||||
|
id,message = dataprep.save_workout_database(csvfilename,r,
|
||||||
|
workouttype=workouttype,
|
||||||
|
title=title,notes=comments,
|
||||||
|
totaldist=totaldist,
|
||||||
|
totaltime=totaltime)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
hours = int(totaltime/3600.)
|
return id,message
|
||||||
minutes = int((totaltime - 3600.*hours)/60.)
|
|
||||||
seconds = int(totaltime - 3600.*hours - 60.*minutes)
|
|
||||||
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
|
|
||||||
|
|
||||||
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
|
|
||||||
|
|
||||||
|
|
||||||
summary = row.summary()
|
|
||||||
summary += '\n'
|
|
||||||
summary += row.intervalstats()
|
|
||||||
|
|
||||||
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
|
|
||||||
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
|
|
||||||
|
|
||||||
# check for duplicate start times
|
|
||||||
ws = Workout.objects.filter(starttime=workoutstarttime,
|
|
||||||
user=r)
|
|
||||||
if (len(ws) != 0):
|
|
||||||
warnings.warn("Probably a duplicate workout",UserWarning)
|
|
||||||
|
|
||||||
# Create the Workout object
|
|
||||||
w = Workout(user=r,name=title,
|
|
||||||
date=workoutdate,workouttype=workouttype,
|
|
||||||
duration=duration,distance=totaldist,
|
|
||||||
weightcategory=r.weightcategory,
|
|
||||||
starttime=workoutstarttime,
|
|
||||||
csvfilename=csvfilename,notes=comments,
|
|
||||||
uploadedtoc2=0,summary=summary,
|
|
||||||
averagehr=averagehr,maxhr=maxhr,
|
|
||||||
startdatetime=rowdatetime)
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
return w.id
|
|
||||||
|
|
||||||
# Create workout from SportTracks Data, which are slightly different
|
# Create workout from SportTracks Data, which are slightly different
|
||||||
# than Strava or Concept2 data
|
# than Strava or Concept2 data
|
||||||
@@ -582,7 +535,8 @@ def add_workout_from_stdata(user,importid,data):
|
|||||||
times_location = times_distance
|
times_location = times_distance
|
||||||
latcoord = np.zeros(len(times_distance))
|
latcoord = np.zeros(len(times_distance))
|
||||||
loncoord = np.zeros(len(times_distance))
|
loncoord = np.zeros(len(times_distance))
|
||||||
|
if workouttype == 'water':
|
||||||
|
workouttype = 'rower'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = splitstdata(data['cadence'])
|
res = splitstdata(data['cadence'])
|
||||||
@@ -668,89 +622,17 @@ def add_workout_from_stdata(user,importid,data):
|
|||||||
|
|
||||||
timestr = strftime("%Y%m%d-%H%M%S")
|
timestr = strftime("%Y%m%d-%H%M%S")
|
||||||
|
|
||||||
# auto smoothing
|
|
||||||
pace = df[' Stroke500mPace (sec/500m)'].values
|
|
||||||
velo = 500./pace
|
|
||||||
|
|
||||||
f = df['TimeStamp (sec)'].diff().mean()
|
|
||||||
windowsize = 2*(int(10./(f)))+1
|
|
||||||
|
|
||||||
df['originalvelo'] = velo
|
|
||||||
|
|
||||||
if windowsize > 3 and windowsize<len(velo):
|
|
||||||
velo2 = savgol_filter(velo,windowsize,3)
|
|
||||||
else:
|
|
||||||
velo2 = velo
|
|
||||||
|
|
||||||
velo3 = pd.Series(velo2)
|
|
||||||
velo3 = velo3.replace([-np.inf,np.inf],np.nan)
|
|
||||||
velo3 = velo3.fillna(method='ffill')
|
|
||||||
|
|
||||||
pace2 = 500./abs(velo3)
|
|
||||||
df[' Stroke500mPace (sec/500m)'] = pace2
|
|
||||||
|
|
||||||
df = df.fillna(0)
|
|
||||||
|
|
||||||
# end autosmoothing
|
|
||||||
|
|
||||||
csvfilename ='media/Import_'+str(importid)+'.csv'
|
csvfilename ='media/Import_'+str(importid)+'.csv'
|
||||||
|
|
||||||
res = df.to_csv(csvfilename+'.gz',index_label='index',
|
res = df.to_csv(csvfilename+'.gz',index_label='index',
|
||||||
compression='gzip')
|
compression='gzip')
|
||||||
|
|
||||||
# make workout
|
id,message = dataprep.save_workout_database(csvfilename,r,
|
||||||
powerperc = 100*np.array([r.pw_ut2,
|
workouttype=workouttype,
|
||||||
r.pw_ut1,
|
title=title,
|
||||||
r.pw_at,
|
notes=comments)
|
||||||
r.pw_tr,r.pw_an])/r.ftp
|
|
||||||
|
|
||||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
return (id,message)
|
||||||
hrut1=r.ut1,hrat=r.at,
|
|
||||||
hrtr=r.tr,hran=r.an,ftp=r.ftp,
|
|
||||||
powerperc=powerperc,powerzones=r.powerzones)
|
|
||||||
row = rdata(csvfilename,rower=rr)
|
|
||||||
|
|
||||||
averagehr = row.df[' HRCur (bpm)'].mean()
|
|
||||||
maxhr = row.df[' HRCur (bpm)'].max()
|
|
||||||
|
|
||||||
totaldist = row.df['cum_dist'].max()
|
|
||||||
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
|
|
||||||
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
|
|
||||||
|
|
||||||
|
|
||||||
hours = int(totaltime/3600.)
|
|
||||||
minutes = int((totaltime - 3600.*hours)/60.)
|
|
||||||
seconds = int(totaltime - 3600.*hours - 60.*minutes)
|
|
||||||
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
|
|
||||||
|
|
||||||
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
|
|
||||||
|
|
||||||
|
|
||||||
summary = row.summary()
|
|
||||||
summary += '\n'
|
|
||||||
summary += row.intervalstats()
|
|
||||||
|
|
||||||
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
|
|
||||||
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
|
|
||||||
|
|
||||||
# check for duplicate start times
|
|
||||||
ws = Workout.objects.filter(starttime=workoutstarttime,
|
|
||||||
user=r)
|
|
||||||
if (len(ws) != 0):
|
|
||||||
print "Warning: This workout probably already exists in the database"
|
|
||||||
|
|
||||||
w = Workout(user=r,name=title,
|
|
||||||
date=workoutdate,workouttype=workouttype,
|
|
||||||
duration=duration,distance=totaldist,
|
|
||||||
weightcategory=r.weightcategory,
|
|
||||||
starttime=workoutstarttime,
|
|
||||||
csvfilename=csvfilename,notes=comments,
|
|
||||||
uploadedtoc2=0,summary=summary,
|
|
||||||
averagehr=averagehr,maxhr=maxhr,
|
|
||||||
startdatetime=rowdatetime)
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
return w.id
|
|
||||||
|
|
||||||
# Checks if user has Concept2 tokens, resets tokens if they are
|
# Checks if user has Concept2 tokens, resets tokens if they are
|
||||||
# expired.
|
# expired.
|
||||||
@@ -765,7 +647,7 @@ def c2_open(user):
|
|||||||
if res[0] != None:
|
if res[0] != None:
|
||||||
thetoken = res[0]
|
thetoken = res[0]
|
||||||
else:
|
else:
|
||||||
thetoken = r.c2token
|
raise C2NoTokenError("User has no token")
|
||||||
else:
|
else:
|
||||||
thetoken = r.c2token
|
thetoken = r.c2token
|
||||||
|
|
||||||
@@ -3933,12 +3815,23 @@ def workout_getstravaworkout_view(request,stravaid):
|
|||||||
def workout_getstravaworkout_view(request,stravaid):
|
def workout_getstravaworkout_view(request,stravaid):
|
||||||
res = stravastuff.get_strava_workout(request.user,stravaid)
|
res = stravastuff.get_strava_workout(request.user,stravaid)
|
||||||
strokedata = res[1]
|
strokedata = res[1]
|
||||||
data = res[0]
|
data = res[0]
|
||||||
id,message = add_workout_from_strokedata(request.user,stravaid,data,strokedata,
|
id,message = add_workout_from_strokedata(request.user,stravaid,data,strokedata,
|
||||||
source='strava')
|
source='strava')
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
w.uploadedtostrava=stravaid
|
w.uploadedtostrava=stravaid
|
||||||
w.save()
|
w.save()
|
||||||
|
if message:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs = {
|
||||||
|
'message':message,
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs = {
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@@ -3947,11 +3840,21 @@ def workout_getsporttracksworkout_view(request,sporttracksid):
|
|||||||
def workout_getsporttracksworkout_view(request,sporttracksid):
|
def workout_getsporttracksworkout_view(request,sporttracksid):
|
||||||
res = sporttracksstuff.get_sporttracks_workout(request.user,sporttracksid)
|
res = sporttracksstuff.get_sporttracks_workout(request.user,sporttracksid)
|
||||||
data = res.json()
|
data = res.json()
|
||||||
|
|
||||||
id,message = add_workout_from_stdata(request.user,sporttracksid,data)
|
id,message = add_workout_from_stdata(request.user,sporttracksid,data)
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
w.uploadedtosporttracks=sporttracksid
|
w.uploadedtosporttracks=sporttracksid
|
||||||
w.save()
|
w.save()
|
||||||
|
if message:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs = {
|
||||||
|
'id':id,
|
||||||
|
'message':message,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs = {
|
||||||
|
'id':id,
|
||||||
})
|
})
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
@@ -3987,7 +3890,7 @@ def workout_getc2workout_view(request,c2id):
|
|||||||
# We have stroke data
|
# We have stroke data
|
||||||
if res2.status_code == 200:
|
if res2.status_code == 200:
|
||||||
strokedata = pd.DataFrame.from_dict(res2.json()['data'])
|
strokedata = pd.DataFrame.from_dict(res2.json()['data'])
|
||||||
# create the workout
|
# create the workout
|
||||||
id,message = add_workout_from_strokedata(request.user,c2id,data,strokedata,
|
id,message = add_workout_from_strokedata(request.user,c2id,data,strokedata,
|
||||||
source='c2')
|
source='c2')
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
@@ -4021,8 +3924,19 @@ def workout_getc2workout_view(request,c2id):
|
|||||||
units,types,results)
|
units,types,results)
|
||||||
|
|
||||||
rowdata.write_csv(w.csvfilename,gzip=True)
|
rowdata.write_csv(w.csvfilename,gzip=True)
|
||||||
dataprep.update_strokedata(w.id,rowdata.df)
|
dataprep.update_strokedata(w.id,rowdata.df)
|
||||||
|
|
||||||
|
if message:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs = {
|
||||||
|
'message':message,
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs = {
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
else:
|
else:
|
||||||
@@ -4053,6 +3967,7 @@ def workout_getc2workout_view(request,c2id):
|
|||||||
|
|
||||||
# This is the main view for processing uploaded files
|
# This is the main view for processing uploaded files
|
||||||
@login_required()
|
@login_required()
|
||||||
|
def workout_upload_view(request,message=""):
|
||||||
r = Rower.objects.get(user=request.user)
|
r = Rower.objects.get(user=request.user)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = DocumentsForm(request.POST,request.FILES)
|
form = DocumentsForm(request.POST,request.FILES)
|
||||||
@@ -4070,283 +3985,82 @@ def workout_upload_view(request,message=""):
|
|||||||
|
|
||||||
|
|
||||||
f1 = res[0] # file name
|
f1 = res[0] # file name
|
||||||
f2 = res[1] # file name incl media directory
|
|
||||||
|
|
||||||
# get file type (ErgData, NK, BoatCoach, etc
|
|
||||||
fileformat = get_file_type(f2)
|
|
||||||
if len(fileformat)==3 and fileformat[0]=='zip':
|
|
||||||
f_to_be_deleted = f2
|
|
||||||
with zipfile.ZipFile(f2) as z:
|
|
||||||
# for now, we're getting only the first file
|
|
||||||
# from the NK zip file (issue #69 on bitbucket)
|
|
||||||
f2 = z.extract(z.namelist()[0],path='media/')
|
|
||||||
fileformat = fileformat[2]
|
|
||||||
f2 = res[1] # file name incl media directory
|
f2 = res[1] # file name incl media directory
|
||||||
|
|
||||||
# Some people try to upload Concept2 logbook summaries
|
|
||||||
if fileformat == 'c2log':
|
id,message = dataprep.new_workout_from_file(r,f2,
|
||||||
os.remove(f2)
|
workouttype=workouttype,
|
||||||
|
title = t,
|
||||||
|
notes='')
|
||||||
if not id:
|
if not id:
|
||||||
url = reverse(workout_upload_view,
|
url = reverse(workout_upload_view,
|
||||||
args=[str(message)])
|
args=[str(message)])
|
||||||
response = HttpResponseRedirect(url)
|
response = HttpResponseRedirect(url)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
# Some people try to upload RowPro summary logs
|
else:
|
||||||
if fileformat == 'rowprolog':
|
if message:
|
||||||
os.remove(f2)
|
url = reverse(workout_edit_view,
|
||||||
message = "This RowPro logbook summary does not contain stroke data. Please use the Stroke Data CSV file for the individual workout in your log."
|
kwargs = {
|
||||||
url = reverse(workout_upload_view,
|
'id':id,
|
||||||
args=[str(message)])
|
'message':message,
|
||||||
response = HttpResponseRedirect(url)
|
})
|
||||||
|
else:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs = {
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
|
||||||
|
response = HttpResponseRedirect(url)
|
||||||
w = Workout.objects.get(id=id)
|
w = Workout.objects.get(id=id)
|
||||||
|
|
||||||
# Sometimes people try an unsupported file type.
|
if (make_plot):
|
||||||
# Send an email to info@rowsandall.com with the file attached
|
imagename = f1[:-4]+'.png'
|
||||||
# for me to check if it is a bug, or a new file type
|
fullpathimagename = 'static/plots/'+imagename
|
||||||
# worth supporting
|
|
||||||
if fileformat == 'unknown':
|
|
||||||
message = "We couldn't recognize the file type"
|
|
||||||
url = reverse(workout_upload_view,
|
|
||||||
args=[str(message)])
|
|
||||||
response = HttpResponseRedirect(url)
|
|
||||||
if settings.DEBUG:
|
|
||||||
res = handle_sendemail_unrecognized.delay(f2,
|
|
||||||
request.user.email)
|
|
||||||
|
|
||||||
else:
|
|
||||||
res = queuehigh.enqueue(handle_sendemail_unrecognized,
|
|
||||||
f2,request.user.email)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
summary = ''
|
|
||||||
# handle non-Painsled by converting it to painsled
|
|
||||||
# compatible CSV
|
|
||||||
try:
|
|
||||||
if (fileformat != 'csv'):
|
|
||||||
# handle RowPro:
|
|
||||||
if (fileformat == 'rp'):
|
|
||||||
row = RowProParser(f2)
|
|
||||||
# handle TCX
|
|
||||||
if (fileformat == 'tcx'):
|
|
||||||
row = TCXParser(f2)
|
|
||||||
|
|
||||||
# handle Mystery
|
|
||||||
if (fileformat == 'mystery'):
|
|
||||||
row = MysteryParser(f2)
|
|
||||||
|
|
||||||
# handle RowPerfect
|
|
||||||
if (fileformat == 'rowperfect3'):
|
|
||||||
row = RowPerfectParser(f2)
|
|
||||||
|
|
||||||
# handle TCX no HR
|
|
||||||
if (fileformat == 'tcxnohr'):
|
|
||||||
row = TCXParserNoHR(f2)
|
|
||||||
|
|
||||||
# handle ErgData
|
|
||||||
if (fileformat == 'ergdata'):
|
|
||||||
row = ErgDataParser(f2)
|
|
||||||
|
|
||||||
# handle Mike
|
|
||||||
if (fileformat == 'bcmike'):
|
|
||||||
row = BoatCoachAdvancedParser(f2)
|
|
||||||
|
|
||||||
# handle BoatCoach
|
|
||||||
if (fileformat == 'boatcoach'):
|
|
||||||
row = BoatCoachParser(f2)
|
|
||||||
|
|
||||||
# handle painsled desktop
|
|
||||||
if (fileformat == 'painsleddesktop'):
|
|
||||||
row = painsledDesktopParser(f2)
|
|
||||||
|
|
||||||
# handle speed coach GPS
|
|
||||||
if (fileformat == 'speedcoach'):
|
|
||||||
row = speedcoachParser(f2)
|
|
||||||
|
|
||||||
# handle speed coach GPS 2
|
|
||||||
if (fileformat == 'speedcoach2'):
|
|
||||||
row = SpeedCoach2Parser(f2)
|
|
||||||
try:
|
|
||||||
summary = row.allstats()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# handle ErgStick
|
|
||||||
if (fileformat == 'ergstick'):
|
|
||||||
row = ErgStickParser(f2)
|
|
||||||
|
|
||||||
# handle FIT
|
|
||||||
if (fileformat == 'fit'):
|
|
||||||
row = FITParser(f2)
|
|
||||||
# The FIT files have nice lap/split summaries
|
|
||||||
# so we make use of it
|
|
||||||
s = fitsummarydata(f2)
|
|
||||||
s.setsummary()
|
|
||||||
summary = s.summarytext
|
|
||||||
|
|
||||||
# Save the Painsled compatible CSV file and delete
|
|
||||||
# the uploaded file
|
|
||||||
f_to_be_deleted = f2
|
|
||||||
# should delete file
|
|
||||||
f2 = f2[:-4]+'o.csv'
|
|
||||||
row.write_csv(f2,gzip=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
os.remove(f_to_be_deleted)
|
|
||||||
except:
|
|
||||||
os.remove(f_to_be_deleted+'.gz')
|
|
||||||
|
|
||||||
u = request.user
|
u = request.user
|
||||||
r = Rower.objects.get(user=request.user)
|
r = Rower.objects.get(user=request.user)
|
||||||
powerperc = 100*np.array([r.pw_ut2,
|
powerperc = 100*np.array([r.pw_ut2,
|
||||||
r.pw_ut1,
|
r.pw_ut1,
|
||||||
r.pw_at,
|
r.pw_at,
|
||||||
r.pw_tr,r.pw_an])/r.ftp
|
r.pw_tr,r.pw_an])/r.ftp
|
||||||
|
|
||||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
hrpwrdata = {
|
||||||
hrut1=r.ut1,hrat=r.at,
|
'hrmax':r.max,
|
||||||
hrtr=r.tr,hran=r.an,ftp=r.ftp,
|
'hrut2':r.ut2,
|
||||||
powerperc=powerperc,powerzones=r.powerzones)
|
'hrut1':r.ut1,
|
||||||
row = rdata(f2,rower=rr)
|
'hrat':r.at,
|
||||||
if row == 0:
|
'hrtr':r.tr,
|
||||||
|
'hran':r.an,
|
||||||
|
'ftp':r.ftp,
|
||||||
|
'powerperc':serialize_list(powerperc),
|
||||||
|
'powerzones':serialize_list(r.powerzones),
|
||||||
}
|
}
|
||||||
|
|
||||||
# auto smoothing
|
# make plot - asynchronous task
|
||||||
pace = row.df[' Stroke500mPace (sec/500m)'].values
|
plotnrs = {
|
||||||
velo = 500./pace
|
'timeplot':1,
|
||||||
|
'distanceplot':2,
|
||||||
f = row.df['TimeStamp (sec)'].diff().mean()
|
'pieplot':3,
|
||||||
windowsize = 2*(int(10./(f)))+1
|
|
||||||
if not 'originalvelo' in row.df:
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if windowsize > 3 and windowsize<len(velo):
|
plotnr = plotnrs[plottype]
|
||||||
|
if (workouttype=='water'):
|
||||||
|
plotnr = plotnr+3
|
||||||
|
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
res = handle_makeplot.delay(f1,f2,t,
|
||||||
|
hrpwrdata,plotnr,
|
||||||
imagename)
|
imagename)
|
||||||
else:
|
else:
|
||||||
velo2 = velo
|
res = queue.enqueue(handle_makeplot,f1,f2,
|
||||||
|
t,hrpwrdata,
|
||||||
velo3 = pd.Series(velo2)
|
|
||||||
velo3 = velo3.replace([-np.inf,np.inf],np.nan)
|
|
||||||
velo3 = velo3.fillna(method='ffill')
|
|
||||||
|
|
||||||
pace2 = 500./abs(velo3)
|
|
||||||
|
|
||||||
row.df[' Stroke500mPace (sec/500m)'] = pace2
|
|
||||||
|
|
||||||
row.df = row.df.fillna(0)
|
|
||||||
|
|
||||||
row.write_csv(f2,gzip=True)
|
|
||||||
try:
|
|
||||||
os.remove(f2)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# recalculate power data
|
|
||||||
if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides':
|
|
||||||
try:
|
|
||||||
row.erg_recalculatepower()
|
|
||||||
row.write_csv(f2,gzip=True)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if fileformat != 'fit' and summary == '':
|
|
||||||
summary = row.summary()
|
|
||||||
summary += '\n'
|
|
||||||
summary += row.intervalstats_painsled()
|
|
||||||
|
|
||||||
averagehr = row.df[' HRCur (bpm)'].mean()
|
|
||||||
maxhr = row.df[' HRCur (bpm)'].max()
|
|
||||||
|
|
||||||
totaldist = row.df['cum_dist'].max()
|
|
||||||
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
|
|
||||||
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
|
|
||||||
|
|
||||||
hours = int(totaltime/3600.)
|
|
||||||
minutes = int((totaltime - 3600.*hours)/60.)
|
|
||||||
seconds = int(totaltime - 3600.*hours - 60.*minutes)
|
|
||||||
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
|
|
||||||
|
|
||||||
|
|
||||||
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
|
|
||||||
|
|
||||||
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
|
|
||||||
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
|
|
||||||
workoutstartdatetime = thetimezone.localize(row.rowdatetime).astimezone(utc)
|
|
||||||
|
|
||||||
# check for duplicate start times
|
|
||||||
r = Rower.objects.get(user=request.user)
|
|
||||||
|
|
||||||
ws = Workout.objects.filter(starttime=workoutstarttime,
|
|
||||||
user=r)
|
|
||||||
if (len(ws) != 0):
|
|
||||||
message = "Warning: This workout probably already exists in the database"
|
|
||||||
|
|
||||||
w = Workout(user=r,name=t,date=workoutdate,
|
|
||||||
workouttype=workouttype,
|
|
||||||
duration=duration,distance=totaldist,
|
|
||||||
weightcategory=r.weightcategory,
|
|
||||||
starttime=workoutstarttime,
|
|
||||||
csvfilename=f2,notes=notes,summary=summary,
|
|
||||||
maxhr=maxhr,averagehr=averagehr,
|
|
||||||
startdatetime=workoutstartdatetime)
|
|
||||||
|
|
||||||
w.save()
|
|
||||||
|
|
||||||
# put stroke data in database
|
|
||||||
res = dataprep.dataprep(row.df,id=w.id,
|
|
||||||
bands=True,barchart=True,
|
|
||||||
otwpower=True,empower=True)
|
|
||||||
|
|
||||||
# Make Plot
|
|
||||||
if (make_plot):
|
|
||||||
imagename = f1[:-4]+'.png'
|
|
||||||
fullpathimagename = 'static/plots/'+imagename
|
|
||||||
u = request.user
|
|
||||||
r = Rower.objects.get(user=request.user)
|
|
||||||
powerperc = 100*np.array([r.pw_ut2,
|
|
||||||
r.pw_ut1,
|
|
||||||
r.pw_at,
|
|
||||||
r.pw_tr,r.pw_an])/r.ftp
|
|
||||||
|
|
||||||
|
|
||||||
hrpwrdata = {
|
|
||||||
'hrmax':r.max,
|
|
||||||
'hrut2':r.ut2,
|
|
||||||
'hrut1':r.ut1,
|
|
||||||
'hrat':r.at,
|
|
||||||
'hrtr':r.tr,
|
|
||||||
'hran':r.an,
|
|
||||||
'ftp':r.ftp,
|
|
||||||
'powerperc':serialize_list(powerperc),
|
|
||||||
'powerzones':serialize_list(r.powerzones),
|
|
||||||
}
|
|
||||||
|
|
||||||
# make plot - asynchronous task
|
|
||||||
plotnrs = {
|
|
||||||
'timeplot':1,
|
|
||||||
'distanceplot':2,
|
|
||||||
'pieplot':3,
|
|
||||||
}
|
|
||||||
|
|
||||||
plotnr = plotnrs[plottype]
|
|
||||||
if (workouttype=='water'):
|
|
||||||
plotnr,imagename)
|
plotnr,imagename)
|
||||||
|
|
||||||
|
|
||||||
if settings.DEBUG:
|
i = GraphImage(workout=w,
|
||||||
res = handle_makeplot.delay(f1,f2,t,
|
creationdatetime=timezone.now(),
|
||||||
hrpwrdata,plotnr,
|
filename=fullpathimagename)
|
||||||
imagename)
|
|
||||||
else:
|
|
||||||
res = queue.enqueue(handle_makeplot,f1,f2,
|
|
||||||
t,hrpwrdata,
|
|
||||||
plotnr,imagename)
|
|
||||||
|
|
||||||
|
|
||||||
i = GraphImage(workout=w,
|
|
||||||
creationdatetime=timezone.now(),
|
|
||||||
filename=fullpathimagename)
|
|
||||||
i.save()
|
i.save()
|
||||||
|
|
||||||
# upload to C2
|
# upload to C2
|
||||||
@@ -4355,7 +4069,6 @@ def workout_upload_view(request,message=""):
|
|||||||
thetoken = c2_open(request.user)
|
thetoken = c2_open(request.user)
|
||||||
except C2NoTokenError:
|
except C2NoTokenError:
|
||||||
return HttpResponseRedirect("/rowers/me/c2authorize/")
|
return HttpResponseRedirect("/rowers/me/c2authorize/")
|
||||||
try:
|
|
||||||
try:
|
try:
|
||||||
c2userid = c2stuff.get_userid(thetoken)
|
c2userid = c2stuff.get_userid(thetoken)
|
||||||
data = c2stuff.createc2workoutdata(w)
|
data = c2stuff.createc2workoutdata(w)
|
||||||
@@ -4383,28 +4096,29 @@ def workout_upload_view(request,message=""):
|
|||||||
s= json.loads(response.text)
|
s= json.loads(response.text)
|
||||||
c2id = s['data']['id']
|
c2id = s['data']['id']
|
||||||
w.uploadedtoc2 = c2id
|
w.uploadedtoc2 = c2id
|
||||||
w.save()
|
w.save()
|
||||||
|
except:
|
||||||
except:
|
message = "C2 upload failed"
|
||||||
message = "C2 upload failed"
|
url = reverse(workout_edit_view,
|
||||||
url = reverse(workout_edit_view,
|
|
||||||
kwargs={
|
kwargs={
|
||||||
'message':message,
|
'message':message,
|
||||||
'id':str(w.id),
|
'id':str(w.id),
|
||||||
})
|
})
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
|
|
||||||
# redirect to workout edit page
|
|
||||||
url = "/rowers/workout/"+str(w.id)+"/edit"
|
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
except:
|
|
||||||
if settings.DEBUG:
|
|
||||||
errorstring = str(sys.exc_info()[0])
|
|
||||||
print errorstring
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
url = reverse(workout_upload_view,
|
|
||||||
args=[str(message)])
|
if message:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs={
|
||||||
|
'message':message,
|
||||||
|
'id':w.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
else:
|
||||||
|
url = reverse(workout_edit_view,
|
||||||
|
kwargs = {
|
||||||
|
'id':w.id,
|
||||||
|
})
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
else:
|
else:
|
||||||
response = render(request,
|
response = render(request,
|
||||||
@@ -5367,20 +5081,34 @@ def team_leave_view(request,id=0):
|
|||||||
url = reverse(rower_teams_view)
|
url = reverse(rower_teams_view)
|
||||||
response = HttpResponseRedirect(url)
|
response = HttpResponseRedirect(url)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
from rowers.forms import TeamInviteCodeForm
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
|
def rower_teams_view(request,message='',successmessage=''):
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = TeamInviteCodeForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
code = form.cleaned_data['code']
|
||||||
|
res,text = teams.process_invite_code(request.user,code)
|
||||||
|
if res:
|
||||||
|
successmessage = text
|
||||||
|
else:
|
||||||
|
message = text
|
||||||
|
else:
|
||||||
|
form = TeamInviteCodeForm()
|
||||||
|
|
||||||
r = Rower.objects.get(user=request.user)
|
r = Rower.objects.get(user=request.user)
|
||||||
ts = Team.objects.filter(rower=r)
|
ts = Team.objects.filter(rower=r)
|
||||||
myteams = Team.objects.filter(manager=request.user)
|
myteams = Team.objects.filter(manager=request.user)
|
||||||
otherteams = Team.objects.filter(private='open').exclude(rower=r).exclude(manager=request.user).order_by('name')
|
otherteams = Team.objects.filter(private='open').exclude(rower=r).exclude(manager=request.user).order_by('name')
|
||||||
teams.remove_expired_invites()
|
teams.remove_expired_invites()
|
||||||
|
|
||||||
print "aap",otherteams
|
|
||||||
|
|
||||||
invites = TeamInvite.objects.filter(user=request.user)
|
invites = TeamInvite.objects.filter(user=request.user)
|
||||||
requests = TeamRequest.objects.filter(user=request.user)
|
requests = TeamRequest.objects.filter(user=request.user)
|
||||||
myrequests = TeamRequest.objects.filter(team__in=myteams)
|
myrequests = TeamRequest.objects.filter(team__in=myteams)
|
||||||
|
myinvites = TeamInvite.objects.filter(team__in=myteams)
|
||||||
|
|
||||||
print form
|
print form
|
||||||
|
|
||||||
return render(request, 'teams.html',
|
return render(request, 'teams.html',
|
||||||
@@ -5390,6 +5118,7 @@ def rower_teams_view(request,message='',successmessage=''):
|
|||||||
'invites':invites,
|
'invites':invites,
|
||||||
'otherteams':otherteams,
|
'otherteams':otherteams,
|
||||||
'requests':requests,
|
'requests':requests,
|
||||||
|
'myrequests':myrequests,
|
||||||
'form':form,
|
'form':form,
|
||||||
'message':message,
|
'message':message,
|
||||||
'successmessage':successmessage,
|
'successmessage':successmessage,
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ from settings import *
|
|||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),},
|
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||||
|
'HOST': 'localhost'
|
||||||
|
},
|
||||||
# 'TEST': {
|
# 'TEST': {
|
||||||
# 'CHARSET': 'utf8',
|
# 'CHARSET': 'utf8',
|
||||||
# 'COLLATION': 'utf8_general_ci',
|
# 'COLLATION': 'utf8_general_ci',
|
||||||
|
|||||||
Reference in New Issue
Block a user