diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 4f62e80d..ab3bdd13 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -83,7 +83,7 @@ queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('default') from rowsandall_app.settings import SITE_URL -from rowers.mytypes import otwtypes +from rowers.mytypes import otwtypes,otetypes from rowers.database import * from rowers.opaque import encoder @@ -998,6 +998,8 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', if dosummary: summary = row.allstats() + + timezone_str = 'UTC' try: workoutstartdatetime = timezone.make_aware(row.rowdatetime) @@ -1050,6 +1052,9 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', maxhr = np.nan_to_num(maxhr) averagehr = np.nan_to_num(averagehr) + dragfactor = 0 + if workouttype in otetypes: + dragfactor = row.dragfactor t = datetime.datetime.strptime(duration,"%H:%M:%S.%f") delta = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second) @@ -1079,6 +1084,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', w = Workout(user=r, name=title, date=workoutdate, workouttype=workouttype, boattype=boattype, + dragfactor=dragfactor, duration=duration, distance=totaldist, weightcategory=weightcategory, adaptiveclass=adaptiveclass, diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index c17283a9..282894bd 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -748,8 +748,9 @@ def fitnessmetric_chart(fitnessmetrics,user,workoutmode='rower',startdate=None, power2k = power2k, date = date, power1hr = power1hr, - fdate=groups['dates'].map(lambda x: x.strftime('%d-%m-%Y')) ) + fdate=groups['dates'].map(lambda x: x.strftime('%Y-%m-%d')) ) + ) # fit @@ -3146,7 +3147,7 @@ def interactive_flex_chart2(id=0,promember=0, plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, - tools=TOOLS, + tools=TOOLS,toolbar_location='above', toolbar_sticky=False ) diff --git a/rowers/models.py b/rowers/models.py index 2f8c8844..1201fdd6 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -2536,6 +2536,7 @@ class Workout(models.Model): max_length=100) distance = models.IntegerField(default=0,blank=True) duration = models.TimeField(default=1,blank=True) + dragfactor = models.IntegerField(default=0,blank=True) trimp = models.IntegerField(default=-1,blank=True) rscore = models.IntegerField(default=-1,blank=True) hrtss = models.IntegerField(default=-1,blank=True) @@ -2960,6 +2961,7 @@ class WorkoutForm(ModelForm): 'distance', 'workouttype', 'boattype', + 'dragfactor', 'weightcategory', 'adaptiveclass', 'notes', diff --git a/rowers/tasks.py b/rowers/tasks.py index 07ca5969..01def2df 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -265,10 +265,10 @@ def handle_check_race_course(self, row = rdata(csvfile=f1) except IOError: try: - row = rdata(f1 + '.csv') + row = rdata(csvfile=f1 + '.csv') except IOError: try: - row = rdata(f1 + '.gz') + row = rdata(csvfile=f1 + '.gz') except IOError: return 0 @@ -526,13 +526,13 @@ def handle_update_empower(self, havedata = 1 try: - rowdata = rdata(f1) + rowdata = rdata(csvfile=f1) except IOError: try: - rowdata = rdata(f1 + '.csv') + rowdata = rdata(csvfile=f1 + '.csv') except IOError: try: - rowdata = rdata(f1 + '.gz') + rowdata = rdata(csvfile=f1 + '.gz') except IOError: havedata = 0 @@ -597,13 +597,13 @@ def handle_calctrimp(id, engine = create_engine(database_url, echo=False) try: - rowdata = rdata(csvfilename) + rowdata = rdata(csvfile=csvfilename) except IOError: try: - rowdata = rdata(csvfilename + '.csv') + rowdata = rdata(csvfile=csvfilename + '.csv') except IOError: try: - rowdata = rdata(csvfilename + '.gz') + rowdata = rdata(csvfile=csvfilename + '.gz') except IOError: return 0 @@ -719,13 +719,13 @@ def handle_updatedps(useremail, workoutids, debug=False,**kwargs): for wid, f1 in workoutids: havedata = 1 try: - rowdata = rdata(f1) + rowdata = rdata(csvfile=f1) except IOError: try: - rowdata = rdata(f1 + '.csv') + rowdata = rdata(csvfile=f1 + '.csv') except IOError: try: - rowdata = rdata(f1 + '.gz') + rowdata = rdata(csvfile=f1 + '.gz') except IOError: havedata = 0 @@ -1384,12 +1384,12 @@ def handle_otwsetpower(self,f1, boattype, weightvalue, try: - rowdata = rdata(f1) + rowdata = rdata(csvfile=f1) except IOError: try: - rowdata = rdata(f1 + '.csv') + rowdata = rdata(csvfile=f1 + '.csv') except IOError: - rowdata = rdata(f1 + '.gz') + rowdata = rdata(csvfile=f1 + '.gz') weightvalue = float(weightvalue) @@ -1490,13 +1490,13 @@ def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs): therows = [] for f1 in workoutfilenames: try: - rowdata = rdata(f1) + rowdata = rdata(csvfile=f1) except IOError: try: - rowdata = rdata(f1 + '.csv') + rowdata = rdata(csvfile=f1 + '.csv') except IOError: try: - rowdata = rdata(f1 + '.gz') + rowdata = rdata(csvfile=f1 + '.gz') except IOError: rowdata = 0 if rowdata != 0: @@ -1653,9 +1653,9 @@ def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename, ftp=ftp, powerperc=powerperc, powerzones=powerzones) try: - row = rdata(f2, rower=rr) + row = rdata(csvfile=f2, rower=rr) except IOError: - row = rdata(f2 + '.gz', rower=rr) + row = rdata(csvfile=f2 + '.gz', rower=rr) try: haspower = row.df[' Power (watts)'].mean() > 50 diff --git a/rowers/templates/workout_form.html b/rowers/templates/workout_form.html index 047a8a2c..40346ee1 100644 --- a/rowers/templates/workout_form.html +++ b/rowers/templates/workout_form.html @@ -32,7 +32,18 @@ $( document ).ready(function() { } else { $('#id_boattype').toggle(false); $('#id_boattype').val('1x'); - } +} + if ( + $(this).val() == 'rower' + || $(this).val() == 'dynamic' + || $(this).val() == 'slides' + ) { + $('#id_dragfactor').toggle(true); + } else { + $('#id_dragfactor').toggle(false); + $('#id_dragfactor').val('0'); +} + }); $('#id_workouttype').change(); }); diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py index 547f13b6..3bff8112 100644 --- a/rowers/templatetags/rowerfilters.py +++ b/rowers/templatetags/rowerfilters.py @@ -11,7 +11,7 @@ from rowers.utils import calculate_age from rowers.models import ( course_length,WorkoutComment, TrainingMacroCycle,TrainingMesoCycle, TrainingMicroCycle, - Rower,Workout + Rower,Workout,SiteAnnouncement ) from rowers.plannedsessions import ( race_can_register, race_can_submit,race_rower_status @@ -33,6 +33,12 @@ import arrow from six import string_types +@register.filter +def nogoals(user): + targets = TrainingTarget.objects.filter(rowers=user.rower, + date__gte=datetime.date.today()) + return len(targets)==0 + def strfdelta(tdelta): minutes,seconds = divmod(tdelta.seconds,60) tenths = int(tdelta.microseconds/1e5) @@ -333,6 +339,15 @@ def user_teams(user): return teams +@register.filter +def announcements(request): + announcements = SiteAnnouncement.objects.filter( + expires__gte=datetime.date.today()).order_by( + "-created", + "-id" + ) + + return announcements[0:4] @register.filter def has_teams(user): diff --git a/rowers/tests/test_uploads.py b/rowers/tests/test_uploads.py index b691dcb7..27264a58 100644 --- a/rowers/tests/test_uploads.py +++ b/rowers/tests/test_uploads.py @@ -100,6 +100,7 @@ class ViewTest(TestCase): 'adaptiveclass':'PR1', 'workouttype':'rower', 'boattype':'1x', + 'dragfactor':'112', 'private':True, 'notes':'noot mies', } diff --git a/rowers/tests/testdata/testdata.csv.gz b/rowers/tests/testdata/testdata.csv.gz index 56336034..8c745892 100644 Binary files a/rowers/tests/testdata/testdata.csv.gz and b/rowers/tests/testdata/testdata.csv.gz differ diff --git a/rowers/urls.py b/rowers/urls.py index b7b67c0e..99a1dcf8 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -147,6 +147,8 @@ urlpatterns = [ name='workouts_view'), # url(r'^(?P\d+)/list-workouts/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.workouts_view, # name='workouts_view'), + url(r'^list-workouts/ranking/user/(?P\d+)/$',views.workouts_view,{'rankingonly':True}, + name='workouts_view'), url(r'^list-workouts/user/(?P\d+)/$',views.workouts_view, name='workouts_view'), # url(r'^list-workouts/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/user/(?P\d+)/$',views.workouts_view, diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index d5ca9e42..a2dd3f36 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -3328,6 +3328,18 @@ def workout_edit_view(request,id=0,message="",successmessage=""): if (checkworkoutuser(request.user,row)==False): raise PermissionDenied("Access denied") + if request.user.rower.rowerplan == 'basic' and 'speedcoach2' in row.workoutsource: + data = getsmallrowdata_db(['wash'],ids=[encoder.decode_hex(id)]) + try: + if data['wash'].std() != 0: + url = reverse('paidplans') + messages.info( + request, + 'Some Empower Oarlock data are only available to users with a paid plan'.format(u=url) + ) + except: + pass + form = WorkoutForm(instance=row) if request.method == 'POST': @@ -3345,6 +3357,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""): distance = form.cleaned_data['distance'] private = form.cleaned_data['private'] notes = form.cleaned_data['notes'] + newdragfactor = form.cleaned_data['dragfactor'] thetimezone = form.cleaned_data['timezone'] try: @@ -3416,6 +3429,11 @@ def workout_edit_view(request,id=0,message="",successmessage=""): row.timezone = thetimezone row.plannedsession = ps + dragchanged = False + if newdragfactor != row.dragfactor: + row.dragfactor = newdragfactor + dragchanged = True + try: row.save() except IntegrityError: @@ -3427,6 +3445,12 @@ def workout_edit_view(request,id=0,message="",successmessage=""): # change data in csv file r = rdata(row.csvfilename) + if dragchanged: + try: + r.change_drag(newdragfactor) + except AttributeError: + pass + if r == 0: return HttpResponse("Error: CSV Data File Not Found") r.rowdatetime = startdatetime diff --git a/static/css/rowsandall2.css b/static/css/rowsandall2.css index 388f56eb..2493cdd4 100644 --- a/static/css/rowsandall2.css +++ b/static/css/rowsandall2.css @@ -240,6 +240,7 @@ th.rotate > div > span { padding: .2em .5em .2em 0em; } + .site-announcement { font: 1.0em/1.2em sans-serif; text-decoration: none; @@ -253,6 +254,19 @@ th.rotate > div > span { border: solid 1px #333; } +.site-announcement-white { + font: 1.0em/1.2em sans-serif; + text-decoration: none; + display: block; + padding: .2em .5em .2em .5em; + zoom: 1; +/* border-radius: .5em; */ +/* -moz-border-radius: .5em; */ +/* -webkit-border-radius: .5em; */ + text-align: left; + border: solid 1px #fff; +} + .contentli { diff --git a/static/css/styles2.css b/static/css/styles2.css index e3dc143f..d7d23e7d 100644 --- a/static/css/styles2.css +++ b/static/css/styles2.css @@ -80,6 +80,15 @@ padding: 15px; } + ad h1 { + font-weight: bold; + text-align: left; + font-size: 1.4em; + /* color: #dddddd; */ + color: #f8f8ff; + padding: 15px; + } + aside h1 a { font-weight: bold; text-align: left; @@ -647,8 +656,8 @@ "side-nav nav nav" "sidebar content content" "sidebar content content" - "sidebar content content" - "sidebar footer footer" + "ad content content" + "ad footer footer" "ad footer footer" } diff --git a/templates/newbase.html b/templates/newbase.html index 5ae54c80..9a5c0549 100644 --- a/templates/newbase.html +++ b/templates/newbase.html @@ -309,10 +309,27 @@ + {% if request|announcements %} +

What's New?

+ {% for a in request|announcements %} +
+
+ {{ a.created }}: + {{ a.announcement|urlize }} +
+
+ + {% endfor %} + {% endif %} + {% if user.is_authenticated and user|nogoals %} +

+ Create a Training Target! +

+ {% endif %} {% block ad %} - - -

Prygl Rowing Camps

+
+ +

Prygl Rowing Camps

{% endblock %}