Merge branch 'feature/trainingplans' into develop
This commit is contained in:
@@ -95,5 +95,5 @@ def coursetime_paths(data,paths,finalmaxmin='min'):
|
||||
entrytime = data['time'].max()
|
||||
entrydistance = data['cum_dist'].max()
|
||||
coursecompleted = False
|
||||
|
||||
|
||||
return entrytime, entrydistance, coursecompleted
|
||||
|
||||
517
rowers/models.py
517
rowers/models.py
@@ -840,6 +840,7 @@ def checkworkoutuser(user,workout):
|
||||
except Rower.DoesNotExist:
|
||||
return False
|
||||
|
||||
|
||||
# Check if user is coach or rower
|
||||
def checkaccessuser(user,rower):
|
||||
try:
|
||||
@@ -979,11 +980,60 @@ class TrainingTargetForm(ModelForm):
|
||||
class TrainingPlan(models.Model):
|
||||
rower = models.ForeignKey(Rower)
|
||||
name = models.CharField(max_length=150,blank=True)
|
||||
target = models.ForeignKey(TrainingTarget,blank=True)
|
||||
target = models.ForeignKey(TrainingTarget,blank=True,null=True)
|
||||
startdate = models.DateField(default=timezone.now)
|
||||
enddate = models.DateField(
|
||||
default=half_year_from_now)
|
||||
|
||||
def __unicode__(self):
|
||||
name = self.name
|
||||
startdate = self.startdate
|
||||
enddate = self.enddate
|
||||
firstname = self.rower.user.first_name
|
||||
lastname = self.rower.user.last_name
|
||||
|
||||
stri = u'Training Plan for {firstname} {lastname} {s} - {e}: {name}'.format(
|
||||
s = startdate.strftime('%Y-%m-%d'),
|
||||
e = enddate.strftime('%Y-%m-%d'),
|
||||
firstname = firstname,
|
||||
lastname = lastname,
|
||||
name=name
|
||||
)
|
||||
|
||||
return stri
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.enddate < self.startdate:
|
||||
startdate = self.startdate
|
||||
enddate = self.enddate
|
||||
self.startdate = enddate
|
||||
self.enddate = startdate
|
||||
|
||||
otherplans = TrainingPlan.objects.filter(rower=self.rower).exclude(pk=self.pk).order_by("-startdate")
|
||||
|
||||
for otherplan in otherplans:
|
||||
if otherplan.startdate <= self.enddate and otherplan.startdate >= self.startdate:
|
||||
self.enddate = otherplan.startdate-datetime.timedelta(days=1)
|
||||
if otherplan.enddate >= self.startdate and otherplan.enddate <= self.enddate:
|
||||
self.startdate = otherplan.enddate+datetime.timedelta(days=1)
|
||||
|
||||
if not self.enddate <= self.startdate:
|
||||
super(TrainingPlan,self).save(*args, **kwargs)
|
||||
|
||||
macrocycles = TrainingMacroCycle.objects.filter(plan = self)
|
||||
if not macrocycles:
|
||||
m = TrainingMacroCycle(
|
||||
plan = self,
|
||||
name = 'Filler',
|
||||
startdate = self.startdate,
|
||||
enddate = self.enddate,
|
||||
)
|
||||
|
||||
m.save()
|
||||
|
||||
else:
|
||||
createmacrofillers(self)
|
||||
|
||||
class TrainingPlanForm(ModelForm):
|
||||
class Meta:
|
||||
model = TrainingPlan
|
||||
@@ -1009,6 +1059,253 @@ cycletypechoices = (
|
||||
('userdefined','User Defined')
|
||||
)
|
||||
|
||||
def createmacrofillers(plan):
|
||||
fillers = TrainingMacroCycle.objects.filter(
|
||||
plan = plan, type = 'filler'
|
||||
)
|
||||
|
||||
for f in fillers:
|
||||
f.delete()
|
||||
|
||||
cycles = TrainingMacroCycle.objects.filter(
|
||||
plan = plan
|
||||
).order_by("-startdate")
|
||||
|
||||
if not cycles:
|
||||
macr = TrainingMacroCycle(
|
||||
plan=plan,
|
||||
startdate = plan.startdate,
|
||||
enddate = plan.enddate,
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
|
||||
thedate = plan.enddate
|
||||
while cycles:
|
||||
if cycles[0].enddate < thedate:
|
||||
macr = TrainingMacroCycle(
|
||||
plan=plan,
|
||||
startdate = cycles[0].enddate+datetime.timedelta(days=1),
|
||||
enddate = thedate,
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
thedate = cycles[0].startdate-datetime.timedelta(days=1)
|
||||
cycles = cycles[1:]
|
||||
|
||||
cycles = TrainingMacroCycle.objects.filter(
|
||||
plan = plan
|
||||
).order_by("startdate")
|
||||
|
||||
if cycles[0].startdate > plan.startdate:
|
||||
macr = TrainingMacroCycle(
|
||||
plan=plan,
|
||||
startdate = plan.startdate,
|
||||
enddate = cycles[0].startdate-datetime.timedelta(days=1),
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
|
||||
def createmesofillers(plan):
|
||||
fillers = TrainingMesoCycle.objects.filter(
|
||||
plan = plan, type = 'filler'
|
||||
)
|
||||
|
||||
for f in fillers:
|
||||
f.delete()
|
||||
|
||||
cycles = TrainingMesoCycle.objects.filter(
|
||||
plan = plan
|
||||
).order_by("-startdate")
|
||||
|
||||
if not cycles:
|
||||
macr = TrainingMesoCycle(
|
||||
plan = plan,
|
||||
startdate = plan.startdate,
|
||||
enddate = plan.enddate,
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
|
||||
thedate = plan.enddate
|
||||
while cycles:
|
||||
if cycles[0].enddate < thedate:
|
||||
macr = TrainingMesoCycle(
|
||||
plan=plan,
|
||||
startdate = cycles[0].enddate+datetime.timedelta(days=1),
|
||||
enddate = thedate,
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
thedate = cycles[0].startdate-datetime.timedelta(days=1)
|
||||
cycles = cycles[1:]
|
||||
|
||||
cycles = TrainingMesoCycle.objects.filter(
|
||||
plan = plan
|
||||
).order_by("startdate")
|
||||
|
||||
if cycles[0].startdate > plan.startdate:
|
||||
macr = TrainingMesoCycle(
|
||||
plan=plan,
|
||||
startdate = plan.startdate,
|
||||
enddate = cycles[0].startdate-datetime.timedelta(days=1),
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
|
||||
|
||||
def createmicrofillers(plan):
|
||||
fillers = TrainingMicroCycle.objects.filter(
|
||||
plan = plan, type = 'filler'
|
||||
)
|
||||
|
||||
for f in fillers:
|
||||
f.delete()
|
||||
|
||||
cycles = TrainingMicroCycle.objects.filter(
|
||||
plan = plan
|
||||
).order_by("-startdate")
|
||||
|
||||
if not cycles:
|
||||
macr = TrainingMicroCycle(
|
||||
plan=plan,
|
||||
startdate = plan.startdate,
|
||||
enddate = plan.enddate,
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
|
||||
thedate = plan.enddate
|
||||
while cycles:
|
||||
if cycles[0].enddate < thedate:
|
||||
macr = TrainingMicroCycle(
|
||||
plan=plan,
|
||||
startdate = cycles[0].enddate+datetime.timedelta(days=1),
|
||||
enddate = thedate,
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
thedate = cycles[0].startdate-datetime.timedelta(days=1)
|
||||
cycles = cycles[1:]
|
||||
|
||||
cycles = TrainingMicroCycle.objects.filter(
|
||||
plan = plan
|
||||
).order_by("startdate")
|
||||
|
||||
if cycles[0].startdate > plan.startdate:
|
||||
macr = TrainingMicroCycle(
|
||||
plan=plan,
|
||||
startdate = plan.startdate,
|
||||
enddate = cycles[0].startdate-datetime.timedelta(days=1),
|
||||
type='filler',
|
||||
name='Filler'
|
||||
)
|
||||
macr.save()
|
||||
|
||||
def microcyclecheckdates(plan):
|
||||
cycles = TrainingMicroCycle.objects.filter(
|
||||
plan=plan
|
||||
).order_by("-startdate")
|
||||
|
||||
thedate = plan.enddate
|
||||
while cycles:
|
||||
if cycles[0].enddate < plan.startdate:
|
||||
cycles[0].delete()
|
||||
if cycles[0].startdate > plan.enddate:
|
||||
cycles[0].delete()
|
||||
if cycles[0].enddate > thedate:
|
||||
cycles[0].enddate = thedate
|
||||
cycles[0].save()
|
||||
thedate = cycles[0].startdate-datetime.timedelta(days=1)
|
||||
cycles = cycles[1:]
|
||||
|
||||
cycles = TrainingMicroCycle.objects.filter(
|
||||
plan=plan
|
||||
).order_by("startdate")
|
||||
|
||||
thedate = plan.startdate
|
||||
while cycles:
|
||||
if cycles[0].startdate < thedate:
|
||||
cycles[0].startdate = thedate
|
||||
cycles[0].save()
|
||||
try:
|
||||
thedate = cycles[1].startdate-datetime.timedelta(days=1)
|
||||
except IndexError:
|
||||
pass
|
||||
cycles = cycles[1:]
|
||||
|
||||
def mesocyclecheckdates(plan):
|
||||
cycles = TrainingMesoCycle.objects.filter(
|
||||
plan=plan
|
||||
).order_by("-startdate")
|
||||
|
||||
thedate = plan.enddate
|
||||
while cycles:
|
||||
if cycles[0].enddate < plan.startdate:
|
||||
cycles[0].delete()
|
||||
if cycles[0].startdate > plan.enddate:
|
||||
cycles[0].delete()
|
||||
if cycles[0].enddate > thedate:
|
||||
cycles[0].enddate = thedate
|
||||
cycles[0].save()
|
||||
thedate = cycles[0].startdate-datetime.timedelta(days=1)
|
||||
cycles = cycles[1:]
|
||||
|
||||
cycles = TrainingMesoCycle.objects.filter(
|
||||
plan=plan
|
||||
).order_by("startdate")
|
||||
|
||||
thedate = plan.startdate
|
||||
while cycles:
|
||||
if cycles[0].startdate < thedate:
|
||||
cycles[0].startdate = thedate
|
||||
cycles[0].save()
|
||||
try:
|
||||
thedate = cycles[1].startdate-datetime.timedelta(days=1)
|
||||
except IndexError:
|
||||
pass
|
||||
cycles = cycles[1:]
|
||||
|
||||
def macrocyclecheckdates(plan):
|
||||
cycles = TrainingMacroCycle.objects.filter(
|
||||
plan=plan
|
||||
).order_by("-startdate")
|
||||
|
||||
thedate = plan.enddate
|
||||
while cycles:
|
||||
if cycles[0].enddate < plan.startdate:
|
||||
cycles[0].delete()
|
||||
if cycles[0].startdate > plan.enddate:
|
||||
cycles[0].delete()
|
||||
if cycles[0].enddate > thedate:
|
||||
cycles[0].enddate = thedate
|
||||
cycles[0].save()
|
||||
thedate = cycles[0].startdate-datetime.timedelta(days=1)
|
||||
cycles = cycles[1:]
|
||||
|
||||
cycles = TrainingMacroCycle.objects.filter(
|
||||
plan=plan
|
||||
).order_by("startdate")
|
||||
|
||||
thedate = plan.startdate
|
||||
while cycles:
|
||||
if cycles[0].startdate < thedate:
|
||||
cycles[0].startdate = thedate
|
||||
cycles[0].save()
|
||||
try:
|
||||
thedate = cycles[1].startdate-datetime.timedelta(days=1)
|
||||
except IndexError:
|
||||
pass
|
||||
cycles = cycles[1:]
|
||||
|
||||
class TrainingMacroCycle(models.Model):
|
||||
plan = models.ForeignKey(TrainingPlan)
|
||||
name = models.CharField(max_length=150,blank=True)
|
||||
@@ -1016,10 +1313,85 @@ class TrainingMacroCycle(models.Model):
|
||||
enddate = models.DateField(
|
||||
default=half_year_from_now)
|
||||
notes = models.TextField(max_length=300,blank=True)
|
||||
|
||||
type = models.CharField(default='filler',
|
||||
choices=cycletypechoices,
|
||||
max_length=150)
|
||||
|
||||
plantime = models.IntegerField(default=0,verbose_name='Planned Duration')
|
||||
plandistance = models.IntegerField(default=0,verbose_name='Planned Distance')
|
||||
planrscore = models.IntegerField(default=0,verbose_name='Planned rScore')
|
||||
plantrimp = models.IntegerField(default=0,verbose_name='Planned TRIMP')
|
||||
|
||||
actualtime = models.IntegerField(default=0,verbose_name='Actual Duration')
|
||||
actualdistance = models.IntegerField(default=0,verbose_name='Actual Distance')
|
||||
actualrscore = models.IntegerField(default=0,verbose_name='Actual rScore')
|
||||
actualtrimp = models.IntegerField(default=0,verbose_name='Actual TRIMP')
|
||||
|
||||
def __unicode__(self):
|
||||
stri = 'Macro Cycle - {n} ({sd} - {ed})'.format(
|
||||
n = self.name,
|
||||
sd = self.startdate,
|
||||
ed = self.enddate,
|
||||
)
|
||||
|
||||
return stri
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.enddate < self.startdate:
|
||||
startdate = self.startdate
|
||||
enddate = self.enddate
|
||||
self.startdate = enddate
|
||||
self.enddate = startdate
|
||||
|
||||
fillers = TrainingMacroCycle.objects.filter(
|
||||
plan=self.plan,type='filler')
|
||||
for f in fillers:
|
||||
f.delete()
|
||||
|
||||
if self.enddate > self.plan.enddate:
|
||||
self.enddate = self.plan.enddate
|
||||
|
||||
if self.startdate < self.plan.startdate:
|
||||
self.startdate = self.plan.startdate
|
||||
|
||||
othercycles = TrainingMacroCycle.objects.filter(
|
||||
plan=self.plan).exclude(pk=self.pk).order_by("-startdate")
|
||||
|
||||
for othercycle in othercycles:
|
||||
if othercycle.startdate <= self.enddate and othercycle.startdate >= self.startdate:
|
||||
self.enddate = othercycle.startdate-datetime.timedelta(days=1)
|
||||
|
||||
if othercycle.enddate >= self.startdate and othercycle.enddate <= self.enddate:
|
||||
self.startdate = othercycle.enddate+datetime.timedelta(days=1)
|
||||
|
||||
if not self.enddate <= self.startdate:
|
||||
super(TrainingMacroCycle,self).save(*args, **kwargs)
|
||||
|
||||
|
||||
mesocycles = TrainingMesoCycle.objects.filter(plan = self)
|
||||
if not mesocycles:
|
||||
meso = TrainingMesoCycle(
|
||||
plan = self,
|
||||
name = 'Filler',
|
||||
startdate = self.startdate,
|
||||
enddate = self.enddate,
|
||||
)
|
||||
|
||||
meso.save()
|
||||
else:
|
||||
createmesofillers(self)
|
||||
|
||||
class TrainingMacroCycleForm(ModelForm):
|
||||
class Meta:
|
||||
model = TrainingMacroCycle
|
||||
fields = ['name','startdate','enddate','notes']
|
||||
|
||||
widgets = {
|
||||
'startdate': AdminDateWidget(),
|
||||
'enddate': AdminDateWidget()
|
||||
}
|
||||
|
||||
class TrainingMesoCycle(models.Model):
|
||||
plan = models.ForeignKey(TrainingMacroCycle)
|
||||
name = models.CharField(max_length=150,blank=True)
|
||||
@@ -1031,6 +1403,69 @@ class TrainingMesoCycle(models.Model):
|
||||
choices=cycletypechoices,
|
||||
max_length=150)
|
||||
|
||||
plantime = models.IntegerField(default=0,verbose_name='Planned Duration')
|
||||
plandistance = models.IntegerField(default=0,verbose_name='Planned Distance')
|
||||
planrscore = models.IntegerField(default=0,verbose_name='Planned rScore')
|
||||
plantrimp = models.IntegerField(default=0,verbose_name='Planned TRIMP')
|
||||
|
||||
actualtime = models.IntegerField(default=0,verbose_name='Actual Duration')
|
||||
actualdistance = models.IntegerField(default=0,verbose_name='Actual Distance')
|
||||
actualrscore = models.IntegerField(default=0,verbose_name='Actual rScore')
|
||||
actualtrimp = models.IntegerField(default=0,verbose_name='Actual TRIMP')
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
stri = 'Meso Cycle - {n} ({sd} - {ed})'.format(
|
||||
n = self.name,
|
||||
sd = self.startdate,
|
||||
ed = self.enddate,
|
||||
)
|
||||
|
||||
return stri
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.enddate < self.startdate:
|
||||
startdate = self.startdate
|
||||
enddate = self.enddate
|
||||
self.startdate = enddate
|
||||
self.enddate = startdate
|
||||
|
||||
fillers = TrainingMesoCycle.objects.filter(
|
||||
plan=self.plan,type='filler')
|
||||
for f in fillers:
|
||||
f.delete()
|
||||
|
||||
if self.enddate > self.plan.enddate:
|
||||
self.enddate = self.plan.enddate
|
||||
|
||||
if self.startdate < self.plan.startdate:
|
||||
self.startdate = self.plan.startdate
|
||||
|
||||
othercycles = TrainingMesoCycle.objects.filter(
|
||||
plan=self.plan).exclude(pk=self.pk).order_by("-startdate")
|
||||
|
||||
for othercycle in othercycles:
|
||||
if othercycle.startdate <= self.enddate and othercycle.startdate >= self.startdate:
|
||||
self.enddate = othercycle.startdate-datetime.timedelta(days=1)
|
||||
|
||||
if othercycle.enddate >= self.startdate and othercycle.enddate <= self.enddate:
|
||||
self.startdate = othercycle.enddate+datetime.timedelta(days=1)
|
||||
|
||||
if not self.enddate <= self.startdate:
|
||||
super(TrainingMesoCycle,self).save(*args, **kwargs)
|
||||
|
||||
microcycles = TrainingMicroCycle.objects.filter(plan = self)
|
||||
if not microcycles:
|
||||
micro = TrainingMicroCycle(
|
||||
plan = self,
|
||||
name = 'Filler',
|
||||
startdate = self.startdate,
|
||||
enddate = self.enddate,
|
||||
)
|
||||
|
||||
micro.save()
|
||||
else:
|
||||
createmicrofillers(self)
|
||||
|
||||
class TrainingMicroCycle(models.Model):
|
||||
plan = models.ForeignKey(TrainingMesoCycle)
|
||||
@@ -1043,15 +1478,81 @@ class TrainingMicroCycle(models.Model):
|
||||
choices=cycletypechoices,
|
||||
max_length=150)
|
||||
|
||||
plantime = models.IntegerField(default=0,verbose_name='Planned Duration')
|
||||
plandistance = models.IntegerField(default=0,verbose_name='Planned Distance')
|
||||
planrscore = models.IntegerField(default=0,verbose_name='Planned rScore')
|
||||
plantrimp = models.IntegerField(default=0,verbose_name='Planned TRIMP')
|
||||
|
||||
# Needs some error checking
|
||||
# - Microcycles should not overlap with other microcycles, same for MesoCycles, MacroCycles
|
||||
# - When a TrainingPlan is created, it should create 1 "collector" Macro, Meso & MicroCycle - this is invisible for users who choose to not use cycles
|
||||
# - When a new Microcycle is inserted, the "collector" cycle is automatically adjusted to "go out of the way" of the new MicroCycle - and similar for Macro & Meso
|
||||
# - If the entire MesoCycle is filled with user defined MicroCycles - there are no "filler" MicroCycles
|
||||
# - Sessions are automatically linked to the correct Cycles based on their start/end date - no need for a hard link
|
||||
actualtime = models.IntegerField(default=0,verbose_name='Actual Duration')
|
||||
actualdistance = models.IntegerField(default=0,verbose_name='Actual Distance')
|
||||
actualrscore = models.IntegerField(default=0,verbose_name='Actual rScore')
|
||||
actualtrimp = models.IntegerField(default=0,verbose_name='Actual TRIMP')
|
||||
|
||||
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
stri = 'Micro Cycle - {n} ({sd} - {ed})'.format(
|
||||
n = self.name,
|
||||
sd = self.startdate,
|
||||
ed = self.enddate,
|
||||
)
|
||||
|
||||
return stri
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.enddate < self.startdate:
|
||||
startdate = self.startdate
|
||||
enddate = self.enddate
|
||||
self.startdate = enddate
|
||||
self.enddate = startdate
|
||||
|
||||
fillers = TrainingMicroCycle.objects.filter(
|
||||
plan=self.plan,type='filler')
|
||||
for f in fillers:
|
||||
f.delete()
|
||||
|
||||
if self.enddate > self.plan.enddate:
|
||||
self.enddate = self.plan.enddate
|
||||
|
||||
if self.startdate < self.plan.startdate:
|
||||
self.startdate = self.plan.startdate
|
||||
|
||||
othercycles = TrainingMicroCycle.objects.filter(
|
||||
plan=self.plan).exclude(pk=self.pk).order_by("-startdate")
|
||||
|
||||
for othercycle in othercycles:
|
||||
if othercycle.startdate <= self.enddate and othercycle.startdate >= self.startdate:
|
||||
self.enddate = othercycle.startdate-datetime.timedelta(days=1)
|
||||
|
||||
if othercycle.enddate >= self.startdate and othercycle.enddate <= self.enddate:
|
||||
self.startdate = othercycle.enddate+datetime.timedelta(days=1)
|
||||
|
||||
|
||||
|
||||
if not self.enddate <= self.startdate:
|
||||
super(TrainingMicroCycle,self).save(*args, **kwargs)
|
||||
|
||||
class TrainingMesoCycleForm(ModelForm):
|
||||
class Meta:
|
||||
model = TrainingMesoCycle
|
||||
fields = ['name','startdate','enddate','notes']
|
||||
|
||||
widgets = {
|
||||
'startdate': AdminDateWidget(),
|
||||
'enddate': AdminDateWidget()
|
||||
}
|
||||
|
||||
class TrainingMicroCycleForm(ModelForm):
|
||||
class Meta:
|
||||
model = TrainingMicroCycle
|
||||
fields = ['name','startdate','enddate','notes']
|
||||
|
||||
widgets = {
|
||||
'startdate': AdminDateWidget(),
|
||||
'enddate': AdminDateWidget()
|
||||
}
|
||||
|
||||
# Cycle error checking goes in forms
|
||||
|
||||
# model for Planned Session (Workout, Challenge, Test)
|
||||
class PlannedSession(models.Model):
|
||||
|
||||
@@ -10,7 +10,7 @@ import uuid
|
||||
from django.conf import settings
|
||||
import pytz
|
||||
from utils import myqueue,calculate_age,totaltime_sec_to_string
|
||||
|
||||
import re
|
||||
import django_rq
|
||||
queue = django_rq.get_queue('default')
|
||||
queuelow = django_rq.get_queue('low')
|
||||
@@ -296,52 +296,28 @@ def is_session_complete_ws(ws,ps):
|
||||
if record.coursecompleted:
|
||||
ratio = record.distance/ps.sessionvalue
|
||||
return ratio,'completed',completiondate
|
||||
|
||||
if ps.course:
|
||||
(
|
||||
coursetime,
|
||||
coursemeters,
|
||||
coursecompleted
|
||||
) = get_time_course(ws,ps.course)
|
||||
if coursecompleted:
|
||||
return 1.0,'completed',completiondate
|
||||
else:
|
||||
return ratio,'partial',completiondate
|
||||
else:
|
||||
if ps.criterium == 'exact':
|
||||
if ratio == 1.0:
|
||||
return ratio,'completed',completiondate
|
||||
else:
|
||||
if not completiondate:
|
||||
completiondate = ws.reverse()[0].date
|
||||
return ratio,'partial',completiondate
|
||||
elif ps.criterium == 'minimum':
|
||||
if ratio >= 1.0:
|
||||
return ratio,'completed',completiondate
|
||||
else:
|
||||
if not completiondate:
|
||||
completiondate = ws.reverse()[0].date
|
||||
|
||||
return ratio,'partial',completiondate
|
||||
else:
|
||||
if ratio>cratiomin and ratio<cratiomax:
|
||||
return ratio,'completed',completiondate
|
||||
else:
|
||||
ratio = record.distance/ps.sessionvalue
|
||||
return ratio,'partial',completiondate
|
||||
return (0,'partial',None)
|
||||
elif ps.sessiontype == 'coursetest':
|
||||
vs = CourseTestResult.objects.filter(plannedsession=ps)
|
||||
wids = [w.id for w in ws]
|
||||
for record in vs:
|
||||
if record.workoutid in wids:
|
||||
if record.coursecompleted:
|
||||
ratio = record.distance/ps.sessionvalue
|
||||
ratio = record.distance/float(ps.sessionvalue)
|
||||
return ratio,'completed',completiondate
|
||||
else:
|
||||
ratio = record.distance/float(ps.sessionvalue)
|
||||
return ratio,'partial',completiondate
|
||||
|
||||
# we're still here - no record, need to create one
|
||||
if ws:
|
||||
record = CourseTestResult(
|
||||
userid=ws[0].user.id,
|
||||
plannedsession=ps,
|
||||
workoutid=ws[0].id,
|
||||
duration=dt.time(0,0),
|
||||
coursecompleted=False,
|
||||
)
|
||||
@@ -349,38 +325,9 @@ def is_session_complete_ws(ws,ps):
|
||||
job = myqueue(queue,handle_check_race_course,ws[0].csvfilename,
|
||||
ws[0].id,ps.course.id,record.id,
|
||||
mode='coursetest')
|
||||
|
||||
if ps.course:
|
||||
(
|
||||
coursetime,
|
||||
coursemeters,
|
||||
coursecompleted
|
||||
) = courses.get_time_course(ws,ps.course)
|
||||
if coursecompleted:
|
||||
return 1.0,'completed',completiondate
|
||||
else:
|
||||
return ratio,'partial',completiondate
|
||||
else:
|
||||
if ps.criterium == 'exact':
|
||||
if ratio == 1.0:
|
||||
return ratio,'completed',completiondate
|
||||
else:
|
||||
if not completiondate:
|
||||
completiondate = ws.reverse()[0].date
|
||||
return ratio,'partial',completiondate
|
||||
elif ps.criterium == 'minimum':
|
||||
if ratio >= 1.0:
|
||||
return ratio,'completed',completiondate
|
||||
else:
|
||||
if not completiondate:
|
||||
completiondate = ws.reverse()[0].date
|
||||
|
||||
return ratio,'partial',completiondate
|
||||
else:
|
||||
if ratio>cratiomin and ratio<cratiomax:
|
||||
return ratio,'completed',completiondate
|
||||
else:
|
||||
return ratio,'partial',completiondate
|
||||
return (0,'not done',None)
|
||||
|
||||
|
||||
else:
|
||||
if not completiondate:
|
||||
@@ -391,6 +338,7 @@ def is_session_complete_ws(ws,ps):
|
||||
def is_session_complete(r,ps):
|
||||
status = 'not done'
|
||||
|
||||
|
||||
if r not in ps.rower.all():
|
||||
return 0,'not assigned',None
|
||||
|
||||
@@ -426,6 +374,8 @@ def remove_rower_session(r,ps):
|
||||
|
||||
def get_dates_timeperiod(timeperiod):
|
||||
# set start end date according timeperiod
|
||||
daterangetester = re.compile('^(\d+-\d+-\d+)\/(\d+-\d+-\d+)')
|
||||
|
||||
if timeperiod=='today':
|
||||
startdate=date.today()
|
||||
enddate=date.today()
|
||||
@@ -466,6 +416,19 @@ def get_dates_timeperiod(timeperiod):
|
||||
enddate = startdate+timezone.timedelta(days=32)
|
||||
enddate = enddate.replace(day=1)
|
||||
enddate = enddate-timezone.timedelta(days=1)
|
||||
elif daterangetester.match(timeperiod):
|
||||
startdatestring = daterangetester.match(timeperiod).group(1)
|
||||
enddatestring = daterangetester.match(timeperiod).group(2)
|
||||
try:
|
||||
startdate = dt.datetime.strptime(startdatestring,'%Y-%m-%d').date()
|
||||
enddate = dt.datetime.strptime(enddatestring,'%Y-%m-%d').date()
|
||||
if startdate > enddate:
|
||||
startdate2 = enddate
|
||||
enddate = startdate
|
||||
startdate = startdate2
|
||||
except ValueError:
|
||||
startdate = date.today()
|
||||
enddate = date.today()
|
||||
else:
|
||||
startdate = date.today()
|
||||
enddate = date.today()
|
||||
|
||||
@@ -255,7 +255,7 @@ def handle_check_race_course(self,
|
||||
rowdata.rename(columns = {
|
||||
' latitude':'latitude',
|
||||
' longitude':'longitude',
|
||||
' ElapsedTime (sec)': 'time',
|
||||
'TimeStamp (sec)': 'time',
|
||||
}, inplace=True)
|
||||
|
||||
rowdata.fillna(method='backfill',inplace=True)
|
||||
@@ -299,9 +299,9 @@ def handle_check_race_course(self,
|
||||
cseconds = []
|
||||
cmeters = []
|
||||
ccomplete = []
|
||||
|
||||
|
||||
for startt in entrytimes:
|
||||
|
||||
|
||||
rowdata2 = rowdata[rowdata['time']>(startt-10.)]
|
||||
|
||||
(
|
||||
@@ -322,6 +322,7 @@ def handle_check_race_course(self,
|
||||
coursetimeseconds = coursetimeseconds-coursetimefirst
|
||||
coursemeters = coursemeters-coursemetersfirst
|
||||
|
||||
|
||||
cseconds.append(coursetimeseconds)
|
||||
cmeters.append(coursemeters)
|
||||
ccomplete.append(coursecompleted)
|
||||
@@ -335,6 +336,7 @@ def handle_check_race_course(self,
|
||||
|
||||
records = records[records['coursecompleted'] == True]
|
||||
|
||||
|
||||
if len(records):
|
||||
coursecompleted = True
|
||||
mintime = records['coursetimeseconds'].min()
|
||||
|
||||
@@ -138,7 +138,19 @@
|
||||
Analyse power vs piece duration to make predictions, for erg pieces.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid_2 suffix_2 alpha">
|
||||
<div class="grid_2">
|
||||
<p>
|
||||
{% if user|is_planmember %}
|
||||
<a class="button blue small" href="/rowers/fitness-progress">Power Progress</a>
|
||||
{% else %}
|
||||
<a class="button blue small" href="/rowers/promembership">Power Progress</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
Monitoring power duration evidence from all your workouts. Feel free to explore.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid_2 omega">
|
||||
<p>
|
||||
{% if user|is_planmember %}
|
||||
<a class="button blue small" href="/rowers/laboratory">The Labs</a>
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
<div class="grid_2 alpha">
|
||||
<p>
|
||||
{% if user|is_planmember %}
|
||||
<a class="button blue small" href="/rowers/fitness-progress">Power Progress</a>
|
||||
<a class="button blue small" href="/rowers/createplan">Training Target</a>
|
||||
{% else %}
|
||||
<a class="button blue small" href="/rowers/promembership">Power Progress</a>
|
||||
<a class="button blue small" href="/rowers/promembership">Training Target</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
Monitoring power duration evidence from all your workouts. Feel free to explore.
|
||||
Experiments with a training target and plan builder
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for result in ranking %}
|
||||
{% if result|lookup:'coursecompleted' %}
|
||||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
<td>{{ result|lookup:'name' }}</td>
|
||||
@@ -73,6 +74,7 @@
|
||||
<td>{{ result|lookup:'date'|date:"Y-m-d" }}</td>
|
||||
<td>{{ result|lookup:'type' }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
{% load rowerfilters %}
|
||||
<div class="grid_2 alpha">
|
||||
<p>
|
||||
{% if timeperiod and rower %}
|
||||
<a class="button gray small" href="/rowers/sessions/{{ timeperiod }}/rower/{{ rower.id }}">Plan Overview</a>
|
||||
{% elif timeperiod %}
|
||||
<a class="button gray small" href="/rowers/sessions/{{ timeperiod }}">Plan Overview</a>
|
||||
{% else %}
|
||||
<a class="button gray small" href="/rowers/sessions">Plan Overview</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="grid_2 dropdown alpha">
|
||||
<button class="grid_2 alpha button gray small dropbtn">Overview</button>
|
||||
<div class="dropdown-content">
|
||||
{% if timeperiod and rower %}
|
||||
<a class="button gray small" href="/rowers/sessions/{{ timeperiod }}/rower/{{ rower.id }}">Sessions Overview</a>
|
||||
{% elif timeperiod %}
|
||||
<a class="button gray small" href="/rowers/sessions/{{ timeperiod }}">Sessions Overview</a>
|
||||
{% else %}
|
||||
<a class="button gray small" href="/rowers/sessions">Sessions Overview</a>
|
||||
{% endif %}
|
||||
{% if plan %}
|
||||
<a class="button gray small" href="/rowers/plan/{{ plan.id }}">Plan Overview</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid_2">
|
||||
<p>
|
||||
|
||||
221
rowers/templates/trainingplan.html
Normal file
221
rowers/templates/trainingplan.html
Normal file
@@ -0,0 +1,221 @@
|
||||
{% extends "base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load rowerfilters %}
|
||||
|
||||
{% block title %}Rowsandall Training Plans{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<style>
|
||||
#mypointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="grid_12">
|
||||
<div class="grid_12 alpha">
|
||||
<h1>Training Plan - {{ plan.name }}</h1>
|
||||
<p>This plan starts on {{ plan.startdate }} and ends on {{ plan.enddate }}. The training plan target is: {{ plan.target.name }} on {{ plan.target.date }}.</p>
|
||||
<p><a href="/rowers/editplan/{{ plan.id }}">Edit the plan</a></p>
|
||||
</div>
|
||||
<div class="grid_4 alpha">
|
||||
<h2>Macro Cycles</h2>
|
||||
</div>
|
||||
<div class="grid_4 alpha">
|
||||
<h2>Meso Cycles</h2>
|
||||
</div>
|
||||
<div class="grid_4">
|
||||
<h2>Micro Cycles</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid_12 alpha">
|
||||
{% now "Y-m-d" as todays_date %}
|
||||
{% for key,macrocycle in cycles.items %}
|
||||
<div class="grid_12 alpha">
|
||||
{% if macrocycle.0.type == 'filler' %}
|
||||
<div class="grid_4 filler alpha">
|
||||
{% else %}
|
||||
<div class="grid_4 palegreen alpha">
|
||||
{% endif %}
|
||||
<div class="padded">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<th colspan="4">
|
||||
{{ macrocycle.0.name }} ({{ macrocycle.0.startdate }} - {{ macrocycle.0.enddate }})
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dist (m)</td>
|
||||
<td>t (min)</td>
|
||||
<td>rScore</td>
|
||||
<td>TRIMP</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>plan</td>
|
||||
<td>{{ macrocycle.0.plandistance }}</td>
|
||||
<td>{{ macrocycle.0.plantime }}</td>
|
||||
<td>{{ maccrocycle.0.planrscore }}</td>
|
||||
<td>{{ macrocycle.0.plantrimp }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>actual</td>
|
||||
<td>{{ macrocycle.0.actualdistance }}</td>
|
||||
<td>{{ macrocycle.0.actualtime }}</td>
|
||||
<td>{{ macrocycle.0.actualrscore }}</td>
|
||||
<td>{{ macrocycle.0.actualtrimp }}</td>
|
||||
</tr>
|
||||
{% if todays_date <= macrocycle.0.enddate|date:"Y-m-d" %}
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<a href="/rowers/macrocycle/{{ macrocycle.0.id }}">edit</a>
|
||||
/
|
||||
<a href="/rowers/deletemacrocycle/{{ macrocycle.0.id }}">delete</a>
|
||||
/
|
||||
<a href='/rowers/sessions/{{ macrocycle.0.startdate|date:"Y-m-d" }}/{{ macrocycle.0.enddate|date:"Y-m-d" }}'>sessions</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid_8 alpha">
|
||||
{% for key, mesocycle in macrocycle.1.items %}
|
||||
{% if mesocycle.0.type == 'filler' %}
|
||||
<div class="grid_4 filler alpha">
|
||||
{% else %}
|
||||
<div class="grid_4 lightsalmon alpha">
|
||||
{% endif %}
|
||||
<div class="padded">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<th colspan="4">
|
||||
{{ mesocycle.0.name }} ({{ mesocycle.0.startdate }} - {{ mesocycle.0.enddate }})
|
||||
</th>
|
||||
</tr>
|
||||
{% if mesocycle.0.plan.type == 'userdefined' %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dist (m)</td>
|
||||
<td>t (min)</td>
|
||||
<td>rScore</td>
|
||||
<td>TRIMP</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>plan</td>
|
||||
<td>{{ mesocycle.0.plandistance }}</td>
|
||||
<td>{{ mesocycle.0.plantime }}</td>
|
||||
<td>{{ mesocycle.0.planrscore }}</td>
|
||||
<td>{{ mesocycle.0.plantrimp }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>actual</td>
|
||||
<td>{{ mesocycle.0.actualdistance }}</td>
|
||||
<td>{{ mesocycle.0.actualtime }}</td>
|
||||
<td>{{ mesocycle.0.actualrscore }}</td>
|
||||
<td>{{ mesocycle.0.actualtrimp }}</td>
|
||||
</tr>
|
||||
{% if todays_date <= mesocycle.0.enddate|date:"Y-m-d" %}
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<a href="/rowers/microcycle/{{ mesocycle.0.id }}">edit</a>
|
||||
/
|
||||
<a href="/rowers/deletemicrocycle/{{ mesocycle.0.id }}">delete</a>
|
||||
/
|
||||
<a href='/rowers/sessions/{{ mesocycle.0.startdate|date:"Y-m-d" }}/{{ mesocycle.0.enddate|date:"Y-m-d" }}'>sessions</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid_4 omega">
|
||||
{% for microcycle in mesocycle.1 %}
|
||||
{% if microcycle.type == 'filler' %}
|
||||
<div class="grid_4 filler">
|
||||
{% else %}
|
||||
<div class="grid_4 paleblue ">
|
||||
{% endif %}
|
||||
<div class="padded">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<th colspan="4">
|
||||
{{ microcycle.name }} ({{ microcycle.startdate }} - {{ microcycle.enddate }})
|
||||
</th>
|
||||
</tr>
|
||||
{% if microcycle.plan.type == 'userdefined' %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dist (m)</td>
|
||||
<td>t (min)</td>
|
||||
<td>rScore</td>
|
||||
<td>TRIMP</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>plan</td>
|
||||
<td>{{ microcycle.plandistance }}</td>
|
||||
<td>{{ microcycle.plantime }}</td>
|
||||
<td>{{ microcycle.planrscore }}</td>
|
||||
<td>{{ microcycle.plantrimp }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>actual</td>
|
||||
<td>{{ microcycle.actualdistance }}</td>
|
||||
<td>{{ microcycle.actualtime }}</td>
|
||||
<td>{{ microcycle.actualrscore }}</td>
|
||||
<td>{{ microcycle.actualtrimp }}</td>
|
||||
</tr>
|
||||
{% if todays_date <= microcycle.enddate|date:"Y-m-d" %}
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<a href="/rowers/microcycle/{{ microcycle.id }}">edit</a>
|
||||
/
|
||||
<a href="/rowers/deletemicrocycle/{{ microcycle.id }}">delete</a>
|
||||
/
|
||||
<a href='/rowers/sessions/{{ microcycle.startdate|date:"Y-m-d" }}/{{ microcycle.enddate|date:"Y-m-d" }}'>sessions</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="grid_12">
|
||||
<p>Click on the plan cycles to edit their names, start and end dates. The gray "filler"
|
||||
cycles are generated, adjusted and deleted automatically to ensure the entire plan
|
||||
duration is covered with non-overlapping cycles.
|
||||
Once you edit a filler cycle, it become a user-defined cycle, which cannot be deleted
|
||||
by the system.</p>
|
||||
<p>Filler cycles which have a filler cycle as a parent cannot be edited
|
||||
or deleted. You have to edit the parent cycle first. The reason is
|
||||
that children of filler cycles are not safe. They are deleted when
|
||||
their parent is deleted by the system.</p>
|
||||
<p>Click on "Sessions" in the cycle of your interest to see details
|
||||
of the individual training sessions planned for this period.</p>
|
||||
<p>A good way to organize the plan is to think of micro cycles as training weeks. Macro cycles
|
||||
are typically used to address specific phases of preparation and to indicate the racing
|
||||
season and may span several months.
|
||||
Meso cycles can be used to group sequences of three to five light, medium and
|
||||
hard weeks. It is recommended to work from left to right, starting with the macro cycles.</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -15,7 +15,23 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="grid_12">
|
||||
<div class="grid_12 alpha">
|
||||
{% if user.is_authenticated and user|is_manager %}
|
||||
<div class="grid_2 prefix_8 dropdown">
|
||||
<button class="grid_2 alpha button green small dropbtn">
|
||||
{{ rower.user.first_name }} {{ rower.user.last_name }}
|
||||
</button>
|
||||
<div class="dropdown-content">
|
||||
{% for member in user|team_members %}
|
||||
<a class="button green small" href="/rowers/createplan/{{ member.id }}">{{ member.first_name }} {{ member.last_name }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid_12 alpha">
|
||||
<div id="targets_table" class="grid_8 alpha">
|
||||
<h1>Training Targets</h1>
|
||||
|
||||
@@ -34,6 +50,8 @@
|
||||
<td> {{ target.date }}</td>
|
||||
<td> {{ target.name }}</td>
|
||||
<td> {{ target.notes }}</td>
|
||||
<td> <a href="/rowers/edittarget/{{ target.id }}">Edit</a>
|
||||
<td> <a href="/rowers/deletetarget/{{ target.id }}">Delete</a>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@@ -62,8 +80,8 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid_12">
|
||||
|
||||
<div class="grid_12 alpha">
|
||||
|
||||
<div id="courses_table" class="grid_8 alpha">
|
||||
<h1>Plans</h1>
|
||||
|
||||
@@ -81,7 +99,10 @@
|
||||
<tr>
|
||||
<td> {{ plan.startdate }} </td>
|
||||
<td> {{ plan.enddate }}</td>
|
||||
<td> {{ plan.name }}</td>
|
||||
<td><a href="/rowers/plan/{{ plan.id }}">{{ plan.name }}</a></td>
|
||||
<td> <a href="/rowers/editplan/{{ plan.id }}">Edit</a></td>
|
||||
<td> <a href="/rowers/plan/{{ plan.id }}">Plan</a></td>
|
||||
<td> <a href="/rowers/deleteplan/{{ plan.id }}">Delete</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
30
rowers/templates/trainingplan_delete.html
Normal file
30
rowers/templates/trainingplan_delete.html
Normal file
@@ -0,0 +1,30 @@
|
||||
{% extends "base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load rowerfilters %}
|
||||
|
||||
{% block title %}Rowsandall Training Plans{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<style>
|
||||
#mypointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="grid_12 alpha">
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<p>Are you sure you want to delete <i>{{ object }}</i>?</p>
|
||||
<div id="formbutton" class="grid_1 prefix_2">
|
||||
<input class="button red" type="submit" value="Confirm">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
32
rowers/templates/trainingplan_edit.html
Normal file
32
rowers/templates/trainingplan_edit.html
Normal file
@@ -0,0 +1,32 @@
|
||||
{% extends "base.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load rowerfilters %}
|
||||
|
||||
{% block title %}Rowsandall Training Plans{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<style>
|
||||
#mypointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="grid_12">
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
</table>
|
||||
<div class="grid_1 prefix_2 suffix_9 alpha">
|
||||
<input class="button green" type="submit" value="Save">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -275,3 +275,10 @@ def future_registered(race,r):
|
||||
is_complete, has_registered = race_rower_status(r,race)
|
||||
is_open = race.evaluation_closure > timezone.now()
|
||||
return has_registered and not is_complete and is_open
|
||||
|
||||
@property
|
||||
def is_past_due(self):
|
||||
return datetime.date.today() > self.date
|
||||
@property
|
||||
def is_not_past_due(self):
|
||||
return datetime.date.today() <= self.date
|
||||
|
||||
@@ -20,7 +20,6 @@ from subprocess import call
|
||||
import re
|
||||
|
||||
from verbalexpressions import VerEx
|
||||
import re
|
||||
|
||||
import django_rq
|
||||
queue = django_rq.get_queue('default')
|
||||
|
||||
@@ -420,7 +420,19 @@ urlpatterns = [
|
||||
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'^createplan$',views.rower_create_trainingplan),
|
||||
url(r'^createplan/(?P<id>\d+)$',views.rower_create_trainingplan),
|
||||
url(r'^createplan/(?P<userid>\d+)$',views.rower_create_trainingplan),
|
||||
url(r'^deleteplan/(?P<pk>\d+)$',views.TrainingPlanDelete.as_view()),
|
||||
url(r'^deletemicrocycle/(?P<pk>\d+)$',views.MicroCycleDelete.as_view()),
|
||||
url(r'^deletemesocycle/(?P<pk>\d+)$',views.MesoCycleDelete.as_view()),
|
||||
url(r'^deletemacrocycle/(?P<pk>\d+)$',views.MacroCycleDelete.as_view()),
|
||||
# url(r'^deleteplan/(?P<id>\d+)$',views.rower_delete_trainingplan),
|
||||
url(r'^plan/(?P<id>\d+)$',views.rower_trainingplan_view),
|
||||
url(r'^macrocycle/(?P<pk>\d+)$',views.TrainingMacroCycleUpdate.as_view()),
|
||||
url(r'^mesocycle/(?P<pk>\d+)$',views.TrainingMesoCycleUpdate.as_view()),
|
||||
url(r'^microcycle/(?P<pk>\d+)$',views.TrainingMicroCycleUpdate.as_view()),
|
||||
url(r'^deletetarget/(?P<id>\d+)$',views.rower_delete_trainingtarget),
|
||||
url(r'^editplan/(?P<pk>\d+)$',views.TrainingPlanUpdate.as_view()),
|
||||
url(r'^edittarget/(?P<pk>\d+)$',views.TrainingTargetUpdate.as_view()),
|
||||
url(r'^workout/(?P<id>\d+)/test\_strokedata$',views.strokedataform),
|
||||
|
||||
url(r'^sessions/teamcreate$',views.plannedsession_teamcreate_view),
|
||||
|
||||
555
rowers/views.py
555
rowers/views.py
@@ -27,6 +27,9 @@ import codecs
|
||||
import isodate
|
||||
|
||||
from django.shortcuts import render
|
||||
|
||||
from django.views.generic.edit import UpdateView,DeleteView
|
||||
|
||||
from django.http import (
|
||||
HttpResponse, HttpResponseRedirect,
|
||||
HttpResponseForbidden, HttpResponseNotAllowed,
|
||||
@@ -42,7 +45,8 @@ from rowers.forms import (
|
||||
VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm,
|
||||
RaceResultFilterForm,PowerIntervalUpdateForm
|
||||
)
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.urlresolvers import reverse, reverse_lazy
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.template import RequestContext
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
@@ -68,6 +72,10 @@ from rowers.models import (
|
||||
TrainingPlan,TrainingPlanForm,TrainingTarget,TrainingTargetForm,
|
||||
TrainingMacroCycle,TrainingMesoCycle,TrainingMicroCycle,
|
||||
TrainingTarget,TrainingTargetForm,
|
||||
TrainingMacroCycleForm,createmacrofillers,
|
||||
createmicrofillers, createmesofillers,
|
||||
microcyclecheckdates,mesocyclecheckdates,macrocyclecheckdates,
|
||||
TrainingMesoCycleForm, TrainingMicroCycleForm,
|
||||
)
|
||||
from rowers.models import (
|
||||
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
|
||||
@@ -125,6 +133,9 @@ from rowers.tasks_standalone import addcomment2
|
||||
from django.contrib import messages
|
||||
from async_messages import messages as a_messages
|
||||
|
||||
from django.contrib.admin.widgets import AdminDateWidget,AdminTimeWidget,AdminSplitDateTime
|
||||
|
||||
|
||||
import requests
|
||||
import json
|
||||
from rest_framework.renderers import JSONRenderer
|
||||
@@ -197,6 +208,7 @@ class JSONResponse(HttpResponse):
|
||||
|
||||
def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
|
||||
|
||||
|
||||
if notpermanent == False:
|
||||
if rowerid == 0 and 'rowerid' in request.session:
|
||||
rowerid = request.session['rowerid']
|
||||
@@ -12453,8 +12465,18 @@ def plannedsession_multiclone_view(
|
||||
|
||||
dateshiftform = SessionDateShiftForm()
|
||||
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
|
||||
return render(request, 'plannedsessions_multiclone_select.html',
|
||||
{'plannedsessions':sps,
|
||||
'plan':trainingplan,
|
||||
'dateform':dateform,
|
||||
'startdate':startdate,
|
||||
'enddate':enddate,
|
||||
@@ -12471,6 +12493,7 @@ def plannedsession_multiclone_view(
|
||||
def plannedsession_create_view(request,timeperiod='thisweek',rowerid=0):
|
||||
|
||||
r = getrequestrower(request,rowerid=rowerid)
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
if request.method == 'POST':
|
||||
sessioncreateform = PlannedSessionForm(request.POST)
|
||||
@@ -12527,31 +12550,60 @@ def plannedsession_create_view(request,timeperiod='thisweek',rowerid=0):
|
||||
fstartdate = arrow.get(request.session['fstartdate']).date()
|
||||
except KeyError:
|
||||
fstartdate = timezone.now().date()
|
||||
if fstartdate < startdate:
|
||||
fstartdate = startdate
|
||||
try:
|
||||
fenddate = arrow.get(request.session['fenddate']).date()
|
||||
except KeyError:
|
||||
fenddate = timezone.now().date()
|
||||
if fenddate > enddate:
|
||||
fenddate = enddate
|
||||
try:
|
||||
fprefdate = arrow.get(request.session['fprefdate']).date()
|
||||
except KeyError:
|
||||
fprefdate = timezone.now().date()
|
||||
|
||||
if fprefdate < startdate:
|
||||
fprefdate = startdate
|
||||
|
||||
if fprefdate > enddate:
|
||||
fprefdate = enddate
|
||||
|
||||
forminitial = {
|
||||
'startdate':fstartdate,
|
||||
'enddate':fenddate,
|
||||
'preferreddate':fprefdate
|
||||
}
|
||||
else:
|
||||
forminitial = {}
|
||||
preferreddate = startdate
|
||||
if preferreddate < timezone.now().date():
|
||||
preferreddate = timezone.now().date()
|
||||
|
||||
if preferreddate > enddate:
|
||||
preferreddate = enddate
|
||||
|
||||
forminitial = {
|
||||
'startdate':startdate,
|
||||
'enddate':enddate,
|
||||
'preferreddate':preferreddate,
|
||||
}
|
||||
|
||||
sessioncreateform = PlannedSessionForm(initial=forminitial)
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
sps = get_sessions(r,startdate=startdate,enddate=enddate)
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
|
||||
return render(request,'plannedsessioncreate.html',
|
||||
{
|
||||
'teams':get_my_teams(request.user),
|
||||
'plan':trainingplan,
|
||||
'form':sessioncreateform,
|
||||
'plannedsessions':sps,
|
||||
'rower':r,
|
||||
@@ -12568,6 +12620,14 @@ def plannedsession_multicreate_view(request,timeperiod='thisweek',
|
||||
r = getrequestrower(request,rowerid=rowerid)
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
sps = get_sessions(r,startdate=startdate,enddate=enddate)
|
||||
|
||||
m = Rower.objects.get(user=request.user)
|
||||
@@ -12642,6 +12702,7 @@ def plannedsession_multicreate_view(request,timeperiod='thisweek',
|
||||
context = {
|
||||
'ps_formset':ps_formset,
|
||||
'rower':r,
|
||||
'plan':trainingplan,
|
||||
'timeperiod':timeperiod,
|
||||
'teams':get_my_teams(request.user),
|
||||
'extrasessions': extrasessions+1
|
||||
@@ -12667,6 +12728,14 @@ def plannedsession_teamcreate_view(request,timeperiod='thisweek',
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
sps = []
|
||||
for team in teams:
|
||||
res = get_sessions_manager(request.user,startdate=startdate,enddate=enddate)
|
||||
@@ -12739,6 +12808,7 @@ def plannedsession_teamcreate_view(request,timeperiod='thisweek',
|
||||
return render(request,'plannedsessionteamcreate.html',
|
||||
{
|
||||
'teams':get_my_teams(request.user),
|
||||
'plan':trainingplan,
|
||||
'form':sessioncreateform,
|
||||
'teamform':sessionteamselectform,
|
||||
'timeperiod':timeperiod,
|
||||
@@ -12766,6 +12836,14 @@ def plannedsession_teamedit_view(request,timeperiod='thisweek',
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
sps = []
|
||||
rowers = []
|
||||
for team in teams:
|
||||
@@ -12852,6 +12930,7 @@ def plannedsession_teamedit_view(request,timeperiod='thisweek',
|
||||
return render(request,'plannedsessionteamedit.html',
|
||||
{
|
||||
'plannedsession':ps,
|
||||
'plan':trainingplan,
|
||||
'teams':get_my_teams(request.user),
|
||||
'form':sessioncreateform,
|
||||
'teamform':sessionteamselectform,
|
||||
@@ -12867,6 +12946,8 @@ def plannedsessions_coach_view(request,timeperiod='thisweek',
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
trainingplan = None
|
||||
|
||||
if teamid != 0:
|
||||
try:
|
||||
theteam = Team.objects.get(id=teamid)
|
||||
@@ -12916,6 +12997,7 @@ def plannedsessions_coach_view(request,timeperiod='thisweek',
|
||||
{
|
||||
'myteams':myteams,
|
||||
'plannedsessions':sps,
|
||||
'plan':trainingplan,
|
||||
'statusdict':statusdict,
|
||||
'timeperiod':timeperiod,
|
||||
'rowers':rowers,
|
||||
@@ -12931,7 +13013,16 @@ def plannedsessions_view(request,timeperiod='thisweek',rowerid=0):
|
||||
r = getrequestrower(request,rowerid=rowerid)
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
|
||||
sps = get_sessions(r,startdate=startdate,enddate=enddate)
|
||||
|
||||
completeness = {}
|
||||
@@ -12954,6 +13045,7 @@ def plannedsessions_view(request,timeperiod='thisweek',rowerid=0):
|
||||
{
|
||||
'teams':get_my_teams(request.user),
|
||||
'plannedsessions':sps,
|
||||
'plan':trainingplan,
|
||||
'rower':r,
|
||||
'timeperiod':timeperiod,
|
||||
'completeness':completeness,
|
||||
@@ -12969,6 +13061,14 @@ def plannedsessions_print_view(request,timeperiod='thisweek',rowerid=0):
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
sps = get_sessions(r,startdate=startdate,enddate=enddate)
|
||||
|
||||
completeness = {}
|
||||
@@ -12978,6 +13078,7 @@ def plannedsessions_print_view(request,timeperiod='thisweek',rowerid=0):
|
||||
return render(request,'plannedsessions_print.html',
|
||||
{
|
||||
'teams':get_my_teams(request.user),
|
||||
'plan':trainingplan,
|
||||
'plannedsessions':sps,
|
||||
'rower':r,
|
||||
'startdate':startdate,
|
||||
@@ -12998,6 +13099,14 @@ def plannedsessions_manage_view(request,timeperiod='thisweek',rowerid=0,
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
sps = get_sessions(r,startdate=startdate,enddate=enddate)
|
||||
if initialsession==0:
|
||||
try:
|
||||
@@ -13098,6 +13207,7 @@ def plannedsessions_manage_view(request,timeperiod='thisweek',rowerid=0,
|
||||
return render(request,'plannedsessionsmanage.html',
|
||||
{
|
||||
'teams':get_my_teams(request.user),
|
||||
'plan':trainingplan,
|
||||
'plannedsessions':sps,
|
||||
'workouts':ws,
|
||||
'timeperiod':timeperiod,
|
||||
@@ -13108,6 +13218,7 @@ def plannedsessions_manage_view(request,timeperiod='thisweek',rowerid=0,
|
||||
|
||||
|
||||
# Clone an existing planned session
|
||||
# need clarity on cloning behavior time shift
|
||||
@user_passes_test(hasplannedsessions,login_url="/rowers/planmembership/",
|
||||
redirect_field_name=None)
|
||||
def plannedsession_clone_view(request,id=0,rowerid=0,
|
||||
@@ -13117,6 +13228,14 @@ def plannedsession_clone_view(request,id=0,rowerid=0,
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
try:
|
||||
ps = PlannedSession.objects.get(id=id)
|
||||
except PlannedSession.DoesNotExist:
|
||||
@@ -13134,8 +13253,9 @@ def plannedsession_clone_view(request,id=0,rowerid=0,
|
||||
|
||||
ps.startdate = timezone.now().date()
|
||||
ps.enddate = (timezone.now()+deltadays).date()
|
||||
ps.preferreddate = ps.preferreddate+deltadays
|
||||
ps.name += ' (copy)'
|
||||
|
||||
|
||||
ps.save()
|
||||
|
||||
for rower in rowers:
|
||||
@@ -13164,6 +13284,14 @@ def plannedsession_edit_view(request,id=0,timeperiod='thisweek',rowerid=0):
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
|
||||
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
try:
|
||||
ps = PlannedSession.objects.get(id=id)
|
||||
except PlannedSession.DoesNotExist:
|
||||
@@ -13213,6 +13341,7 @@ def plannedsession_edit_view(request,id=0,timeperiod='thisweek',rowerid=0):
|
||||
return render(request,'plannedsessionedit.html',
|
||||
{
|
||||
'teams':get_my_teams(request.user),
|
||||
'plan':trainingplan,
|
||||
'form':sessioncreateform,
|
||||
'plannedsessions':sps,
|
||||
'thesession':ps,
|
||||
@@ -13289,9 +13418,12 @@ def plannedsession_view(request,id=0,rowerid=0,
|
||||
'distance': w.distance,
|
||||
'time': dddelta,
|
||||
'type': w.workouttype,
|
||||
'coursecompleted':True,
|
||||
}
|
||||
if ps.sessiontype == 'coursetest':
|
||||
vs = CourseTestResult.objects.filter(plannedsession=ps)
|
||||
vs = CourseTestResult.objects.filter(plannedsession=ps,
|
||||
workoutid=w.id)
|
||||
|
||||
if vs:
|
||||
for record in vs:
|
||||
if record.workoutid == w.id:
|
||||
@@ -13305,20 +13437,27 @@ def plannedsession_view(request,id=0,rowerid=0,
|
||||
microseconds=t.microsecond
|
||||
)
|
||||
wdict['distance'] = int(round(coursemeters))
|
||||
wdict['coursecompleted'] = coursecompleted
|
||||
else:
|
||||
(
|
||||
coursetimeseconds,
|
||||
coursemeters,
|
||||
coursecompleted
|
||||
) = courses.get_time_course([w],ps.course)
|
||||
intsecs = int(coursetimeseconds)
|
||||
microsecs = int(1.e6*(coursetimeseconds-intsecs))
|
||||
record = CourseTestResult(
|
||||
userid=w.user.id,
|
||||
workoutid=w.id,
|
||||
plannedsession=ps,
|
||||
duration=w.duration,
|
||||
coursecompleted=False,
|
||||
)
|
||||
record.save()
|
||||
job = myqueue(queue,handle_check_race_course,
|
||||
w.csvfilename,w.id,ps.course.id,
|
||||
record.id,mode='coursetest')
|
||||
|
||||
intsecs = 0
|
||||
microsecs = 0
|
||||
|
||||
wdict['time'] = datetime.timedelta(
|
||||
seconds=intsecs,
|
||||
microseconds=microsecs
|
||||
)
|
||||
wdict['distance'] = int(round(coursemeters))
|
||||
# taking workout duration plus 1 minute penalty
|
||||
wdict['time'] = w.duration
|
||||
wdict['distance'] = ps.course.distance
|
||||
wdict['coursecompleted'] = False
|
||||
|
||||
|
||||
ranking.append(wdict)
|
||||
@@ -13327,6 +13466,14 @@ def plannedsession_view(request,id=0,rowerid=0,
|
||||
|
||||
# if coursetest, need to reorder the ranking
|
||||
|
||||
startdate,enddate = get_dates_timeperiod(timeperiod)
|
||||
try:
|
||||
trainingplan = TrainingPlan.objects.filter(
|
||||
startdate__lte = startdate,
|
||||
rower = r,
|
||||
enddate__gte = enddate)[0]
|
||||
except IndexError:
|
||||
trainingplan = None
|
||||
|
||||
return render(request,'plannedsessionview.html',
|
||||
{
|
||||
@@ -13341,6 +13488,7 @@ def plannedsession_view(request,id=0,rowerid=0,
|
||||
'manager':m,
|
||||
'rower':r,
|
||||
'ratio':ratio,
|
||||
'plan':trainingplan,
|
||||
'status':status,
|
||||
'results':resultsdict,
|
||||
'plannedsession':ps,
|
||||
@@ -14171,12 +14319,11 @@ def virtualevent_submit_result_view(request,id=0):
|
||||
})
|
||||
|
||||
@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None)
|
||||
def rower_create_trainingplan(request,id=0):
|
||||
def rower_create_trainingplan(request,userid=0):
|
||||
|
||||
therower = getrequestrower(request,userid=id)
|
||||
therower = getrequestrower(request,userid=userid)
|
||||
theuser = therower.user
|
||||
|
||||
|
||||
if request.method == 'POST' and 'date' in request.POST:
|
||||
targetform = TrainingTargetForm(request.POST)
|
||||
if targetform.is_valid():
|
||||
@@ -14221,10 +14368,376 @@ def rower_create_trainingplan(request,id=0):
|
||||
return render(request,'trainingplan_create.html',
|
||||
{
|
||||
'form':form,
|
||||
'rower':therower,
|
||||
'plans':plans,
|
||||
'targets':targets,
|
||||
'targetform':targetform,
|
||||
})
|
||||
|
||||
@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None)
|
||||
def rower_delete_trainingtarget(request,id=0):
|
||||
try:
|
||||
target = TrainingTarget.objects.get(id=id)
|
||||
except TrainingPlan.DoesNotExist:
|
||||
raise Http404("Training Plan Does Not Exist")
|
||||
|
||||
if checkaccessuser(request.user,target.rower):
|
||||
target.delete()
|
||||
messages.info(request,"We have deleted the training plan")
|
||||
else:
|
||||
raise PermissionDenied("Access denied")
|
||||
|
||||
url = reverse(rower_create_trainingplan)
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None)
|
||||
def rower_delete_trainingplan(request,id=0):
|
||||
try:
|
||||
plan = TrainingPlan.objects.get(id=id)
|
||||
except TrainingPlan.DoesNotExist:
|
||||
raise Http404("Training Plan Does Not Exist")
|
||||
|
||||
if checkaccessuser(request.user,plan.rower):
|
||||
plan.delete()
|
||||
messages.info(request,"We have deleted the training plan")
|
||||
else:
|
||||
raise PermissionDenied("Access denied")
|
||||
|
||||
url = reverse(rower_create_trainingplan)
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
class TrainingPlanDelete(DeleteView):
|
||||
model = TrainingPlan
|
||||
template_name = 'trainingplan_delete.html'
|
||||
success_url = reverse_lazy(rower_create_trainingplan)
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(TrainingPlanDelete, self).get_object(*args, **kwargs)
|
||||
if not checkaccessuser(self.request.user,obj.plan.rower):
|
||||
raise Http404
|
||||
|
||||
return obj
|
||||
|
||||
class MicroCycleDelete(DeleteView):
|
||||
model = TrainingMicroCycle
|
||||
template_name = 'trainingplan_delete.html'
|
||||
|
||||
def get_success_url(self):
|
||||
plan = self.object.plan.plan.plan
|
||||
createmacrofillers(plan)
|
||||
return reverse(rower_trainingplan_view,
|
||||
kwargs = {
|
||||
'id':plan.id
|
||||
})
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(MicroCycleDelete, self).get_object(*args, **kwargs)
|
||||
if not checkaccessuser(self.request.user,obj.plan.plan.plan.rower):
|
||||
raise Http404
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
class MesoCycleDelete(DeleteView):
|
||||
model = TrainingMesoCycle
|
||||
template_name = 'trainingplan_delete.html'
|
||||
|
||||
def get_success_url(self):
|
||||
plan = self.object.plan.plan
|
||||
createmacrofillers(plan)
|
||||
return reverse(rower_trainingplan_view,
|
||||
kwargs = {
|
||||
'id':plan.id
|
||||
})
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(MesoCycleDelete, self).get_object(*args, **kwargs)
|
||||
if not checkaccessuser(self.request.user,obj.plan.plan.rower):
|
||||
raise Http404
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
class MacroCycleDelete(DeleteView):
|
||||
model = TrainingMacroCycle
|
||||
template_name = 'trainingplan_delete.html'
|
||||
|
||||
def get_success_url(self):
|
||||
plan = self.object.plan
|
||||
createmacrofillers(plan)
|
||||
return reverse(rower_trainingplan_view,
|
||||
kwargs = {
|
||||
'id':plan.id
|
||||
})
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(MacroCycleDelete, self).get_object(*args, **kwargs)
|
||||
if not checkaccessuser(self.request.user,obj.plan.rower):
|
||||
raise Http404
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
|
||||
|
||||
@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None)
|
||||
def rower_trainingplan_view(request,id=0):
|
||||
try:
|
||||
plan = TrainingPlan.objects.get(id=id)
|
||||
except TrainingPlan.DoesNotExist:
|
||||
raise Http404("Training Plan Does Not Exist")
|
||||
|
||||
if not checkaccessuser(request.user,plan.rower):
|
||||
raise PermissionDenied("Access denied")
|
||||
|
||||
createmacrofillers(plan)
|
||||
macrocycles = TrainingMacroCycle.objects.filter(plan=plan).order_by("startdate")
|
||||
|
||||
count = 0
|
||||
cycles = {}
|
||||
|
||||
r = plan.rower
|
||||
|
||||
for m in macrocycles:
|
||||
createmesofillers(m)
|
||||
m.plantime = 0
|
||||
m.actualtime = 0
|
||||
m.plandistance = 0
|
||||
m.actualdistance = 0
|
||||
m.planrscore = 0
|
||||
m.actualrscore = 0
|
||||
m.plantrimp = 0
|
||||
m.actualtrimp = 0
|
||||
|
||||
|
||||
mesocycles = TrainingMesoCycle.objects.filter(plan=m).order_by("startdate")
|
||||
mesos = {}
|
||||
count2 = 0
|
||||
for me in mesocycles:
|
||||
createmicrofillers(me)
|
||||
me.plantime = 0
|
||||
me.actualtime = 0
|
||||
me.plandistance = 0
|
||||
me.actualdistance = 0
|
||||
me.planrscore = 0
|
||||
me.actualrscore = 0
|
||||
me.plantrimp = 0
|
||||
me.actualtrimp = 0
|
||||
|
||||
microcycles = TrainingMicroCycle.objects.filter(plan=me).order_by("startdate")
|
||||
|
||||
for mm in microcycles:
|
||||
sps = PlannedSession.objects.filter(
|
||||
rower = plan.rower,
|
||||
startdate__lte=mm.enddate,
|
||||
enddate__gte=mm.startdate)
|
||||
|
||||
|
||||
mm.plantime = 0
|
||||
mm.actualtime = 0
|
||||
mm.plandistance = 0
|
||||
mm.actualdistance = 0
|
||||
mm.planrscore = 0
|
||||
mm.actualrscore = 0
|
||||
mm.plantrimp = 0
|
||||
mm.actualtrimp = 0
|
||||
|
||||
|
||||
if mm.type == 'userdefined':
|
||||
for ps in sps:
|
||||
ratio, status, cdate = is_session_complete(r,ps)
|
||||
if ps.sessionmode == 'time':
|
||||
mm.plantime += ps.sessionvalue
|
||||
mm.actualtime += int(ps.sessionvalue*ratio)
|
||||
elif ps.sessionmode == 'distance':
|
||||
mm.plandistance += ps.sessionvalue
|
||||
mm.actualdistance += int(ps.sessionvalue*ratio)
|
||||
elif ps.sessionmode == 'rScore':
|
||||
mm.planrscore += ps.sessionvalue
|
||||
mm.actualrscore += int(ps.sessionvalue*ratio)
|
||||
elif ps.sessionmode == 'TRIMP':
|
||||
mm.plantrimp += ps.sessionvalue
|
||||
mm.actualtrimp += int(ps.sessionvalue*ratio)
|
||||
|
||||
mm.save()
|
||||
|
||||
me.plantime += mm.plantime
|
||||
me.actualtime += mm.actualtime
|
||||
me.plandistance += mm.plandistance
|
||||
me.actualdistance += mm.actualdistance
|
||||
me.planrscore += mm.planrscore
|
||||
me.actualrscore += mm.actualrscore
|
||||
me.plantrimp += mm.plantrimp
|
||||
me.actualtrimp += mm.actualtrimp
|
||||
|
||||
if me.type == 'userdefined':
|
||||
me.save()
|
||||
|
||||
m.plantime += me.plantime
|
||||
m.actualtime += me.actualtime
|
||||
m.plandistance += me.plandistance
|
||||
m.actualdistance += me.actualdistance
|
||||
m.planrscore += me.planrscore
|
||||
m.actualrscore += me.actualrscore
|
||||
m.plantrimp += me.plantrimp
|
||||
m.actualtrimp += me.actualtrimp
|
||||
|
||||
|
||||
mesos[count2] = (me, microcycles)
|
||||
count2 += 1
|
||||
|
||||
if m.type == 'userdefined':
|
||||
m.save()
|
||||
cycles[count] = (m,mesos)
|
||||
count += 1
|
||||
|
||||
|
||||
return render(request,'trainingplan.html',
|
||||
{
|
||||
'plan':plan,
|
||||
'cycles':cycles,
|
||||
}
|
||||
)
|
||||
|
||||
class TrainingMacroCycleUpdate(UpdateView):
|
||||
model = TrainingMacroCycle
|
||||
template_name = 'trainingplan_edit.html'
|
||||
form_class = TrainingMacroCycleForm
|
||||
|
||||
|
||||
def get_success_url(self):
|
||||
plan = self.object.plan
|
||||
createmacrofillers(plan)
|
||||
return reverse(rower_trainingplan_view,
|
||||
kwargs = {
|
||||
'id':plan.id
|
||||
}
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
form.instance.post_date = datetime.datetime.now()
|
||||
macrocycle = form.save()
|
||||
mesocyclecheckdates(macrocycle)
|
||||
return super(TrainingMacroCycleUpdate, self).form_valid(form)
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(TrainingMacroCycleUpdate, self).get_object(*args, **kwargs)
|
||||
if not checkaccessuser(self.request.user,obj.plan.rower):
|
||||
raise Http404
|
||||
else:
|
||||
obj.type = 'userdefined'
|
||||
obj.save()
|
||||
return obj
|
||||
|
||||
class TrainingMesoCycleUpdate(UpdateView):
|
||||
model = TrainingMesoCycle
|
||||
template_name = 'trainingplan_edit.html'
|
||||
form_class = TrainingMesoCycleForm
|
||||
|
||||
|
||||
def get_success_url(self):
|
||||
plan = self.object.plan
|
||||
createmesofillers(plan)
|
||||
return reverse(rower_trainingplan_view,
|
||||
kwargs = {
|
||||
'id':plan.plan.id
|
||||
}
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
form.instance.post_date = datetime.datetime.now()
|
||||
mesocycle = form.save()
|
||||
microcyclecheckdates(mesocycle)
|
||||
return super(TrainingMesoCycleUpdate, self).form_valid(form)
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(TrainingMesoCycleUpdate, self).get_object(*args, **kwargs)
|
||||
r = obj.plan.plan.rower
|
||||
if not checkaccessuser(self.request.user,r):
|
||||
raise Http404
|
||||
else:
|
||||
obj.type = 'userdefined'
|
||||
obj.save()
|
||||
obj.plan.type = 'userdefined'
|
||||
obj.plan.save()
|
||||
return obj
|
||||
|
||||
class TrainingMicroCycleUpdate(UpdateView):
|
||||
model = TrainingMicroCycle
|
||||
template_name = 'trainingplan_edit.html'
|
||||
form_class = TrainingMicroCycleForm
|
||||
|
||||
|
||||
def get_success_url(self):
|
||||
plan = self.object.plan
|
||||
createmicrofillers(plan)
|
||||
return reverse(rower_trainingplan_view,
|
||||
kwargs = {
|
||||
'id':plan.plan.plan.id
|
||||
}
|
||||
)
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
form.instance.post_date = datetime.datetime.now()
|
||||
microcycle = form.save()
|
||||
|
||||
return super(TrainingMicroCycleUpdate, self).form_valid(form)
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(TrainingMicroCycleUpdate, self).get_object(*args, **kwargs)
|
||||
r = obj.plan.plan.plan.rower
|
||||
if not checkaccessuser(self.request.user,r):
|
||||
raise Http404
|
||||
else:
|
||||
obj.type = 'userdefined'
|
||||
obj.save()
|
||||
obj.plan.type = 'userdefined'
|
||||
obj.plan.save()
|
||||
return obj
|
||||
|
||||
class TrainingPlanUpdate(UpdateView):
|
||||
model = TrainingPlan
|
||||
template_name = 'trainingplan_edit.html'
|
||||
form_class = TrainingPlanForm
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse(rower_create_trainingplan)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
form.instance.post_date = datetime.datetime.now()
|
||||
plan = form.save()
|
||||
macrocyclecheckdates(plan)
|
||||
return super(TrainingPlanUpdate, self).form_valid(form)
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(TrainingPlanUpdate, self).get_object(*args, **kwargs)
|
||||
if not checkaccessuser(self.request.user,obj.rower):
|
||||
raise Http404
|
||||
return obj
|
||||
|
||||
class TrainingTargetUpdate(UpdateView):
|
||||
model = TrainingTarget
|
||||
template_name = 'trainingplan_edit.html'
|
||||
form_class = TrainingTargetForm
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse(rower_create_trainingplan)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
form.instance.post_date = datetime.datetime.now()
|
||||
plan = form.save()
|
||||
return super(TrainingTargetUpdate, self).form_valid(form)
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(TrainingTargetUpdate, self).get_object(*args, **kwargs)
|
||||
if not checkaccessuser(self.request.user,obj.rower):
|
||||
raise Http404
|
||||
return obj
|
||||
|
||||
|
||||
@@ -490,6 +490,44 @@ a.button {
|
||||
color: #a9c08c;
|
||||
}
|
||||
|
||||
/* palegreen */
|
||||
.palegreen {
|
||||
background: palegreen;
|
||||
box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
-moz-box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
}
|
||||
|
||||
/* paleblue */
|
||||
.paleblue {
|
||||
# padding: 8px;
|
||||
background: aliceblue;
|
||||
box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
-moz-box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
}
|
||||
|
||||
/* lightsalmon */
|
||||
.lightsalmon {
|
||||
# padding: 4px;
|
||||
background: lightsalmon;
|
||||
box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
-moz-box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
}
|
||||
|
||||
/* filler */
|
||||
.filler {
|
||||
background: darkgray;
|
||||
box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
-moz-box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
box-shadow:inset 0px 0px 0px 6px #fff;
|
||||
}
|
||||
|
||||
.padded {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* pink */
|
||||
.pink {
|
||||
color: #feeef5;
|
||||
|
||||
Reference in New Issue
Block a user