diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..9b34d71a
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+venv
+config.yaml
diff --git a/.gitignore b/.gitignore
index 0dc8c5c9..ad18f5a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,7 @@ manage.py
# migrations
/rowers/migrations/
/cvkbrno/migrations/
+/survey/migrations/
# secrets
config.yaml
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..d35cc5c4
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,3 @@
+FROM rosti/python:3.6
+WORKDIR /srv/app/
+COPY . .
diff --git a/app.py b/app.py
new file mode 100644
index 00000000..8d4b6fe1
--- /dev/null
+++ b/app.py
@@ -0,0 +1,10 @@
+#!/srv/bin/venv python3.6
+import os
+import sys
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rowsandall_app.settings")
+
+from django.core.wsgi import get_wsgi_application
+application = get_wsgi_application()
+
+#execute_from_command_line(sys.argv)
diff --git a/rowers/admin.py b/rowers/admin.py
index cf091c81..26c6d660 100644
--- a/rowers/admin.py
+++ b/rowers/admin.py
@@ -17,7 +17,8 @@ from .models import (
# Register your models here so you can use them in the Admin module
-# Rower details directly under the User
+
+# Rower details directly under the User
class RowerInline(admin.StackedInline):
model = Rower
can_delete = False
@@ -73,7 +74,7 @@ class UserAdmin(admin.ModelAdmin):
('Permissions',
{'fields':
('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions',)}),)
-
+
search_fields = ["username","first_name","last_name","email"]
def rowerplan(self, obj):
@@ -90,7 +91,7 @@ class FavoriteChartAdmin(admin.ModelAdmin):
class C2WorldClassAgePerformanceAdmin(admin.ModelAdmin):
list_display = ('sex','weightcategory','age','distance','power','name','season')
-
+
class SiteAnnouncementAdmin(admin.ModelAdmin):
list_display = ('announcement','created','modified','expires','dotweet')
@@ -99,7 +100,7 @@ class TeamAdmin(admin.ModelAdmin):
class TeamInviteAdmin(admin.ModelAdmin):
list_display = ('issuedate','team','user','code')
-
+
class TeamRequestAdmin(admin.ModelAdmin):
list_display = ('issuedate','team','user','code')
@@ -136,7 +137,7 @@ class IndoorVirtualRaceResultAdmin(admin.ModelAdmin):
class PaidPlanAdmin(admin.ModelAdmin):
list_display = ('name','shortname','price','paymenttype','paymentprocessor','external_id')
-
+
admin.site.unregister(User)
admin.site.register(User,UserAdmin)
admin.site.register(Workout,WorkoutAdmin)
diff --git a/rowers/alerts.py b/rowers/alerts.py
index 886c34f6..de333677 100644
--- a/rowers/alerts.py
+++ b/rowers/alerts.py
@@ -196,3 +196,11 @@ def alert_get_stats(alert,nperiod=0):
}
# run alert report
+
+# check alert permission
+def checkalertowner(alert,user):
+ if alert.manager == user:
+ return True
+ if alert.rower.user == user:
+ return True
+ return False
diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py
index 87895291..4a082f35 100644
--- a/rowers/c2stuff.py
+++ b/rowers/c2stuff.py
@@ -18,6 +18,7 @@ from iso8601 import ParseError
import numpy
import json
+from json.decoder import JSONDecodeError
from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET
diff --git a/rowers/dataprep.py b/rowers/dataprep.py
index bbfd6ffb..3912e8c1 100644
--- a/rowers/dataprep.py
+++ b/rowers/dataprep.py
@@ -1081,7 +1081,8 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
makeprivate=False,
oarlength=2.89, inboard=0.88,
forceunit='lbs',
- consistencychecks=False):
+ consistencychecks=False,
+ impeller=False):
message = None
powerperc = 100 * np.array([r.pw_ut2,
@@ -1289,7 +1290,8 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
startdatetime=workoutstartdatetime,
inboard=inboard, oarlength=oarlength,
timezone=timezone_str,
- privacy=privacy)
+ privacy=privacy,
+ impeller=impeller)
try:
w.save()
except ValidationError:
@@ -1421,24 +1423,30 @@ def handle_nonpainsled(f2, fileformat, summary=''):
oarlength = 2.89
inboard = 0.88
hasrecognized = False
+ impeller = False
row,hasrecognized,summary,fileformat = parsenonpainsled(fileformat,f2,summary)
# Handle c2log
if (fileformat == 'c2log' or fileformat == 'rowprolog'):
- return (0,'',0,0,'')
+ return (0,'',0,0,'',impeller)
if not hasrecognized:
- return (0,'',0,0,'')
+ return (0,'',0,0,'',impeller)
f_to_be_deleted = f2
# should delete file
f2 = f2[:-4] + 'o.csv'
- try:
- row2 = rrdata(df = row.df)
- row2.write_csv(f2, gzip=True)
- except:
- return (0,'',0,0,'')
+ row2 = rrdata(df = row.df)
+ if 'speedcoach2' in fileformat:
+ # impeller consistency
+ impellerdata, consistent, ratio = row.impellerconsistent(threshold=0.3)
+ if impellerdata and consistent:
+ impeller = True
+ if impellerdata and not consistent:
+ row2.use_gpsdata()
+ row2.write_csv(f2, gzip=True)
+
# os.remove(f2)
try:
@@ -1449,7 +1457,7 @@ def handle_nonpainsled(f2, fileformat, summary=''):
except:
pass
- return (f2, summary, oarlength, inboard, fileformat)
+ return (f2, summary, oarlength, inboard, fileformat, impeller)
# Create new workout from file and store it in the database
# This routine should be used everywhere in views.py and mailprocessing.py
@@ -1464,6 +1472,7 @@ def new_workout_from_file(r, f2,
makeprivate=False,
notes=''):
message = None
+ impeller = False
try:
fileformat = get_file_type(f2)
except (IOError,UnicodeDecodeError):
@@ -1476,6 +1485,7 @@ def new_workout_from_file(r, f2,
inboard = 0.88
if len(fileformat) == 3 and fileformat[0] == 'zip':
f_to_be_deleted = f2
+ impeller = False
workoutsbox = Mailbox.objects.filter(name='workouts')[0]
msg = Message(mailbox=workoutsbox,
from_header=r.user.email,
@@ -1543,7 +1553,7 @@ def new_workout_from_file(r, f2,
# handle non-Painsled by converting it to painsled compatible CSV
if (fileformat != 'csv'):
- f2, summary, oarlength, inboard, fileformat = handle_nonpainsled(
+ f2, summary, oarlength, inboard, fileformat, impeller = handle_nonpainsled(
f2,
fileformat,
summary=summary
@@ -1571,7 +1581,8 @@ def new_workout_from_file(r, f2,
summary=summary,
inboard=inboard, oarlength=oarlength,
title=title,
- forceunit='N'
+ forceunit='N',
+ impeller=impeller,
)
return (id, message, f2)
@@ -1782,6 +1793,11 @@ def delete_strokedata(id):
dirname = 'media/strokedata_{id}.parquet.gz'.format(id=id)
try:
shutil.rmtree(dirname)
+ except OSError:
+ try:
+ os.remove(dirname)
+ except FileNotFoundError:
+ pass
except FileNotFoundError:
pass
diff --git a/rowers/forms.py b/rowers/forms.py
index 46de978c..20882308 100644
--- a/rowers/forms.py
+++ b/rowers/forms.py
@@ -31,6 +31,12 @@ formaxlabels = axlabels.copy()
formaxlabels.pop('None')
parchoices = list(sorted(formaxlabels.items(), key = lambda x:x[1]))
+class SurveyForm(forms.Form):
+ surveydone = forms.ChoiceField(
+ required=True,
+ choices=(('YES','YES'),('NO','NO')),
+ label='Will you take a 2 minute survey to help improve rowsandall?',
+ widget = forms.RadioSelect)
class FlexibleDecimalField(forms.DecimalField):
@@ -115,7 +121,6 @@ class EmailForm(forms.Form):
lastname = forms.CharField(max_length=255)
email = forms.EmailField()
subject = forms.CharField(max_length=255)
- botcheck = forms.CharField(max_length=5)
message = forms.CharField()
disqualificationreasons = (
diff --git a/rowers/mailprocessing.py b/rowers/mailprocessing.py
index 9d3d824d..37017602 100644
--- a/rowers/mailprocessing.py
+++ b/rowers/mailprocessing.py
@@ -49,7 +49,7 @@ def send_confirm(user, name, link, options):
fullemail = user.email
subject = 'New Workout Added: '+name
-
+
res = send_template_email('Rowsandall ',
[fullemail],
subject,'confirmemail.html',
@@ -86,6 +86,7 @@ def rdata(file, rower=rrower()):
def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
""" This one is used in processemail """
workouttype = 'rower'
+ impeller = False
try:
datafilename = datafile.name
@@ -108,7 +109,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
if testing:
print('Fileformat = ',fileformat)
-
+
f,e = os.path.splitext(datafilename)
if fileformat == 'unknown' and 'txt' not in e:
fcopy = "media/"+datafilename
@@ -134,12 +135,12 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
summary = ''
-
+
# handle non-Painsled
if fileformat == 'att':
return 0
if fileformat != 'csv':
- filename_mediadir, summary, oarlength, inboard,fileformat = dataprep.handle_nonpainsled(
+ filename_mediadir, summary, oarlength, inboard,fileformat,impeller = dataprep.handle_nonpainsled(
'media/' + datafilename, fileformat, summary)
if not filename_mediadir:
return 0
@@ -148,7 +149,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
inboard = 0.88
oarlength = 2.89
- row = rdata(filename_mediadir)
+ row = rdata(filename_mediadir)
if row == 0:
return 0
@@ -168,7 +169,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
row.write_csv(datafilename, gzip=True)
dosummary = (fileformat != 'fit' and 'speedcoach2' not in fileformat)
dosummary = dosummary or summary == ''
-
+
if name == '':
name = 'Workout from Background Queue'
@@ -181,7 +182,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
oarlength=oarlength,
title=name,
workoutsource=fileformat,
- notes=''
+ notes='',impeller=impeller,
)
diff --git a/rowers/management/commands/processalerts.py b/rowers/management/commands/processalerts.py
index febfe20f..12937fcd 100644
--- a/rowers/management/commands/processalerts.py
+++ b/rowers/management/commands/processalerts.py
@@ -45,7 +45,7 @@ class Command(BaseCommand):
# explanatorytexts
othertexts = [alert.description()]
-
+
# send email
job = myqueue(queue,handle_send_email_alert,
alert.manager.email,
@@ -58,11 +58,11 @@ class Command(BaseCommand):
# advance next_run
if not testing:
- alert.next_run = datetime.date.today() + datetime.timedelta(days=alert.period)
+ alert.next_run = datetime.date.today() + datetime.timedelta(days=alert.period-1)
alert.save()
if testing:
print('{nr} alerts found'.format(nr = len(todaysalerts)))
-
+
self.stdout.write(self.style.SUCCESS(
'Successfully processed alerts'))
diff --git a/rowers/metrics.py b/rowers/metrics.py
index 242cfe56..ab32687b 100644
--- a/rowers/metrics.py
+++ b/rowers/metrics.py
@@ -15,7 +15,7 @@ from math import log10
nometrics = [
'originalvelo',
- 'cumdist',
+# 'cumdist',
'strokes_slsh_min',
' WorkPerStroke (joules)',
' activityIdx',
@@ -258,7 +258,7 @@ rowingmetrics = (
'ax_min': 0,
'ax_max': 30,
'default': 0,
- 'sigfigs': 0,
+ 'sigfigs': 1,
'mode':'water',
'type': 'pro',
'group': 'stroke'}),
diff --git a/rowers/middleware.py b/rowers/middleware.py
index 7b9abb86..42087eeb 100644
--- a/rowers/middleware.py
+++ b/rowers/middleware.py
@@ -1,4 +1,3 @@
-
from django.utils import timezone
from rowers.models import Workout, PowerTimeFitnessMetric, Rower, PaidPlan
import datetime
@@ -22,10 +21,10 @@ def getrower(user):
def do_update(user,mode='rower',days=42):
r = getrower(user)
-
+
startdate = timezone.now()-datetime.timedelta(days=days)
- # test if not something already done
+ # test if not something already done
now_date = timezone.now().strftime('%Y-%m-%d')
ms = PowerTimeFitnessMetric.objects.filter(
user=user,
@@ -37,11 +36,11 @@ def do_update(user,mode='rower',days=42):
else:
max_workout_id = max([m.last_workout for m in ms])
last_update_date = ms[0].date.strftime('%Y-%m-%d')
-
+
#last_update_date = max([m.date.strftime('%Y-%m-%d') for m in ms])
-
+
if mode == 'rower':
workouts = Workout.objects.filter(
user=r,
@@ -59,7 +58,7 @@ def do_update(user,mode='rower',days=42):
except ValueError:
max_id = 0
-
+
if last_update_date < now_date and max_workout_id < max_id:
job = myqueue(queuelow,
handle_updatefitnessmetric,
@@ -73,7 +72,7 @@ def do_update(user,mode='rower',days=42):
class PowerTimeFitnessMetricMiddleWare(object):
def __init__(self, get_response):
self.get_response = get_response
-
+
def __call__(self, request):
# Code to be executed before the view is called
if request.user.is_authenticated:
@@ -83,7 +82,7 @@ class PowerTimeFitnessMetricMiddleWare(object):
response = self.get_response(request)
return response
-
+
from django.shortcuts import redirect
@@ -98,8 +97,29 @@ allowed_paths = [
'/rowers/me/gdpr-optin-confirm'
'/rowers/exportallworkouts/',
'/rowers/exportallworkouts',
+ '/rowers/survey/'
]
+class SurveyMiddleWare(object):
+ def __init__(self, get_response):
+ self.get_response = get_response
+
+ def __call__(self, request):
+ if request.user.is_authenticated and request.path not in allowed_paths:
+ r = getrower(request.user)
+ nexturl = request.path
+ if 'survey' in nexturl:
+ nexturl = '/rowers/list-workouts'
+ mustseesurvey = request.user.date_joined <= timezone.now()-datetime.timedelta(days=14) and not r.surveydone
+ if mustseesurvey:
+ return redirect(
+ '/rowers/survey/?next=%s' % nexturl
+ )
+
+ response = self.get_response(request)
+
+ return response
+
class GDPRMiddleWare(object):
def __init__(self, get_response):
self.get_response = get_response
@@ -137,7 +157,7 @@ class RowerPlanMiddleWare(object):
r.paidplan = basicplans[0]
r.save()
# remove from Free Coach groups
-
+
# send email
job = myqueue(queue,
handle_sendemail_expired,
diff --git a/rowers/models.py b/rowers/models.py
index d73bb683..6d9b7ac9 100644
--- a/rowers/models.py
+++ b/rowers/models.py
@@ -730,6 +730,8 @@ class Rower(models.Model):
# Privacy Data
gdproptin = models.BooleanField(default=False)
gdproptindate = models.DateTimeField(blank=True,null=True)
+ surveydone = models.BooleanField(default=False)
+ surveydonedate = models.DateTimeField(blank=True,null=True)
# Heart Rate Zone data
@@ -2734,6 +2736,7 @@ class Workout(models.Model):
choices=privacychoices)
rankingpiece = models.BooleanField(default=False,verbose_name='Ranking Piece')
duplicate = models.BooleanField(default=False,verbose_name='Duplicate Workout')
+ impeller = models.BooleanField(default=False,verbose_name='Impeller')
def save(self, *args, **kwargs):
user = self.user
@@ -3202,12 +3205,12 @@ class WorkoutForm(ModelForm):
# Used for the rowing physics calculations
class AdvancedWorkoutForm(ModelForm):
- quick_calc = forms.BooleanField(initial=True,required=False)
- go_service = forms.BooleanField(initial=False,required=False,label='Experimental')
+ #quick_calc = forms.BooleanField(initial=True,required=False)
+ #go_service = forms.BooleanField(initial=False,required=False,label='Experimental')
class Meta:
model = Workout
- fields = ['boattype','weightvalue','quick_calc']
+ fields = ['boattype','weightvalue']
class RowerExportForm(ModelForm):
class Meta:
diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py
index ce71c7c8..1064db19 100644
--- a/rowers/plannedsessions.py
+++ b/rowers/plannedsessions.py
@@ -706,6 +706,7 @@ def get_team(request):
def get_dates_timeperiod(request,startdatestring='',enddatestring='',
defaulttimeperiod='thisweek'):
# set start end date according timeperiod
+ # should always return datetime.date
timeperiod = request.GET.get('when')
@@ -720,8 +721,8 @@ def get_dates_timeperiod(request,startdatestring='',enddatestring='',
startdate = dt.datetime.strptime(startdatestring,'%Y-%m-%d').date()
enddate = dt.datetime.strptime(enddatestring,'%Y-%m-%d').date()
except ValueError:
- startdate = parser.parse(startdatestring,fuzzy=True)
- enddate = parser.parse(enddatestring, fuzzy=True)
+ startdate = parser.parse(startdatestring,fuzzy=True).date()
+ enddate = parser.parse(enddatestring, fuzzy=True).date()
return startdate,enddate
diff --git a/rowers/tasks.py b/rowers/tasks.py
index 259a7acd..a0d9986e 100644
--- a/rowers/tasks.py
+++ b/rowers/tasks.py
@@ -1465,19 +1465,11 @@ def handle_otwsetpower(self,f1, boattype, weightvalue,
else:
debug = False
- if 'quick_calc' in kwargs:
- usetable = kwargs['quick_calc']
- else:
- usetable = False
-
- if 'go_service' in kwargs:
- goservice = kwargs['go_service']
- else:
- goservice = False
-
kwargs['jobid'] = job_id
+
+
weightvalue = float(weightvalue)
# check what the real file name is
@@ -1518,6 +1510,8 @@ def handle_otwsetpower(self,f1, boattype, weightvalue,
progressurl += "/rowers/record-progress/"
progressurl += job_id+'/'
+ goservice = True
+
if goservice:
# do something (this should return from go service)
with grpc.insecure_channel(
diff --git a/rowers/templates/email.html b/rowers/templates/email.html
index 474c3765..86fd7b2e 100644
--- a/rowers/templates/email.html
+++ b/rowers/templates/email.html
@@ -3,115 +3,134 @@
{% block main %}
Contact us through email
+
-
- {% if form.errors %}
-
- Please correct the error{{ form.errors|pluralize }} below.
-
- {% endif %}
-
-
-
+
+ {% if form.errors %}
+
+ Please correct the error{{ form.errors|pluralize }} below.
+
+ {% endif %}
+
+
+ {% csrf_token %}
+
+
+
+
+
- Bug reporting, feature requests
-
-
- Bug reports and feature requests can be done through our BitBucket page. Please check on the following link if your bug or issue is a known one. Feel free to file any feature request.
-
-
+ Bug reporting, feature requests
+
+
+ Bug reports and feature requests can be done through our BitBucket page. Please check on the following link if your bug or issue is a known one. Feel free to file any feature request.
+
+
- Facebook Group
-
- We run a facebook group where you can post questions and report problems,
- especially if you think the wider user community benefits from the answers.
-
-
+ Facebook Group
-
- Twitter
-
- You can also check me on Twitter:
-
- When the site is down, this is the appropriate channel to look for apologies, updates, and offer help.
-
-
+ We run a facebook group where you can post questions and report problems,
+ especially if you think the wider user community benefits from the answers.
+
+
-
- Rowsandall s.r.o.
-
- Rowsandall s.r.o.
- Nové sady 988/2
- 602 00 Brno
- Czech Republic
- IČ: 070 48 572
- DIČ: CZ 070 48 572 (Nejsme plátce DPH)
- Datová schránka: 7897syr
- Email: info@rowsandall.com
- The company is registered in the business register at the
- Regional Court in Brno (Společnost je zapsána v obchodním rejstříku vedeném u Krajského soudu v Brně, oddíl C, vložka 105845)
-
+
+ Twitter
-
-
-{% endblock %}
+ You can also check me on Twitter:
+
+ When the site is down, this is the appropriate channel to look for apologies, updates, and offer help.
+
+
-{% block sidebar %}
-{% include 'menu_help.html' %}
-{% endblock %}
+
+ Rowsandall s.r.o.
-
+ Rowsandall s.r.o.
+ Nové sady 988/2
+ 602 00 Brno
+ Czech Republic
+ IČ: 070 48 572
+ DIČ: CZ 070 48 572 (Nejsme plátce DPH)
+ Datová schránka: 7897syr
+ Email: info@rowsandall.com
+ The company is registered in the business register at the
+ Regional Court in Brno (Společnost je zapsána v obchodním rejstříku vedeném u Krajského soudu v Brně, oddíl C, vložka 105845)
+
+
+
+
+ {% endblock %}
+
+ {% block sidebar %}
+ {% include 'menu_help.html' %}
+ {% endblock %}
+
+ {% block scripts %}
+
+
+ {% endblock %}
diff --git a/rowers/templates/embedded_video.html b/rowers/templates/embedded_video.html
index 298577e6..5543733b 100644
--- a/rowers/templates/embedded_video.html
+++ b/rowers/templates/embedded_video.html
@@ -29,6 +29,8 @@
{% block meta %}
{% leaflet_js %}
{% leaflet_css %}
+
+
{% endlanguage %}
diff --git a/rowers/templates/embedded_video_mini.html b/rowers/templates/embedded_video_mini.html
new file mode 100644
index 00000000..20288285
--- /dev/null
+++ b/rowers/templates/embedded_video_mini.html
@@ -0,0 +1,689 @@
+{% extends "newbase.html" %}
+{% load staticfiles %}
+{% load rowerfilters %}
+{% load i18n %}
+{% load leaflet_tags %}
+
+
+
+{% block title %}Workout Video{% endblock %}
+{% block og_title %}{{ analysis.name }}{% endblock %}
+{% block description %}Rowing Video Analysis:{{ analysis.name }}{% endblock %}
+{% block og_description %}Rowing Video Analysis:{{ analysis.name }}{% endblock %}
+{% block og_image %}
+{% if analysis %}
+
+
+{% else %}
+
+
+{% endif %}
+{% endblock %}
+
+{% if analysis %}
+{% block image_src %}
+
+{% endblock %}
+{% endif %}
+
+{% block meta %}
+{% leaflet_js %}
+{% leaflet_css %}
+
+
+
+
+
+
+{% endblock %}
+
+{% block main %}
+
+
+
+{% language 'en' %}
+Video Analysis for {{ workout.name }}
+
+
+ Playing the video will advance the data in synchronization. Use the regular
+ YouTube controls to move around in the video and play it.
+ In this reduced view, you cannot edit the video analysis. There is a separate
+ view for that here .
+
+
+
+
+
+ Share
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ mapdiv | safe}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if 'basic' in metricsgroups %}
+
+
+
+
+
+
+ {% endif %}
+ {% if 'forcepower' in metricsgroups %}
+
+
+
+ {% endif %}
+ {% if 'athlete' in metricsgroups %}
+
+
+
+ {% endif %}
+ {% if 'stroke' in metricsgroups %}
+ {% if workout.workouttype == 'water' %}
+
+
+
+ {% endif %}
+ {% endif %}
+
+
+
+
+
+
+
+{% endlanguage %}
+
+{% endblock %}
+
+{% block sidebar %}
+{% include 'menu_workout.html' %}
+{% endblock %}
diff --git a/rowers/templates/menu_workout.html b/rowers/templates/menu_workout.html
index f6edffd0..5c06f2a4 100644
--- a/rowers/templates/menu_workout.html
+++ b/rowers/templates/menu_workout.html
@@ -287,10 +287,25 @@
OTW Power
+ {% if 'speedcoach2' in workout.workoutsource %}
+
+
+
+ {% if workout.impeller %} {% else %}• {% endif %}Use GPS data
+
+
+
+
+
+ {% if workout.impeller %}• {% else %} {% endif %}Use Impeller data
+
+
+ {% endif %}
{% endif %}
- In-Stroke Metrics
+
+ In-Stroke Metrics
diff --git a/rowers/templates/paymentconfirmationemail.html b/rowers/templates/paymentconfirmationemail.html
index 0bc62f45..1d97167c 100644
--- a/rowers/templates/paymentconfirmationemail.html
+++ b/rowers/templates/paymentconfirmationemail.html
@@ -7,6 +7,17 @@
Thank you. We have received the payment of € {{ amount }} for Rowsandall related services.
+
+ With your contribution, you are helping to keep this service to the rowing community
+ running. As the founder and developer of the Rowsandall.com site I am very interested
+ to know what you think of Rowsandall.com, as well as suggestions for improvements.
+
+
+
+ So don't hesitate to respond to this email and let me know. I will read and respond to each
+ email.
+
+
Please contact our customer service by replying to this email if you have any further
questions regarding the payment.
@@ -16,4 +27,3 @@
Best Regards, the Rowsandall Team
{% endblock %}
-
diff --git a/rowers/templates/plantrialwelcome.html b/rowers/templates/plantrialwelcome.html
new file mode 100644
index 00000000..5f588c43
--- /dev/null
+++ b/rowers/templates/plantrialwelcome.html
@@ -0,0 +1,31 @@
+{% extends "emailbase.html" %}
+
+{% block body %}
+Dear {{ first_name }} ,
+
+
+ Welcome on the trial for the Self-Coach plan.
+
+
+As the developer of the Rowsandall.com site I am very interested to know what you think of Rowsandall.com. Especially, I'd like to understand how you started using the site, what you are looking for, and what you think could be improved.
+
+
+The Self-Coach functionality allows you to create training plans and sessions for you and your training group. Feel free to contact me any time you need help.
+
+
+I'd also love to hear a bit about your rowing background.
+
+
+
+ So don't hesitate to respond to this email and let me know. I will read and respond to each
+ email.
+
+
+Thank you very much for your help and for supporting rowsandall.com .
+
+
+
+
+ Best Regards, the Rowsandall Team
+
+{% endblock %}
diff --git a/rowers/templates/protrialewelcome.html b/rowers/templates/protrialewelcome.html
new file mode 100644
index 00000000..a7bf7892
--- /dev/null
+++ b/rowers/templates/protrialewelcome.html
@@ -0,0 +1,33 @@
+{% extends "emailbase.html" %}
+
+{% block body %}
+Dear {{ first_name }} ,
+
+
+ Welcome on the trial for the Pro plan.
+
+
+As the developer of the Rowsandall.com site I am very interested to know
+what you think of Rowsandall.com.
+Especially, I'd like to understand how you started using the site,
+what you are looking for, and what you think could be improved.
+
+
+
+I'd also love to hear a bit about your rowing background.
+
+
+
+ So don't hesitate to respond to this email and let me know. I will read and respond to each
+ email.
+
+
+
+Thank you very much for your help and for supporting rowsandall.com .
+
+
+
+
+ Best Regards, the Rowsandall Team
+
+{% endblock %}
diff --git a/rowers/templates/subscription_update_email.html b/rowers/templates/subscription_update_email.html
index d805d0d5..6f0cee59 100644
--- a/rowers/templates/subscription_update_email.html
+++ b/rowers/templates/subscription_update_email.html
@@ -5,22 +5,34 @@
Thank you. We have received the payment of € {{ amount }} for
- your updated Rowsandall subscription.
- You are now on the Rowsandall paid plan "{{ planname }}".
+ your updated Rowsandall subscription.
+ You are now on the Rowsandall paid plan "{{ planname }}".
+
+ With your contribution, you are helping to keep this service to the rowing community
+ running. As the founder and developer of the Rowsandall.com site I am very interested
+ to know what you think of Rowsandall.com, as well as suggestions for improvements.
+
+
+
+ So don't hesitate to respond to this email and let me know. I will read and respond to each
+ email.
+
+
{% if recurring=='recurring' %}
+ Some more information about the subscription.
The subscription cost is €{{ price }} per year.
Your next charge is due on {{ end_of_billing_period }}. We will charge you automatically
- on that date.
+ on that date.
The subscription will keep running until you change or stop it. At any point in time you
can change the automatically renewing subscription to a "one year only" subscription through
the upgrade page . On this page, you can also
- upgrade your subscription.
+ upgrade your subscription.
{% else %}
@@ -28,7 +40,7 @@
The price of the subscription is €{{ price }}. You have paid €{{ amount }} as a
prorated cost of your upgrade.
This one year subscription will automatically end on {{ end_of_billing_period }}. You can
- renew your subscription after that.
+ renew your subscription after that.
@@ -60,4 +72,3 @@
Best Regards, the Rowsandall Team
{% endblock %}
-
diff --git a/rowers/templates/survey.html b/rowers/templates/survey.html
new file mode 100644
index 00000000..1e5fc0fb
--- /dev/null
+++ b/rowers/templates/survey.html
@@ -0,0 +1,47 @@
+{% extends "newbase.html" %}
+{% load staticfiles %}
+{% load rowerfilters %}
+
+{% block title %}File loading{% endblock %}
+
+{% block meta %}
+
+
+
+{% endblock %}
+
+{% block main %}
+
+{% endblock %}
+
+{% block sidebar %}
+{% include 'menu_profile.html' %}
+{% endblock %}
diff --git a/rowers/templates/survey2.html b/rowers/templates/survey2.html
new file mode 100644
index 00000000..a59c8179
--- /dev/null
+++ b/rowers/templates/survey2.html
@@ -0,0 +1,48 @@
+{% extends "newbase.html" %}
+{% load staticfiles %}
+{% load rowerfilters %}
+
+{% block title %}Rowsandall {% endblock %}
+
+
+{% block meta %}
+
+
+{% endblock %}
+
+
+{% block main %}
+
+
+
+{% endblock %}
+
+
+
+
+
+{% block sidebar %}
+{% include 'menu_profile.html' %}
+{% endblock %}
diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py
index d7f9dd4a..b3b7b5d5 100644
--- a/rowers/templatetags/rowerfilters.py
+++ b/rowers/templatetags/rowerfilters.py
@@ -48,7 +48,7 @@ def sigdig(value, digits = 3):
# return integers as is
if value % 1 == 0:
return value
-
+
places = digits - order - 1
if places > 0:
fmtstr = "%%.%df" % (places)
@@ -83,7 +83,7 @@ def strfdelta(tdelta):
seconds=seconds,
tenths=tenths,
)
-
+
return res
from rowers.teams import rower_get_managers
@@ -91,13 +91,13 @@ from rowers.teams import rower_get_managers
@register.filter
def alertstatspercentage(list,i):
alertstats = list[i-1]
-
+
return alertstats["percentage"]
@register.filter
def alertstartdate(list,i):
alertstats = list[i-1]
-
+
return alertstats["startdate"]
@register.filter
@@ -109,7 +109,7 @@ def alertnperiod(list,i):
@register.filter
def alertenddate(list,i):
alertstats = list[i-1]
-
+
return alertstats["enddate"]
@register.filter
@@ -121,6 +121,45 @@ def is_coach(rower,rowers):
return True
+@register.filter
+def waterpower(x,rower):
+ if rower is not None:
+ return int(x*(100-rower.otwslack)/100.)
+ return int(x)
+
+@register.filter
+def round20(x):
+ try:
+ return int(20.*(1+int(int(x)/20)))
+ except ValueError:
+ return 20
+
+@register.filter
+def round100(x):
+ try:
+ return int(100.*(1+int(int(x)/100)))
+ except ValueError:
+ return 100
+
+@register.filter
+def majorticks(maxval):
+ ticks = range(1+int(maxval/100.))
+ newticks =[]
+ for t in ticks:
+ newticks.append(t*100)
+
+ return newticks
+
+@register.filter
+def hrmajorticks(maxval,minval):
+ ticks = range(int((maxval-minval)/20.)-1)
+ newticks =[]
+ for t in ticks:
+ newticks.append(100+t*20)
+
+ print(newticks)
+ return newticks
+
def strfdeltah(tdelta):
hours, rest = divmod(tdelta.seconds,3600)
minutes,seconds = divmod(rest,60)
@@ -131,7 +170,7 @@ def strfdeltah(tdelta):
seconds=seconds,
tenths=tenths,
)
-
+
return res
def secondstotimestring(tdelta):
@@ -142,7 +181,7 @@ def secondstotimestring(tdelta):
minutes=minutes,
seconds=seconds,
)
-
+
return res
@register.filter
@@ -218,7 +257,7 @@ def nextperiodstart(timeperiod):
newenddate = newstartdate+timedelta
return newstartdate.strftime("%Y-%m-%d")
-
+
@register.filter
def previousperiodend(timeperiod):
startdate,enddate = getstartenddate(timeperiod)
@@ -243,7 +282,7 @@ def previousperiodstart(timeperiod):
newstartdate = startdate-timedelta-datetime.timedelta(days=1)
return newstartdate.strftime("%Y-%m-%d")
-
+
@register.filter
def paceprint(d):
if (d == None):
@@ -288,11 +327,11 @@ def rkuserid(user):
rkuserid = runkeeperstuff.get_userid(thetoken)
return rkuserid
-
+
@register.filter
def courselength(course):
return course_length(course)
-
+
@register.filter(is_safe=True)
def jsdict(dict,key):
s = dict.get(key)
@@ -306,7 +345,7 @@ def lookup(dict, key):
s = dict.get(key)
except KeyError:
return None
-
+
if isinstance(s,string_types) and len(s) > 22:
s = s[:22]
return s
@@ -317,7 +356,7 @@ def lookuplong(dict, key):
s = dict.get(key)
except KeyError:
return None
-
+
return s
@register.filter
@@ -329,11 +368,11 @@ def ualookup(dict, key):
if key=='duration':
s = secondstotimestring(int(s))
-
+
if key=='starttime':
s = dateutil.parser.parse(s)
-
+
return s
from rowers.models import PlannedSession
@@ -343,7 +382,7 @@ def is_session_manager(id,user):
ps = PlannedSession.objects.get(id=id)
except PlannedSession.DoesNotExist:
return False
-
+
return ps.manager == user
from rowers.models import checkworkoutuser
@@ -358,7 +397,7 @@ def may_edit(workout,request):
return mayedit
-
+
@register.filter
def mayeditplan(obj,request):
@@ -376,11 +415,11 @@ def mayeditplan(obj,request):
rr = Rower.objects.get(user=request.user)
if checkaccessuser(request.user,obj.rower) and rr.rowerplan not in ['basic','pro']:
mayedit = True
-
+
return mayedit
-
+
@register.filter(name='times')
def times(number):
return range(number)
@@ -480,7 +519,7 @@ def team_members(user):
@register.filter
def openactions(user):
myteams = Team.objects.filter(manager=user)
-
+
invites = TeamInvite.objects.filter(user=user).count()
requests = TeamRequest.objects.filter(user=user).count()
myrequests = TeamRequest.objects.filter(team__in=myteams).count()
@@ -491,7 +530,7 @@ def openactions(user):
coachrequests = CoachRequest.objects.filter(coach=user.rower).count()
return invites+requests+myrequests+myinvites+mycoachoffers+coachoffers+mycoachrequests+coachrequests
-
+
@register.filter
def team_rowers(user):
@@ -518,7 +557,7 @@ def coach_rowers(user):
else:
thelist = [c for c in coach_getcoachees(user.rower)]
return thelist
-
+
@register.filter
def verbosetimeperiod(timeperiod):
@@ -538,7 +577,7 @@ def verbosetimeperiod(timeperiod):
verbose = timeperiod
return verbose
-
+
from datetime import date
@ register.filter
@@ -557,8 +596,8 @@ def is_future_date(the_date):
def amount(value):
vs = '{v}.00'.format(v=int(value))
return vs
-
-
+
+
@register.filter
def date_dif(the_date):
@@ -569,7 +608,7 @@ def date_dif(the_date):
else:
return 1
-
+
@register.filter
def can_register(race,r):
return race_can_register(r,race)
@@ -618,7 +657,7 @@ def userurl(path,member):
tpattern = re.compile('team\/\d+/')
if tpattern.search(path) is not None:
path = tpattern.sub('',path)
-
+
if pattern.search(path) is not None:
replaced = pattern.sub(userstring,path)
else:
@@ -635,7 +674,7 @@ def teamurl(path,team):
upattern = re.compile('\/user\/\d+/')
if upattern.search(path) is not None:
path = upattern.sub('/',path)
-
+
if pattern.search(path) is not None:
replaced = pattern.sub(teamstring,path)
@@ -726,13 +765,13 @@ def nextworkout(workout,user):
).exclude(id=workout.id)
except ValueError:
return 0
-
+
if ws:
return encoder.encode_hex(ws[0].id)
else:
return 0
-
+
@register.filter
def previousworkout(workout,user):
@@ -762,6 +801,3 @@ def previousworkout(workout,user):
return encoder.encode_hex(ws[0].id)
else:
return 0
-
-
-
diff --git a/rowers/tests/test_aavirtualevents.py b/rowers/tests/test_aavirtualevents.py
index a5be7e82..13609595 100644
--- a/rowers/tests/test_aavirtualevents.py
+++ b/rowers/tests/test_aavirtualevents.py
@@ -20,7 +20,7 @@ class VirtualEventViewTest(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach')
self.c = Client()
@@ -36,7 +36,7 @@ class VirtualEventViewTest(TestCase):
self.rpiet = Rower.objects.create(user=self.upiet,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='basic')
self.piet_workouts = WorkoutFactory.create_batch(5, user=self.rpiet)
@@ -49,7 +49,7 @@ class VirtualEventViewTest(TestCase):
self.rklaas = Rower.objects.create(user=self.uklaas,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='basic')
self.klaas_workouts = WorkoutFactory.create_batch(5, user=self.rklaas)
@@ -62,7 +62,7 @@ class VirtualEventViewTest(TestCase):
self.rhenk = Rower.objects.create(user=self.uhenk,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='basic')
self.henk_workouts = WorkoutFactory.create_batch(5, user=self.rhenk)
@@ -83,7 +83,7 @@ class VirtualEventViewTest(TestCase):
self.lastweek = lastweek
self.intwoweeks = intwoweeks
-
+
# erg races
self.openergrace = VirtualRace.objects.create(
name = faker.word(),
@@ -104,7 +104,7 @@ class VirtualEventViewTest(TestCase):
country = 'Indoor',
manager = self.u
)
-
+
self.submitergrace = VirtualRace.objects.create(
name = faker.word(),
startdate = yesterday.date(),
@@ -143,7 +143,7 @@ class VirtualEventViewTest(TestCase):
)
result = plannedsessions.add_rower_race(self.rpiet,self.submitergrace)
-
+
# register Henk for submitergrace
self.henkrecord = IndoorVirtualRaceResult.objects.create(
userid = self.rhenk.id,
@@ -161,7 +161,7 @@ class VirtualEventViewTest(TestCase):
)
result = plannedsessions.add_rower_race(self.rhenk,self.submitergrace)
-
+
# course
coursefile = 'rowers/tests/testdata/course_22.kml'
@@ -176,8 +176,8 @@ class VirtualEventViewTest(TestCase):
course = courses.createcourse(self.r,cname,polygons,notes=cnotes)
self.course = course
-
-
+
+
# otw races
self.openotwrace = VirtualRace.objects.create(
name = faker.word(),
@@ -247,11 +247,11 @@ class VirtualEventViewTest(TestCase):
distance=result['totaldist'],
workouttype = 'water',
)
-
+
# OTW not matching course
result = get_random_file(filename='rowers/tests/testdata/onwater2.csv')
-
+
self.wwater = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -262,11 +262,11 @@ class VirtualEventViewTest(TestCase):
)
-
+
# OTE 1k
result = get_random_file(filename='rowers/tests/testdata/duzend_ote.csv')
-
+
self.wduzend_r = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=nu.time(),
@@ -279,7 +279,7 @@ class VirtualEventViewTest(TestCase):
# Piet
result = get_random_file(filename='rowers/tests/testdata/duzend_ote.csv')
-
+
self.wduzend_rpiet = WorkoutFactory(user=self.rpiet,
csvfilename=result['filename'],
starttime=nu.time(),
@@ -292,7 +292,7 @@ class VirtualEventViewTest(TestCase):
# Klaas
result = get_random_file(filename='rowers/tests/testdata/duzend_ote.csv')
-
+
self.wduzend_rklaas = WorkoutFactory(user=self.rklaas,
csvfilename=result['filename'],
starttime=nu.time(),
@@ -305,7 +305,7 @@ class VirtualEventViewTest(TestCase):
# Henk
result = get_random_file(filename='rowers/tests/testdata/duzend_ote.csv')
-
+
self.wduzend_rhenk = WorkoutFactory(user=self.rhenk,
csvfilename=result['filename'],
starttime=nu.time(),
@@ -317,7 +317,7 @@ class VirtualEventViewTest(TestCase):
-
+
# OTE different
result = get_random_file()
self.wother_rpiet = WorkoutFactory(user=self.rpiet,
@@ -334,8 +334,8 @@ class VirtualEventViewTest(TestCase):
os.remove('rowers/tests/testdata/temp/course.kml')
except (FileNotFoundError, OSError, IOError):
pass
-
-
+
+
#Scenarios
@@ -344,7 +344,7 @@ class VirtualEventViewTest(TestCase):
def test_races_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = reverse('virtualevents_view')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -360,7 +360,7 @@ class VirtualEventViewTest(TestCase):
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
-
+
form_data = {
'country':'All',
'regattatype':'ongoing'
@@ -370,7 +370,7 @@ class VirtualEventViewTest(TestCase):
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
-
+
form_data = {
'country':'All',
'regattatype':'previous'
@@ -380,13 +380,13 @@ class VirtualEventViewTest(TestCase):
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
-
-
+
+
# set up new OTE race
def test_new_indoorrace(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = reverse('indoorvirtualevent_create_view')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -421,15 +421,15 @@ class VirtualEventViewTest(TestCase):
self.assertRedirects(response,
expected_url = reverse('virtualevents_view'),
status_code=302,target_status_code=200)
-
-
-
+
+
+
# set up new OTE race
def test_edit_indoorrace(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = reverse('indoorvirtualevent_edit_view',
kwargs={'id':self.openergrace.id})
response = self.c.get(url)
@@ -466,17 +466,17 @@ class VirtualEventViewTest(TestCase):
expected_url = reverse('virtualevent_view',
kwargs={'id':self.openergrace.id}),
status_code=302,target_status_code=200)
-
-
-
+
+
+
# set up new otw race
# set up new OTE race
def test_new_race(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = reverse('virtualevent_create_view')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -513,7 +513,7 @@ class VirtualEventViewTest(TestCase):
def test_edit_race(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = reverse('virtualevent_edit_view',kwargs={'id':self.openotwrace.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -547,12 +547,12 @@ class VirtualEventViewTest(TestCase):
expected_url = reverse('virtualevent_view',
kwargs={'id':self.openotwrace.id}),
status_code=302,target_status_code=200)
-
+
# view
def test_race_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = reverse('virtualevent_view',kwargs={'id':self.openotwrace.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -565,21 +565,21 @@ class VirtualEventViewTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
url = reverse('virtualevent_view',kwargs={'id':self.submitergrace.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
# register # withdraw
def test_register_race_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = reverse('indoorvirtualevent_register_view',
kwargs={'id':self.openergrace.id})
-
+
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -607,7 +607,7 @@ class VirtualEventViewTest(TestCase):
login = self.c.login(username=self.upiet.username, password=self.passwordpiet)
self.assertTrue(login)
-
+
url = reverse('indoorvirtualevent_register_view',kwargs={'id':self.openergrace.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -653,10 +653,10 @@ class VirtualEventViewTest(TestCase):
def test_register_otwrace_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = reverse('virtualevent_register_view',
kwargs={'id':self.openotwrace.id})
-
+
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -705,7 +705,7 @@ class VirtualEventViewTest(TestCase):
response = self.c.post(url,form_data,follow=True)
expected_url = reverse('virtualevent_view',kwargs={'id':self.openotwrace.id})
-
+
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
@@ -716,13 +716,13 @@ class VirtualEventViewTest(TestCase):
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
-
+
# submit result (OTE)
def test_ote_submit(self):
login = self.c.login(username=self.upiet.username, password=self.passwordpiet)
self.assertTrue(login)
-
+
url = reverse('virtualevent_submit_result_view',
kwargs={'id':self.submitergrace.id,
'workoutid':self.wduzend_rpiet.id})
@@ -741,7 +741,7 @@ class VirtualEventViewTest(TestCase):
therecord = IndoorVirtualRaceResult.objects.get(userid=self.rpiet.id,
race=self.submitergrace,
id=self.pietrecord.id)
-
+
self.assertTrue(therecord.coursecompleted)
@@ -755,7 +755,7 @@ class VirtualEventViewTest(TestCase):
def test_ote_submitfalse(self):
login = self.c.login(username=self.upiet.username, password=self.passwordpiet)
self.assertTrue(login)
-
+
url = reverse('virtualevent_submit_result_view',
kwargs={'id':self.submitergrace.id,
'workoutid':self.wother_rpiet.id})
@@ -774,7 +774,7 @@ class VirtualEventViewTest(TestCase):
therecord = IndoorVirtualRaceResult.objects.get(userid=self.rpiet.id,
race=self.submitergrace,
id=self.pietrecord.id)
-
+
self.assertTrue(not therecord.coursecompleted)
@@ -782,7 +782,7 @@ class VirtualEventViewTest(TestCase):
def test_otw_submit(self):
login = self.c.login(username=self.upiet.username, password=self.passwordpiet)
self.assertTrue(login)
-
+
url = reverse('virtualevent_submit_result_view',
kwargs={'id':self.submitotwrace.id,
'workoutid':self.wuh_otw.id})
@@ -819,7 +819,7 @@ class VirtualEventViewTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
def test_otw_courses_edit(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
@@ -850,5 +850,4 @@ class VirtualEventViewTest(TestCase):
# standalone
# calculate course adherence
- # other background jobs
-
+ # other background jobs
diff --git a/rowers/tests/test_analysis.py b/rowers/tests/test_analysis.py
index a4a0de04..50b0ab36 100644
--- a/rowers/tests/test_analysis.py
+++ b/rowers/tests/test_analysis.py
@@ -9,15 +9,15 @@ from .statements import *
nu = datetime.datetime.now()
from rowers.views import *
-
+
class WorkoutCompareTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -42,7 +42,7 @@ class WorkoutCompareTest(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/team-compare-select/workout/'+encoded1+'/team/0/user/1/'
response = self.c.get(url)
@@ -74,14 +74,14 @@ class WorkoutCompareTest(TestCase):
self.assertEqual(response.status_code,200)
-
+
class BoxPlotTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -107,7 +107,7 @@ class BoxPlotTest(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/user-boxplot-select/'
response = self.c.get(url)
@@ -169,17 +169,17 @@ class BoxPlotTest(TestCase):
response = self.c.get('/rowers/user-boxplot-data/')
-
+
self.assertEqual(response.status_code,200)
-
+
class ListWorkoutTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -223,14 +223,14 @@ class ListWorkoutTest(TestCase):
response = self.c.post(url, form_data)
self.assertEqual(response.status_code,200)
-
+
class PlannedSessionTests(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -281,7 +281,7 @@ class ForcecurveTest(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -314,10 +314,10 @@ class ForcecurveTest(TestCase):
class CumStatsTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -347,14 +347,14 @@ class CumStatsTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
class CumFlexTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -393,7 +393,7 @@ class CumFlexTest(TestCase):
u'4+',
u'8+',
u'8x+']
-
+
form_data = {
'startdate':startdate,
'enddate':enddate,
@@ -409,7 +409,7 @@ class CumFlexTest(TestCase):
self.factory.user = self.u
form = FlexAxesForm(self.factory,form_data)
-
+
url = '/rowers/flexall/'
@@ -447,19 +447,19 @@ class CumFlexTest(TestCase):
session['options'] = options
session.save()
response = self.c.get('/')
-
+
url = '/rowers/flexalldata/'
response = self.c.get(url)
self.assertEqual(response.status_code, 200)
-
+
class MultiFlexTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -498,7 +498,7 @@ class MultiFlexTest(TestCase):
u'4+',
u'8+',
u'8x+']
-
+
form_data = {
'startdate':startdate,
'enddate':enddate,
@@ -550,18 +550,18 @@ class MultiFlexTest(TestCase):
session['options'] = options
session.save()
response = self.c.get('/')
-
+
url = '/rowers/user-multiflex-data/'
response = self.c.get(url)
self.assertEqual(response.status_code, 200)
-
+
class HistoTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -603,7 +603,7 @@ class HistoTest(TestCase):
u'4+',
u'8+',
u'8x+']
-
+
form_data = {
'startdate':startdate,
'enddate':enddate,
@@ -614,11 +614,11 @@ class HistoTest(TestCase):
url = '/rowers/histo/'
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
response = self.c.post(url, form_data)
self.assertEqual(response.status_code,200)
-
+
options = {
'includereststrokes':False,
'rankingonly':False,
@@ -647,10 +647,10 @@ class HistoTest(TestCase):
class WorkoutCompareTestNew(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -675,7 +675,7 @@ class WorkoutCompareTestNew(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/user-analysis-select/compare/'
response = self.c.get(url)
@@ -724,7 +724,7 @@ class WorkoutCompareTestNew(TestCase):
result = form.is_valid()
if not result:
print(form.errors)
-
+
self.assertTrue(form.is_valid())
self.assertTrue(optionsform.is_valid())
self.assertTrue(dateform.is_valid())
@@ -736,10 +736,10 @@ class WorkoutCompareTestNew(TestCase):
class WorkoutBoxPlotTestNew(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -764,7 +764,7 @@ class WorkoutBoxPlotTestNew(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/user-analysis-select/boxplot/'
response = self.c.get(url)
@@ -812,7 +812,7 @@ class WorkoutBoxPlotTestNew(TestCase):
result = form.is_valid()
if not result:
print(form.errors)
-
+
self.assertTrue(form.is_valid())
self.assertTrue(optionsform.is_valid())
self.assertTrue(dateform.is_valid())
@@ -824,10 +824,10 @@ class WorkoutBoxPlotTestNew(TestCase):
class WorkoutHistoTestNew(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -852,7 +852,7 @@ class WorkoutHistoTestNew(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/user-analysis-select/histo/'
response = self.c.get(url)
@@ -900,7 +900,7 @@ class WorkoutHistoTestNew(TestCase):
result = form.is_valid()
if not result:
print(form.errors)
-
+
self.assertTrue(form.is_valid())
self.assertTrue(optionsform.is_valid())
self.assertTrue(dateform.is_valid())
@@ -912,10 +912,10 @@ class WorkoutHistoTestNew(TestCase):
class WorkoutFlexallTestNew(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -940,7 +940,7 @@ class WorkoutFlexallTestNew(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/user-analysis-select/flexall/'
response = self.c.get(url)
@@ -988,7 +988,7 @@ class WorkoutFlexallTestNew(TestCase):
result = form.is_valid()
if not result:
print(form.errors)
-
+
self.assertTrue(form.is_valid())
self.assertTrue(optionsform.is_valid())
self.assertTrue(dateform.is_valid())
@@ -1000,10 +1000,10 @@ class WorkoutFlexallTestNew(TestCase):
class WorkoutStatsTestNew(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -1028,7 +1028,7 @@ class WorkoutStatsTestNew(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/user-analysis-select/stats/'
response = self.c.get(url)
@@ -1082,8 +1082,8 @@ class WorkoutStatsTestNew(TestCase):
script, div = statsdata(workouts,options)
script, div = comparisondata(workouts,options)
-
-
+
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
def test_workouts_stats_submit(self, mocked_sqlalchemy,
@@ -1126,7 +1126,7 @@ class WorkoutStatsTestNew(TestCase):
result = form.is_valid()
if not result:
print(form.errors)
-
+
self.assertTrue(form.is_valid())
self.assertTrue(optionsform.is_valid())
self.assertTrue(dateform.is_valid())
@@ -1134,4 +1134,3 @@ class WorkoutStatsTestNew(TestCase):
response = self.c.post('/rowers/user-analysis-select/',form_data)
self.assertEqual(response.status_code,200)
-
diff --git a/rowers/tests/test_aworkouts.py b/rowers/tests/test_aworkouts.py
index 1b23d1b6..d82bc9ac 100644
--- a/rowers/tests/test_aworkouts.py
+++ b/rowers/tests/test_aworkouts.py
@@ -33,10 +33,10 @@ def create_image(storage, filename, size=(100, 100), image_mode='RGB', image_for
class WorkoutViewTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -48,7 +48,7 @@ class WorkoutViewTest(TestCase):
self.u.save()
result = get_random_file(filename='rowers/tests/testdata/onwater2.csv')
-
+
self.wwater = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -75,7 +75,7 @@ class WorkoutViewTest(TestCase):
)
result = get_random_file(filename='rowers/tests/testdata/erg1.csv')
-
+
self.werg1 = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -86,7 +86,7 @@ class WorkoutViewTest(TestCase):
)
result = get_random_file(filename='rowers/tests/testdata/erg2.csv')
-
+
self.werg2 = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -97,7 +97,7 @@ class WorkoutViewTest(TestCase):
)
result = get_random_file(filename='rowers/tests/testdata/erg2.csv')
-
+
self.werg2copy = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -107,9 +107,9 @@ class WorkoutViewTest(TestCase):
workouttype = 'rower',
)
-
+
result = get_random_file(filename='rowers/tests/testdata/erg3.csv')
-
+
self.werg3 = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -141,7 +141,7 @@ class WorkoutViewTest(TestCase):
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_joins(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
@@ -154,7 +154,7 @@ class WorkoutViewTest(TestCase):
d1 = self.werg1.date-datetime.timedelta(days=2)
d2 = self.werg2.date+datetime.timedelta(days=2)
-
+
date_form_data = {
'startdate': d1.strftime('%Y-%m%d'),
'enddate': d2.strftime('%Y-%m%d')
@@ -162,7 +162,7 @@ class WorkoutViewTest(TestCase):
response = self.c.post(url,date_form_data)
self.assertEqual(response.status_code,200)
-
+
url = reverse('workouts_join_view')
response = self.c.get(url,follow=True)
@@ -197,7 +197,7 @@ class WorkoutViewTest(TestCase):
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
@patch('rowers.middleware.myqueue')
@@ -224,8 +224,8 @@ class WorkoutViewTest(TestCase):
'plottype':'line',
'teamid': '',
}
-
-
+
+
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
@@ -269,7 +269,7 @@ class WorkoutViewTest(TestCase):
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_smoothen(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
@@ -287,7 +287,7 @@ class WorkoutViewTest(TestCase):
'id':encoder.encode_hex(self.wwater.id)
}
)
-
+
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
@@ -302,12 +302,12 @@ class WorkoutViewTest(TestCase):
'id':encoder.encode_hex(self.wwater.id)
}
)
-
+
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_windform(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
@@ -363,7 +363,7 @@ class WorkoutViewTest(TestCase):
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_setpowerform(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
@@ -409,7 +409,7 @@ class WorkoutViewTest(TestCase):
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_commentview(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
@@ -435,7 +435,7 @@ class WorkoutViewTest(TestCase):
url = reverse('workout_unsubscribe_view',kwargs={'id':encoder.encode_hex(self.wwater.id)})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_mapview(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
@@ -471,7 +471,7 @@ class WorkoutViewTest(TestCase):
#if not form.is_valid():
# print form.errors
#self.assertTrue(form.is_valid())
-
+
response = self.c.post(url,form_data,format='multipart',follow=True)
expected_url = reverse(self.r.defaultlandingpage,
@@ -480,7 +480,7 @@ class WorkoutViewTest(TestCase):
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
@patch('rowers.dataprep.getrowdata_db',side_effect=mocked_getrowdata_db)
@@ -536,7 +536,7 @@ class WorkoutViewTest(TestCase):
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_editsummaryview(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
@@ -590,7 +590,7 @@ class WorkoutViewTest(TestCase):
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db')
def test_workout_delete(self, mocked_sqlalchemy, mocked_getsmallrowdata_db):
@@ -611,4 +611,3 @@ class WorkoutViewTest(TestCase):
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
-
diff --git a/rowers/tests/test_basicrower.py b/rowers/tests/test_basicrower.py
index bd889be3..268ab876 100644
--- a/rowers/tests/test_basicrower.py
+++ b/rowers/tests/test_basicrower.py
@@ -15,10 +15,10 @@ from rowers.views import get_workout
class SimpleViewTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='basic')
@@ -59,4 +59,3 @@ class SimpleViewTest(TestCase):
self.assertRedirects(response,
expected_url='/rowers/list-workouts/',
status_code=302,target_status_code=200)
-
diff --git a/rowers/tests/test_courses.py b/rowers/tests/test_courses.py
index a6a976ad..723dbc74 100644
--- a/rowers/tests/test_courses.py
+++ b/rowers/tests/test_courses.py
@@ -11,7 +11,7 @@ class CoursesTest(TestCase):
self.u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
)
@@ -73,9 +73,8 @@ class CoursesTest(TestCase):
response = self.c.get('/rowers/courses/1/downloadkml/')
self.assertEqual(response.status_code,200)
-
+
self.assertEquals(
response.get('Content-Disposition'),
'attachment; filename="course_1.kml"'
)
-
diff --git a/rowers/tests/test_cpchart.py b/rowers/tests/test_cpchart.py
index 5429b1cb..4ab3a2bb 100644
--- a/rowers/tests/test_cpchart.py
+++ b/rowers/tests/test_cpchart.py
@@ -13,15 +13,15 @@ from rowers.utils import calculate_age
import rowers.dataprep as dataprep
-
+
@override_settings(TESTING=True)
class OTWCPChartTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,sex='male',
+ gdproptin=True,surveydone=True,sex='male',
weightcategory='hwt',
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -45,8 +45,8 @@ class OTWCPChartTest(TestCase):
totaldist = row.df['cum_dist'].max()
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
-
+
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -54,7 +54,7 @@ class OTWCPChartTest(TestCase):
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
duration = datetime.time(hour=hours,minute=minutes,second=seconds)
-
+
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
@@ -104,16 +104,16 @@ class OTWCPChartTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code, 200)
-
-
+
+
@override_settings(TESTING=True)
class CPChartTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,sex='male',
+ gdproptin=True,surveydone=True,sex='male',
weightcategory='hwt',
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -146,7 +146,7 @@ class CPChartTest(TestCase):
perfsdf = pd.read_csv('rowers/tests/testdata/calcageperformance.csv')
r = self.u.rower
-
+
for i in perfsdf.index:
perf = CalcAgePerformance(
age = age,
@@ -156,14 +156,14 @@ class CPChartTest(TestCase):
weightcategory = r.weightcategory
)
perf.save()
-
+
def tearDown(self):
for workout in self.user_workouts:
try:
os.remove(workout.csvfilename)
except (IOError, FileNotFoundError,OSError):
pass
-
+
def test_analytics_page(self):
login = self.c.login(username=self.u.username,password=self.password)
self.assertTrue(login)
@@ -228,7 +228,7 @@ class CPChartTest(TestCase):
r = self.u.rower
age = calculate_age(r.birthdate)
-
+
wcdurations = []
wcpower = []
durations = [1,4,30,60]
@@ -244,7 +244,7 @@ class CPChartTest(TestCase):
)
jsondf = df.to_json()
-
+
result = handle_getagegrouprecords(
jsondf,distances,durations,age,r.sex,r.weightcategory)
@@ -258,8 +258,8 @@ class CPChartTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
-
+
+
@patch('rowers.dataprep.fetchcperg', side_effect = mocked_fetchcperg)
@patch('rowers.dataprep.create_engine')
def test_rankingpieces(self, mocked_fetchcperg, mocked_sqlalchemy):
@@ -322,5 +322,3 @@ class CPChartTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code, 200)
-
-
diff --git a/rowers/tests/test_emails.py b/rowers/tests/test_emails.py
index 27bf2795..b65bcd9c 100644
--- a/rowers/tests/test_emails.py
+++ b/rowers/tests/test_emails.py
@@ -12,23 +12,23 @@ class EmailUpload(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.theadmin = UserFactory(is_staff=True)
self.rtheadmin = Rower.objects.create(user=self.theadmin,
birthdate = faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
-
+
nu = datetime.datetime.now()
workoutsbox = Mailbox.objects.create(name='workouts1')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
-
+
m = Message(mailbox=workoutsbox,
from_header = u.email,
subject = "run",
@@ -73,23 +73,23 @@ class ZipEmailUpload(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.theadmin = UserFactory(is_staff=True)
self.rtheadmin = Rower.objects.create(user=self.theadmin,
birthdate = faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
-
+
nu = datetime.datetime.now()
workoutsbox = Mailbox.objects.create(name='workouts1')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
-
+
m = Message(mailbox=workoutsbox,
from_header = u.email,
subject = "Sprint",
@@ -127,7 +127,7 @@ workout water
w = ws[4]
self.assertEqual(w.name,'Sprint (5)')
-
+
@override_settings(TESTING=True)
class EmailUniCodeUpload(TestCase):
def setUp(self):
@@ -135,23 +135,23 @@ class EmailUniCodeUpload(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.theadmin = UserFactory(is_staff=True)
self.rtheadmin = Rower.objects.create(user=self.theadmin,
birthdate = faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
-
+
nu = datetime.datetime.now()
workoutsbox = Mailbox.objects.create(name='workouts2')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
-
+
m = Message(mailbox=workoutsbox,
from_header = u.email,
subject = "Třeboň",
@@ -196,23 +196,23 @@ class EmailBikeErgUpload(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.theadmin = UserFactory(is_staff=True)
self.rtheadmin = Rower.objects.create(user=self.theadmin,
birthdate = faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
-
+
nu = datetime.datetime.now()
workoutsbox = Mailbox.objects.create(name='workouts2')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
-
+
m = Message(mailbox=workoutsbox,
from_header = u.email,
subject = "bikeerg",
@@ -257,23 +257,23 @@ class EmailBikeUpload(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.theadmin = UserFactory(is_staff=True)
self.rtheadmin = Rower.objects.create(user=self.theadmin,
birthdate = faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
-
+
nu = datetime.datetime.now()
workoutsbox = Mailbox.objects.create(name='workouts3')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
-
+
m = Message(mailbox=workoutsbox,
from_header = u.email,
subject = "bike",
@@ -311,9 +311,9 @@ workout bike
w = ws[0]
self.assertEqual(w.workouttype,'Bike')
-
-
-#@pytest.mark.django_db
+
+
+#@pytest.mark.django_db
@override_settings(TESTING=True)
class EmailTests(TestCase):
def setUp(self):
@@ -321,24 +321,24 @@ class EmailTests(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.theadmin = UserFactory(is_staff=True)
self.rtheadmin = Rower.objects.create(user=self.theadmin,
birthdate = faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
-
+
nu = datetime.datetime.now()
workoutsbox = Mailbox.objects.create(name='workouts4')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
-
+
for filename in os.listdir(u'rowers/tests/testdata/emails'):
m = Message(mailbox=workoutsbox,
from_header = u.email,
@@ -384,7 +384,7 @@ race 1
os.remove(path)
except (IOError,FileNotFoundError,OSError):
pass
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.polarstuff.get_polar_notifications')
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
@@ -396,7 +396,7 @@ race 1
self.assertIn('Successfully processed email attachments',out.getvalue())
-
+
@override_settings(TESTING=True)
class EmailAdminUpload(TestCase):
def setUp(self):
@@ -404,7 +404,7 @@ class EmailAdminUpload(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
birthdate = faker.profile()['birthdate']
)
@@ -412,10 +412,10 @@ class EmailAdminUpload(TestCase):
self.theadmin = UserFactory(is_staff=True)
self.rtheadmin = Rower.objects.create(user=self.theadmin,
birthdate = faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
-
+
self.race = RaceFactory(manager = self.theadmin)
nu = datetime.datetime.now()
@@ -423,7 +423,7 @@ class EmailAdminUpload(TestCase):
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
-
+
m = Message(mailbox=workoutsbox,
from_header = self.theadmin.email,
subject = "johnsworkout",
@@ -460,7 +460,7 @@ race 1
if not len(ws):
for w in Workout.objects.all():
print(w)
-
+
self.assertEqual(len(ws),1)
w = ws[0]
@@ -473,4 +473,3 @@ race 1
result = results[0]
self.assertTrue(result.coursecompleted)
-
diff --git a/rowers/tests/test_empower.py b/rowers/tests/test_empower.py
index 4681113a..9073dd0c 100644
--- a/rowers/tests/test_empower.py
+++ b/rowers/tests/test_empower.py
@@ -14,10 +14,10 @@ class EmpowerTest(TestCase):
'sander@ds.ds',
'koeinsloot',
)
- r = Rower.objects.create(user=u,rowerplan='coach',gdproptin=True,
+ r = Rower.objects.create(user=u,rowerplan='coach',gdproptin=True,surveydone=True,
gdproptindate=timezone.now())
self.c = Client()
-
+
self.nu = datetime.datetime.now()
filename = 'rowers/tests/testdata/testdata.csv'
otwfilename = 'rowers/tests/testdata/empower.csv'
@@ -27,20 +27,20 @@ class EmpowerTest(TestCase):
starttime=self.nu.strftime('%H:%M:%S'),
duration="0:55:00",distance=8000,
csvfilename=filename)
-
+
self.wote = Workout.objects.create(name='testworkout',
workouttype='Indoor Rower',
user=r,date=self.nu.strftime('%Y-%m-%d'),
starttime=self.nu.strftime('%H:%M:%S'),
duration="0:55:00",distance=8000,
csvfilename=otwfilename)
-
+
powerperc = 100*np.array([r.pw_ut2,
r.pw_ut1,
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
-
+
self.hrdata = {
'hrmax':r.max,
'hrut2':r.ut2,
diff --git a/rowers/tests/test_flexchart.py b/rowers/tests/test_flexchart.py
index 96ed9e52..27869afa 100644
--- a/rowers/tests/test_flexchart.py
+++ b/rowers/tests/test_flexchart.py
@@ -9,10 +9,10 @@ from .statements import *
class WorkoutViewTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
showfavoritechartnotes=True)
@@ -25,7 +25,7 @@ class WorkoutViewTest(TestCase):
self.u.save()
result = get_random_file(filename='rowers/tests/testdata/onwater2.csv')
-
+
self.wwater = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -47,7 +47,7 @@ class WorkoutViewTest(TestCase):
)
result = get_random_file(filename='rowers/tests/testdata/erg1.csv')
-
+
self.werg1 = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -58,7 +58,7 @@ class WorkoutViewTest(TestCase):
)
result = get_random_file(filename='rowers/tests/testdata/erg2.csv')
-
+
self.werg2 = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -69,7 +69,7 @@ class WorkoutViewTest(TestCase):
)
result = get_random_file(filename='rowers/tests/testdata/erg3.csv')
-
+
self.werg3 = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
@@ -98,7 +98,7 @@ class WorkoutViewTest(TestCase):
notes=faker.word(),
user=self.r
)
-
+
def tearDown(self):
pass
@@ -113,7 +113,7 @@ class WorkoutViewTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
# change chart
form_data = {
'xaxis':'time',
@@ -161,7 +161,7 @@ class WorkoutViewTest(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
# change chart
form_data = {
'xaxis':'time',
@@ -190,4 +190,4 @@ class WorkoutViewTest(TestCase):
}
response = self.c.post(url,form_data)
- self.assertEqual(response.status_code,200)
+ self.assertEqual(response.status_code,200)
diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py
index 1612cef5..03710671 100644
--- a/rowers/tests/test_imports.py
+++ b/rowers/tests/test_imports.py
@@ -10,7 +10,7 @@ nu = datetime.datetime.now()
import rowers
-@pytest.mark.django_db
+@pytest.mark.django_db
@override_settings(TESTING=True)
class C2Objects(DjangoTestCase):
def setUp(self):
@@ -22,7 +22,7 @@ class C2Objects(DjangoTestCase):
self.u.first_name = 'John'
self.u.last_name = 'Sander'
self.u.save()
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
@@ -33,9 +33,9 @@ class C2Objects(DjangoTestCase):
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
-
+
filename = 'rowers/tests/testdata/testdata.csv'
-
+
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
@@ -44,7 +44,7 @@ class C2Objects(DjangoTestCase):
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -65,15 +65,15 @@ class C2Objects(DjangoTestCase):
csvfilename=filename
)
-
+
@patch('rowers.c2stuff.Session', side_effect=mocked_requests)
def test_c2_callback(self, mock_Session):
response = self.c.get('/call_back?code=dsdoij232s',follow=True)
-
+
self.assertEqual(response.status_code, 200)
-
+
@patch('rowers.c2stuff.Session', side_effect=mocked_requests)
def test_c2_token_refresh(self, mock_Session):
response = self.c.get('/rowers/me/c2refresh/',follow=True)
@@ -99,7 +99,7 @@ class C2Objects(DjangoTestCase):
response = self.c.get('/rowers/workout/c2list',follow=True)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
@patch('rowers.dataprep.create_engine')
def test_c2_import(self, mock_get, mocked_sqlalchemy):
@@ -112,7 +112,7 @@ class C2Objects(DjangoTestCase):
self.assertEqual(response.status_code, 200)
-
+
@patch('rowers.dataprep.create_engine')
def test_strokedata(self, mocked_sqlalchemy):
with open('rowers/tests/testdata/c2stroketestdata.txt','r') as infile:
@@ -157,7 +157,7 @@ class C2ObjectsTokenExpired(DjangoTestCase):
self.u.first_name = 'John'
self.u.last_name = 'Sander'
self.u.save()
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
@@ -168,9 +168,9 @@ class C2ObjectsTokenExpired(DjangoTestCase):
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
-
+
filename = 'rowers/tests/testdata/testdata.csv'
-
+
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
@@ -179,7 +179,7 @@ class C2ObjectsTokenExpired(DjangoTestCase):
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -200,7 +200,7 @@ class C2ObjectsTokenExpired(DjangoTestCase):
csvfilename=filename
)
-
+
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
@@ -209,7 +209,7 @@ class C2ObjectsTokenExpired(DjangoTestCase):
response = self.c.get('/rowers/workout/c2list',follow=True)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
@patch('rowers.dataprep.create_engine')
def test_c2_import(self, mock_get, mocked_sqlalchemy):
@@ -222,9 +222,9 @@ class C2ObjectsTokenExpired(DjangoTestCase):
self.assertEqual(response.status_code, 200)
-
-
-#@pytest.mark.django_db
+
+
+#@pytest.mark.django_db
@override_settings(TESTING=True)
class StravaObjects(DjangoTestCase):
def setUp(self):
@@ -236,7 +236,7 @@ class StravaObjects(DjangoTestCase):
self.u.first_name = 'John'
self.u.last_name = 'Sander'
self.u.save()
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
@@ -247,9 +247,9 @@ class StravaObjects(DjangoTestCase):
self.r.save()
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
-
+
filename = 'rowers/tests/testdata/testdata.csv'
-
+
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
@@ -258,7 +258,7 @@ class StravaObjects(DjangoTestCase):
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -329,10 +329,10 @@ class StravaObjects(DjangoTestCase):
self.assertEqual(result,"987654321234567898765432123456789")
-
-#@pytest.mark.django_db
+
+#@pytest.mark.django_db
@override_settings(TESTING=True)
-class STObjects(DjangoTestCase):
+class STObjects(DjangoTestCase):
def setUp(self):
self.c = Client()
self.u = User.objects.create_user('john',
@@ -342,7 +342,7 @@ class STObjects(DjangoTestCase):
self.u.first_name = 'John'
self.u.last_name = 'Sander'
self.u.save()
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
@@ -355,9 +355,9 @@ class STObjects(DjangoTestCase):
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
-
+
filename = 'rowers/tests/testdata/testdata.csv'
-
+
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
@@ -366,7 +366,7 @@ class STObjects(DjangoTestCase):
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -391,10 +391,10 @@ class STObjects(DjangoTestCase):
def test_sporttracks_callback(self, mock_post):
response = self.c.get('/sporttracks_callback?code=dsdoij232s',follow=True)
-
+
self.assertEqual(response.status_code, 200)
-
+
@patch('rowers.sporttracksstuff.requests.post', side_effect=mocked_requests)
def test_sporttracks_token_refresh(self, mock_post):
response = self.c.get('/rowers/me/sporttracksrefresh/',follow=True)
@@ -419,7 +419,7 @@ class STObjects(DjangoTestCase):
response = self.c.get('/rowers/workout/sporttracksimport',follow=True)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.imports.requests.get', side_effect=mocked_requests)
def test_sporttracks_import(self, mock_get):
@@ -478,9 +478,9 @@ class STObjects(DjangoTestCase):
res = add_workout_from_data(self.u,1,data,data)
-#@pytest.mark.django_db
+#@pytest.mark.django_db
@override_settings(TESTING=True)
-class RunKeeperObjects(DjangoTestCase):
+class RunKeeperObjects(DjangoTestCase):
def setUp(self):
self.c = Client()
self.u = User.objects.create_user('john',
@@ -490,7 +490,7 @@ class RunKeeperObjects(DjangoTestCase):
self.u.first_name = 'John'
self.u.last_name = 'Sander'
self.u.save()
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
@@ -502,9 +502,9 @@ class RunKeeperObjects(DjangoTestCase):
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
-
+
filename = 'rowers/tests/testdata/testdata.csv'
-
+
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
@@ -513,7 +513,7 @@ class RunKeeperObjects(DjangoTestCase):
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -557,7 +557,7 @@ class RunKeeperObjects(DjangoTestCase):
response = self.c.get('/rowers/workout/runkeeperimport',follow=True)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.imports.requests.get', side_effect=mocked_requests)
def test_runkeeper_import(self, mock_get):
@@ -570,10 +570,10 @@ class RunKeeperObjects(DjangoTestCase):
self.assertEqual(response.status_code, 200)
-
-@pytest.mark.django_db
+
+@pytest.mark.django_db
@override_settings(TESTING=True)
-class UAObjects(DjangoTestCase):
+class UAObjects(DjangoTestCase):
def setUp(self):
self.c = Client()
self.u = User.objects.create_user('john',
@@ -583,7 +583,7 @@ class UAObjects(DjangoTestCase):
self.u.first_name = 'John'
self.u.last_name = 'Sander'
self.u.save()
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
@@ -596,9 +596,9 @@ class UAObjects(DjangoTestCase):
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
-
+
filename = 'rowers/tests/testdata/testdata.csv'
-
+
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
@@ -607,7 +607,7 @@ class UAObjects(DjangoTestCase):
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -632,10 +632,10 @@ class UAObjects(DjangoTestCase):
def test_underarmour_callback(self, mock_post):
response = self.c.get('/underarmour_callback?code=dsdoij232s',follow=True)
-
+
self.assertEqual(response.status_code, 200)
-
+
@patch('rowers.underarmourstuff.requests.post', side_effect=mocked_requests)
def test_underarmour_token_refresh(self, mock_post):
response = self.c.get('/rowers/me/underarmourrefresh/',follow=True)
@@ -660,7 +660,7 @@ class UAObjects(DjangoTestCase):
response = self.c.get('/rowers/workout/underarmourimport',follow=True)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.imports.requests.get', side_effect=mocked_requests)
@patch('rowers.dataprep.create_engine')
def test_underarmour_import(self, mock_get, mocked_sqlalchemy):
@@ -674,9 +674,9 @@ class UAObjects(DjangoTestCase):
self.assertEqual(response.status_code, 200)
-#@pytest.mark.django_db
+#@pytest.mark.django_db
@override_settings(TESTING=True)
-class TPObjects(DjangoTestCase):
+class TPObjects(DjangoTestCase):
def setUp(self):
self.c = Client()
self.u = User.objects.create_user('john',
@@ -686,7 +686,7 @@ class TPObjects(DjangoTestCase):
self.u.first_name = 'John'
self.u.last_name = 'Sander'
self.u.save()
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
@@ -699,9 +699,9 @@ class TPObjects(DjangoTestCase):
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
-
+
filename = 'rowers/tests/testdata/testdata.csv'
-
+
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
@@ -710,7 +710,7 @@ class TPObjects(DjangoTestCase):
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -735,10 +735,10 @@ class TPObjects(DjangoTestCase):
def test_tp_callback(self, mock_post):
response = self.c.get('/tp_callback?code=dsdoij232s',follow=True)
-
+
self.assertEqual(response.status_code, 200)
-
+
@patch('rowers.tpstuff.requests.post', side_effect=mocked_requests)
def test_tp_token_refresh(self, mock_post):
response = self.c.get('/rowers/me/tprefresh/',follow=True)
@@ -761,7 +761,7 @@ class TPObjects(DjangoTestCase):
self.assertEqual(response.status_code, 302)
-#@pytest.mark.django_db
+#@pytest.mark.django_db
@override_settings(TESTING=True)
class AutoExportTests(TestCase):
def setUp(self):
@@ -769,7 +769,7 @@ class AutoExportTests(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
diff --git a/rowers/tests/test_interactivecharts.py b/rowers/tests/test_interactivecharts.py
index 4d7fb2cd..7572d68e 100644
--- a/rowers/tests/test_interactivecharts.py
+++ b/rowers/tests/test_interactivecharts.py
@@ -14,7 +14,7 @@ class InteractiveChartTest(TestCase):
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.nu = datetime.datetime.now()
@@ -26,7 +26,7 @@ class InteractiveChartTest(TestCase):
starttime=self.nu.strftime('%H:%M:%S'),
duration="0:55:00",distance=8000,
csvfilename=self.filename)
-
+
self.wote = Workout.objects.create(name='testworkout',
workouttype='Indoor Rower',
user=r,date=self.nu.strftime('%Y-%m-%d'),
@@ -40,7 +40,7 @@ class InteractiveChartTest(TestCase):
def test_painsled(self, mocked_sqlalchemy, mocked_read_df_sql):
u = User.objects.get(username='john')
r = Rower.objects.get(user=u)
-
+
rr = rrower(hrmax=r.max,hrut2=r.ut2,
hrut1=r.ut1,hrat=r.at,
hrtr=r.tr,hran=r.an,ftp=r.ftp)
@@ -59,7 +59,7 @@ class InteractiveChartTest(TestCase):
@patch('rowers.dataprep.read_df_sql')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
def test_interactive_chart2(self, mocked_sqlalchemy,mocked_read_df_sql,
- mocked_getsmallrowdata_db):
+ mocked_getsmallrowdata_db):
res = iplots.interactive_chart(self.wote.id,promember=1)
@patch('rowers.dataprep.create_engine')
@@ -69,7 +69,7 @@ class InteractiveChartTest(TestCase):
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.read_df_sql')
- def test_interactive_chart4(self, mocked_sqlalchemy,mocked_read_df_sql):
+ def test_interactive_chart4(self, mocked_sqlalchemy,mocked_read_df_sql):
res = iplots.interactive_bar_chart(self.wote.id,promember=1)
@patch('rowers.dataprep.create_engine')
@@ -90,7 +90,7 @@ class InteractiveChartTest(TestCase):
@patch('rowers.dataprep.read_df_sql')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
def test_interactive_chart7(self, mocked_sqlalchemy,mocked_read_df_sql,
- mocked_getsmallrowdata_db):
+ mocked_getsmallrowdata_db):
res = iplots.interactive_flex_chart2(self.wote.id,promember=0,
xparam='time',
yparam1='pace',yparam2='spm')
@@ -98,8 +98,8 @@ class InteractiveChartTest(TestCase):
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.read_df_sql')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
- def test_interactive_chart8(self, mocked_sqlalchemy,mocked_read_df_sql,
- mocked_getsmallrowdata_db):
+ def test_interactive_chart8(self, mocked_sqlalchemy,mocked_read_df_sql,
+ mocked_getsmallrowdata_db):
res = iplots.interactive_flex_chart2(self.wote.id,
promember=0,xparam='distance',
yparam1='pace',yparam2='spm')
@@ -108,23 +108,23 @@ class InteractiveChartTest(TestCase):
@patch('rowers.dataprep.read_df_sql')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
def test_interactive_chart9(self, mocked_sqlalchemy,mocked_read_df_sql,
- mocked_getsmallrowdata_db):
+ mocked_getsmallrowdata_db):
res = iplots.interactive_flex_chart2(self.wote.id,
promember=1,xparam='time',
yparam1='pace',yparam2='hr')
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.read_df_sql')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
- def test_interactive_chart10(self, mocked_sqlalchemy,mocked_read_df_sql,
- mocked_getsmallrowdata_db):
+ def test_interactive_chart10(self, mocked_sqlalchemy,mocked_read_df_sql,
+ mocked_getsmallrowdata_db):
res = iplots.interactive_flex_chart2(self.wote.id,
promember=1,xparam='distance',
yparam1='pace',yparam2='hr')
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.read_df_sql')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
- def test_interactive_chart11(self, mocked_sqlalchemy,mocked_read_df_sql,
- mocked_getsmallrowdata_db):
+ def test_interactive_chart11(self, mocked_sqlalchemy,mocked_read_df_sql,
+ mocked_getsmallrowdata_db):
res = iplots.interactive_flex_chart2(self.wote.id,
promember=1,xparam='time',
yparam1='pace',yparam2='spm')
@@ -132,10 +132,8 @@ class InteractiveChartTest(TestCase):
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.read_df_sql')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
- def test_interactive_chart12(self, mocked_sqlalchemy,mocked_read_df_sql,
- mocked_getsmallrowdata_db):
+ def test_interactive_chart12(self, mocked_sqlalchemy,mocked_read_df_sql,
+ mocked_getsmallrowdata_db):
res = iplots.interactive_flex_chart2(self.wote.id,promember=1,
xparam='distance',
yparam1='pace',yparam2='spm')
-
-
diff --git a/rowers/tests/test_misc.py b/rowers/tests/test_misc.py
index f572f495..cf97672c 100644
--- a/rowers/tests/test_misc.py
+++ b/rowers/tests/test_misc.py
@@ -9,15 +9,15 @@ from .statements import *
nu = datetime.datetime.now()
-
-#@pytest.mark.django_db
+
+#@pytest.mark.django_db
class WorkoutTests(TestCase):
def setUp(self):
redis_connection.publish('tasks','KILL')
self.u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
nu = datetime.datetime.now()
@@ -30,14 +30,14 @@ class WorkoutTests(TestCase):
def test_checkworkoutuser(self):
self.assertEqual(checkworkoutuser(self.u,self.w),True)
-#@pytest.mark.django_db
+#@pytest.mark.django_db
class C2Tests(TestCase):
def setUp(self):
redis_connection.publish('tasks','KILL')
self.u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.nu = datetime.datetime.now()
@@ -54,7 +54,7 @@ class C2Tests(TestCase):
-#@pytest.mark.django_db
+#@pytest.mark.django_db
class subroutinetests(TestCase):
def setUp(self):
redis_connection.publish('tasks','KILL')
@@ -77,6 +77,3 @@ class subroutinetests(TestCase):
jsond = json.dumps(data)
data = c2stuff.createc2workoutdata_as_splits(w)
jsond = json.dumps(data)
-
-
-
diff --git a/rowers/tests/test_newusers.py b/rowers/tests/test_newusers.py
index 2d5960e3..bdfae610 100644
--- a/rowers/tests/test_newusers.py
+++ b/rowers/tests/test_newusers.py
@@ -8,7 +8,7 @@ from .statements import *
nu = datetime.datetime.now()
-#@pytest.mark.django_db
+#@pytest.mark.django_db
@override_settings(TESTING=True)
class NewUserRegistrationTest(TestCase):
def setUp(self):
@@ -20,7 +20,7 @@ class NewUserRegistrationTest(TestCase):
os.remove('rowsandall_workouts_2018-01-01_2019-01-01.csv')
except:
pass
-
+
@patch('rowers.dataprep.workout_summary_to_df',side_effect=mock_workout_summaries)
def test_newuser(self,mock_workout_summaries):
form_data = {
@@ -40,9 +40,9 @@ class NewUserRegistrationTest(TestCase):
form = RegistrationFormUniqueEmail(form_data)
self.assertTrue(form.is_valid())
-
+
response = self.c.post('/rowers/register/', form_data, follow=True)
-
+
self.assertRedirects(response,
expected_url='/rowers/me/gdpr-optin/?next=/rowers/list-workouts/',
status_code=302,target_status_code=200)
@@ -73,7 +73,7 @@ class NewUserRegistrationTest(TestCase):
response = self.c.post(url,form_data)
self.assertTrue(response.status_code,200)
-
+
url = '/rowers/me/delete/'
form_data = {
@@ -84,6 +84,3 @@ class NewUserRegistrationTest(TestCase):
self.assertRedirects(response,
expected_url='/login/',
status_code=302,target_status_code=200)
-
-
-
diff --git a/rowers/tests/test_payments.py b/rowers/tests/test_payments.py
index cc23d5e0..b2795935 100644
--- a/rowers/tests/test_payments.py
+++ b/rowers/tests/test_payments.py
@@ -15,7 +15,7 @@ class PaymentTest(TestCase):
def setUp(self):
# settings.DEBUG = True
-
+
p1 = PaidPlan(
shortname='free',
name='Basic',
@@ -64,7 +64,7 @@ class PaymentTest(TestCase):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -79,7 +79,7 @@ class PaymentTest(TestCase):
u.save()
login = self.c.login(username=u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/billing/'
response = self.c.get(url)
@@ -93,7 +93,7 @@ class PaymentTest(TestCase):
for code, name in list(countries):
if name.lower() == country.lower():
countrycode = code
-
+
form_data = {
'street_address':faker.street_address(),
'city':faker.city(),
@@ -112,7 +112,7 @@ class PaymentTest(TestCase):
self.assertEqual(response.status_code,200)
expected_url = '/rowers/checkout/'+str(plan.id)+'/'
-
+
self.assertRedirects(response,
expected_url = expected_url,
status_code=302,target_status_code=200)
@@ -122,7 +122,7 @@ class PaymentTest(TestCase):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -139,10 +139,10 @@ class PaymentTest(TestCase):
r.save()
u.set_password(self.password)
u.save()
-
+
login = self.c.login(username=u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/upgrade/'
response = self.c.get(url)
@@ -156,7 +156,7 @@ class PaymentTest(TestCase):
for code, name in list(countries):
if name.lower() == country.lower():
countrycode = code
-
+
form_data = {
'street_address':faker.street_address(),
'city':faker.city(),
@@ -175,7 +175,7 @@ class PaymentTest(TestCase):
self.assertEqual(response.status_code,200)
expected_url = '/rowers/upgradecheckout/'+str(plan.id)+'/'
-
+
self.assertRedirects(response,
expected_url = expected_url,
status_code=302,target_status_code=200)
@@ -185,7 +185,7 @@ class PaymentTest(TestCase):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -208,10 +208,10 @@ class PaymentTest(TestCase):
r.save()
u.set_password(self.password)
u.save()
-
+
login = self.c.login(username=u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/downgrade/'
response = self.c.get(url)
@@ -222,7 +222,7 @@ class PaymentTest(TestCase):
for code, name in list(countries):
if name.lower() == country.lower():
countrycode = code
-
+
form_data = {
'street_address':faker.street_address(),
'city':faker.city(),
@@ -241,7 +241,7 @@ class PaymentTest(TestCase):
self.assertEqual(response.status_code,200)
expected_url = '/rowers/downgradecheckout/'+str(plans[0].id)+'/'
-
+
self.assertRedirects(response,
expected_url = expected_url,
status_code=302,target_status_code=200)
@@ -251,7 +251,7 @@ class PaymentTest(TestCase):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -274,22 +274,22 @@ class PaymentTest(TestCase):
r.paidplan = plan
r.save()
-
+
login = self.c.login(username=u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/me/cancelsubscriptions/'
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
@patch('rowers.views.braintreestuff.gateway',side_effect=MockBraintreeGateway)
def test_planstobasic_view(self,mocked_gateway):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -312,10 +312,10 @@ class PaymentTest(TestCase):
r.paidplan = plan
r.save()
-
+
login = self.c.login(username=u.username, password=self.password)
self.assertTrue(login)
-
+
url = '/rowers/me/cancelsubscription/34/'
response = self.c.get(url,follow=True)
@@ -329,7 +329,7 @@ class PaymentTest(TestCase):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -344,13 +344,13 @@ class PaymentTest(TestCase):
r.save()
result = mocktest(r)
self.assertEqual(result,'121')
-
+
@patch('rowers.views.braintreestuff.create_subscription', side_effect=mock_create_subscription)
def test_checkouts_view(self,mock_subscription):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -396,7 +396,7 @@ class PaymentTest(TestCase):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -435,13 +435,13 @@ class PaymentTest(TestCase):
self.assertRedirects(response,
expected_url = '/rowers/paymentcompleted/?amount=20.00',
status_code=302,target_status_code=200)
-
+
@patch('rowers.views.braintreestuff.update_subscription', side_effect=mock_update_subscription)
def test_downgrade_checkouts_view(self,mock_subscription):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -480,13 +480,13 @@ class PaymentTest(TestCase):
self.assertRedirects(response,
expected_url = '/rowers/downgradecompleted/',
status_code=302,target_status_code=200)
-
+
@patch('rowers.views.braintreestuff.create_subscription', side_effect=mock_create_subscription)
def test_checkouts_view(self,mock_subscription):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -536,7 +536,7 @@ class PaymentTest(TestCase):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -575,13 +575,13 @@ class PaymentTest(TestCase):
self.assertRedirects(response,
expected_url = '/rowers/paymentcompleted/?amount=20.00',
status_code=302,target_status_code=200)
-
+
@patch('rowers.views.braintreestuff.update_subscription', side_effect=mock_update_subscription)
def test_downgrade_checkouts_view(self,mock_subscription):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
paymentprocessor='braintree',
@@ -620,4 +620,3 @@ class PaymentTest(TestCase):
self.assertRedirects(response,
expected_url = '/rowers/downgradecompleted/',
status_code=302,target_status_code=200)
-
diff --git a/rowers/tests/test_permissions.py b/rowers/tests/test_permissions.py
index a82002a7..2213a7b8 100644
--- a/rowers/tests/test_permissions.py
+++ b/rowers/tests/test_permissions.py
@@ -23,7 +23,7 @@ class PermissionsFreeCoach(TestCase):
self.ufreecoach = UserFactory(username='coachuser')
self.rfreecoach = Rower.objects.create(user=self.ufreecoach,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='freecoach',clubsize=100)
self.coachinggroup = CoachingGroup.objects.create()
@@ -33,11 +33,11 @@ class PermissionsFreeCoach(TestCase):
self.password = faker.word()
self.ufreecoach.set_password(self.password)
self.ufreecoach.save()
-
+
self.uplan = UserFactory(username='planuser')
self.rplan = Rower.objects.create(user=self.uplan,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan)
@@ -45,11 +45,11 @@ class PermissionsFreeCoach(TestCase):
self.password = faker.word()
self.uplan.set_password(self.password)
self.uplan.save()
-
+
self.upro = UserFactory(username='prouser')
self.rpro = Rower.objects.create(user=self.upro,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro_workouts = WorkoutFactory.create_batch(5, user=self.rpro)
@@ -61,7 +61,7 @@ class PermissionsFreeCoach(TestCase):
self.uplan2 = UserFactory(username='planuser2')
self.rplan2 = Rower.objects.create(user=self.uplan2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2)
@@ -69,11 +69,11 @@ class PermissionsFreeCoach(TestCase):
self.password = faker.word()
self.uplan2.set_password(self.password)
self.uplan2.save()
-
+
self.upro2 = UserFactory(username='prouser2')
self.rpro2 = Rower.objects.create(user=self.upro2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro2_workouts = WorkoutFactory.create_batch(5, user=self.rpro2)
@@ -85,7 +85,7 @@ class PermissionsFreeCoach(TestCase):
self.ubasic = UserFactory(username='basicuser')
self.rbasic = Rower.objects.create(user=self.ubasic,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='basic')
self.ubasic_workouts = WorkoutFactory.create_batch(5, user=self.rbasic)
@@ -93,9 +93,9 @@ class PermissionsFreeCoach(TestCase):
self.ubasicpassword = faker.word()
self.ubasic.set_password(self.ubasicpassword)
self.ubasic.save()
-
-
-
+
+
+
## TeamFreeCoach
self.teamfreecoach = Team.objects.create(
@@ -120,8 +120,8 @@ class PermissionsFreeCoach(TestCase):
)
self.assertEqual(team2.manager,self.ufreecoach)
-
-
+
+
team3 = Team.objects.create(
name = 'ThirdTeam',
notes = faker.text(),
@@ -129,9 +129,9 @@ class PermissionsFreeCoach(TestCase):
)
self.assertEqual(team3.manager,self.ufreecoach)
-
-
-
+
+
+
## Free coach can create more than one group
def test_plan_groupmanager(self):
team1 = Team.objects.create(
@@ -147,11 +147,11 @@ class PermissionsFreeCoach(TestCase):
notes = faker.text(),
manager = self.ufreecoach,
)
-
- self.assertEqual(team2.manager,self.ufreecoach)
-
-
+ self.assertEqual(team2.manager,self.ufreecoach)
+
+
+
## Free Coach can create planned sessions and team planned sessions
## Self Coach and higher can create planned sessions and team planned sessions
def test_plan_create_session(self):
@@ -161,7 +161,7 @@ class PermissionsFreeCoach(TestCase):
comment=faker.text()
)
self.assertEqual(ps.manager,self.ufreecoach)
-
+
def test_coach_create_session(self):
ps = PlannedSession.objects.create(
manager=self.ufreecoach,
@@ -169,8 +169,8 @@ class PermissionsFreeCoach(TestCase):
comment=faker.text()
)
self.assertEqual(ps.manager,self.ufreecoach)
-
-
+
+
## Basic cannot join groups led by Free Coach
def test_add_basic_pro_or_plan(self):
with transaction.atomic():
@@ -191,7 +191,7 @@ class PermissionsFreeCoach(TestCase):
distance=result['totaldist'],
workouttype = 'rower',
)
-
+
@override_settings(TESTING=True)
class PermissionsBasicsTests(TestCase):
def setUp(self):
@@ -201,7 +201,7 @@ class PermissionsBasicsTests(TestCase):
self.ucoach = UserFactory(username='coachuser')
self.rcoach = Rower.objects.create(user=self.ucoach,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach',clubsize=10)
self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach)
@@ -212,11 +212,11 @@ class PermissionsBasicsTests(TestCase):
self.password = faker.word()
self.ucoach.set_password(self.password)
self.ucoach.save()
-
+
self.uplan = UserFactory(username='planuser')
self.rplan = Rower.objects.create(user=self.uplan,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan)
@@ -224,11 +224,11 @@ class PermissionsBasicsTests(TestCase):
self.password = faker.word()
self.uplan.set_password(self.password)
self.uplan.save()
-
+
self.upro = UserFactory(username='prouser')
self.rpro = Rower.objects.create(user=self.upro,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro_workouts = WorkoutFactory.create_batch(5, user=self.rpro)
@@ -240,7 +240,7 @@ class PermissionsBasicsTests(TestCase):
self.uplan2 = UserFactory(username='planuser2')
self.rplan2 = Rower.objects.create(user=self.uplan2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2)
@@ -248,11 +248,11 @@ class PermissionsBasicsTests(TestCase):
self.password = faker.word()
self.uplan2.set_password(self.password)
self.uplan2.save()
-
+
self.upro2 = UserFactory(username='prouser2')
self.rpro2 = Rower.objects.create(user=self.upro2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro2_workouts = WorkoutFactory.create_batch(5, user=self.rpro2)
@@ -264,7 +264,7 @@ class PermissionsBasicsTests(TestCase):
self.ubasic = UserFactory(username='basicuser')
self.rbasic = Rower.objects.create(user=self.ubasic,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='basic')
self.ubasic_workouts = WorkoutFactory.create_batch(5, user=self.rbasic)
@@ -272,9 +272,9 @@ class PermissionsBasicsTests(TestCase):
self.ubasicpassword = faker.word()
self.ubasic.set_password(self.ubasicpassword)
self.ubasic.save()
-
-
-
+
+
+
## TeamPro, TeamCoach, TeamSelfCoach
self.teampro = Team.objects.create(
@@ -293,9 +293,9 @@ class PermissionsBasicsTests(TestCase):
manager=self.ucoach)
# Requirements
-
+
## Low level
-
+
## Coach can have any number of groups
def test_coach_groupmanager(self):
team1 = Team.objects.create(
@@ -313,8 +313,8 @@ class PermissionsBasicsTests(TestCase):
)
self.assertEqual(team2.manager,self.ucoach)
-
-
+
+
team3 = Team.objects.create(
name = 'ThirdTeam',
notes = faker.text(),
@@ -322,15 +322,15 @@ class PermissionsBasicsTests(TestCase):
)
self.assertEqual(team3.manager,self.ucoach)
-
-
-
+
+
+
## Basic athletes can be member of Coach led group
def test_add_coach(self):
self.rbasic.team.add(self.teamcoach)
self.assertIn(self.teamcoach,self.rbasic.team.all())
-
-
+
+
## Self coach can create one group
## Self coach cannot create more than one group
def test_plan_groupmanager(self):
@@ -348,9 +348,9 @@ class PermissionsBasicsTests(TestCase):
notes = faker.text(),
manager = self.uplan,
)
-
-
-
+
+
+
## Pro users (and higher) can join group led by other Pro (or higher) user
def test_add_proplan_pro_or_plan(self):
self.rpro.team.add(self.teamplan)
@@ -371,9 +371,9 @@ class PermissionsBasicsTests(TestCase):
self.rcoach.team.add(self.teampro)
self.assertIn(self.teampro,self.rcoach.team.all())
-
-
-
+
+
+
## Coach can create planned sessions and team planned sessions
## Self Coach and higher can create planned sessions and team planned sessions
def test_plan_create_session(self):
@@ -383,7 +383,7 @@ class PermissionsBasicsTests(TestCase):
comment=faker.text()
)
self.assertEqual(ps.manager,self.uplan)
-
+
def test_coach_create_session(self):
ps = PlannedSession.objects.create(
manager=self.ucoach,
@@ -391,7 +391,7 @@ class PermissionsBasicsTests(TestCase):
comment=faker.text()
)
self.assertEqual(ps.manager,self.ucoach)
-
+
## Pro can have one group
## Pro cannot create more than one group
def test_pro_groupmanager(self):
@@ -409,8 +409,8 @@ class PermissionsBasicsTests(TestCase):
notes = faker.text(),
manager = self.upro,
)
-
-
+
+
## Pro or Basic cannot create planned sessions or team planned sessions
def test_pro_create_plannedsession(self):
with self.assertRaises(ValidationError):
@@ -419,7 +419,7 @@ class PermissionsBasicsTests(TestCase):
name = faker.word(),
comment = faker.text()
)
-
+
def test_basic_create_plannedsession(self):
with self.assertRaises(ValidationError):
ps = PlannedSession.objects.create(
@@ -427,7 +427,7 @@ class PermissionsBasicsTests(TestCase):
name = faker.word(),
comment = faker.text()
)
-
+
## Basic cannot join groups led by Pro or Self Coach
def test_add_basic_pro_or_plan(self):
with transaction.atomic():
@@ -437,7 +437,7 @@ class PermissionsBasicsTests(TestCase):
with transaction.atomic():
with self.assertRaises(ValidationError):
self.rbasic.team.add(self.teampro)
-
+
## Basic cannot manage a group
def test_basic_groupmanager(self):
@@ -461,7 +461,7 @@ class PermissionsViewTests(TestCase):
self.ucoach = UserFactory(username='coachuser')
self.rcoach = Rower.objects.create(user=self.ucoach,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach',clubsize=10)
self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach)
@@ -472,11 +472,11 @@ class PermissionsViewTests(TestCase):
self.ucoachpassword = faker.word()
self.ucoach.set_password(self.ucoachpassword)
self.ucoach.save()
-
+
self.uplan = UserFactory(username='planuser')
self.rplan = Rower.objects.create(user=self.uplan,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan)
@@ -484,11 +484,11 @@ class PermissionsViewTests(TestCase):
self.uplanpassword = faker.word()
self.uplan.set_password(self.uplanpassword)
self.uplan.save()
-
+
self.upro = UserFactory(username='prouser')
self.rpro = Rower.objects.create(user=self.upro,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro_workouts = WorkoutFactory.create_batch(5, user=self.rpro)
@@ -500,7 +500,7 @@ class PermissionsViewTests(TestCase):
self.uplan2 = UserFactory(username='planuser2')
self.rplan2 = Rower.objects.create(user=self.uplan2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2)
@@ -508,11 +508,11 @@ class PermissionsViewTests(TestCase):
self.uplan2password = faker.word()
self.uplan2.set_password(self.uplan2password)
self.uplan2.save()
-
+
self.upro2 = UserFactory(username='prouser2')
self.rpro2 = Rower.objects.create(user=self.upro2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro2_workouts = WorkoutFactory.create_batch(5, user=self.rpro2)
@@ -524,7 +524,7 @@ class PermissionsViewTests(TestCase):
self.ubasic = UserFactory(username='basicuser')
self.rbasic = Rower.objects.create(user=self.ubasic,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='basic')
self.ubasic_workouts = WorkoutFactory.create_batch(5, user=self.rbasic)
@@ -532,9 +532,9 @@ class PermissionsViewTests(TestCase):
self.ubasicpassword = faker.word()
self.ubasic.set_password(self.ubasicpassword)
self.ubasic.save()
-
-
-
+
+
+
## TeamPro, TeamCoach, TeamSelfCoach
self.teampro = Team.objects.create(
@@ -557,7 +557,7 @@ class PermissionsViewTests(TestCase):
def test_coach_groups_create(self):
login = self.c.login(username=self.ucoach.username, password=self.ucoachpassword)
self.assertTrue(login)
-
+
url = reverse('team_create_view')
response = self.c.get(url)
@@ -574,7 +574,7 @@ class PermissionsViewTests(TestCase):
form = TeamForm(form_data)
if not form.is_valid():
print(form.errors)
-
+
self.assertTrue(form.is_valid())
expected_url = reverse('rower_teams_view')
@@ -596,7 +596,7 @@ class PermissionsViewTests(TestCase):
form = TeamForm(form_data)
if not form.is_valid():
print(form.errors)
-
+
self.assertTrue(form.is_valid())
expected_url = reverse('rower_teams_view')
@@ -605,7 +605,7 @@ class PermissionsViewTests(TestCase):
self.assertRedirects(response,
expected_url=expected_url,
status_code=302,target_status_code=200)
-
+
## Basic athletes can be member of Coach led group
## Coach can create planned sessions and team planned sessions
@@ -682,7 +682,7 @@ class PermissionsViewTests(TestCase):
'theuser':self.ubasic.id,
}
)
-
+
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -700,7 +700,7 @@ class PermissionsViewTests(TestCase):
'theuser':self.ubasic.id,
}
)
-
+
response = self.c.get(url)
self.assertEqual(response.status_code,403)
@@ -747,11 +747,11 @@ class PermissionsViewTests(TestCase):
self.assertRedirects(response,
expected_url = url,
status_code=302,target_status_code=200)
-
+
aantal2 = len(Workout.objects.filter(user=self.rbasic))
self.assertEqual(aantal2,aantal+1)
-
+
## Coach can upload on behalf of athlete - if team allows
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
@@ -791,11 +791,11 @@ class PermissionsViewTests(TestCase):
self.assertRedirects(response,
expected_url = url,
status_code=302,target_status_code=200)
-
+
aantal2 = len(Workout.objects.filter(user=self.rbasic))
self.assertEqual(aantal2,aantal)
-
+
## Coach can edit athlete's workout
def test_coach_edit_athlete_workout(self):
self.rbasic.team.add(self.teamcoach)
@@ -809,13 +809,13 @@ class PermissionsViewTests(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,403)
-
+
## Self coach can create one group
## Self coach cannot create more than one group
def test_plan_groups_create(self):
login = self.c.login(username=self.uplan.username, password=self.uplanpassword)
self.assertTrue(login)
-
+
url = reverse('team_create_view')
response = self.c.get(url)
@@ -832,7 +832,7 @@ class PermissionsViewTests(TestCase):
form = TeamForm(form_data)
if not form.is_valid():
print(form.errors)
-
+
self.assertTrue(form.is_valid())
expected_url = reverse('rower_teams_view')
@@ -854,7 +854,7 @@ class PermissionsViewTests(TestCase):
form = TeamForm(form_data)
if not form.is_valid():
print(form.errors)
-
+
self.assertTrue(form.is_valid())
expected_url = reverse('paidplans')
@@ -927,7 +927,7 @@ class PermissionsViewTests(TestCase):
'theuser':self.ubasic.id,
}
)
-
+
response = self.c.get(url)
self.assertEqual(response.status_code,403)
@@ -952,7 +952,7 @@ class PermissionsViewTests(TestCase):
def test_pro_groups_create(self):
login = self.c.login(username=self.upro.username, password=self.upropassword)
self.assertTrue(login)
-
+
url = reverse('team_create_view')
response = self.c.get(url)
@@ -969,7 +969,7 @@ class PermissionsViewTests(TestCase):
form = TeamForm(form_data)
if not form.is_valid():
print(form.errors)
-
+
self.assertTrue(form.is_valid())
expected_url = reverse('rower_teams_view')
@@ -991,7 +991,7 @@ class PermissionsViewTests(TestCase):
form = TeamForm(form_data)
if not form.is_valid():
print(form.errors)
-
+
self.assertTrue(form.is_valid())
expected_url = reverse('paidplans')
@@ -1049,7 +1049,7 @@ class PermissionsViewTests(TestCase):
'theuser':self.ubasic.id,
}
)
-
+
response = self.c.get(url)
self.assertEqual(response.status_code,403)
@@ -1095,7 +1095,7 @@ class PermissionsViewTests(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
## Self Coach users can see team members' workout, but not edit
def test_plan_edit_athlete_workout(self):
@@ -1117,7 +1117,7 @@ class PermissionsViewTests(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
## Basic users can see team members' workout, but not edit
def test_basic_edit_athlete_workout(self):
@@ -1148,7 +1148,7 @@ class PermissionsViewTests(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
# workflow
url = reverse('workout_workflow_view',
kwargs={'id':encoder.encode_hex(self.uplan2_workouts[0].id)}
@@ -1165,7 +1165,7 @@ class PermissionsViewTests(TestCase):
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
+
## Pro users (and higher) can join group led by other Pro (or higher) user
def test_team_member_request_pro_pro(self):
login = self.c.login(username=self.upro.username,password=self.upropassword)
@@ -1215,7 +1215,7 @@ class PermissionsCoachingTests(TestCase):
self.ucoach = UserFactory(username='coachuser')
self.rcoach = Rower.objects.create(user=self.ucoach,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='coach',clubsize=10)
self.ucoach_workouts = WorkoutFactory.create_batch(5, user=self.rcoach)
@@ -1226,11 +1226,11 @@ class PermissionsCoachingTests(TestCase):
self.ucoachpassword = faker.word()
self.ucoach.set_password(self.ucoachpassword)
self.ucoach.save()
-
+
self.uplan = UserFactory(username='planuser')
self.rplan = Rower.objects.create(user=self.uplan,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan_workouts = WorkoutFactory.create_batch(5, user=self.rplan)
@@ -1238,11 +1238,11 @@ class PermissionsCoachingTests(TestCase):
self.password = faker.word()
self.uplan.set_password(self.password)
self.uplan.save()
-
+
self.upro = UserFactory(username='prouser')
self.rpro = Rower.objects.create(user=self.upro,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro_workouts = WorkoutFactory.create_batch(5, user=self.rpro)
@@ -1254,7 +1254,7 @@ class PermissionsCoachingTests(TestCase):
self.uplan2 = UserFactory(username='planuser2')
self.rplan2 = Rower.objects.create(user=self.uplan2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='plan')
self.uplan2_workouts = WorkoutFactory.create_batch(5, user=self.rplan2)
@@ -1262,11 +1262,11 @@ class PermissionsCoachingTests(TestCase):
self.password = faker.word()
self.uplan2.set_password(self.password)
self.uplan2.save()
-
+
self.upro2 = UserFactory(username='prouser2')
self.rpro2 = Rower.objects.create(user=self.upro2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='pro')
self.upro2_workouts = WorkoutFactory.create_batch(5, user=self.rpro2)
@@ -1278,7 +1278,7 @@ class PermissionsCoachingTests(TestCase):
self.ubasic = UserFactory(username='basicuser')
self.rbasic = Rower.objects.create(user=self.ubasic,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,gdproptindate=timezone.now(),
+ gdproptin=True,surveydone=True,gdproptindate=timezone.now(),
rowerplan='basic')
self.ubasic_workouts = WorkoutFactory.create_batch(5, user=self.rbasic)
@@ -1286,9 +1286,9 @@ class PermissionsCoachingTests(TestCase):
self.ubasicpassword = faker.word()
self.ubasic.set_password(self.ubasicpassword)
self.ubasic.save()
-
-
-
+
+
+
## TeamPro, TeamCoach, TeamSelfCoach
self.teampro = Team.objects.create(
@@ -1360,7 +1360,7 @@ class PermissionsCoachingTests(TestCase):
coachingrequests = CoachOffer.objects.filter(user=self.ubasic)
self.assertEqual(len(coachingrequests),0)
-
+
def test_athlete_request_coach_reject(self):
login = self.c.login(username=self.ubasic.username,password=self.ubasicpassword)
self.assertTrue(login)
@@ -1421,7 +1421,7 @@ class PermissionsCoachingTests(TestCase):
coachingrequests = CoachOffer.objects.filter(user=self.ubasic)
self.assertEqual(len(coachingrequests),0)
-
+
def test_athlete_request_coach_accept_coach_drop(self):
login = self.c.login(username=self.ubasic.username,password=self.ubasicpassword)
self.assertTrue(login)
@@ -1512,7 +1512,7 @@ class PermissionsCoachingTests(TestCase):
coaches = teams.rower_get_coaches(self.rbasic)
self.assertEqual(len(coaches),0)
-
+
def test_coach_offer_athlete_accept_coach_drop(self):
login = self.c.login(username=self.ucoach.username,password=self.ucoachpassword)
self.assertTrue(login)
@@ -1558,7 +1558,7 @@ class PermissionsCoachingTests(TestCase):
coaches = teams.rower_get_coaches(self.rbasic)
self.assertEqual(len(coaches),0)
-
+
def test_athlete_request_coach_accept_athlete_drop(self):
login = self.c.login(username=self.ubasic.username,password=self.ubasicpassword)
@@ -1611,7 +1611,7 @@ class PermissionsCoachingTests(TestCase):
coaches = teams.rower_get_coaches(self.rbasic)
self.assertEqual(len(coaches),0)
-
+
# coach related
## coach disappears from list when downgrading
diff --git a/rowers/tests/test_plans.py b/rowers/tests/test_plans.py
index d69a3dc9..613478da 100644
--- a/rowers/tests/test_plans.py
+++ b/rowers/tests/test_plans.py
@@ -17,7 +17,7 @@ class TrainingPlanTest(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -175,7 +175,7 @@ class SessionLinkTest(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -348,7 +348,7 @@ class SessionCompleteTest(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -603,7 +603,7 @@ class ChallengeCompleteTest(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -827,7 +827,7 @@ class MandatoryTestCompleteTest(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -1040,7 +1040,7 @@ class PlannedSessionsView(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
self.r.save()
@@ -1049,7 +1049,7 @@ class PlannedSessionsView(TestCase):
self.u2 = UserFactory(username='testbasicuser')
self.r2 = Rower.objects.create(user=self.u2,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='basic')
diff --git a/rowers/tests/test_rowerplans.py b/rowers/tests/test_rowerplans.py
index 6aeea434..d87f1a56 100644
--- a/rowers/tests/test_rowerplans.py
+++ b/rowers/tests/test_rowerplans.py
@@ -11,10 +11,10 @@ from rowers.views import hasplannedsessions,iscoachmember,ispromember
class TrialsTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='basic')
@@ -46,7 +46,7 @@ class TrialsTest(TestCase):
self.r.plantrialexpires = (nu+datetime.timedelta(days=10)).date()
self.r.save()
-
+
self.assertEqual(hasplannedsessions(self.u),True)
self.assertEqual(iscoachmember(self.u),False)
self.assertEqual(ispromember(self.u),True)
@@ -60,10 +60,7 @@ class TrialsTest(TestCase):
self.r.plantrialexpires = (nu+datetime.timedelta(days=10)).date()
self.r.save()
-
+
self.assertEqual(hasplannedsessions(self.u),True)
self.assertEqual(iscoachmember(self.u),False)
self.assertEqual(ispromember(self.u),True)
-
-
-
diff --git a/rowers/tests/test_settings.py b/rowers/tests/test_settings.py
index 3dbe555b..b9a44653 100644
--- a/rowers/tests/test_settings.py
+++ b/rowers/tests/test_settings.py
@@ -7,14 +7,14 @@ from __future__ import unicode_literals
from .statements import *
-#@pytest.mark.django_db
+#@pytest.mark.django_db
class DataTest(TestCase):
def setUp(self):
redis_connection.publish('tasks','KILL')
u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- r = Rower.objects.create(user=u,gdproptin=True,
+ r = Rower.objects.create(user=u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now()
)
self.nu = datetime.datetime.now()
diff --git a/rowers/tests/test_simplefunctions.py b/rowers/tests/test_simplefunctions.py
index 22cc3140..904fb01f 100644
--- a/rowers/tests/test_simplefunctions.py
+++ b/rowers/tests/test_simplefunctions.py
@@ -11,14 +11,32 @@ from django.http import Http404
from rowers.views import get_workout
+class TestDateTime(TestCase):
+ def setUp(self):
+ self.factory = RequestFactory()
+
+ def tearDown(self):
+ pass
+
+ def test_get_dates(self):
+ request = self.factory.get('/rowers/sessions/create/user/230/?startdate=13.01.2020&enddate=19.01.2020')
+ startdate,enddate = get_dates_timeperiod(request)
+
+ teststart = datetime.date(2020,1,1)
+ self.assertTrue(teststartenddate)
+
+
# tests simple functions from views.py
class SimpleViewTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -36,11 +54,11 @@ class SimpleViewTest(TestCase):
except (IOError, FileNotFoundError,OSError):
pass
-
+
def test_getrequestrower(self):
user_no_rower = UserFactory(username='norower')
user_no_rower.set_password(faker.word())
-
+
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
@@ -75,7 +93,7 @@ class SimpleViewTest(TestCase):
self.assertRedirects(response,
expected_url='/rowers/email/',
status_code=302,target_status_code=200)
-
+
def test_getworkout(self):
with assert_raises(Http404):
@@ -108,7 +126,3 @@ class SimpleViewTest(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertEqual(login,False)
-
-
-
-
diff --git a/rowers/tests/test_staticcharts.py b/rowers/tests/test_staticcharts.py
index db0b4235..cd7bc7ed 100644
--- a/rowers/tests/test_staticcharts.py
+++ b/rowers/tests/test_staticcharts.py
@@ -9,7 +9,7 @@ nu = datetime.datetime.now()
-#@pytest.mark.django_db
+#@pytest.mark.django_db
@override_settings(TESTING=True)
class PlotTests(TestCase):
def setUp(self):
@@ -18,7 +18,7 @@ class PlotTests(TestCase):
'sander@ds.ds',
'koeinsloot')
r = Rower.objects.create(user=u,
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='basic')
self.nu = datetime.datetime.now()
@@ -29,14 +29,14 @@ class PlotTests(TestCase):
starttime=self.nu.strftime('%H:%M:%S'),
duration="0:55:00",distance=8000,
csvfilename=filename)
-
+
self.wote = Workout.objects.create(name='testworkout',
workouttype='Indoor Rower',
user=r,date=self.nu.strftime('%Y-%m-%d'),
starttime=self.nu.strftime('%H:%M:%S'),
duration="0:55:00",distance=8000,
csvfilename=filename)
-
+
# timestr = strftime("%Y%m%d-%H%M%S")
# imagename = f1+timestr+'.png'
# fullpathimagename = 'static/plots/'+imagename
@@ -45,7 +45,7 @@ class PlotTests(TestCase):
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
-
+
self.hrdata = {
'hrmax':r.max,
'hrut2':r.ut2,
@@ -64,7 +64,7 @@ class PlotTests(TestCase):
@patch('rowers.tasks.FigureCanvas')
def test_ote_plots(self, mocked_rowingdata, mocked_canvas):
w = self.wote
- f1 = 'testdata.csv'[:-4]
+ f1 = 'testdata.csv'[:-4]
timestr = strftime("%Y%m%d-%H%M%S")
imagename = f1+timestr+'.png'
fullpathimagename = 'static/plots/'+imagename
@@ -72,7 +72,7 @@ class PlotTests(TestCase):
plotnr = 1
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -85,7 +85,7 @@ class PlotTests(TestCase):
plotnr = 1
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -98,7 +98,7 @@ class PlotTests(TestCase):
plotnr = 2
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -111,7 +111,7 @@ class PlotTests(TestCase):
plotnr = 3
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -124,7 +124,7 @@ class PlotTests(TestCase):
plotnr = 4
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -137,7 +137,7 @@ class PlotTests(TestCase):
plotnr = 5
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -150,7 +150,7 @@ class PlotTests(TestCase):
plotnr = 6
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -163,7 +163,7 @@ class PlotTests(TestCase):
plotnr = 7
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -176,7 +176,7 @@ class PlotTests(TestCase):
plotnr = 8
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -189,7 +189,7 @@ class PlotTests(TestCase):
plotnr = 13
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -203,7 +203,7 @@ class PlotTests(TestCase):
@patch('rowers.tasks.FigureCanvas')
def test_chartrequests(self, mocked_rowingdata, mocked_canvas):
opid = encoder.encode_hex(self.wotw.id)
-
+
url = reverse('workout_add_chart_view',
kwargs={'id':opid,
'plotnr':13
@@ -212,7 +212,7 @@ class PlotTests(TestCase):
workout_edit_url = reverse('workout_edit_view',
kwargs={'id':opid})
-
+
login = self.c.login(username='john', password='koeinsloot')
self.assertTrue(login)
@@ -246,12 +246,12 @@ class PlotTests(TestCase):
self.assertEqual(len(i),0)
-
+
@patch('rowers.tasks.rdata')
@patch('rowers.tasks.FigureCanvas')
def test_otw_plots(self, mocked_rowingdata, mocked_canvas):
w = self.wotw
- f1 = 'testdata.csv'[:-4]
+ f1 = 'testdata.csv'[:-4]
timestr = strftime("%Y%m%d-%H%M%S")
imagename = f1+timestr+'.png'
fullpathimagename = 'static/plots/'+imagename
@@ -259,7 +259,7 @@ class PlotTests(TestCase):
plotnr = 1
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -272,7 +272,7 @@ class PlotTests(TestCase):
plotnr = 1
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -285,7 +285,7 @@ class PlotTests(TestCase):
plotnr = 2
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -298,7 +298,7 @@ class PlotTests(TestCase):
plotnr = 3
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -311,7 +311,7 @@ class PlotTests(TestCase):
plotnr = 4
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -324,7 +324,7 @@ class PlotTests(TestCase):
plotnr = 5
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -337,7 +337,7 @@ class PlotTests(TestCase):
plotnr = 6
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -350,7 +350,7 @@ class PlotTests(TestCase):
plotnr = 7
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -363,7 +363,7 @@ class PlotTests(TestCase):
plotnr = 8
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -376,7 +376,7 @@ class PlotTests(TestCase):
plotnr = 9
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
@@ -389,7 +389,7 @@ class PlotTests(TestCase):
plotnr = 13
if (w.workouttype=='water'):
plotnr = plotnr+3
-
+
res = handle_makeplot(f1,w.csvfilename,
w.name,self.hrdata,plotnr,imagename)
i = GraphImage(workout=w,creationdatetime=self.nu,
diff --git a/rowers/tests/test_team.py b/rowers/tests/test_team.py
index 99119a2c..05d16b5a 100644
--- a/rowers/tests/test_team.py
+++ b/rowers/tests/test_team.py
@@ -38,10 +38,10 @@ class TeamTest(TestCase):
for i in range(6):
u = UserFactory(username=usernames[i])
self.users.append(u)
-
+
r = Rower.objects.create(
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
user=u,
@@ -53,7 +53,7 @@ class TeamTest(TestCase):
u.set_password(password)
u.save()
self.user_passwords.append(password)
-
+
workouts = WorkoutFactory.create_batch(5, user=r)
for w in workouts:
@@ -64,7 +64,7 @@ class TeamTest(TestCase):
self.u = self.users[0]
self.password = self.user_passwords[0]
-
+
self.t = TeamFactory(manager=self.u)
# need to set up some requests for testing (they are not good below)
@@ -105,7 +105,7 @@ class TeamTest(TestCase):
self.assertRedirects(response,
expected_url='/rowers/me/teams/'.format(t=self.t.id),
status_code=302,target_status_code=200)
-
+
def test_teamview(self):
login = self.c.login(username=self.u.username, password = self.password)
self.assertTrue(login)
@@ -113,9 +113,9 @@ class TeamTest(TestCase):
url = '/rowers/team/{t}/'.format(t=self.t.id)
response = self.c.get(url)
self.assertEqual(response.status_code, 200)
-
+
def test_teamview_member(self):
-
+
id,comment = add_member(self.t.id,self.users[1].rower)
self.assertEqual(id,self.t.id)
@@ -132,7 +132,7 @@ class TeamTest(TestCase):
login = self.c.login(username=self.users[2].username, password = self.user_passwords[2])
self.assertTrue(login)
-
+
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
@@ -147,11 +147,11 @@ class TeamTest(TestCase):
print(u)
print(response.status_code)
self.assertIn(response.status_code,[200,302])
-
+
login = self.c.login(username=self.users[1].username,
password = self.user_passwords[1])
self.assertTrue(login)
-
+
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
@@ -166,14 +166,14 @@ class TeamTest(TestCase):
print(u)
print(response.status_code)
self.assertIn(response.status_code,[200,302])
-
+
def test_teamsview_manager(self):
url = '/rowers/me/teams/'
login = self.c.login(username=self.u,password=self.password)
self.assertTrue(login)
-
+
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
@@ -190,14 +190,14 @@ class TeamTest(TestCase):
self.assertIn(response.status_code,[200,302])
def test_teamview_member_request(self):
-
+
login = self.c.login(username=self.users[3].username, password = self.user_passwords[3])
self.assertTrue(login)
url = '/rowers/team/{t}/requestmembership/{u}/'.format(
t=self.t.id,
u=self.users[3].id)
-
+
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code, 200)
@@ -226,8 +226,8 @@ class TeamTest(TestCase):
self.assertRedirects(response,
expected_url='/rowers/me/teams/',
status_code=302,target_status_code=200)
-
-
+
+
def test_team_invite_view(self):
login = self.c.login(username=self.u.username, password = self.password)
self.assertTrue(login)
@@ -238,11 +238,11 @@ class TeamTest(TestCase):
'email': self.users[1].email,
'user': u''
}
-
+
response = self.c.post(url, form_data)
self.assertEqual(response.status_code, 200)
-
-@override_settings(TESTING=True)
+
+@override_settings(TESTING=True)
class TeamTestLowLevel(TestCase):
def setUp(self):
redis_connection.publish('tasks','KILL')
@@ -261,10 +261,10 @@ class TeamTestLowLevel(TestCase):
for i in range(6):
u = UserFactory(username=usernames[i])
self.users.append(u)
-
+
r = Rower.objects.create(
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
user=u,
@@ -276,7 +276,7 @@ class TeamTestLowLevel(TestCase):
u.set_password(password)
u.save()
self.user_passwords.append(password)
-
+
workouts = WorkoutFactory.create_batch(5, user=r)
for w in workouts:
@@ -287,7 +287,7 @@ class TeamTestLowLevel(TestCase):
self.u = self.users[0]
self.password = self.user_passwords[0]
-
+
self.t = TeamFactory(manager=self.u)
@@ -353,5 +353,3 @@ class TeamTestLowLevel(TestCase):
# cannot create invite for team you don't manage
id, comment = create_invite(self.t, self.users[3],self.users[4])
self.assertEqual(id,0)
-
-
diff --git a/rowers/tests/test_units.py b/rowers/tests/test_units.py
index 7546603a..95f76243 100644
--- a/rowers/tests/test_units.py
+++ b/rowers/tests/test_units.py
@@ -26,7 +26,7 @@ class ForceUnits(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -164,7 +164,7 @@ class TestForceUnit(TestCase):
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
diff --git a/rowers/tests/test_uploads.py b/rowers/tests/test_uploads.py
index aa2ea98c..22f9a4e5 100644
--- a/rowers/tests/test_uploads.py
+++ b/rowers/tests/test_uploads.py
@@ -9,7 +9,7 @@ nu = datetime.datetime.now()
from rowers.views import add_defaultfavorites
-#@pytest.mark.django_db
+#@pytest.mark.django_db
@override_settings(TESTING=True)
class ViewTest(TestCase):
def setUp(self):
@@ -18,13 +18,13 @@ class ViewTest(TestCase):
self.u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
- self.r = Rower.objects.create(user=self.u,gdproptin=True,
+ self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
)
add_defaultfavorites(self.r)
-
+
self.nu = datetime.datetime.now()
def test_upload_view_notloggedin(self):
@@ -35,13 +35,13 @@ class ViewTest(TestCase):
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_db)
def test_upload_view_sled(self, mocked_sqlalchemy,mocked_getsmallrowdata_db):
login = self.c.login(username='john',password='koeinsloot')
self.assertTrue(login)
-
+
filename = 'rowers/tests/testdata/testdata.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -70,7 +70,7 @@ class ViewTest(TestCase):
response = self.c.get('/rowers/workout/'+encoded1+'/edit/', form_data, follow=True)
self.assertEqual(response.status_code, 200)
-
+
response = self.c.get('/rowers/workout/'+encoded1+'/histo/', form_data, follow=True)
self.assertEqual(response.status_code, 200)
@@ -108,7 +108,7 @@ class ViewTest(TestCase):
self.assertTrue(form.is_valid())
response = self.c.post('/rowers/workout/'+encoded1+'/edit/', form_data, follow=True)
self.assertEqual(response.status_code, 200)
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
@@ -128,11 +128,11 @@ class ViewTest(TestCase):
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
@patch('rowers.dataprep.create_engine')
def test_upload_view_sled_negativetime(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/tim.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -157,7 +157,7 @@ class ViewTest(TestCase):
response = self.c.post('/rowers/workout/upload/', form_data, follow=True)
-
+
self.assertRedirects(response, expected_url='/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
@@ -165,9 +165,9 @@ class ViewTest(TestCase):
response = self.c.get('/rowers/workout/'+encoded1+'/', form_data, follow=True)
self.assertEqual(response.status_code, 200)
-
+
f.close()
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
try:
@@ -175,12 +175,12 @@ class ViewTest(TestCase):
except (FileNotFoundError,OSError):
pass
-
-
+
+
@patch('rowers.dataprep.create_engine')
def test_upload_view_sled_noname(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/testdata.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -216,7 +216,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_logcard(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/logcard.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -245,12 +245,12 @@ class ViewTest(TestCase):
-
+
@patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.TCXParser')
def test_upload_view_TCX_CN(self, mocked_sqlalchemy, mocked_tcx_parser):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/crewnerddata.tcx'
f = open(filename,'rb')
file_data = {'file': f}
@@ -300,7 +300,7 @@ class ViewTest(TestCase):
def test_upload_view_TCX_SpeedCoach2a(self, mocked_sqlalchemy,
mocked_tcx_parser):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/Speedcoach2example.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -337,7 +337,7 @@ class ViewTest(TestCase):
def test_upload_view_TCX_SpeedCoach2b(self, mocked_sqlalchemy,
mocked_tcx_parser):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/Speedcoach2example.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -371,12 +371,12 @@ class ViewTest(TestCase):
- @patch('rowers.dataprep.create_engine')
+ @patch('rowers.dataprep.create_engine')
@patch('rowers.dataprep.TCXParser')
def test_upload_view_TCX_SpeedCoach2c(self, mocked_sqlalchemy,
mocked_tcx_parser):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/speedcoach3test3.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -412,7 +412,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_SpeedCoach2v127(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/SpeedCoach2Linkv1.27.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -449,7 +449,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_SpeedCoach2v127intervals(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/SpeedCoach2Link_interval.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -488,7 +488,7 @@ class ViewTest(TestCase):
def test_upload_view_TCX_NoHR(self, mocked_sqlalchemy,
mocked_tcx_parser):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/NoHR.tcx'
f = open(filename,'rb')
file_data = {'file': f}
@@ -526,7 +526,7 @@ class ViewTest(TestCase):
def test_upload_view_TCX_CN(self, mocked_sqlalchemy,
mocked_tcx_parser):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/rowinginmotionexample.tcx'
f = open(filename,'rb')
file_data = {'file': f}
@@ -559,7 +559,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_RP(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/RP_testdata.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -580,7 +580,7 @@ class ViewTest(TestCase):
self.assertRedirects(response, expected_url='/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
try:
@@ -592,7 +592,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_Mystery(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/mystery.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -613,7 +613,7 @@ class ViewTest(TestCase):
self.assertRedirects(response, expected_url='/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
try:
@@ -625,7 +625,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_RP_interval(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/RP_interval.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -646,7 +646,7 @@ class ViewTest(TestCase):
self.assertRedirects(response, expected_url='/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
try:
@@ -655,11 +655,11 @@ class ViewTest(TestCase):
pass
-
+
@patch('rowers.dataprep.create_engine')
def test_upload_view_sled_desktop(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/painsled_desktop_example.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -680,7 +680,7 @@ class ViewTest(TestCase):
self.assertRedirects(response, expected_url='/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
try:
@@ -691,7 +691,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_sled_ergdata(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/ergdata_example.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -712,7 +712,7 @@ class ViewTest(TestCase):
self.assertRedirects(response, expected_url='/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
try:
@@ -723,7 +723,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_sled_boatcoach(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/boatcoach.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -744,7 +744,7 @@ class ViewTest(TestCase):
self.assertRedirects(response, expected_url='/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
try:
@@ -755,7 +755,7 @@ class ViewTest(TestCase):
@patch('rowers.dataprep.create_engine')
def test_upload_view_sled_ergstick(self, mocked_sqlalchemy):
self.c.login(username='john',password='koeinsloot')
-
+
filename = 'rowers/tests/testdata/ergstick.csv'
f = open(filename,'rb')
file_data = {'file': f}
@@ -776,11 +776,10 @@ class ViewTest(TestCase):
self.assertRedirects(response, expected_url='/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
self.assertEqual(response.status_code, 200)
-
+
w = Workout.objects.get(id=1)
f_to_be_deleted = w.csvfilename
try:
os.remove(f_to_be_deleted+'.gz')
except (FileNotFoundError,OSError):
pass
-
diff --git a/rowers/tests/test_user.py b/rowers/tests/test_user.py
index 65dd006c..92cff5e1 100644
--- a/rowers/tests/test_user.py
+++ b/rowers/tests/test_user.py
@@ -18,13 +18,13 @@ class UserMiddleWareTest(TestCase):
'sander@ds.ds',
'koeinsloot')
self.r = Rower.objects.create(user=u)
-
+
self.c = Client()
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
filename = 'rowers/tests/testdata/testdata.csv'
-
+
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
@@ -33,7 +33,7 @@ class UserMiddleWareTest(TestCase):
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
-
+
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
@@ -53,13 +53,13 @@ class UserMiddleWareTest(TestCase):
duration=duration,distance=totaldist,
csvfilename=filename
)
-
-
+
+
def test_middleware(self):
response = self.c.get('/rowers/list-workouts',follow=True)
self.assertEqual(response.status_code,200)
-
-
+
+
class UserTestsNoRower(TestCase):
def setUp(self):
u = User.objects.create_user('john',
@@ -69,18 +69,18 @@ class UserTestsNoRower(TestCase):
self.c = Client()
self.c.login(username='john',password='koeinsloot')
-
+
def test_user(self):
response = self.c.get('/rowers/list-workouts',follow=True)
self.assertEqual(response.status_code,200)
-
+
class UserPreferencesTest(TestCase):
def setUp(self):
self.u = UserFactory()
-
+
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
- gdproptin=True,
+ gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
@@ -123,14 +123,14 @@ class UserPreferencesTest(TestCase):
userform = UserForm(form_data,instance=self.u)
self.assertTrue(form.is_valid())
self.assertTrue(userform.is_valid())
-
+
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
response = self.c.get(url)
self.assertEqual(response.status_code,200)
-
-
+
+
def test_exportsettings(self):
login = self.c.login(username=self.u.username,password=self.password)
self.assertTrue(login)
@@ -149,15 +149,15 @@ class UserPreferencesTest(TestCase):
'sporttracks_auto_export':False,
'strava_auto_export':False,
'strava_auto_import':False,
- 'trainingpeaks_auto_export':False,
+ 'trainingpeaks_auto_export':False,
}
form = RowerExportForm(form_data)
self.assertTrue(form.is_valid())
-
+
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
-
+
def test_zones_workflowsettings(self):
login = self.c.login(username=self.u.username,password=self.password)
@@ -174,7 +174,7 @@ class UserPreferencesTest(TestCase):
u'middlepanel-7-panel':u'None',
u'middlepanel-8-panel':u'None',
u'middlepanel-INITIAL_FORMS':'8',
- u'middlepanel-MAX_NUM_FORMS':u'1000',
+ u'middlepanel-MAX_NUM_FORMS':u'1000',
u'middlepanel-MIN_NUM_FORMS':u'0',
u'middlepanel-TOTAL_FORMS':u'8',
}
@@ -182,7 +182,7 @@ class UserPreferencesTest(TestCase):
MiddlePanelFormSet = formset_factory(WorkFlowMiddlePanelElement,extra=1)
middlepanel_formset = MiddlePanelFormSet(post_data,prefix='middlepanel')
self.assertTrue(middlepanel_formset.is_valid())
-
+
url = '/rowers/me/workflowconfig2/'
response = self.c.get(url)
@@ -190,7 +190,7 @@ class UserPreferencesTest(TestCase):
response = self.c.post(url,post_data)
self.assertEqual(response.status_code,200)
-
+
def test_zones_preferences(self):
login = self.c.login(username=self.u.username,password=self.password)
self.assertTrue(login)
@@ -209,7 +209,7 @@ class UserPreferencesTest(TestCase):
self.assertTrue(form.is_valid())
url = '/rowers/me/preferences/'
-
+
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -228,7 +228,7 @@ class UserPreferencesTest(TestCase):
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
-
+
form_data = {
'pw_ut2':150,
'pw_ut1':160,
@@ -245,5 +245,3 @@ class UserPreferencesTest(TestCase):
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
-
-
diff --git a/rowers/tests/testdata/course.kml b/rowers/tests/testdata/course.kml
new file mode 100644
index 00000000..56451bb7
--- /dev/null
+++ b/rowers/tests/testdata/course.kml
@@ -0,0 +1,57 @@
+
+
+
+ Courses.kml
+
+ Courses
+
+ CrewNerd Examples - Uherské Hradiště
+ 1
+
+ Start
+
+ 1
+
+
+ 17.4893745389,49.109471228,0 17.4911067423,49.1094811918,0 17.4909527884,49.1103411557,0 17.4888918133,49.1102899098,0 17.4893745389,49.109471228,0 17.4893745389,49.109471228,0
+
+
+
+
+
+ Turn
+
+ 1
+
+
+ 17.4836181002,49.0979347215,0 17.489332427,49.0981702202,0 17.4888058511,49.1024117428,0 17.4836162032,49.1030885423,0 17.4836181002,49.0979347215,0 17.4836181002,49.0979347215,0
+
+
+
+
+
+ Turn
+
+ 1
+
+
+ 17.4928830266,49.0866607478,0 17.4973472737,49.0861776065,0 17.4994059869,49.0903340046,0 17.4942740099,49.0899098202,0 17.4928830266,49.0866607478,0 17.4928830266,49.0866607478,0
+
+
+
+
+
+ Finish
+
+ 1
+
+
+ 17.4627698339,49.0723911762,0 17.4630054316,49.071305244,0 17.4643666779,49.0712945663,0 17.4641649495,49.0724875988,0 17.4627698339,49.0723911762,0 17.4627698339,49.0723911762,0
+
+
+
+
+
+
+
+
diff --git a/rowers/urls.py b/rowers/urls.py
index 2a9c39d6..7146d4da 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -283,6 +283,10 @@ urlpatterns = [
re_path(r'^graph/(?P\d+)/delete/$',views.GraphDelete.as_view(),name='graph_delete'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/get-thumbnails/$',views.get_thumbnails,
name='get_thumbnails'),
+ re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/otwuseimpeller/$',views.otw_use_impeller,
+ name='otw_use_impeller'),
+ re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/otwusegps/$',views.otw_use_gps,
+ name='otw_use_gps'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/toggle-ranking/$',views.workout_toggle_ranking,
name='workout_toggle_ranking'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/get-testscript/$',views.get_testscript,
@@ -346,6 +350,8 @@ urlpatterns = [
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/video/$',views.workout_video_create_view,
name='workout_video_create_view'),
re_path(r'^video/(?P\d+)/delete/$',views.VideoDelete.as_view(),name='video_delete'),
+ re_path(r'^video/(?P\w.+)/m/$',views.workout_video_view_mini,
+ name='workout_video_view_mini'),
re_path(r'^video/(?P\w.+)/$',views.workout_video_view,
name='workout_video_view'),
re_path(r'^videos/',views.list_videos,name='list_videos'),
@@ -443,6 +449,7 @@ urlpatterns = [
re_path(r'^user-multiflex-data/$',views.multiflex_data,name='multiflex_data'),
re_path(r'^me/deactivate/$',views.deactivate_user,name='deactivate_user'),
re_path(r'^me/delete/$',views.remove_user,name='remove_user'),
+ re_path(r'^survey/$',views.survey,name='survey'),
re_path(r'^me/gdpr-optin-confirm/?/$',views.user_gdpr_confirm,name='user_gdpr_confirm'),
re_path(r'^me/gdpr-optin-confirm/$',views.user_gdpr_confirm,name='user_gdpr_confirm'),
re_path(r'^me/gdpr-optin/?/$',views.user_gdpr_optin,name='user_gdpr_optin'),
diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py
index a7ea6a70..4cf62a9e 100644
--- a/rowers/views/analysisviews.py
+++ b/rowers/views/analysisviews.py
@@ -4322,9 +4322,10 @@ def agegrouprecordview(request,sex='male',weightcategory='hwt',
})
# alert overview view
-@user_passes_test(ispromember, login_url="/rowers/paidplans",
- message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
- redirect_field_name=None)
+#@user_passes_test(ispromember, login_url="/rowers/paidplans",
+# message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
+# redirect_field_name=None)
+@login_required
def alerts_view(request,userid=0):
r = getrequestrower(request,userid=userid)
@@ -4436,9 +4437,7 @@ def alert_create_view(request,userid=0):
})
# alert report view
-@user_passes_test(ispromember, login_url="/rowers/paidplans",
- message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
- redirect_field_name=None)
+@login_required()
def alert_report_view(request,id=0,userid=0,nperiod=0):
r = getrequestrower(request,userid=userid)
if userid == 0:
@@ -4453,7 +4452,7 @@ def alert_report_view(request,id=0,userid=0,nperiod=0):
raise Http404("This alert doesn't exist")
- if alert.manager != request.user:
+ if not checkalertowner(alert,request.user):
raise PermissionDenied('You are not allowed to edit this Alert')
stats = alert_get_stats(alert,nperiod=nperiod)
@@ -4505,7 +4504,7 @@ def alert_edit_view(request,id=0,userid=0):
raise Http404("This alert doesn't exist")
- if alert.manager != request.user:
+ if not alert.manager != request.user:
raise PermissionDenied('You are not allowed to edit this Alert')
FilterFormSet = formset_factory(ConditionEditForm, formset=BaseConditionFormSet,extra=0)
@@ -4603,6 +4602,7 @@ def alert_edit_view(request,id=0,userid=0):
})
# alert delete view
+
class AlertDelete(DeleteView):
login_requird = True
model = Alert
@@ -4650,6 +4650,9 @@ class AlertDelete(DeleteView):
def get_object(self, *args, **kwargs):
obj = super(AlertDelete, self).get_object(*args, **kwargs)
+ if obj.manager != self.request.user:
+ raise PermissionDenied("You are not allowed to delete this Alert")
+
# some checks
return obj
diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py
index c820b2ae..05910fbc 100644
--- a/rowers/views/planviews.py
+++ b/rowers/views/planviews.py
@@ -445,8 +445,9 @@ def plannedsession_create_view(request,
sps = get_sessions(r,startdate=startdate,enddate=enddate).exclude(
sessiontype='race')
-
- sessiontemplates = PlannedSession.objects.filter(manager=request.user,is_template=True)
+ sessiontemplates = PlannedSession.objects.filter(
+ manager=request.user,
+ is_template=True).order_by("name")
try:
trainingplan = TrainingPlan.objects.filter(
@@ -1511,11 +1512,11 @@ def plannedsession_teamclone_view(request,id=0):
ps.name += ' (copy)'
ps.is_template = False
- deltadays = ps.enddate-ps.startdate
+ deltadays = ps.preferreddate-ps.startdate
- ps.startdate = timezone.now().date()
- ps.enddate = (timezone.now()+deltadays).date()
- ps.preferreddate = ps.preferreddate+deltadays
+ ps.startdate = startdate
+ ps.enddate = enddate
+ ps.preferreddate = startdate+deltadays
ps.save()
diff --git a/rowers/views/statements.py b/rowers/views/statements.py
index 1f1e700d..aab50741 100644
--- a/rowers/views/statements.py
+++ b/rowers/views/statements.py
@@ -60,7 +60,7 @@ from rowers.forms import (
MetricsForm,DisqualificationForm,disqualificationreasons,
disqualifiers,SearchForm,BillingForm,PlanSelectForm,
VideoAnalysisCreateForm,WorkoutSingleSelectForm,
- VideoAnalysisMetricsForm,
+ VideoAnalysisMetricsForm,SurveyForm,
)
from django.urls import reverse, reverse_lazy
@@ -158,7 +158,8 @@ from rowsandall_app.settings import (
RUNKEEPER_CLIENT_ID,RUNKEEPER_REDIRECT_URI,RUNKEEPER_CLIENT_SECRET,
TP_CLIENT_ID,TP_REDIRECT_URI,TP_CLIENT_KEY,TP_CLIENT_SECRET,
BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY,
- PAYMENT_PROCESSING_ON
+ PAYMENT_PROCESSING_ON,
+ RECAPTCHA_SITE_KEY, RECAPTCHA_SITE_SECRET
)
#from rowers.tasks_standalone import addcomment2
@@ -1073,28 +1074,39 @@ def add_defaultfavorites(r):
f.save()
return 1
+
# Shows email form and sends it if submitted
def sendmail(request):
if request.method == 'POST':
+ # test recaptcha
+ response_string = request.POST.get('g-recaptcha-response')
+ # replace below with settings
+ recaptcha_secret = RECAPTCHA_SITE_SECRET
+ url = 'https://www.google.com/recaptcha/api/siteverify'
+ data = {
+ 'secret':recaptcha_secret,
+ 'response': response_string,
+ }
+ response = requests.post(url,data=data,verify=True)
+ success = False
+ if response.status_code == 200:
+ success = response.json().get('success')
+
form = EmailForm(request.POST)
- if form.is_valid():
+ if form.is_valid() and success:
firstname = form.cleaned_data['firstname']
lastname = form.cleaned_data['lastname']
email = form.cleaned_data['email']
- subject = form.cleaned_data['subject']
- botcheck = form.cleaned_data['botcheck'].lower()
+ subject = 'Rowsandall Contact Form:'+form.cleaned_data['subject']
message = form.cleaned_data['message']
- if botcheck == 'yes':
- try:
- fullemail = firstname + " " + lastname + " " + "<" + email + ">"
- send_mail(subject, message, fullemail, ['info@rowsandall.com'])
- return HttpResponseRedirect('/rowers/email/thankyou/')
- except:
- return HttpResponseRedirect('/rowers/email/')
- else:
- messages.error(request,'You have to answer YES to the question')
- return HttpResponseRedirect('/rowers/email/')
+ fullemail = firstname + " " + lastname + " " + "<" + email + ">"
+ send_mail(subject, message, fullemail, ['info@rowsandall.com'])
+ return HttpResponseRedirect('/rowers/email/thankyou/')
else:
+ if not success:
+ messages.error(request,'Bots are not welcome')
+ else:
+ messages.error(request,'Something went wrong. Please try again')
return HttpResponseRedirect('/rowers/email/')
else:
return HttpResponseRedirect('/rowers/email/')
diff --git a/rowers/views/userviews.py b/rowers/views/userviews.py
index a8aea814..205104fe 100644
--- a/rowers/views/userviews.py
+++ b/rowers/views/userviews.py
@@ -5,6 +5,31 @@ from __future__ import unicode_literals
from rowers.views.statements import *
+@login_required()
+def survey(request):
+
+ r = getrower(request.user)
+
+ surveyform = SurveyForm()
+
+ if request.method == 'POST':
+ form = SurveyForm(request.POST)
+ r.surveydone = True
+ r.surveydonedate = timezone.now()
+ r.save()
+
+ nexturl = request.GET.get('next')
+ return HttpResponseRedirect(nexturl)
+
+ context = {
+ 'teams':get_my_teams(request.user),
+ 'rower':r,
+ 'form':surveyform,
+ }
+
+
+ return render(request,'survey.html',context)
+
@login_required()
def start_trial_view(request):
r = getrower(request.user)
@@ -13,23 +38,30 @@ def start_trial_view(request):
messages.error(request,'You do not qualify for a trial')
url = '/rowers/paidplans'
return HttpResponseRedirect(url)
-
+
r.protrialexpires = datetime.date.today()+datetime.timedelta(13)
r.save()
url = reverse('workouts_view')
messages.info(request,'We have started your 14 day trial period')
-
+
subject2 = "User started Pro Trial"
message2 = "User Started Pro Trial.\n"
message2 += request.user.email + "\n"
message2 += "User name: "+request.user.username
-
+
send_mail(subject2, message2,
'Rowsandall Server ',
['roosendaalsander@gmail.com'])
-
+
+ send_template_email('Rowsandall ',
+ [r.user.email],
+ 'Welcome to the Rowsandall Pro Trial',
+ 'protrialewelcome.html',
+ {'first_name':r.user.first_name,
+ 'last_name':r.user.last_name})
+
return HttpResponseRedirect(url)
@login_required()
@@ -40,7 +72,7 @@ def start_plantrial_view(request):
messages.error(request,'You do not qualify for a trial')
url = '/rowers/paidplans'
return HttpResponseRedirect(url)
-
+
r.plantrialexpires = datetime.date.today()+datetime.timedelta(13)
r.protrialexpires = datetime.date.today()+datetime.timedelta(13)
r.save()
@@ -48,16 +80,23 @@ def start_plantrial_view(request):
url = reverse('workouts_view')
messages.info(request,'We have started your 14 day trial period')
-
+
subject2 = "User started Plan Trial"
message2 = "User Started Plan Trial.\n"
message2 += request.user.email + "\n"
message2 += "User name: "+request.user.username
-
+
send_mail(subject2, message2,
'Rowsandall Server ',
['roosendaalsander@gmail.com'])
-
+
+ send_template_email('Rowsandall ',
+ [r.user.email],
+ 'Welcome to the Rowsandall Self-Coach Trial',
+ 'plantrialwelcome.html',
+ {'first_name':r.user.first_name,
+ 'last_name':r.user.last_name})
+
return HttpResponseRedirect(url)
# Page where user can manage his favorite charts
@@ -79,7 +118,7 @@ def rower_favoritecharts_view(request,userid=0):
FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=0)
if aantal==0:
FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=1)
-
+
if request.method == 'POST':
favorites_formset = FavoriteChartFormSet(request.POST)
@@ -115,7 +154,7 @@ def rower_favoritecharts_view(request,userid=0):
messages.error(request,message)
else:
favorites_formset = FavoriteChartFormSet(initial=favorites_data)
-
+
context = {
'favorites_formset':favorites_formset,
@@ -123,8 +162,8 @@ def rower_favoritecharts_view(request,userid=0):
'rower':r,
}
-
-
+
+
return render(request,'favoritecharts.html',context)
# page where user sets his export settings
@@ -154,7 +193,7 @@ def rower_exportsettings_view(request,userid=0):
'name': 'Export Settings'
}
]
-
+
return render(request, 'rower_exportsettings.html',
{'form':form,
'rower':r,
@@ -367,7 +406,7 @@ def rower_prefs_view(request,userid=0,message=""):
'rower':r,
})
-
+
# Revoke an app that you granted access through the API.
# this views is called when you press a button on the User edit page
# the button is only there when you have granted access to an app
@@ -401,7 +440,7 @@ def rower_update_empower_view(
r = getrower(request.user)
except Rower.DoesNotExist:
raise Http404("Rower doesn't exist")
-
+
if request.method == 'POST' and 'daterange' in request.POST:
dateform = DateRangeForm(request.POST)
if dateform.is_valid():
@@ -416,7 +455,7 @@ def rower_update_empower_view(
'startdate':startdate,
'enddate':enddate,
})
-
+
if request.method == 'POST' and 'workouts' in request.POST:
form = WorkoutMultipleCompareForm(request.POST)
@@ -424,7 +463,7 @@ def rower_update_empower_view(
cd = form.cleaned_data
workouts = cd['workouts']
workoutdicts = []
-
+
for w in workouts:
if w.user != r:
message = "You can only alter your own workouts"
@@ -440,7 +479,7 @@ def rower_update_empower_view(
messages.error(request,message)
else:
-
+
workoutdict = {
'id':w.id,
'boattype':w.boattype,
@@ -454,7 +493,7 @@ def rower_update_empower_view(
w.workoutsource = 'speedcoach2corrected'
w.save()
-
+
job = myqueue(queuelow,handle_update_empower,
request.user.email,workoutdicts,
debug=False,
@@ -479,7 +518,7 @@ def rower_update_empower_view(
workoutsource='speedcoach2',
user=r,
).order_by("-date","-starttime")
-
+
form = WorkoutMultipleCompareForm()
form.fields["workouts"].queryset = workouts
# GET request = prepare form
@@ -491,5 +530,3 @@ def rower_update_empower_view(
'form':form,
'rower':r
})
-
-
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index e50c618e..f72537f9 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -48,6 +48,116 @@ def get_video_id(url):
else:
raise ValueError
+# Show a video compared with data
+def workout_video_view_mini(request,id=''):
+ try:
+ id = encoder.decode_hex(id)
+ analysis = VideoAnalysis.objects.get(id=id)
+ except VideoAnalysis.DoesNotExist:
+ raise Http404("Video Analysis does not exist")
+
+ w = analysis.workout
+ delay = analysis.delay
+
+ if w.workouttype in mytypes.otwtypes:
+ mode = 'water'
+ else:
+ mode = 'erg'
+
+ if request.user.is_authenticated:
+ mayedit = checkworkoutuser(request.user,w) and isprorower(request.user.rower)
+ rower = request.user.rower
+ else:
+ mayedit = False
+ rower = None
+
+ # get video ID and offset
+ if mayedit and request.method == 'POST':
+ form = VideoAnalysisCreateForm(request.POST)
+ metricsform = VideoAnalysisMetricsForm(request.POST,mode=mode)
+ if form.is_valid() and metricsform.is_valid():
+ video_id = form.cleaned_data['url']
+ try:
+ video_id = get_video_id(form.cleaned_data['url'])
+ except (TypeError,ValueError):
+ pass
+ delay = form.cleaned_data['delay']
+ metricsgroups = metricsform.cleaned_data['groups']
+ if 'save_button' in request.POST:
+ analysis.name = form.cleaned_data['name']
+ analysis.video_id = video_id
+ analysis.delay = delay
+ analysis.metricsgroups = metricsgroups
+ analysis.save()
+ else:
+ video_id = id
+ delay = 0
+ elif mayedit:
+ form = VideoAnalysisCreateForm(
+ initial = {
+ 'name':analysis.name,
+ 'delay': analysis.delay,
+ 'url': analysis.video_id,
+ }
+ )
+ metricsform = VideoAnalysisMetricsForm(initial={'groups':analysis.metricsgroups},
+ mode=mode)
+ metricsgroups = analysis.metricsgroups
+ video_id = analysis.video_id
+ else:
+ form = None
+ metricsform = None
+ metricsgroups = analysis.metricsgroups
+
+ data, metrics, maxtime = dataprep.get_video_data(w,groups=metricsgroups,mode=mode)
+ hascoordinates = pd.Series(data['latitude']).std() > 0
+ # create map
+ if hascoordinates:
+ mapscript, mapdiv = leaflet_chart_video(data['latitude'],data['longitude'],
+ w.name)
+ else:
+ mapscript, mapdiv = interactive_chart_video(data)
+ data['longitude'] = data['spm']
+ data['latitude'] = list(range(len(data['spm'])))
+
+
+ breadcrumbs = [
+ {
+ 'url':'/rowers/list-workouts/',
+ 'name':'Workouts'
+ },
+ {
+ 'url':get_workout_default_page(request,encoder.encode_hex(w.id)),
+ 'name': w.name
+ },
+ {
+ 'url':reverse('workout_video_view_mini',kwargs={'id':encoder.encode_hex(analysis.id)}),
+ 'name': 'Video Analysis'
+ }
+
+ ]
+
+
+ return render(request,
+ 'embedded_video_mini.html',
+ {
+ 'workout':w,
+ 'rower':rower,
+ 'data': json.dumps(data,default=default),
+ 'mapscript': mapscript,
+ 'mapdiv': mapdiv,
+ 'video_id': analysis.video_id,
+ 'form':form,
+ 'breadcrumbs':breadcrumbs,
+ 'analysis':analysis,
+ 'maxtime':maxtime,
+ 'metrics':metrics,
+ 'locked': True,
+ 'metricsform':metricsform,
+ 'metricsgroups': metricsgroups,
+ 'siteurl': settings.SITE_URL,
+ })
+
# Show a video compared with data
def workout_video_view(request,id=''):
@@ -346,18 +456,54 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
'teams':get_my_teams(request.user),
})
-# Test asynchronous tasking and messaging
-#@login_required()
-#def workout_test_task_view(request,id=0):
-# row = Workout.objects.get(id=id)
-# res = myqueue(queuehigh,addcomment2,request.user.id,row.id)#
-#
-#
-# url = reverse('workout_edit_view',
-# kwargs = {
-# 'id':int(id),
-# })
-# return HttpResponseRedirect(url)
+# Switch from GPS to Impeller (only for SpeedCoach 2, if impeller data)
+@login_required
+def otw_use_impeller(request,id=0):
+ w = get_workout(id)
+
+ if (checkworkoutuser(request.user,w)==False):
+ raise PermissionDenied("Access denied")
+
+ row = rdata(w.csvfilename)
+ success = row.use_impellerdata()
+ if success:
+ row.write_csv(w.csvfilename)
+ dataprep.update_strokedata(w.id,row.df)
+ w.impeller = True
+ w.save()
+ messages.info(request,'The distance and speed data are now based on Impeller data')
+ else:
+ messages.error(request,'No impeller data found')
+
+ url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
+
+ return HttpResponseRedirect(url)
+
+
+# Switch from Impeller to GPS (only for SpeedCoach 2, if impeller data)
+@login_required
+def otw_use_gps(request,id=0):
+ w = get_workout(id)
+
+ if (checkworkoutuser(request.user,w)==False):
+ raise PermissionDenied("Access denied")
+
+ row = rdata(w.csvfilename)
+ success = row.use_gpsdata()
+ if success:
+ row.write_csv(w.csvfilename)
+ dataprep.update_strokedata(w.id,row.df)
+ w.impeller = False
+ w.save()
+ messages.info(request,'The distance and speed data are now based on GPS data')
+ else:
+ messages.error(request,'No GPS data found')
+
+ url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
+
+ return HttpResponseRedirect(url)
+
+
# Show Stroke power histogram for a workout
@login_required()
@@ -2623,8 +2769,8 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
form = AdvancedWorkoutForm(request.POST)
if form.is_valid():
- quick_calc = form.cleaned_data['quick_calc']
- go_service = form.cleaned_data['go_service']
+ #quick_calc = form.cleaned_data['quick_calc']
+ #go_service = form.cleaned_data['go_service']
boattype = form.cleaned_data['boattype']
weightvalue = form.cleaned_data['weightvalue']
w.boattype = boattype
@@ -2669,8 +2815,8 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""):
first_name,last_name,emailaddress,encoder.decode_hex(id),
ps=[r.p0,r.p1,r.p2,r.p3],
ratio=r.cpratio,
- quick_calc = quick_calc,
- go_service=go_service,
+ # quick_calc = quick_calc,
+ # go_service=go_service,
emailbounced = r.emailbounced
)
diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py
index 2df72fc8..4ab15697 100644
--- a/rowsandall_app/settings.py
+++ b/rowsandall_app/settings.py
@@ -47,6 +47,7 @@ ALLOWED_HOSTS = CFG['allowed_hosts']
INSTALLED_APPS = [
'rowers',
+ 'survey',
# 'cvkbrno',
'django.contrib.admin',
'django.contrib.auth',
@@ -97,6 +98,7 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'tz_detect.middleware.TimezoneMiddleware',
+ 'rowers.middleware.SurveyMiddleWare',
'rowers.middleware.GDPRMiddleWare',
'rowers.middleware.PowerTimeFitnessMetricMiddleWare',
'rowers.middleware.RowerPlanMiddleWare',
@@ -494,3 +496,13 @@ try:
CELERY = CFG['use_celery']
except KeyError:
CELERY = False
+
+
+# Recaptcha
+
+try:
+ RECAPTCHA_SITE_KEY = CFG['recaptcha_site_key']
+ RECAPTCHA_SITE_SECRET = CFG['recaptcha_site_secret']
+except KeyError:
+ RECAPTCHA_SITE_KEY = ''
+ RECAPTCHA_SITE_SECRET = ''
diff --git a/rowsandall_app/settings_dev.py b/rowsandall_app/settings_dev.py
index ad4c57c1..d40f8ca2 100644
--- a/rowsandall_app/settings_dev.py
+++ b/rowsandall_app/settings_dev.py
@@ -60,7 +60,7 @@ DEBUG = True
TEMPLATES[0]['OPTIONS']['debug'] = DEBUG
-ALLOWED_HOSTS = ['localhost']
+ALLOWED_HOSTS = ['localhost','127.0.0.1']
# INSTALLED_APPS += ['debug_toolbar',]
diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py
index ec1b60df..b6bcca18 100644
--- a/rowsandall_app/urls.py
+++ b/rowsandall_app/urls.py
@@ -22,6 +22,7 @@ from django.views.generic import TemplateView
from rowsandall_app.views import rootview, landingview
from django.contrib.auth import views as auth_views
from rowers import views as rowersviews
+from survey import views as surveyviews
import django
@@ -65,6 +66,7 @@ urlpatterns += [
{'next_page': '/'},
name='logout',),
re_path(r'^rowers/',include('rowers.urls')),
+ re_path(r'^survey/',include('survey.urls')),
# re_path(r'^cvkbrno/',include('cvkbrno.urls')),
# re_path(r'^admin/rq/',include('django_rq_dashboard.urls')),
re_path(r'^call\_back',rowersviews.rower_process_callback),
diff --git a/rowsandall_workouts_2017-09-28_2018-09-28.csv b/rowsandall_workouts_2017-09-28_2018-09-28.csv
deleted file mode 100644
index b767fb45..00000000
--- a/rowsandall_workouts_2017-09-28_2018-09-28.csv
+++ /dev/null
@@ -1,434 +0,0 @@
-,Stroke Data CSV,Stroke Data TCX,TRIMP Training Load,TSS Training Load,date,distance (m),duration ,name,notes,timezone,type,weight (kg),weight category
-0,https://rowsandall.com/rowers/workout/2542/emailcsv,https://rowsandall.com/rowers/workout/2542/emailtcx,0,0,1970-01-01 00:00:00+00:00,9578,00:47:55.400000,Test Auto Sync Pro User,,Europe/Prague,rower,80.0,lwt
-1,https://rowsandall.com/rowers/workout/2500/emailcsv,https://rowsandall.com/rowers/workout/2500/emailtcx,0,0,2014-02-26 20:32:33+00:00,65,00:00:02,Sample Workout JSON,,UTC,water,80.0,lwt
-2,https://rowsandall.com/rowers/workout/3033/emailcsv,https://rowsandall.com/rowers/workout/3033/emailtcx,95,264,2015-06-02 06:29:02+00:00,14002,00:59:37.700000,Test P,,Europe/Prague,water,80.0,hwt
-3,https://rowsandall.com/rowers/workout/2501/emailcsv,https://rowsandall.com/rowers/workout/2501/emailtcx,0,0,2016-04-02 08:15:08+00:00,10269,01:05:24,Completed a workout (generic) 6.35 mi on 04/02/16,,Europe/Prague,water,80.0,lwt
-4,https://rowsandall.com/rowers/workout/2408/emailcsv,https://rowsandall.com/rowers/workout/2408/emailtcx,0,0,2016-07-30 08:40:36+00:00,1001,00:03:41,Comparison,,Europe/Berlin,rower,80.0,lwt
-5,https://rowsandall.com/rowers/workout/3032/emailcsv,https://rowsandall.com/rowers/workout/3032/emailtcx,0,0,2016-07-31 12:35:01+00:00,1111,00:04:32.700000,,,Europe/Prague,water,80.0,hwt
-6,https://rowsandall.com/rowers/workout/2572/emailcsv,https://rowsandall.com/rowers/workout/2572/emailtcx,0,0,2016-11-28 08:37:02+00:00,499,00:01:58,BC,,Europe/Prague,rower,80.0,lwt
-7,https://rowsandall.com/rowers/workout/2379/emailcsv,https://rowsandall.com/rowers/workout/2379/emailtcx,0,0,2017-10-27 16:14:42+00:00,742,00:02:25,Test Weba,,Europe/Prague,water,80.0,lwt
-8,https://rowsandall.com/rowers/workout/2380/emailcsv,https://rowsandall.com/rowers/workout/2380/emailtcx,0,0,2017-10-27 16:14:42+00:00,742,00:02:25,Test Weba,,Europe/Belgrade,water,80.0,lwt
-9,https://rowsandall.com/rowers/workout/2521/emailcsv,https://rowsandall.com/rowers/workout/2521/emailtcx,0,0,2017-11-09 09:15:32+00:00,49842,02:19:37,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-10,https://rowsandall.com/rowers/workout/2524/emailcsv,https://rowsandall.com/rowers/workout/2524/emailtcx,0,0,2017-11-09 09:15:32+00:00,49842,02:19:37,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-11,https://rowsandall.com/rowers/workout/2527/emailcsv,https://rowsandall.com/rowers/workout/2527/emailtcx,0,0,2017-11-09 09:15:32+00:00,49842,02:19:37,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-12,https://rowsandall.com/rowers/workout/2531/emailcsv,https://rowsandall.com/rowers/workout/2531/emailtcx,0,0,2017-11-09 09:15:32+00:00,49842,02:19:37,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-13,https://rowsandall.com/rowers/workout/2523/emailcsv,https://rowsandall.com/rowers/workout/2523/emailtcx,0,0,2017-11-09 15:15:32+00:00,0,02:28:28,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-14,https://rowsandall.com/rowers/workout/2526/emailcsv,https://rowsandall.com/rowers/workout/2526/emailtcx,0,0,2017-11-09 15:15:32+00:00,0,02:28:28,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-15,https://rowsandall.com/rowers/workout/2529/emailcsv,https://rowsandall.com/rowers/workout/2529/emailtcx,0,0,2017-11-09 15:15:32+00:00,0,02:28:28,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-16,https://rowsandall.com/rowers/workout/2533/emailcsv,https://rowsandall.com/rowers/workout/2533/emailtcx,0,0,2017-11-09 15:15:32+00:00,0,02:28:28,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-17,https://rowsandall.com/rowers/workout/2520/emailcsv,https://rowsandall.com/rowers/workout/2520/emailtcx,0,0,2017-11-09 18:15:32+00:00,10016,01:06:03,Polar Import,,Europe/Helsinki,rower,80.0,lwt
-18,https://rowsandall.com/rowers/workout/2522/emailcsv,https://rowsandall.com/rowers/workout/2522/emailtcx,0,0,2017-11-09 18:15:32+00:00,10016,01:06:03,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-19,https://rowsandall.com/rowers/workout/2525/emailcsv,https://rowsandall.com/rowers/workout/2525/emailtcx,0,0,2017-11-09 18:15:32+00:00,10016,01:06:03,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-20,https://rowsandall.com/rowers/workout/2528/emailcsv,https://rowsandall.com/rowers/workout/2528/emailtcx,0,0,2017-11-09 18:15:32+00:00,10016,01:06:03,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-21,https://rowsandall.com/rowers/workout/2532/emailcsv,https://rowsandall.com/rowers/workout/2532/emailtcx,0,0,2017-11-09 18:15:32+00:00,10016,01:06:03,Import from Polar Flow,imported through email,Europe/Helsinki,water,80.0,lwt
-22,https://rowsandall.com/rowers/workout/2494/emailcsv,https://rowsandall.com/rowers/workout/2494/emailtcx,0,0,2017-11-12 10:25:00+00:00,10526,00:44:01.700000,Race,,Europe/Rome,water,80.0,lwt
-23,https://rowsandall.com/rowers/workout/2496/emailcsv,https://rowsandall.com/rowers/workout/2496/emailtcx,0,0,2017-11-12 10:25:00+00:00,10526,00:44:01.700000,Race,,Europe/Rome,water,80.0,lwt
-24,https://rowsandall.com/rowers/workout/2497/emailcsv,https://rowsandall.com/rowers/workout/2497/emailtcx,0,0,2017-11-12 10:25:00+00:00,10526,00:44:01.700000,SpdCoach 2,,Europe/Rome,rower,80.0,lwt
-25,https://rowsandall.com/rowers/workout/2498/emailcsv,https://rowsandall.com/rowers/workout/2498/emailtcx,0,0,2017-11-12 10:25:00+00:00,10526,00:44:01.700000,boat speed test,,Europe/Rome,water,80.0,lwt
-26,https://rowsandall.com/rowers/workout/2499/emailcsv,https://rowsandall.com/rowers/workout/2499/emailtcx,0,0,2017-11-12 10:25:00+00:00,10526,00:44:01.700000,Boat Speed test 2,,Europe/Rome,water,80.0,lwt
-27,https://rowsandall.com/rowers/workout/2724/emailcsv,https://rowsandall.com/rowers/workout/2724/emailtcx,0,0,2018-01-01 09:27:47+00:00,5000,00:18:37,C2 Import Workout from 2018-01-01 09:27:47+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-28,https://rowsandall.com/rowers/workout/2723/emailcsv,https://rowsandall.com/rowers/workout/2723/emailtcx,0,0,2018-01-01 09:48:09+00:00,2963,00:13:29,C2 Import Workout from 2018-01-01 09:48:09+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-29,https://rowsandall.com/rowers/workout/2722/emailcsv,https://rowsandall.com/rowers/workout/2722/emailtcx,0,0,2018-01-02 18:22:08+00:00,14183,00:59:49.900000,C2 Import Workout from 2018-01-02 18:22:08+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-30,https://rowsandall.com/rowers/workout/2721/emailcsv,https://rowsandall.com/rowers/workout/2721/emailtcx,0,0,2018-01-03 16:24:47+00:00,4821,00:20:04.500000,C2 Import Workout from 2018-01-03 16:24:47+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-31,https://rowsandall.com/rowers/workout/2720/emailcsv,https://rowsandall.com/rowers/workout/2720/emailtcx,0,0,2018-01-03 16:46:19+00:00,2000,00:07:07.500000,C2 Import Workout from 2018-01-03 16:46:19+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-32,https://rowsandall.com/rowers/workout/2719/emailcsv,https://rowsandall.com/rowers/workout/2719/emailtcx,0,0,2018-01-03 16:57:04+00:00,2997,00:13:35.100000,C2 Import Workout from 2018-01-03 16:57:04+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-33,https://rowsandall.com/rowers/workout/2718/emailcsv,https://rowsandall.com/rowers/workout/2718/emailtcx,0,0,2018-01-06 13:59:30+00:00,4722,00:20:06.200000,C2 Import Workout from 2018-01-06 13:59:30+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-34,https://rowsandall.com/rowers/workout/2717/emailcsv,https://rowsandall.com/rowers/workout/2717/emailtcx,0,0,2018-01-06 14:20:43+00:00,1171,00:04:00,C2 Import Workout from 2018-01-06 14:20:43+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-35,https://rowsandall.com/rowers/workout/2716/emailcsv,https://rowsandall.com/rowers/workout/2716/emailtcx,0,0,2018-01-06 14:25:53+00:00,8006,00:36:13.600000,C2 Import Workout from 2018-01-06 14:25:53+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-36,https://rowsandall.com/rowers/workout/2715/emailcsv,https://rowsandall.com/rowers/workout/2715/emailtcx,0,0,2018-01-07 14:03:51+00:00,2520,00:10:42.700000,C2 Import Workout from 2018-01-07 14:03:51+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-37,https://rowsandall.com/rowers/workout/2714/emailcsv,https://rowsandall.com/rowers/workout/2714/emailtcx,0,0,2018-01-07 14:18:45+00:00,9996,00:42:35.100000,C2 Import Workout from 2018-01-07 14:18:45+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-38,https://rowsandall.com/rowers/workout/2713/emailcsv,https://rowsandall.com/rowers/workout/2713/emailtcx,0,0,2018-01-09 18:22:19+00:00,5267,00:22:34.200000,C2 Import Workout from 2018-01-09 18:22:19+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-39,https://rowsandall.com/rowers/workout/2712/emailcsv,https://rowsandall.com/rowers/workout/2712/emailtcx,0,0,2018-01-09 18:46:20+00:00,1000,00:03:21.400000,C2 Import Workout from 2018-01-09 18:46:20+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-40,https://rowsandall.com/rowers/workout/2711/emailcsv,https://rowsandall.com/rowers/workout/2711/emailtcx,0,0,2018-01-09 18:51:03+00:00,2300,00:10:04.500000,C2 Import Workout from 2018-01-09 18:51:03+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-41,https://rowsandall.com/rowers/workout/2710/emailcsv,https://rowsandall.com/rowers/workout/2710/emailtcx,0,0,2018-01-12 16:09:10+00:00,2008,00:08:39.100000,C2 Import Workout from 2018-01-12 16:09:10+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-42,https://rowsandall.com/rowers/workout/2709/emailcsv,https://rowsandall.com/rowers/workout/2709/emailtcx,0,0,2018-01-12 16:19:00+00:00,500,00:01:33.400000,C2 Import Workout from 2018-01-12 16:19:00+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-43,https://rowsandall.com/rowers/workout/2708/emailcsv,https://rowsandall.com/rowers/workout/2708/emailtcx,0,0,2018-01-12 16:21:06+00:00,2002,00:09:25.600000,C2 Import Workout from 2018-01-12 16:21:06+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-44,https://rowsandall.com/rowers/workout/2707/emailcsv,https://rowsandall.com/rowers/workout/2707/emailtcx,0,0,2018-01-12 16:31:08+00:00,100,00:00:17.600000,C2 Import Workout from 2018-01-12 16:31:08+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-45,https://rowsandall.com/rowers/workout/2706/emailcsv,https://rowsandall.com/rowers/workout/2706/emailtcx,0,0,2018-01-12 16:31:58+00:00,2011,00:08:56.600000,C2 Import Workout from 2018-01-12 16:31:58+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-46,https://rowsandall.com/rowers/workout/2705/emailcsv,https://rowsandall.com/rowers/workout/2705/emailtcx,0,0,2018-01-13 12:40:00+00:00,2000,00:06:55.800000,C2 Import Workout from 2018-01-13 12:40:00+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-47,https://rowsandall.com/rowers/workout/2704/emailcsv,https://rowsandall.com/rowers/workout/2704/emailtcx,0,0,2018-01-16 18:40:49+00:00,2007,00:08:30.800000,C2 Import Workout from 2018-01-16 18:40:49+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-48,https://rowsandall.com/rowers/workout/2703/emailcsv,https://rowsandall.com/rowers/workout/2703/emailtcx,0,0,2018-01-16 18:50:09+00:00,333,00:01:00,C2 Import Workout from 2018-01-16 18:50:09+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-49,https://rowsandall.com/rowers/workout/2702/emailcsv,https://rowsandall.com/rowers/workout/2702/emailtcx,0,0,2018-01-16 18:51:41+00:00,6820,00:31:22.200000,C2 Import Workout from 2018-01-16 18:51:41+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-50,https://rowsandall.com/rowers/workout/2701/emailcsv,https://rowsandall.com/rowers/workout/2701/emailtcx,0,0,2018-01-16 19:24:23+00:00,2008,00:09:01.100000,C2 Import Workout from 2018-01-16 19:24:23+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-51,https://rowsandall.com/rowers/workout/2700/emailcsv,https://rowsandall.com/rowers/workout/2700/emailtcx,0,0,2018-01-18 19:01:45+00:00,2007,00:08:27.600000,C2 Import Workout from 2018-01-18 19:01:45+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-52,https://rowsandall.com/rowers/workout/2699/emailcsv,https://rowsandall.com/rowers/workout/2699/emailtcx,0,0,2018-01-18 19:10:50+00:00,6918,00:29:14.200000,C2 Import Workout from 2018-01-18 19:10:50+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-53,https://rowsandall.com/rowers/workout/2698/emailcsv,https://rowsandall.com/rowers/workout/2698/emailtcx,0,0,2018-01-18 19:40:40+00:00,1217,00:06:11.100000,C2 Import Workout from 2018-01-18 19:40:40+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-54,https://rowsandall.com/rowers/workout/2697/emailcsv,https://rowsandall.com/rowers/workout/2697/emailtcx,0,0,2018-01-18 19:47:32+00:00,6697,00:29:16.700000,C2 Import Workout from 2018-01-18 19:47:32+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-55,https://rowsandall.com/rowers/workout/2696/emailcsv,https://rowsandall.com/rowers/workout/2696/emailtcx,0,0,2018-01-18 20:17:58+00:00,1997,00:09:10.700000,C2 Import Workout from 2018-01-18 20:17:58+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-56,https://rowsandall.com/rowers/workout/2692/emailcsv,https://rowsandall.com/rowers/workout/2692/emailtcx,0,0,2018-01-19 00:00:00+00:00,200,00:02:00.200000,C2 Import Workout from 2018-01-19 00:00:00+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-57,https://rowsandall.com/rowers/workout/2693/emailcsv,https://rowsandall.com/rowers/workout/2693/emailtcx,0,0,2018-01-19 00:00:00+00:00,200,00:01:55,C2 Import Workout from 2018-01-19 00:00:00+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-58,https://rowsandall.com/rowers/workout/2694/emailcsv,https://rowsandall.com/rowers/workout/2694/emailtcx,0,0,2018-01-19 00:00:00+00:00,200,00:02:00,C2 Import Workout from 2018-01-19 00:00:00+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-59,https://rowsandall.com/rowers/workout/2695/emailcsv,https://rowsandall.com/rowers/workout/2695/emailtcx,0,0,2018-01-19 00:00:00+00:00,200,00:01:10,C2 Import Workout from 2018-01-19 00:00:00+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-60,https://rowsandall.com/rowers/workout/2691/emailcsv,https://rowsandall.com/rowers/workout/2691/emailtcx,0,0,2018-01-20 13:22:31+00:00,19381,01:20:39.100000,C2 Import Workout from 2018-01-20 13:22:31+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-61,https://rowsandall.com/rowers/workout/2690/emailcsv,https://rowsandall.com/rowers/workout/2690/emailtcx,0,0,2018-01-24 18:55:23+00:00,210,00:01:43.400000,C2 Import Workout from 2018-01-24 18:55:23+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-62,https://rowsandall.com/rowers/workout/2689/emailcsv,https://rowsandall.com/rowers/workout/2689/emailtcx,0,0,2018-01-24 18:59:06+00:00,2110,00:08:42.700000,C2 Import Workout from 2018-01-24 18:59:06+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-63,https://rowsandall.com/rowers/workout/2688/emailcsv,https://rowsandall.com/rowers/workout/2688/emailtcx,0,0,2018-01-24 19:08:04+00:00,6081,00:25:10,C2 Import Workout from 2018-01-24 19:08:04+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-64,https://rowsandall.com/rowers/workout/2687/emailcsv,https://rowsandall.com/rowers/workout/2687/emailtcx,0,0,2018-01-24 19:24:18+00:00,14426,01:00:12.600000,C2 Import Workout from 2018-01-24 19:24:18+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-65,https://rowsandall.com/rowers/workout/2686/emailcsv,https://rowsandall.com/rowers/workout/2686/emailtcx,0,0,2018-01-27 13:23:26+00:00,14981,01:01:39.600000,C2 Import Workout from 2018-01-27 13:23:26+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-66,https://rowsandall.com/rowers/workout/2685/emailcsv,https://rowsandall.com/rowers/workout/2685/emailtcx,0,0,2018-01-27 14:25:07+00:00,18338,01:15:22.800000,C2 Import Workout from 2018-01-27 14:25:07+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-67,https://rowsandall.com/rowers/workout/2684/emailcsv,https://rowsandall.com/rowers/workout/2684/emailtcx,0,0,2018-02-03 14:20:18+00:00,12181,00:51:46,C2 Import Workout from 2018-02-03 14:20:18+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-68,https://rowsandall.com/rowers/workout/2683/emailcsv,https://rowsandall.com/rowers/workout/2683/emailtcx,0,0,2018-02-06 17:54:01+00:00,7210,00:31:09,C2 Import Workout from 2018-02-06 17:54:01+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-69,https://rowsandall.com/rowers/workout/2682/emailcsv,https://rowsandall.com/rowers/workout/2682/emailtcx,0,0,2018-02-10 09:10:14+00:00,3040,00:12:47.200000,C2 Import Workout from 2018-02-10 09:10:14+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-70,https://rowsandall.com/rowers/workout/2681/emailcsv,https://rowsandall.com/rowers/workout/2681/emailtcx,0,0,2018-02-10 09:23:52+00:00,9305,00:40:50.900000,C2 Import Workout from 2018-02-10 09:23:52+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-71,https://rowsandall.com/rowers/workout/2680/emailcsv,https://rowsandall.com/rowers/workout/2680/emailtcx,0,0,2018-02-10 10:06:00+00:00,2009,00:09:04.200000,C2 Import Workout from 2018-02-10 10:06:00+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-72,https://rowsandall.com/rowers/workout/2679/emailcsv,https://rowsandall.com/rowers/workout/2679/emailtcx,0,0,2018-02-11 16:57:32+00:00,14430,01:01:23,C2 Import Workout from 2018-02-11 16:57:32+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-73,https://rowsandall.com/rowers/workout/2335/emailcsv,https://rowsandall.com/rowers/workout/2335/emailtcx,0,0,2018-02-12 05:02:06+00:00,3872,00:27:12.200000,SpdCoach 1,,America/Los_Angeles,water,80.0,lwt
-74,https://rowsandall.com/rowers/workout/2338/emailcsv,https://rowsandall.com/rowers/workout/2338/emailtcx,0,0,2018-02-12 05:02:06+00:00,9336,09:58:35,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-75,https://rowsandall.com/rowers/workout/2339/emailcsv,https://rowsandall.com/rowers/workout/2339/emailtcx,0,0,2018-02-12 05:02:06+00:00,7522,09:41:48.200000,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-76,https://rowsandall.com/rowers/workout/2341/emailcsv,https://rowsandall.com/rowers/workout/2341/emailtcx,0,0,2018-02-12 05:02:06+00:00,9336,09:58:35,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-77,https://rowsandall.com/rowers/workout/2342/emailcsv,https://rowsandall.com/rowers/workout/2342/emailtcx,0,0,2018-02-12 05:02:06+00:00,9336,09:58:35,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-78,https://rowsandall.com/rowers/workout/2343/emailcsv,https://rowsandall.com/rowers/workout/2343/emailtcx,0,0,2018-02-12 05:02:06+00:00,9336,09:58:35,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-79,https://rowsandall.com/rowers/workout/2410/emailcsv,https://rowsandall.com/rowers/workout/2410/emailtcx,0,0,2018-02-12 05:02:06+00:00,3872,00:27:12.200000,Test,,America/Los_Angeles,water,80.0,lwt
-80,https://rowsandall.com/rowers/workout/2414/emailcsv,https://rowsandall.com/rowers/workout/2414/emailtcx,0,0,2018-02-12 05:02:06+00:00,9336,09:58:35,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-81,https://rowsandall.com/rowers/workout/2416/emailcsv,https://rowsandall.com/rowers/workout/2416/emailtcx,0,0,2018-02-12 05:02:06+00:00,3872,00:27:12.200000,Test aaaa,,America/Los_Angeles,water,80.0,lwt
-82,https://rowsandall.com/rowers/workout/2417/emailcsv,https://rowsandall.com/rowers/workout/2417/emailtcx,0,0,2018-02-12 05:02:06+00:00,9336,09:58:35,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-83,https://rowsandall.com/rowers/workout/2418/emailcsv,https://rowsandall.com/rowers/workout/2418/emailtcx,0,0,2018-02-12 05:02:06+00:00,3872,00:27:12.200000,Test i,,America/Los_Angeles,water,80.0,lwt
-84,https://rowsandall.com/rowers/workout/2419/emailcsv,https://rowsandall.com/rowers/workout/2419/emailtcx,0,0,2018-02-12 05:02:06+00:00,11394,09:42:05.500000,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-85,https://rowsandall.com/rowers/workout/2420/emailcsv,https://rowsandall.com/rowers/workout/2420/emailtcx,0,0,2018-02-12 13:55:06+00:00,3872,00:27:12.200000,Test ii,,America/Los_Angeles,water,80.0,lwt
-86,https://rowsandall.com/rowers/workout/2421/emailcsv,https://rowsandall.com/rowers/workout/2421/emailtcx,0,0,2018-02-12 13:55:06+00:00,350236,00:49:05.500000,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-87,https://rowsandall.com/rowers/workout/2344/emailcsv,https://rowsandall.com/rowers/workout/2344/emailtcx,0,0,2018-02-12 14:02:06+00:00,3872,00:27:12.200000,SpdCoach Sessions,imported through email,America/Los_Angeles,water,80.0,lwt
-88,https://rowsandall.com/rowers/workout/2347/emailcsv,https://rowsandall.com/rowers/workout/2347/emailtcx,0,0,2018-02-12 14:02:06+00:00,9336,00:58:35,Joined Workout,imported through email,America/Los_Angeles,water,80.0,lwt
-89,https://rowsandall.com/rowers/workout/2411/emailcsv,https://rowsandall.com/rowers/workout/2411/emailtcx,0,0,2018-02-12 14:02:06+00:00,3872,00:27:12.200000,Test 2,,America/Los_Angeles,water,80.0,lwt
-90,https://rowsandall.com/rowers/workout/2415/emailcsv,https://rowsandall.com/rowers/workout/2415/emailtcx,0,0,2018-02-12 14:02:06+00:00,9336,00:58:35,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-91,https://rowsandall.com/rowers/workout/2430/emailcsv,https://rowsandall.com/rowers/workout/2430/emailtcx,0,0,2018-02-12 14:02:06+00:00,3872,00:27:12.200000,Water,,America/Los_Angeles,water,80.0,lwt
-92,https://rowsandall.com/rowers/workout/2445/emailcsv,https://rowsandall.com/rowers/workout/2445/emailtcx,0,0,2018-02-12 14:02:06+00:00,3872,00:27:12.200000,Test P,imported through email,America/Los_Angeles,water,80.0,lwt
-93,https://rowsandall.com/rowers/workout/2449/emailcsv,https://rowsandall.com/rowers/workout/2449/emailtcx,0,0,2018-02-12 14:02:06+00:00,3872,00:27:12.200000,Water 2x,imported through email,America/Los_Angeles,water,80.0,lwt
-94,https://rowsandall.com/rowers/workout/2412/emailcsv,https://rowsandall.com/rowers/workout/2412/emailtcx,0,0,2018-02-12 14:22:01+00:00,3650,00:14:53.200000,Test 3,,America/Los_Angeles,water,80.0,lwt
-95,https://rowsandall.com/rowers/workout/2336/emailcsv,https://rowsandall.com/rowers/workout/2336/emailtcx,0,0,2018-02-12 14:29:01+00:00,3650,00:14:53.200000,SpdCoach 2,"
-Summary for your location at 2018-02-12T14:55:00Z: Temperature 9.0C/48.2F. Wind: 2.5 m/s (5.0 kt). Wind Bearing: 280.0 degrees",America/Los_Angeles,water,80.0,lwt
-96,https://rowsandall.com/rowers/workout/2340/emailcsv,https://rowsandall.com/rowers/workout/2340/emailtcx,0,0,2018-02-12 14:29:01+00:00,5464,00:31:40,Joined Workout,,America/Los_Angeles,water,80.0,lwt
-97,https://rowsandall.com/rowers/workout/2345/emailcsv,https://rowsandall.com/rowers/workout/2345/emailtcx,0,0,2018-02-12 14:29:01+00:00,3650,00:14:53.200000,SpdCoach Sessions (2),imported through email,America/Los_Angeles,water,80.0,lwt
-98,https://rowsandall.com/rowers/workout/2433/emailcsv,https://rowsandall.com/rowers/workout/2433/emailtcx,0,0,2018-02-12 14:29:01+00:00,3650,00:14:53.200000,Test,,America/Los_Angeles,rower,80.0,lwt
-99,https://rowsandall.com/rowers/workout/2442/emailcsv,https://rowsandall.com/rowers/workout/2442/emailtcx,0,0,2018-02-12 14:29:01+00:00,3650,00:14:53.200000,Water,imported through email,America/Los_Angeles,water,80.0,lwt
-100,https://rowsandall.com/rowers/workout/2444/emailcsv,https://rowsandall.com/rowers/workout/2444/emailtcx,0,0,2018-02-12 14:29:01+00:00,3650,00:14:53.200000,SpdCoach 2,imported through email,America/Los_Angeles,water,80.0,lwt
-101,https://rowsandall.com/rowers/workout/2337/emailcsv,https://rowsandall.com/rowers/workout/2337/emailtcx,0,0,2018-02-12 14:49:02+00:00,1814,00:11:39,SpdCoach 3,,America/Los_Angeles,water,80.0,lwt
-102,https://rowsandall.com/rowers/workout/2346/emailcsv,https://rowsandall.com/rowers/workout/2346/emailtcx,0,0,2018-02-12 14:49:02+00:00,1814,00:11:39,SpdCoach Sessions (3),imported through email,America/Los_Angeles,water,80.0,lwt
-103,https://rowsandall.com/rowers/workout/2413/emailcsv,https://rowsandall.com/rowers/workout/2413/emailtcx,0,0,2018-02-12 14:49:02+00:00,1814,00:11:39,Test 4,,America/Los_Angeles,water,80.0,lwt
-104,https://rowsandall.com/rowers/workout/2443/emailcsv,https://rowsandall.com/rowers/workout/2443/emailtcx,0,0,2018-02-12 14:49:02+00:00,1814,00:11:39,water weer,imported through email,America/Los_Angeles,water,80.0,lwt
-105,https://rowsandall.com/rowers/workout/2678/emailcsv,https://rowsandall.com/rowers/workout/2678/emailtcx,0,0,2018-02-12 18:39:42+00:00,2014,00:08:37.700000,C2 Import Workout from 2018-02-12 18:39:42+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-106,https://rowsandall.com/rowers/workout/2677/emailcsv,https://rowsandall.com/rowers/workout/2677/emailtcx,0,0,2018-02-12 18:49:03+00:00,10562,00:46:12.400000,C2 Import Workout from 2018-02-12 18:49:03+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-107,https://rowsandall.com/rowers/workout/2676/emailcsv,https://rowsandall.com/rowers/workout/2676/emailtcx,0,0,2018-02-12 19:36:43+00:00,1998,00:09:39.800000,C2 Import Workout from 2018-02-12 19:36:43+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-108,https://rowsandall.com/rowers/workout/2675/emailcsv,https://rowsandall.com/rowers/workout/2675/emailtcx,0,0,2018-02-15 18:16:50+00:00,12440,00:51:41.500000,C2 Import Workout from 2018-02-15 18:16:50+00:00,imported from Concept2 log,UTC,rower,80.0,lwt
-109,https://rowsandall.com/rowers/workout/2674/emailcsv,https://rowsandall.com/rowers/workout/2674/emailtcx,0,0,2018-02-15 19:08:28+00:00,14477,01:00:21.800000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-110,https://rowsandall.com/rowers/workout/2673/emailcsv,https://rowsandall.com/rowers/workout/2673/emailtcx,0,0,2018-02-16 14:24:03+00:00,3012,00:12:58.800000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-111,https://rowsandall.com/rowers/workout/2672/emailcsv,https://rowsandall.com/rowers/workout/2672/emailtcx,0,0,2018-02-16 14:37:40+00:00,5277,00:23:00,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-112,https://rowsandall.com/rowers/workout/2671/emailcsv,https://rowsandall.com/rowers/workout/2671/emailtcx,0,0,2018-02-16 15:01:29+00:00,1036,00:05:03.600000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-113,https://rowsandall.com/rowers/workout/2670/emailcsv,https://rowsandall.com/rowers/workout/2670/emailtcx,0,0,2018-02-16 15:07:03+00:00,5113,00:23:22,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-114,https://rowsandall.com/rowers/workout/2669/emailcsv,https://rowsandall.com/rowers/workout/2669/emailtcx,0,0,2018-02-16 15:34:40+00:00,1259,00:05:48.600000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-115,https://rowsandall.com/rowers/workout/2668/emailcsv,https://rowsandall.com/rowers/workout/2668/emailtcx,0,0,2018-02-18 13:30:59+00:00,13541,00:56:07.300000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-116,https://rowsandall.com/rowers/workout/2667/emailcsv,https://rowsandall.com/rowers/workout/2667/emailtcx,0,0,2018-02-20 18:08:13+00:00,2008,00:08:36.300000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-117,https://rowsandall.com/rowers/workout/2666/emailcsv,https://rowsandall.com/rowers/workout/2666/emailtcx,0,0,2018-02-20 18:17:17+00:00,10914,00:48:06.100000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-118,https://rowsandall.com/rowers/workout/2665/emailcsv,https://rowsandall.com/rowers/workout/2665/emailtcx,0,0,2018-02-20 19:06:36+00:00,1513,00:07:37.300000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-119,https://rowsandall.com/rowers/workout/2381/emailcsv,https://rowsandall.com/rowers/workout/2381/emailtcx,0,0,2018-02-21 06:26:01+00:00,6119,00:27:20.200000,3x2km Racice,,Europe/Prague,water,80.0,lwt
-120,https://rowsandall.com/rowers/workout/2384/emailcsv,https://rowsandall.com/rowers/workout/2384/emailtcx,0,0,2018-02-22 09:32:01+00:00,8000,00:35:08.500000,8k trial,,Europe/Prague,water,80.0,lwt
-121,https://rowsandall.com/rowers/workout/2664/emailcsv,https://rowsandall.com/rowers/workout/2664/emailtcx,0,0,2018-02-22 18:40:03+00:00,11481,00:49:17.400000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-122,https://rowsandall.com/rowers/workout/2663/emailcsv,https://rowsandall.com/rowers/workout/2663/emailtcx,0,0,2018-02-23 15:12:10+00:00,2008,00:08:44.800000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-123,https://rowsandall.com/rowers/workout/2383/emailcsv,https://rowsandall.com/rowers/workout/2383/emailtcx,0,0,2018-02-23 15:17:03+00:00,5918,00:25:10.700000,Horin,,Europe/Prague,water,80.0,lwt
-124,https://rowsandall.com/rowers/workout/2662/emailcsv,https://rowsandall.com/rowers/workout/2662/emailtcx,0,0,2018-02-23 15:21:44+00:00,8804,00:39:58,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-125,https://rowsandall.com/rowers/workout/2661/emailcsv,https://rowsandall.com/rowers/workout/2661/emailtcx,0,0,2018-02-23 16:02:23+00:00,2008,00:09:05,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-126,https://rowsandall.com/rowers/workout/2385/emailcsv,https://rowsandall.com/rowers/workout/2385/emailtcx,0,0,2018-02-24 11:58:09+00:00,17045,01:35:59,Washington,,America/New_York,water,80.0,lwt
-127,https://rowsandall.com/rowers/workout/2660/emailcsv,https://rowsandall.com/rowers/workout/2660/emailtcx,0,0,2018-02-24 15:07:07+00:00,14544,01:01:04.500000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-128,https://rowsandall.com/rowers/workout/2386/emailcsv,https://rowsandall.com/rowers/workout/2386/emailtcx,0,0,2018-02-25 12:24:59+00:00,6182,00:26:24.400000,9x500m/70sec,,Europe/Prague,rower,80.0,lwt
-129,https://rowsandall.com/rowers/workout/2659/emailcsv,https://rowsandall.com/rowers/workout/2659/emailtcx,0,0,2018-02-25 14:15:13+00:00,16623,01:22:28,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-130,https://rowsandall.com/rowers/workout/2400/emailcsv,https://rowsandall.com/rowers/workout/2400/emailtcx,0,0,2018-02-25 22:45:28+00:00,4175,00:25:07.700000,Test CP,,Europe/Prague,rower,80.0,lwt
-131,https://rowsandall.com/rowers/workout/2387/emailcsv,https://rowsandall.com/rowers/workout/2387/emailtcx,0,0,2018-02-27 13:19:44+00:00,2206,00:10:00,StatsError,,Europe/Prague,rower,80.0,lwt
-132,https://rowsandall.com/rowers/workout/2658/emailcsv,https://rowsandall.com/rowers/workout/2658/emailtcx,0,0,2018-02-27 16:32:56+00:00,13549,00:56:44.900000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-133,https://rowsandall.com/rowers/workout/2657/emailcsv,https://rowsandall.com/rowers/workout/2657/emailtcx,0,0,2018-03-03 13:50:12+00:00,2012,00:08:42.700000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-134,https://rowsandall.com/rowers/workout/2656/emailcsv,https://rowsandall.com/rowers/workout/2656/emailtcx,0,0,2018-03-03 14:00:26+00:00,6270,00:26:41.700000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-135,https://rowsandall.com/rowers/workout/2655/emailcsv,https://rowsandall.com/rowers/workout/2655/emailtcx,0,0,2018-03-03 14:27:41+00:00,999,00:05:44.100000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-136,https://rowsandall.com/rowers/workout/2395/emailcsv,https://rowsandall.com/rowers/workout/2395/emailtcx,0,0,2018-03-03 14:33:51+00:00,6098,00:26:35.400000,Flex chart not working,,Europe/Prague,rower,80.0,lwt
-137,https://rowsandall.com/rowers/workout/2654/emailcsv,https://rowsandall.com/rowers/workout/2654/emailtcx,0,0,2018-03-03 14:33:51+00:00,6098,00:26:35.400000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-138,https://rowsandall.com/rowers/workout/2653/emailcsv,https://rowsandall.com/rowers/workout/2653/emailtcx,0,0,2018-03-03 15:01:34+00:00,1559,00:07:16.600000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-139,https://rowsandall.com/rowers/workout/2392/emailcsv,https://rowsandall.com/rowers/workout/2392/emailtcx,0,0,2018-03-05 13:51:23+00:00,13802,01:06:00,Mike's average workout,,Europe/Prague,rower,80.0,lwt
-140,https://rowsandall.com/rowers/workout/2396/emailcsv,https://rowsandall.com/rowers/workout/2396/emailtcx,0,0,2018-03-05 13:51:23+00:00,4058,00:17:00,Mike's average workout (1),,Europe/Prague,rower,80.0,lwt
-141,https://rowsandall.com/rowers/workout/2397/emailcsv,https://rowsandall.com/rowers/workout/2397/emailtcx,0,0,2018-03-05 14:08:23+00:00,9738,00:49:00,Mike's average workout (2),,Europe/Prague,rower,80.0,lwt
-142,https://rowsandall.com/rowers/workout/2389/emailcsv,https://rowsandall.com/rowers/workout/2389/emailtcx,0,0,2018-03-05 17:48:31+00:00,7022,00:29:44.400000,test,wat een kutsessie,Europe/Prague,rower,80.0,lwt
-143,https://rowsandall.com/rowers/workout/2652/emailcsv,https://rowsandall.com/rowers/workout/2652/emailtcx,0,0,2018-03-05 17:48:31+00:00,7022,00:29:45.900000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-144,https://rowsandall.com/rowers/workout/2390/emailcsv,https://rowsandall.com/rowers/workout/2390/emailtcx,0,0,2018-03-05 17:50:46+00:00,5019,00:31:27.500000,,,Europe/Prague,rower,80.0,lwt
-145,https://rowsandall.com/rowers/workout/2651/emailcsv,https://rowsandall.com/rowers/workout/2651/emailtcx,0,0,2018-03-08 18:34:05+00:00,2010,00:08:38.700000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-146,https://rowsandall.com/rowers/workout/2650/emailcsv,https://rowsandall.com/rowers/workout/2650/emailtcx,0,0,2018-03-08 18:43:29+00:00,10444,00:46:52.300000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-147,https://rowsandall.com/rowers/workout/2649/emailcsv,https://rowsandall.com/rowers/workout/2649/emailtcx,0,0,2018-03-08 19:31:31+00:00,269,00:01:42,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-148,https://rowsandall.com/rowers/workout/2398/emailcsv,https://rowsandall.com/rowers/workout/2398/emailtcx,0,0,2018-03-09 11:52:48+00:00,4160,00:13:00,test template,"Dit zijn de notes
-Sommige zinnen zijn heel heel heel heel heel heel heel heel lang Sommige zinnen zijn heel heel heel heel heel heel heel heel lang Sommige zinnen zijn heel heel heel heel heel heel heel heel lang Sommige zinnen zijn heel heel heel heel heel heel heel heel lang
-LAngwoordzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",Europe/Prague,rower,80.0,lwt
-149,https://rowsandall.com/rowers/workout/2399/emailcsv,https://rowsandall.com/rowers/workout/2399/emailtcx,0,0,2018-03-09 11:59:13+00:00,4160,00:13:00,Test P,,Europe/Prague,rower,80.0,lwt
-150,https://rowsandall.com/rowers/workout/2401/emailcsv,https://rowsandall.com/rowers/workout/2401/emailtcx,0,0,2018-03-13 07:32:40+00:00,6479,00:30:27.300000,high power values?,,Europe/Prague,rower,80.0,lwt
-151,https://rowsandall.com/rowers/workout/2648/emailcsv,https://rowsandall.com/rowers/workout/2648/emailtcx,0,0,2018-03-13 18:18:31+00:00,2009,00:08:30,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-152,https://rowsandall.com/rowers/workout/2404/emailcsv,https://rowsandall.com/rowers/workout/2404/emailtcx,0,0,2018-03-13 18:28:00.900000+00:00,9996,00:40:00,C2 Rower Timed. 10.0,"C2 Rower Timed. 10.0km, 40.00 min. (PainSled)",Europe/Prague,rower,80.0,lwt
-153,https://rowsandall.com/rowers/workout/2405/emailcsv,https://rowsandall.com/rowers/workout/2405/emailtcx,0,0,2018-03-13 18:28:00.900000+00:00,10850,00:45:32.400000,C2 Rower Timed. 10.0,"C2 Rower Timed. 10.0km, 40.00 min. (PainSled)",Europe/Prague,rower,80.0,lwt
-154,https://rowsandall.com/rowers/workout/2647/emailcsv,https://rowsandall.com/rowers/workout/2647/emailtcx,0,0,2018-03-13 18:28:01+00:00,10864,00:46:12.800000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-155,https://rowsandall.com/rowers/workout/2646/emailcsv,https://rowsandall.com/rowers/workout/2646/emailtcx,0,0,2018-03-13 19:15:15+00:00,1015,00:05:05.600000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-156,https://rowsandall.com/rowers/workout/2645/emailcsv,https://rowsandall.com/rowers/workout/2645/emailtcx,0,0,2018-03-13 19:18:21+00:00,2009,00:08:29.600000,Imported workout,imported from Concept2 log,UTC,rower,80.0,hwt
-157,https://rowsandall.com/rowers/workout/2644/emailcsv,https://rowsandall.com/rowers/workout/2644/emailtcx,0,0,2018-03-13 19:28:00+00:00,9996,00:40:00,Imported workout,imported from Concept2 log,UTC,rower,80.0,hwt
-158,https://rowsandall.com/rowers/workout/2402/emailcsv,https://rowsandall.com/rowers/workout/2402/emailtcx,0,0,2018-03-13 21:15:46+00:00,1311,00:13:04.100000,Stroke Count,,Europe/Prague,rower,80.0,lwt
-159,https://rowsandall.com/rowers/workout/2403/emailcsv,https://rowsandall.com/rowers/workout/2403/emailtcx,0,0,2018-03-14 19:33:20+00:00,10850,00:45:32.400000,4x10min,,Europe/Prague,rower,80.0,lwt
-160,https://rowsandall.com/rowers/workout/2406/emailcsv,https://rowsandall.com/rowers/workout/2406/emailtcx,0,0,2018-03-15 06:22:52+00:00,336,00:01:00,Test 1 minute,,Europe/Prague,rower,80.0,lwt
-161,https://rowsandall.com/rowers/workout/2422/emailcsv,https://rowsandall.com/rowers/workout/2422/emailtcx,0,0,2018-03-15 06:22:52+00:00,8136,23:59:59.900000,Joined Workout,,Europe/Prague,rower,80.0,lwt
-162,https://rowsandall.com/rowers/workout/2407/emailcsv,https://rowsandall.com/rowers/workout/2407/emailtcx,0,0,2018-03-15 06:23:09+00:00,7800,00:30:00,Thirty Dirty,,Europe/Prague,rower,80.0,lwt
-163,https://rowsandall.com/rowers/workout/2434/emailcsv,https://rowsandall.com/rowers/workout/2434/emailtcx,0,0,2018-03-15 06:25:09+00:00,7800,23:59:59.900000,30 min,,Europe/Prague,rower,80.0,lwt
-164,https://rowsandall.com/rowers/workout/2643/emailcsv,https://rowsandall.com/rowers/workout/2643/emailtcx,0,0,2018-03-15 18:48:48+00:00,2013,00:08:36.700000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-165,https://rowsandall.com/rowers/workout/2425/emailcsv,https://rowsandall.com/rowers/workout/2425/emailtcx,0,0,2018-03-15 18:58:08+00:00,10169,00:44:31.200000,Joined Workout,,Europe/Prague,rower,80.0,lwt
-166,https://rowsandall.com/rowers/workout/2438/emailcsv,https://rowsandall.com/rowers/workout/2438/emailtcx,0,0,2018-03-15 18:58:08+00:00,8157,00:34:21.600000,Test,imported through email,Europe/Prague,rower,80.0,lwt
-167,https://rowsandall.com/rowers/workout/2642/emailcsv,https://rowsandall.com/rowers/workout/2642/emailtcx,0,0,2018-03-15 18:58:08+00:00,8157,00:34:21.500000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-168,https://rowsandall.com/rowers/workout/2423/emailcsv,https://rowsandall.com/rowers/workout/2423/emailtcx,0,0,2018-03-15 18:58:08.620390+00:00,8157,00:34:21.600000,6x4min,,Europe/Prague,rower,80.0,lwt
-169,https://rowsandall.com/rowers/workout/2431/emailcsv,https://rowsandall.com/rowers/workout/2431/emailtcx,0,0,2018-03-15 18:58:08.620390+00:00,8157,00:34:21.600000,Indoor,,Europe/Prague,rower,80.0,lwt
-170,https://rowsandall.com/rowers/workout/2432/emailcsv,https://rowsandall.com/rowers/workout/2432/emailtcx,0,0,2018-03-15 18:58:08.620390+00:00,8157,00:34:21.600000,test,,Europe/Prague,rower,80.0,lwt
-171,https://rowsandall.com/rowers/workout/2435/emailcsv,https://rowsandall.com/rowers/workout/2435/emailtcx,0,0,2018-03-15 18:58:08.620390+00:00,8157,00:34:21.600000,Test,,Europe/Prague,rower,80.0,lwt
-172,https://rowsandall.com/rowers/workout/2436/emailcsv,https://rowsandall.com/rowers/workout/2436/emailtcx,0,0,2018-03-15 18:58:08.620390+00:00,8157,00:34:21.600000,r,,Europe/Prague,rower,80.0,lwt
-173,https://rowsandall.com/rowers/workout/2437/emailcsv,https://rowsandall.com/rowers/workout/2437/emailtcx,0,0,2018-03-15 18:58:08.620390+00:00,8157,00:34:21.600000,a,,Europe/Prague,rower,80.0,lwt
-174,https://rowsandall.com/rowers/workout/2440/emailcsv,https://rowsandall.com/rowers/workout/2440/emailtcx,0,0,2018-03-15 19:33:15+00:00,2012,00:09:24.300000,another one,imported through email,Europe/Prague,rower,80.0,lwt
-175,https://rowsandall.com/rowers/workout/2641/emailcsv,https://rowsandall.com/rowers/workout/2641/emailtcx,0,0,2018-03-15 19:33:15+00:00,2012,00:09:24.300000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-176,https://rowsandall.com/rowers/workout/2424/emailcsv,https://rowsandall.com/rowers/workout/2424/emailtcx,0,0,2018-03-15 19:33:15.009331+00:00,2012,00:09:24.400000,6x4min,,Europe/Prague,rower,80.0,lwt
-177,https://rowsandall.com/rowers/workout/2429/emailcsv,https://rowsandall.com/rowers/workout/2429/emailtcx,0,0,2018-03-16 12:04:52+00:00,9595,00:54:45,Joined Workout,,America/New_York,rower,80.0,lwt
-178,https://rowsandall.com/rowers/workout/2426/emailcsv,https://rowsandall.com/rowers/workout/2426/emailtcx,0,0,2018-03-16 12:09:23+00:00,9269,00:50:14,Test P,,America/New_York,rower,80.0,lwt
-179,https://rowsandall.com/rowers/workout/2428/emailcsv,https://rowsandall.com/rowers/workout/2428/emailtcx,0,0,2018-03-16 12:09:23+00:00,9269,00:50:14,,,America/New_York,rower,80.0,lwt
-180,https://rowsandall.com/rowers/workout/2427/emailcsv,https://rowsandall.com/rowers/workout/2427/emailtcx,0,0,2018-03-16 13:00:52+00:00,326,00:04:03,Water Workout,,America/New_York,water,80.0,lwt
-181,https://rowsandall.com/rowers/workout/2640/emailcsv,https://rowsandall.com/rowers/workout/2640/emailtcx,0,0,2018-03-17 14:14:56+00:00,15231,01:03:19.100000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-182,https://rowsandall.com/rowers/workout/2639/emailcsv,https://rowsandall.com/rowers/workout/2639/emailtcx,0,0,2018-03-18 14:03:27+00:00,3876,00:16:16.200000,Imported workout,imported from Concept2 log,UTC,slides,80.0,lwt
-183,https://rowsandall.com/rowers/workout/2638/emailcsv,https://rowsandall.com/rowers/workout/2638/emailtcx,0,0,2018-03-18 14:20:52+00:00,6000,00:22:17.500000,Imported workout,imported from Concept2 log,UTC,slides,80.0,lwt
-184,https://rowsandall.com/rowers/workout/2637/emailcsv,https://rowsandall.com/rowers/workout/2637/emailtcx,0,0,2018-03-18 14:44:46+00:00,4163,00:19:13.200000,Imported workout,imported from Concept2 log,UTC,slides,80.0,lwt
-185,https://rowsandall.com/rowers/workout/2636/emailcsv,https://rowsandall.com/rowers/workout/2636/emailtcx,0,0,2018-03-22 18:38:59+00:00,2007,00:08:43.800000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-186,https://rowsandall.com/rowers/workout/2635/emailcsv,https://rowsandall.com/rowers/workout/2635/emailtcx,0,0,2018-03-22 18:48:29+00:00,6770,00:29:38.200000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-187,https://rowsandall.com/rowers/workout/2634/emailcsv,https://rowsandall.com/rowers/workout/2634/emailtcx,0,0,2018-03-22 19:18:50+00:00,2010,00:08:46.700000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-188,https://rowsandall.com/rowers/workout/2633/emailcsv,https://rowsandall.com/rowers/workout/2633/emailtcx,0,0,2018-03-24 09:20:07+00:00,15446,01:22:56.300000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-189,https://rowsandall.com/rowers/workout/2451/emailcsv,https://rowsandall.com/rowers/workout/2451/emailtcx,0,0,2018-03-25 09:59:12+00:00,29000,01:50:13,test,,Europe/Zurich,rower,80.0,lwt
-190,https://rowsandall.com/rowers/workout/2452/emailcsv,https://rowsandall.com/rowers/workout/2452/emailtcx,0,0,2018-03-25 09:59:12+00:00,29000,01:50:13,Background processing test,imported through email,Europe/Zurich,water,80.0,lwt
-191,https://rowsandall.com/rowers/workout/2632/emailcsv,https://rowsandall.com/rowers/workout/2632/emailtcx,0,0,2018-03-25 14:29:09+00:00,6664,00:46:07,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-192,https://rowsandall.com/rowers/workout/2453/emailcsv,https://rowsandall.com/rowers/workout/2453/emailtcx,0,0,2018-03-29 13:45:00+00:00,2000,07:25:00,test api,string,UTC,water,80.0,lwt
-193,https://rowsandall.com/rowers/workout/2454/emailcsv,https://rowsandall.com/rowers/workout/2454/emailtcx,0,0,2018-04-02 11:02:55+00:00,3848,00:22:14.200000,RP3 curve,,Europe/Prague,rower,80.0,lwt
-194,https://rowsandall.com/rowers/workout/2455/emailcsv,https://rowsandall.com/rowers/workout/2455/emailtcx,0,0,2018-04-02 11:04:18+00:00,3848,00:22:14.200000,,,Europe/Prague,rower,80.0,lwt
-195,https://rowsandall.com/rowers/workout/2631/emailcsv,https://rowsandall.com/rowers/workout/2631/emailtcx,0,0,2018-04-03 14:34:01+00:00,2822,00:14:43.700000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-196,https://rowsandall.com/rowers/workout/2630/emailcsv,https://rowsandall.com/rowers/workout/2630/emailtcx,0,0,2018-04-03 14:50:01+00:00,7505,00:39:46.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-197,https://rowsandall.com/rowers/workout/2456/emailcsv,https://rowsandall.com/rowers/workout/2456/emailtcx,0,0,2018-04-03 15:50:52+00:00,7200,00:37:44,In Stroke,,Europe/Prague,water,80.0,lwt
-198,https://rowsandall.com/rowers/workout/2457/emailcsv,https://rowsandall.com/rowers/workout/2457/emailtcx,0,0,2018-04-03 15:50:52+00:00,7200,00:37:44,In Stroke 2,,Europe/Prague,water,80.0,lwt
-199,https://rowsandall.com/rowers/workout/2629/emailcsv,https://rowsandall.com/rowers/workout/2629/emailtcx,0,0,2018-04-04 18:30:27+00:00,27,00:00:03.200000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-200,https://rowsandall.com/rowers/workout/2628/emailcsv,https://rowsandall.com/rowers/workout/2628/emailtcx,0,0,2018-04-04 19:00:43+00:00,8309,00:48:07.400000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-201,https://rowsandall.com/rowers/workout/2458/emailcsv,https://rowsandall.com/rowers/workout/2458/emailtcx,0,0,2018-04-07 07:41:02+00:00,10568,01:06:08.800000,2x3km fail,,Europe/Prague,water,80.0,lwt
-202,https://rowsandall.com/rowers/workout/2460/emailcsv,https://rowsandall.com/rowers/workout/2460/emailtcx,0,0,2018-04-07 07:41:02+00:00,10568,01:06:08.800000,Update,,Europe/Prague,water,80.0,lwt
-203,https://rowsandall.com/rowers/workout/2627/emailcsv,https://rowsandall.com/rowers/workout/2627/emailtcx,0,0,2018-04-07 07:41:02+00:00,2243,00:12:20.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-204,https://rowsandall.com/rowers/workout/2626/emailcsv,https://rowsandall.com/rowers/workout/2626/emailtcx,0,0,2018-04-07 07:55:02+00:00,3167,00:16:59.800000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-205,https://rowsandall.com/rowers/workout/2625/emailcsv,https://rowsandall.com/rowers/workout/2625/emailtcx,0,0,2018-04-07 08:14:02+00:00,2977,00:14:58,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-206,https://rowsandall.com/rowers/workout/2623/emailcsv,https://rowsandall.com/rowers/workout/2623/emailtcx,0,0,2018-04-07 08:33:03+00:00,2180,00:14:07.700000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-207,https://rowsandall.com/rowers/workout/2622/emailcsv,https://rowsandall.com/rowers/workout/2622/emailtcx,0,0,2018-04-10 17:38:22+00:00,11703,00:48:59.500000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-208,https://rowsandall.com/rowers/workout/2621/emailcsv,https://rowsandall.com/rowers/workout/2621/emailtcx,0,0,2018-04-10 18:27:53+00:00,17284,01:11:55.500000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-209,https://rowsandall.com/rowers/workout/2620/emailcsv,https://rowsandall.com/rowers/workout/2620/emailtcx,0,0,2018-04-11 18:37:27+00:00,10122,01:15:44.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-210,https://rowsandall.com/rowers/workout/2619/emailcsv,https://rowsandall.com/rowers/workout/2619/emailtcx,0,0,2018-04-12 16:17:02+00:00,10408,00:53:45.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-211,https://rowsandall.com/rowers/workout/2618/emailcsv,https://rowsandall.com/rowers/workout/2618/emailtcx,0,0,2018-04-15 08:34:05+00:00,11129,01:03:38,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-212,https://rowsandall.com/rowers/workout/2617/emailcsv,https://rowsandall.com/rowers/workout/2617/emailtcx,0,0,2018-04-18 13:43:04+00:00,1942,00:10:55.300000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-213,https://rowsandall.com/rowers/workout/2616/emailcsv,https://rowsandall.com/rowers/workout/2616/emailtcx,0,0,2018-04-18 13:57:01+00:00,7979,00:36:10.600000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-214,https://rowsandall.com/rowers/workout/2615/emailcsv,https://rowsandall.com/rowers/workout/2615/emailtcx,0,0,2018-04-18 14:49:06+00:00,1512,00:08:27.600000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-215,https://rowsandall.com/rowers/workout/2614/emailcsv,https://rowsandall.com/rowers/workout/2614/emailtcx,0,0,2018-04-20 15:51:41+00:00,9748,01:06:50.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-216,https://rowsandall.com/rowers/workout/2613/emailcsv,https://rowsandall.com/rowers/workout/2613/emailtcx,0,0,2018-04-21 15:38:04+00:00,5254,00:27:02.700000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-217,https://rowsandall.com/rowers/workout/2612/emailcsv,https://rowsandall.com/rowers/workout/2612/emailtcx,0,0,2018-04-22 07:15:01+00:00,12282,01:08:28.600000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-218,https://rowsandall.com/rowers/workout/2471/emailcsv,https://rowsandall.com/rowers/workout/2471/emailtcx,0,0,2018-04-23 11:00:00+00:00,1017,00:03:55.200000,7x150min/1min,,America/New_York,water,80.0,lwt
-219,https://rowsandall.com/rowers/workout/2472/emailcsv,https://rowsandall.com/rowers/workout/2472/emailtcx,0,0,2018-04-23 11:00:00+00:00,1017,00:03:55.200000,7x15min test 2,,America/New_York,water,80.0,lwt
-220,https://rowsandall.com/rowers/workout/2473/emailcsv,https://rowsandall.com/rowers/workout/2473/emailtcx,0,0,2018-04-23 11:00:00+00:00,1017,00:03:55.200000,7x150min/1min,,America/New_York,water,80.0,lwt
-221,https://rowsandall.com/rowers/workout/2474/emailcsv,https://rowsandall.com/rowers/workout/2474/emailtcx,0,0,2018-04-23 11:00:00+00:00,1017,00:03:55,test firmware,,America/New_York,water,80.0,lwt
-222,https://rowsandall.com/rowers/workout/2478/emailcsv,https://rowsandall.com/rowers/workout/2478/emailtcx,0,0,2018-04-23 11:00:00+00:00,1017,00:03:55.200000,Firmware 2,,America/New_York,water,80.0,lwt
-223,https://rowsandall.com/rowers/workout/2611/emailcsv,https://rowsandall.com/rowers/workout/2611/emailtcx,0,0,2018-04-23 17:46:25+00:00,13558,00:58:11.900000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-224,https://rowsandall.com/rowers/workout/2465/emailcsv,https://rowsandall.com/rowers/workout/2465/emailtcx,0,0,2018-04-23 20:42:00+00:00,8000,00:36:01.500000,Racice,,Europe/Prague,water,80.0,lwt
-225,https://rowsandall.com/rowers/workout/2610/emailcsv,https://rowsandall.com/rowers/workout/2610/emailtcx,0,0,2018-04-24 12:12:03+00:00,2959,00:16:42.700000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-226,https://rowsandall.com/rowers/workout/2609/emailcsv,https://rowsandall.com/rowers/workout/2609/emailtcx,0,0,2018-04-24 12:32:00+00:00,7516,00:38:49.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-227,https://rowsandall.com/rowers/workout/2466/emailcsv,https://rowsandall.com/rowers/workout/2466/emailtcx,0,0,2018-04-24 13:35:30+00:00,9420,00:48:00,,,Europe/Prague,water,80.0,lwt
-228,https://rowsandall.com/rowers/workout/2608/emailcsv,https://rowsandall.com/rowers/workout/2608/emailtcx,0,0,2018-04-25 17:50:26+00:00,10171,01:12:33.600000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-229,https://rowsandall.com/rowers/workout/2470/emailcsv,https://rowsandall.com/rowers/workout/2470/emailtcx,0,0,2018-04-25 22:59:01+00:00,4159,00:26:43.200000,SpeedCoach 7x150m,,America/New_York,water,80.0,lwt
-230,https://rowsandall.com/rowers/workout/2607/emailcsv,https://rowsandall.com/rowers/workout/2607/emailtcx,0,0,2018-04-26 16:18:01+00:00,2016,00:12:30.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-231,https://rowsandall.com/rowers/workout/2606/emailcsv,https://rowsandall.com/rowers/workout/2606/emailtcx,0,0,2018-04-26 16:33:00+00:00,4605,00:22:35.700000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-232,https://rowsandall.com/rowers/workout/2605/emailcsv,https://rowsandall.com/rowers/workout/2605/emailtcx,0,0,2018-04-26 16:56:03+00:00,1301,00:07:07.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-233,https://rowsandall.com/rowers/workout/2604/emailcsv,https://rowsandall.com/rowers/workout/2604/emailtcx,0,0,2018-04-28 08:02:01+00:00,11924,01:18:20.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-234,https://rowsandall.com/rowers/workout/2469/emailcsv,https://rowsandall.com/rowers/workout/2469/emailtcx,0,0,2018-04-29 07:22:01+00:00,8040,00:50:06,Test P,,America/New_York,water,80.0,lwt
-235,https://rowsandall.com/rowers/workout/2603/emailcsv,https://rowsandall.com/rowers/workout/2603/emailtcx,0,0,2018-04-29 07:22:01+00:00,8040,00:50:05.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-236,https://rowsandall.com/rowers/workout/2559/emailcsv,https://rowsandall.com/rowers/workout/2559/emailtcx,0,0,2018-05-03 16:02:08+00:00,10909,01:00:35,Intervals Tests (6),imported through email,Europe/Amsterdam,water,80.0,lwt
-237,https://rowsandall.com/rowers/workout/2602/emailcsv,https://rowsandall.com/rowers/workout/2602/emailtcx,0,0,2018-05-04 05:47:04+00:00,3472,00:18:53.700000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-238,https://rowsandall.com/rowers/workout/2479/emailcsv,https://rowsandall.com/rowers/workout/2479/emailtcx,0,0,2018-05-04 06:07:04+00:00,5997,00:25:53.900000,Zip test,imported through email,Europe/Prague,water,80.0,lwt
-239,https://rowsandall.com/rowers/workout/2481/emailcsv,https://rowsandall.com/rowers/workout/2481/emailtcx,0,0,2018-05-04 06:07:04+00:00,5997,00:25:53.900000,Zip test 2,imported through email,Europe/Prague,water,80.0,lwt
-240,https://rowsandall.com/rowers/workout/2483/emailcsv,https://rowsandall.com/rowers/workout/2483/emailtcx,0,0,2018-05-04 06:07:04+00:00,5997,00:25:53.900000,Test Zip 3,imported through email,Europe/Prague,water,80.0,lwt
-241,https://rowsandall.com/rowers/workout/2601/emailcsv,https://rowsandall.com/rowers/workout/2601/emailtcx,0,0,2018-05-04 06:07:04+00:00,5997,00:25:53.900000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-242,https://rowsandall.com/rowers/workout/2860/emailcsv,https://rowsandall.com/rowers/workout/2860/emailtcx,0,0,2018-05-04 06:07:04+00:00,5997,00:25:53.900000,Zip test,"imported through email
- from speedcoach2v2.15 via rowsandall.com",Europe/Prague,water,80.0,hwt
-243,https://rowsandall.com/rowers/workout/2600/emailcsv,https://rowsandall.com/rowers/workout/2600/emailtcx,0,0,2018-05-04 06:35:04+00:00,1009,00:06:44.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-244,https://rowsandall.com/rowers/workout/2599/emailcsv,https://rowsandall.com/rowers/workout/2599/emailtcx,0,0,2018-05-05 07:06:02+00:00,11180,01:01:01.600000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-245,https://rowsandall.com/rowers/workout/2598/emailcsv,https://rowsandall.com/rowers/workout/2598/emailtcx,0,0,2018-05-05 08:11:04+00:00,1152,00:06:56.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-246,https://rowsandall.com/rowers/workout/2597/emailcsv,https://rowsandall.com/rowers/workout/2597/emailtcx,0,0,2018-05-07 15:41:06+00:00,11019,01:00:40.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-247,https://rowsandall.com/rowers/workout/2490/emailcsv,https://rowsandall.com/rowers/workout/2490/emailtcx,0,0,2018-05-10 09:11:24+00:00,15263,01:39:34,Naarden goed,,Europe/Amsterdam,water,80.0,lwt
-248,https://rowsandall.com/rowers/workout/2491/emailcsv,https://rowsandall.com/rowers/workout/2491/emailtcx,0,0,2018-05-10 09:11:24+00:00,7378,00:44:59,Naarden goed (1),,Europe/Amsterdam,water,80.0,lwt
-249,https://rowsandall.com/rowers/workout/2492/emailcsv,https://rowsandall.com/rowers/workout/2492/emailtcx,0,0,2018-05-10 09:56:24+00:00,7876,00:54:33,Naarden goed (2),,Europe/Amsterdam,water,80.0,lwt
-250,https://rowsandall.com/rowers/workout/2596/emailcsv,https://rowsandall.com/rowers/workout/2596/emailtcx,0,0,2018-05-10 16:15:02+00:00,11983,01:01:26,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-251,https://rowsandall.com/rowers/workout/2485/emailcsv,https://rowsandall.com/rowers/workout/2485/emailtcx,0,0,2018-05-10 16:55:01+00:00,8000,00:36:01.500000,6k,,Europe/Prague,water,80.0,lwt
-252,https://rowsandall.com/rowers/workout/2486/emailcsv,https://rowsandall.com/rowers/workout/2486/emailtcx,0,0,2018-05-10 16:55:01+00:00,8000,00:36:01.500000,Racice 2,,Europe/Prague,water,80.0,lwt
-253,https://rowsandall.com/rowers/workout/2488/emailcsv,https://rowsandall.com/rowers/workout/2488/emailtcx,0,0,2018-05-11 07:02:52+00:00,15364,01:22:34,Naarden 1,,Europe/Amsterdam,water,80.0,lwt
-254,https://rowsandall.com/rowers/workout/2504/emailcsv,https://rowsandall.com/rowers/workout/2504/emailtcx,0,0,2018-05-12 10:01:00+00:00,16814,01:42:53,DC,"Summary for your location at 2018-05-12T12:52:00Z: Temperature 21.1C/69.9F. Wind: 3.0 m/s (6.0 kt). Wind Bearing: 30.0 degrees
-Summary for your location at 2018-05-12T10:52:00Z: Temperature 19.4C/66.9F. Wind: 3.0 m/s (6.0 kt). Wind Bearing: 40.0 degrees
-Summary for your location at 2018-05-12T11:52:00Z: Temperature 20.6C/69.0F. Wind: 3.6 m/s (7.0 kt). Wind Bearing: 20.0 degrees
-Summary for your location at 2018-05-12T10:52:26+00:00: Clear. Temperature 64.52F/18.0C. Wind: 0.96 m/s. Wind Bearing: 29 degrees",America/New_York,water,80.0,lwt
-255,https://rowsandall.com/rowers/workout/2931/emailcsv,https://rowsandall.com/rowers/workout/2931/emailtcx,0,0,2018-05-12 14:22:12+00:00,6510,00:46:56,Test P,,Europe/Bratislava,water,80.0,hwt
-256,https://rowsandall.com/rowers/workout/2513/emailcsv,https://rowsandall.com/rowers/workout/2513/emailtcx,0,0,2018-05-13 07:57:02+00:00,4605,00:35:11.700000,Quad,,Europe/Bratislava,water,80.0,lwt
-257,https://rowsandall.com/rowers/workout/2595/emailcsv,https://rowsandall.com/rowers/workout/2595/emailtcx,0,0,2018-05-13 07:57:02+00:00,4605,00:35:11.600000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-258,https://rowsandall.com/rowers/workout/2502/emailcsv,https://rowsandall.com/rowers/workout/2502/emailtcx,0,0,2018-05-13 09:22:49+00:00,973,00:03:53.900000,Completed a workout (generic) 0.6 mi on 05/13/18,,Europe/Bratislava,water,80.0,lwt
-259,https://rowsandall.com/rowers/workout/2503/emailcsv,https://rowsandall.com/rowers/workout/2503/emailtcx,0,0,2018-05-13 09:22:49+00:00,973,00:03:53.900000,Completed a workout (generic) 0.6 mi on 05/13/18,,Europe/Bratislava,water,80.0,lwt
-260,https://rowsandall.com/rowers/workout/2594/emailcsv,https://rowsandall.com/rowers/workout/2594/emailtcx,0,0,2018-05-13 16:50:32+00:00,2723,00:27:17.200000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-261,https://rowsandall.com/rowers/workout/2593/emailcsv,https://rowsandall.com/rowers/workout/2593/emailtcx,0,0,2018-05-13 16:51:01+00:00,5929,00:43:44.500000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-262,https://rowsandall.com/rowers/workout/2855/emailcsv,https://rowsandall.com/rowers/workout/2855/emailtcx,0,0,2018-05-14 13:53:04+00:00,6091,00:25:00.200000,Hradiste,"
- from csv via rowsandall.com",Europe/Prague,water,80.0,lwt
-263,https://rowsandall.com/rowers/workout/2963/emailcsv,https://rowsandall.com/rowers/workout/2963/emailtcx,0,0,2018-05-14 13:53:04+00:00,6091,00:25:00.200000,Hradiste,"
- from csv via rowsandall.com",Europe/Prague,water,80.0,hwt
-264,https://rowsandall.com/rowers/workout/2493/emailcsv,https://rowsandall.com/rowers/workout/2493/emailtcx,0,0,2018-05-15 10:35:00+00:00,10526,00:44:01.700000,Turin,,Europe/Rome,water,80.0,lwt
-265,https://rowsandall.com/rowers/workout/2489/emailcsv,https://rowsandall.com/rowers/workout/2489/emailtcx,0,0,2018-05-17 17:40:00+00:00,15364,01:22:34,Naarden 2,,Europe/Amsterdam,water,80.0,lwt
-266,https://rowsandall.com/rowers/workout/2464/emailcsv,https://rowsandall.com/rowers/workout/2464/emailtcx,0,0,2018-05-18 13:02:00+00:00,6091,00:25:00.200000,Hradiste,"Failed to download METAR data
-Failed to download METAR data
-Failed to download METAR data
-Failed to download METAR data
-Failed to download METAR data",Europe/Prague,water,80.0,lwt
-267,https://rowsandall.com/rowers/workout/2505/emailcsv,https://rowsandall.com/rowers/workout/2505/emailtcx,0,0,2018-05-19 11:55:34+00:00,14274,01:12:33.600000,Roos,,America/New_York,water,80.0,lwt
-268,https://rowsandall.com/rowers/workout/2506/emailcsv,https://rowsandall.com/rowers/workout/2506/emailtcx,0,0,2018-05-19 11:55:34+00:00,7384,00:33:59.800000,Roos (1),,America/New_York,water,80.0,lwt
-269,https://rowsandall.com/rowers/workout/2507/emailcsv,https://rowsandall.com/rowers/workout/2507/emailtcx,0,0,2018-05-19 12:29:34+00:00,6885,00:38:32.200000,Roos (2),,America/New_York,water,80.0,lwt
-270,https://rowsandall.com/rowers/workout/2511/emailcsv,https://rowsandall.com/rowers/workout/2511/emailtcx,0,0,2018-05-27 10:17:01+00:00,10663,00:59:29.700000,Test P,,Europe/Prague,water,80.0,lwt
-271,https://rowsandall.com/rowers/workout/2518/emailcsv,https://rowsandall.com/rowers/workout/2518/emailtcx,0,0,2018-05-27 10:17:01+00:00,10663,00:59:29.700000,dubbel,,Europe/Prague,water,80.0,lwt
-272,https://rowsandall.com/rowers/workout/2592/emailcsv,https://rowsandall.com/rowers/workout/2592/emailtcx,0,0,2018-05-27 10:17:01+00:00,10663,00:59:29.600000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-273,https://rowsandall.com/rowers/workout/2591/emailcsv,https://rowsandall.com/rowers/workout/2591/emailtcx,0,0,2018-05-28 15:11:01+00:00,9642,00:56:16.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-274,https://rowsandall.com/rowers/workout/2514/emailcsv,https://rowsandall.com/rowers/workout/2514/emailtcx,0,0,2018-05-30 18:05:25+00:00,11237,01:04:45.500000,Eight,imported through email,Europe/Prague,water,80.0,lwt
-275,https://rowsandall.com/rowers/workout/2516/emailcsv,https://rowsandall.com/rowers/workout/2516/emailtcx,0,0,2018-05-30 18:05:25+00:00,11237,01:04:45.500000,Twee Zonder,imported through email,Europe/Prague,water,80.0,lwt
-276,https://rowsandall.com/rowers/workout/2590/emailcsv,https://rowsandall.com/rowers/workout/2590/emailtcx,0,0,2018-05-30 18:05:25+00:00,11237,01:04:45.500000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-277,https://rowsandall.com/rowers/workout/2512/emailcsv,https://rowsandall.com/rowers/workout/2512/emailtcx,0,0,2018-05-31 16:30:07+00:00,8837,00:47:42.500000,Test,,Europe/Prague,water,80.0,lwt
-278,https://rowsandall.com/rowers/workout/2589/emailcsv,https://rowsandall.com/rowers/workout/2589/emailtcx,0,0,2018-05-31 16:30:07+00:00,8837,00:47:42.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-279,https://rowsandall.com/rowers/workout/2508/emailcsv,https://rowsandall.com/rowers/workout/2508/emailtcx,0,0,2018-06-01 07:57:02+00:00,4605,00:35:11.700000,Piestany,,Europe/Bratislava,water,80.0,lwt
-280,https://rowsandall.com/rowers/workout/2510/emailcsv,https://rowsandall.com/rowers/workout/2510/emailtcx,0,0,2018-06-01 08:02:02+00:00,3975,00:30:08.700000,Piestany (2),,Europe/Bratislava,water,80.0,lwt
-281,https://rowsandall.com/rowers/workout/2509/emailcsv,https://rowsandall.com/rowers/workout/2509/emailtcx,0,0,2018-06-01 11:30:07+00:00,8837,00:47:42.500000,Test,,Europe/Prague,water,80.0,lwt
-282,https://rowsandall.com/rowers/workout/2569/emailcsv,https://rowsandall.com/rowers/workout/2569/emailtcx,0,0,2018-06-01 15:00:00+00:00,11237,01:04:45.500000,Acht Intervals,,Europe/Prague,water,80.0,lwt
-283,https://rowsandall.com/rowers/workout/2588/emailcsv,https://rowsandall.com/rowers/workout/2588/emailtcx,0,0,2018-06-02 17:00:07+00:00,12511,01:07:58,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-284,https://rowsandall.com/rowers/workout/2587/emailcsv,https://rowsandall.com/rowers/workout/2587/emailtcx,0,0,2018-06-03 07:57:02+00:00,10830,01:04:35.900000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-285,https://rowsandall.com/rowers/workout/2586/emailcsv,https://rowsandall.com/rowers/workout/2586/emailtcx,0,0,2018-06-03 15:50:25+00:00,6125,00:48:38.600000,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-286,https://rowsandall.com/rowers/workout/2535/emailcsv,https://rowsandall.com/rowers/workout/2535/emailtcx,0,0,2018-06-05 13:07:02+00:00,0,00:05:01,Test - Delete,,Europe/Prague,rower,80.0,lwt
-287,https://rowsandall.com/rowers/workout/2536/emailcsv,https://rowsandall.com/rowers/workout/2536/emailtcx,0,0,2018-06-05 13:07:02+00:00,0,00:05:01,Test Sync - Delete,"
- from tcx via rowsandall.com",Europe/Prague,rower,80.0,lwt
-288,https://rowsandall.com/rowers/workout/2537/emailcsv,https://rowsandall.com/rowers/workout/2537/emailtcx,0,0,2018-06-05 13:07:02+00:00,0,00:05:01,Test P,"
- from tcx via rowsandall.com",Europe/Prague,rower,80.0,lwt
-289,https://rowsandall.com/rowers/workout/2538/emailcsv,https://rowsandall.com/rowers/workout/2538/emailtcx,0,0,2018-06-05 13:07:02+00:00,0,00:05:01,Test P,imported through email,Europe/Prague,rower,80.0,lwt
-290,https://rowsandall.com/rowers/workout/2539/emailcsv,https://rowsandall.com/rowers/workout/2539/emailtcx,0,0,2018-06-05 13:07:02+00:00,0,00:05:01,Test P,"imported through email
- from tcx via rowsandall.com",Europe/Prague,rower,80.0,lwt
-291,https://rowsandall.com/rowers/workout/2540/emailcsv,https://rowsandall.com/rowers/workout/2540/emailtcx,0,0,2018-06-05 13:07:02+00:00,0,00:05:01,Workout from Background Queue,imported through email,Europe/Prague,rower,80.0,lwt
-292,https://rowsandall.com/rowers/workout/2624/emailcsv,https://rowsandall.com/rowers/workout/2624/emailtcx,0,0,2018-06-05 13:51:01.900000+00:00,12744,01:08:22.100000,imported through ema,imported through email,Europe/Prague,water,80.0,lwt
-293,https://rowsandall.com/rowers/workout/2534/emailcsv,https://rowsandall.com/rowers/workout/2534/emailtcx,0,0,2018-06-05 14:05:02+00:00,0,00:01:33,Import from Polar Flow,imported through email,Europe/Prague,rower,80.0,lwt
-294,https://rowsandall.com/rowers/workout/2519/emailcsv,https://rowsandall.com/rowers/workout/2519/emailtcx,0,0,2018-06-05 14:09:57+00:00,0,00:03:38,TCX from Polar API,,Europe/Prague,water,80.0,lwt
-295,https://rowsandall.com/rowers/workout/2546/emailcsv,https://rowsandall.com/rowers/workout/2546/emailtcx,0,0,2018-06-05 15:51:01+00:00,12744,01:08:22.200000,8x glad,,Europe/Prague,water,80.0,lwt
-296,https://rowsandall.com/rowers/workout/2547/emailcsv,https://rowsandall.com/rowers/workout/2547/emailtcx,0,0,2018-06-05 15:51:01+00:00,12746,01:08:22.200000,1x glad,,Europe/Prague,c-boat,80.0,lwt
-297,https://rowsandall.com/rowers/workout/2548/emailcsv,https://rowsandall.com/rowers/workout/2548/emailtcx,0,68,2018-06-05 15:51:01+00:00,12744,01:08:22.200000,1x glad,,Europe/Prague,water,80.0,lwt
-298,https://rowsandall.com/rowers/workout/2549/emailcsv,https://rowsandall.com/rowers/workout/2549/emailtcx,0,0,2018-06-05 15:51:01+00:00,12746,01:08:22.200000,test,,Europe/Prague,water,80.0,lwt
-299,https://rowsandall.com/rowers/workout/2550/emailcsv,https://rowsandall.com/rowers/workout/2550/emailtcx,0,0,2018-06-05 15:51:01+00:00,12746,01:08:22.200000,test tcx,,Europe/Prague,water,80.0,lwt
-300,https://rowsandall.com/rowers/workout/2552/emailcsv,https://rowsandall.com/rowers/workout/2552/emailtcx,0,0,2018-06-05 15:51:01+00:00,6522,00:33:00,8x glad (1),,Europe/Prague,water,80.0,lwt
-301,https://rowsandall.com/rowers/workout/2585/emailcsv,https://rowsandall.com/rowers/workout/2585/emailtcx,0,0,2018-06-05 15:51:01+00:00,12744,01:08:22.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-302,https://rowsandall.com/rowers/workout/2553/emailcsv,https://rowsandall.com/rowers/workout/2553/emailtcx,0,0,2018-06-05 16:24:01+00:00,6213,00:35:19.500000,8x glad (2),,Europe/Prague,water,80.0,lwt
-303,https://rowsandall.com/rowers/workout/2584/emailcsv,https://rowsandall.com/rowers/workout/2584/emailtcx,0,0,2018-06-06 17:40:24+00:00,5273,00:42:59,Imported workout,imported from Concept2 log,UTC,rower,80.0,lwt
-304,https://rowsandall.com/rowers/workout/2545/emailcsv,https://rowsandall.com/rowers/workout/2545/emailtcx,0,0,2018-06-08 07:25:33+00:00,1994,00:01:59.400000,Test,,Europe/Prague,rower,80.0,hwt
-305,https://rowsandall.com/rowers/workout/2560/emailcsv,https://rowsandall.com/rowers/workout/2560/emailtcx,0,0,2018-06-11 15:21:01+00:00,10369,00:56:21.400000,Intervals Tests (7),imported through email,Europe/Prague,water,80.0,lwt
-306,https://rowsandall.com/rowers/workout/2568/emailcsv,https://rowsandall.com/rowers/workout/2568/emailtcx,0,11,2018-06-11 15:21:01+00:00,10369,00:56:21.400000,3/2/1,"
- 5x5min/5min
- 5x5min/5min",Europe/Prague,water,80.0,lwt
-307,https://rowsandall.com/rowers/workout/2583/emailcsv,https://rowsandall.com/rowers/workout/2583/emailtcx,0,0,2018-06-11 15:21:01+00:00,10369,00:56:21.400000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-308,https://rowsandall.com/rowers/workout/2554/emailcsv,https://rowsandall.com/rowers/workout/2554/emailtcx,0,0,2018-06-13 14:18:19+00:00,16543,01:30:01.300000,Intervals Tests,,America/New_York,rower,80.0,lwt
-309,https://rowsandall.com/rowers/workout/2555/emailcsv,https://rowsandall.com/rowers/workout/2555/emailtcx,0,0,2018-06-13 14:18:35+00:00,12205,01:03:29.500000,Intervals Tests (2),,America/New_York,rower,80.0,lwt
-310,https://rowsandall.com/rowers/workout/2556/emailcsv,https://rowsandall.com/rowers/workout/2556/emailtcx,0,0,2018-06-13 14:18:48+00:00,9016,00:48:28.100000,Intervals Tests (3),"
- 9x1km",America/New_York,rower,80.0,lwt
-311,https://rowsandall.com/rowers/workout/2557/emailcsv,https://rowsandall.com/rowers/workout/2557/emailtcx,0,0,2018-06-13 14:19:01+00:00,4789,00:22:05,Intervals Tests (4),,America/New_York,rower,80.0,lwt
-312,https://rowsandall.com/rowers/workout/2558/emailcsv,https://rowsandall.com/rowers/workout/2558/emailtcx,0,0,2018-06-13 14:19:19+00:00,0,00:22:54,Intervals Tests (5),,Europe/Prague,rower,80.0,lwt
-313,https://rowsandall.com/rowers/workout/2582/emailcsv,https://rowsandall.com/rowers/workout/2582/emailtcx,0,0,2018-06-13 16:11:02+00:00,4191,00:23:36.400000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-314,https://rowsandall.com/rowers/workout/2581/emailcsv,https://rowsandall.com/rowers/workout/2581/emailtcx,0,0,2018-06-15 08:05:04+00:00,7301,00:39:44.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-315,https://rowsandall.com/rowers/workout/2580/emailcsv,https://rowsandall.com/rowers/workout/2580/emailtcx,0,0,2018-06-16 08:04:00+00:00,5182,00:40:48.100000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-316,https://rowsandall.com/rowers/workout/2579/emailcsv,https://rowsandall.com/rowers/workout/2579/emailtcx,0,0,2018-06-16 13:17:06+00:00,8196,00:52:10.500000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-317,https://rowsandall.com/rowers/workout/2950/emailcsv,https://rowsandall.com/rowers/workout/2950/emailtcx,0,0,2018-06-17 10:23:24+00:00,6004,01:00:54,Lunch Run,,Europe/Vienna,water,80.0,hwt
-318,https://rowsandall.com/rowers/workout/2954/emailcsv,https://rowsandall.com/rowers/workout/2954/emailtcx,0,0,2018-06-17 10:23:24+00:00,6004,01:00:54,Lunch Run,,Europe/Vienna,water,80.0,hwt
-319,https://rowsandall.com/rowers/workout/3035/emailcsv,https://rowsandall.com/rowers/workout/3035/emailtcx,0,17,2018-06-17 10:23:24+00:00,6004,01:00:54,Lunch Run, ,Europe/Vienna,other,80.0,hwt
-320,https://rowsandall.com/rowers/workout/2578/emailcsv,https://rowsandall.com/rowers/workout/2578/emailtcx,0,0,2018-06-18 16:05:05+00:00,10313,00:55:54.900000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-321,https://rowsandall.com/rowers/workout/2948/emailcsv,https://rowsandall.com/rowers/workout/2948/emailtcx,0,0,2018-06-18 16:05:05+00:00,10313,00:55:54,Steady,,Europe/Prague,water,80.0,hwt
-322,https://rowsandall.com/rowers/workout/2952/emailcsv,https://rowsandall.com/rowers/workout/2952/emailtcx,0,0,2018-06-18 16:05:05+00:00,10313,00:55:54,Steady,,Europe/Prague,water,80.0,hwt
-323,https://rowsandall.com/rowers/workout/2573/emailcsv,https://rowsandall.com/rowers/workout/2573/emailtcx,0,0,2018-06-19 05:57:02+00:00,10437,00:56:06.900000,Pink,,Europe/Prague,water,80.0,lwt
-324,https://rowsandall.com/rowers/workout/2577/emailcsv,https://rowsandall.com/rowers/workout/2577/emailtcx,0,0,2018-06-19 05:57:02+00:00,10437,00:56:06.900000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-325,https://rowsandall.com/rowers/workout/2946/emailcsv,https://rowsandall.com/rowers/workout/2946/emailtcx,0,0,2018-06-19 05:57:04+00:00,10437,00:56:04,3x6min,,Europe/Prague,water,80.0,hwt
-326,https://rowsandall.com/rowers/workout/2570/emailcsv,https://rowsandall.com/rowers/workout/2570/emailtcx,0,0,2018-06-19 15:11:14.220000+00:00,7538,00:56:14.600000,Test,,Europe/Vienna,water,80.0,lwt
-327,https://rowsandall.com/rowers/workout/2571/emailcsv,https://rowsandall.com/rowers/workout/2571/emailtcx,0,0,2018-06-20 18:24:08+00:00,7538,00:56:14.500000,Ritmo,,Europe/Vienna,water,80.0,lwt
-328,https://rowsandall.com/rowers/workout/2858/emailcsv,https://rowsandall.com/rowers/workout/2858/emailtcx,0,0,2018-06-22 04:33:02.500000+00:00,3344,00:16:55.700000,imported through ema,imported through email,Europe/Prague,water,80.0,hwt
-329,https://rowsandall.com/rowers/workout/2576/emailcsv,https://rowsandall.com/rowers/workout/2576/emailtcx,0,0,2018-06-22 05:41:04+00:00,9298,00:50:44,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-330,https://rowsandall.com/rowers/workout/2944/emailcsv,https://rowsandall.com/rowers/workout/2944/emailtcx,0,0,2018-06-22 05:41:04+00:00,9298,00:50:44,Steady,,Europe/Prague,water,80.0,hwt
-331,https://rowsandall.com/rowers/workout/2575/emailcsv,https://rowsandall.com/rowers/workout/2575/emailtcx,0,0,2018-06-22 06:33:01+00:00,3344,00:16:55.700000,Imported workout,imported from Concept2 log,UTC,water,80.0,lwt
-332,https://rowsandall.com/rowers/workout/2942/emailcsv,https://rowsandall.com/rowers/workout/2942/emailtcx,27,11,2018-06-22 06:33:02+00:00,3344,00:16:54,Steady (2),,Europe/Prague,water,80.0,hwt
-333,https://rowsandall.com/rowers/workout/2940/emailcsv,https://rowsandall.com/rowers/workout/2940/emailtcx,0,0,2018-06-22 10:45:04+00:00,7540,00:56:14,test delete,,Europe/Vienna,water,80.0,hwt
-334,https://rowsandall.com/rowers/workout/2725/emailcsv,https://rowsandall.com/rowers/workout/2725/emailtcx,0,0,2018-06-22 12:17:56+00:00,15642,01:15:00,Mike,"
- 3x20min/5min",Europe/Prague,water,80.0,lwt
-335,https://rowsandall.com/rowers/workout/2726/emailcsv,https://rowsandall.com/rowers/workout/2726/emailtcx,0,0,2018-06-22 12:17:56+00:00,15642,01:15:00,Mike test,,Europe/Prague,water,80.0,lwt
-336,https://rowsandall.com/rowers/workout/2848/emailcsv,https://rowsandall.com/rowers/workout/2848/emailtcx,0,0,2018-06-24 05:34:07+00:00,10194,00:57:48.900000,Imported,,Europe/Prague,water,80.0,lwt
-337,https://rowsandall.com/rowers/workout/2849/emailcsv,https://rowsandall.com/rowers/workout/2849/emailtcx,0,0,2018-06-24 05:34:07.200000+00:00,10194,00:57:48.900000,Imported,,Europe/Prague,water,80.0,lwt
-338,https://rowsandall.com/rowers/workout/2957/emailcsv,https://rowsandall.com/rowers/workout/2957/emailtcx,0,0,2018-06-24 05:34:07.200000+00:00,10194,00:57:48.900000,Imported,,Europe/Prague,water,80.0,hwt
-339,https://rowsandall.com/rowers/workout/2938/emailcsv,https://rowsandall.com/rowers/workout/2938/emailtcx,0,0,2018-06-24 07:34:07+00:00,10194,00:57:43,Double,,Europe/Prague,water,80.0,hwt
-340,https://rowsandall.com/rowers/workout/3059/emailcsv,https://rowsandall.com/rowers/workout/3059/emailtcx,0,0,2018-06-26 15:06:01+00:00,10393,01:00:55.900000,C2 Import Workout from 2018-06-26 15:06:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-341,https://rowsandall.com/rowers/workout/2936/emailcsv,https://rowsandall.com/rowers/workout/2936/emailtcx,42,30,2018-06-26 15:06:04+00:00,5651,00:31:24,Sprintervals,,Europe/Prague,water,80.0,hwt
-342,https://rowsandall.com/rowers/workout/2934/emailcsv,https://rowsandall.com/rowers/workout/2934/emailtcx,0,0,2018-06-26 15:38:08+00:00,1056,00:05:12,Sprintervals (2),,Europe/Brussels,water,80.0,hwt
-343,https://rowsandall.com/rowers/workout/2932/emailcsv,https://rowsandall.com/rowers/workout/2932/emailtcx,0,0,2018-06-26 15:44:06+00:00,3684,00:22:50,Sprintervals (3),,Europe/Prague,water,80.0,hwt
-344,https://rowsandall.com/rowers/workout/2959/emailcsv,https://rowsandall.com/rowers/workout/2959/emailtcx,160,38,2018-06-30 05:31:02.200000+00:00,13878,01:21:16.600000,,"
- from speedcoach2v2.15 via rowsandall.com",Europe/Prague,water,80.0,hwt
-345,https://rowsandall.com/rowers/workout/2958/emailcsv,https://rowsandall.com/rowers/workout/2958/emailtcx,0,0,2018-06-30 07:31:01+00:00,13878,01:21:16.600000,C2 Import Workout from 2018-06-30 07:31:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-346,https://rowsandall.com/rowers/workout/3030/emailcsv,https://rowsandall.com/rowers/workout/3030/emailtcx,80,6031,2018-07-01 11:57:30+00:00,12879,00:57:00,Ride to pub, ,Europe/Prague,other,80.0,hwt
-347,https://rowsandall.com/rowers/workout/3031/emailcsv,https://rowsandall.com/rowers/workout/3031/emailtcx,0,0,2018-07-02 16:21:01+00:00,12532,01:09:16.500000,Test P,,Europe/Prague,water,80.0,hwt
-348,https://rowsandall.com/rowers/workout/3058/emailcsv,https://rowsandall.com/rowers/workout/3058/emailtcx,0,0,2018-07-02 16:21:01+00:00,2858,00:15:40.600000,C2 Import Workout from 2018-07-02 16:21:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-349,https://rowsandall.com/rowers/workout/3063/emailcsv,https://rowsandall.com/rowers/workout/3063/emailtcx,120,79,2018-07-02 16:21:01+00:00,12532,01:09:16.500000,Test Strava Export,,Europe/Prague,water,80.0,hwt
-350,https://rowsandall.com/rowers/workout/3064/emailcsv,https://rowsandall.com/rowers/workout/3064/emailtcx,120,79,2018-07-02 16:21:01+00:00,12532,01:09:16.500000,Test Strava Export,,Europe/Prague,water,80.0,hwt
-351,https://rowsandall.com/rowers/workout/3065/emailcsv,https://rowsandall.com/rowers/workout/3065/emailtcx,0,0,2018-07-02 16:21:01+00:00,12532,01:09:16.500000,Test Strava Export,,Europe/Prague,water,80.0,hwt
-352,https://rowsandall.com/rowers/workout/3066/emailcsv,https://rowsandall.com/rowers/workout/3066/emailtcx,120,79,2018-07-02 16:21:01+00:00,12532,01:09:16.500000,Test Strava Export,,Europe/Prague,water,80.0,hwt
-353,https://rowsandall.com/rowers/workout/3068/emailcsv,https://rowsandall.com/rowers/workout/3068/emailtcx,0,0,2018-07-02 16:21:01+00:00,12532,01:09:16.500000,Should be exported To Strava,,Europe/Prague,water,80.0,hwt
-354,https://rowsandall.com/rowers/workout/3070/emailcsv,https://rowsandall.com/rowers/workout/3070/emailtcx,120,79,2018-07-02 16:21:01+00:00,12532,01:09:16.500000,Should Not Be Exported To Strava,,Europe/Prague,water,80.0,hwt
-355,https://rowsandall.com/rowers/workout/3057/emailcsv,https://rowsandall.com/rowers/workout/3057/emailtcx,0,0,2018-07-02 16:40:02+00:00,2001,00:08:29,C2 Import Workout from 2018-07-02 16:40:02+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-356,https://rowsandall.com/rowers/workout/3056/emailcsv,https://rowsandall.com/rowers/workout/3056/emailtcx,0,0,2018-07-02 16:50:02+00:00,2136,00:09:16.200000,C2 Import Workout from 2018-07-02 16:50:02+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-357,https://rowsandall.com/rowers/workout/3055/emailcsv,https://rowsandall.com/rowers/workout/3055/emailtcx,0,0,2018-07-02 17:01:02+00:00,2058,00:08:38.800000,C2 Import Workout from 2018-07-02 17:01:02+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-358,https://rowsandall.com/rowers/workout/3008/emailcsv,https://rowsandall.com/rowers/workout/3008/emailtcx,22,0,2018-07-02 17:01:05+00:00,2058,00:08:35,2ks with focus (4),,Europe/Prague,water,80.0,hwt
-359,https://rowsandall.com/rowers/workout/3028/emailcsv,https://rowsandall.com/rowers/workout/3028/emailtcx,22,0,2018-07-02 17:01:05+00:00,2058,00:08:35,2ks with focus (4),,Europe/Prague,water,80.0,hwt
-360,https://rowsandall.com/rowers/workout/3054/emailcsv,https://rowsandall.com/rowers/workout/3054/emailtcx,0,0,2018-07-02 17:11:02+00:00,2149,00:09:47.300000,C2 Import Workout from 2018-07-02 17:11:02+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-361,https://rowsandall.com/rowers/workout/3006/emailcsv,https://rowsandall.com/rowers/workout/3006/emailtcx,27,0,2018-07-02 17:11:05+00:00,2149,00:09:44,2ks with focus (5),,Europe/Prague,water,80.0,hwt
-362,https://rowsandall.com/rowers/workout/3026/emailcsv,https://rowsandall.com/rowers/workout/3026/emailtcx,27,0,2018-07-02 17:11:05+00:00,2149,00:09:44,2ks with focus (5),,Europe/Prague,water,80.0,hwt
-363,https://rowsandall.com/rowers/workout/3053/emailcsv,https://rowsandall.com/rowers/workout/3053/emailtcx,0,0,2018-07-02 17:24:02+00:00,1328,00:06:15.500000,C2 Import Workout from 2018-07-02 17:24:02+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-364,https://rowsandall.com/rowers/workout/3004/emailcsv,https://rowsandall.com/rowers/workout/3004/emailtcx,10,0,2018-07-02 17:24:05+00:00,1328,00:06:12,2ks with focus (6),,Europe/Prague,water,80.0,hwt
-365,https://rowsandall.com/rowers/workout/3024/emailcsv,https://rowsandall.com/rowers/workout/3024/emailtcx,10,0,2018-07-02 17:24:05+00:00,1328,00:06:12,2ks with focus (6),,Europe/Prague,water,80.0,hwt
-366,https://rowsandall.com/rowers/workout/2964/emailcsv,https://rowsandall.com/rowers/workout/2964/emailtcx,0,0,2018-07-04 15:06:42+00:00,7350,00:31:07,Test,,Europe/Prague,rower,80.0,hwt
-367,https://rowsandall.com/rowers/workout/2965/emailcsv,https://rowsandall.com/rowers/workout/2965/emailtcx,0,103,2018-07-04 16:19:01+00:00,10471,01:00:27.200000,Test TRIMP,,Europe/Prague,water,80.0,hwt
-368,https://rowsandall.com/rowers/workout/2966/emailcsv,https://rowsandall.com/rowers/workout/2966/emailtcx,0,98,2018-07-04 16:19:01+00:00,10471,01:00:27.200000,Test Rscore,,Europe/Prague,water,80.0,hwt
-369,https://rowsandall.com/rowers/workout/3052/emailcsv,https://rowsandall.com/rowers/workout/3052/emailtcx,0,0,2018-07-04 16:19:01+00:00,10471,01:00:27.100000,C2 Import Workout from 2018-07-04 16:19:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-370,https://rowsandall.com/rowers/workout/2967/emailcsv,https://rowsandall.com/rowers/workout/2967/emailtcx,0,96,2018-07-04 16:19:02+00:00,10471,01:00:26,Startjes,"
- from csv via rowsandall.com",Europe/Prague,water,80.0,hwt
-371,https://rowsandall.com/rowers/workout/3002/emailcsv,https://rowsandall.com/rowers/workout/3002/emailtcx,0,98,2018-07-04 16:19:02+00:00,10471,01:00:26,Startjes,,Europe/Prague,water,80.0,hwt
-372,https://rowsandall.com/rowers/workout/3022/emailcsv,https://rowsandall.com/rowers/workout/3022/emailtcx,0,98,2018-07-04 16:19:02+00:00,10471,01:00:26,Startjes,,Europe/Prague,water,80.0,hwt
-373,https://rowsandall.com/rowers/workout/3051/emailcsv,https://rowsandall.com/rowers/workout/3051/emailtcx,0,0,2018-07-07 07:43:02+00:00,2874,00:16:39.700000,C2 Import Workout from 2018-07-07 07:43:02+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-374,https://rowsandall.com/rowers/workout/3000/emailcsv,https://rowsandall.com/rowers/workout/3000/emailtcx,17,0,2018-07-07 07:43:03+00:00,2874,00:16:38,2x race prep,,Europe/Prague,water,80.0,hwt
-375,https://rowsandall.com/rowers/workout/3020/emailcsv,https://rowsandall.com/rowers/workout/3020/emailtcx,17,0,2018-07-07 07:43:03+00:00,2874,00:16:38,2x race prep,,Europe/Prague,water,80.0,hwt
-376,https://rowsandall.com/rowers/workout/3050/emailcsv,https://rowsandall.com/rowers/workout/3050/emailtcx,0,0,2018-07-07 08:01:01+00:00,743,00:02:45.500000,C2 Import Workout from 2018-07-07 08:01:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-377,https://rowsandall.com/rowers/workout/2998/emailcsv,https://rowsandall.com/rowers/workout/2998/emailtcx,2,0,2018-07-07 08:01:02+00:00,743,00:02:44,2x race prep (2),,Europe/Prague,bike,80.0,hwt
-378,https://rowsandall.com/rowers/workout/3018/emailcsv,https://rowsandall.com/rowers/workout/3018/emailtcx,2,0,2018-07-07 08:01:02+00:00,743,00:02:44,2x race prep (2),,Europe/Prague,water,80.0,hwt
-379,https://rowsandall.com/rowers/workout/3049/emailcsv,https://rowsandall.com/rowers/workout/3049/emailtcx,0,0,2018-07-07 08:05:03+00:00,2827,00:15:21.800000,C2 Import Workout from 2018-07-07 08:05:03+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-380,https://rowsandall.com/rowers/workout/2996/emailcsv,https://rowsandall.com/rowers/workout/2996/emailtcx,21,0,2018-07-07 08:05:06+00:00,2827,00:15:18,2x race prep (3),,Europe/Prague,water,80.0,hwt
-381,https://rowsandall.com/rowers/workout/3016/emailcsv,https://rowsandall.com/rowers/workout/3016/emailtcx,21,0,2018-07-07 08:05:06+00:00,2827,00:15:18,2x race prep (3),,Europe/Prague,water,80.0,hwt
-382,https://rowsandall.com/rowers/workout/3048/emailcsv,https://rowsandall.com/rowers/workout/3048/emailtcx,0,0,2018-07-07 08:22:01+00:00,749,00:03:12.500000,C2 Import Workout from 2018-07-07 08:22:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-383,https://rowsandall.com/rowers/workout/2994/emailcsv,https://rowsandall.com/rowers/workout/2994/emailtcx,4,0,2018-07-07 08:22:02+00:00,749,00:03:11,2x race prep (4),,Europe/Prague,water,80.0,hwt
-384,https://rowsandall.com/rowers/workout/3014/emailcsv,https://rowsandall.com/rowers/workout/3014/emailtcx,4,0,2018-07-07 08:22:02+00:00,749,00:03:11,2x race prep (4),,Europe/Prague,water,80.0,hwt
-385,https://rowsandall.com/rowers/workout/3047/emailcsv,https://rowsandall.com/rowers/workout/3047/emailtcx,0,0,2018-07-07 08:27:03+00:00,2058,00:11:55.800000,C2 Import Workout from 2018-07-07 08:27:03+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-386,https://rowsandall.com/rowers/workout/2992/emailcsv,https://rowsandall.com/rowers/workout/2992/emailtcx,13,14,2018-07-07 08:27:06+00:00,2058,00:11:52,2x race prep (5),,Europe/Prague,water,75.0,hwt
-387,https://rowsandall.com/rowers/workout/3012/emailcsv,https://rowsandall.com/rowers/workout/3012/emailtcx,13,15,2018-07-07 08:27:06+00:00,2058,00:11:52,2x race prep (5),,Europe/Prague,water,80.0,hwt
-388,https://rowsandall.com/rowers/workout/2969/emailcsv,https://rowsandall.com/rowers/workout/2969/emailtcx,100,116,2018-07-08 13:17:02+00:00,10372,01:00:18.100000,HRTSS,,Europe/Prague,water,80.0,hwt
-389,https://rowsandall.com/rowers/workout/3046/emailcsv,https://rowsandall.com/rowers/workout/3046/emailtcx,0,0,2018-07-08 13:17:02+00:00,10372,01:00:18,C2 Import Workout from 2018-07-08 13:17:02+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-390,https://rowsandall.com/rowers/workout/3034/emailcsv,https://rowsandall.com/rowers/workout/3034/emailtcx,0,0,2018-07-08 13:17:08+00:00,10372,01:00:12,Tempovky,,Europe/Prague,water,80.0,hwt
-391,https://rowsandall.com/rowers/workout/3045/emailcsv,https://rowsandall.com/rowers/workout/3045/emailtcx,0,0,2018-07-13 13:08:00+00:00,2481,00:13:41,C2 Import Workout from 2018-07-13 13:08:00+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-392,https://rowsandall.com/rowers/workout/3044/emailcsv,https://rowsandall.com/rowers/workout/3044/emailtcx,0,0,2018-07-13 13:23:01+00:00,4085,00:22:09.200000,C2 Import Workout from 2018-07-13 13:23:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-393,https://rowsandall.com/rowers/workout/3043/emailcsv,https://rowsandall.com/rowers/workout/3043/emailtcx,0,0,2018-07-14 08:59:02+00:00,7051,00:50:00.500000,C2 Import Workout from 2018-07-14 08:59:02+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-394,https://rowsandall.com/rowers/workout/3042/emailcsv,https://rowsandall.com/rowers/workout/3042/emailtcx,0,0,2018-07-14 13:33:00+00:00,4471,00:51:42.100000,C2 Import Workout from 2018-07-14 13:33:00+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-395,https://rowsandall.com/rowers/workout/3041/emailcsv,https://rowsandall.com/rowers/workout/3041/emailtcx,0,0,2018-07-14 15:48:01+00:00,4486,00:56:58.100000,C2 Import Workout from 2018-07-14 15:48:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-396,https://rowsandall.com/rowers/workout/3040/emailcsv,https://rowsandall.com/rowers/workout/3040/emailtcx,0,0,2018-07-15 06:10:01+00:00,4233,00:29:17,C2 Import Workout from 2018-07-15 06:10:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-397,https://rowsandall.com/rowers/workout/3039/emailcsv,https://rowsandall.com/rowers/workout/3039/emailtcx,0,0,2018-07-15 09:01:01+00:00,4978,00:41:45,C2 Import Workout from 2018-07-15 09:01:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-398,https://rowsandall.com/rowers/workout/3038/emailcsv,https://rowsandall.com/rowers/workout/3038/emailtcx,0,0,2018-07-18 05:00:01+00:00,11159,00:59:58,C2 Import Workout from 2018-07-18 05:00:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-399,https://rowsandall.com/rowers/workout/3037/emailcsv,https://rowsandall.com/rowers/workout/3037/emailtcx,0,0,2018-07-20 09:29:01+00:00,8436,00:45:44.500000,C2 Import Workout from 2018-07-20 09:29:01+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-400,https://rowsandall.com/rowers/workout/3036/emailcsv,https://rowsandall.com/rowers/workout/3036/emailtcx,0,0,2018-07-21 05:13:03+00:00,9639,00:54:19.500000,C2 Import Workout from 2018-07-21 05:13:03+00:00,imported from Concept2 log,UTC,water,80.0,lwt
-401,https://rowsandall.com/rowers/workout/3061/emailcsv,https://rowsandall.com/rowers/workout/3061/emailtcx,77,43,2018-08-17 05:16:03+00:00,8315,00:45:11.400000,Brnenske 2k,,Europe/Prague,water,80.0,hwt
-402,https://rowsandall.com/rowers/workout/3075/emailcsv,https://rowsandall.com/rowers/workout/3075/emailtcx,83,28,2018-08-18 07:54:04+00:00,9590,00:55:08,Technique 2x, ,Europe/Prague,water,80.0,hwt
-403,https://rowsandall.com/rowers/workout/3074/emailcsv,https://rowsandall.com/rowers/workout/3074/emailtcx,94,17,2018-08-26 22:00:01.500000+00:00,9903,00:54:36,Imported,,Europe/Prague,bike,80.0,hwt
-404,https://rowsandall.com/rowers/workout/3076/emailcsv,https://rowsandall.com/rowers/workout/3076/emailtcx,94,1104,2018-08-26 22:00:01.500000+00:00,9903,00:54:36,Imported,,Europe/Prague,bike,80.0,hwt
-405,https://rowsandall.com/rowers/workout/3072/emailcsv,https://rowsandall.com/rowers/workout/3072/emailtcx,0,0,2018-08-27 14:36:47+00:00,5855,00:14:58.700000,Bike Erg,,Europe/Prague,bikeerg,80.0,hwt
-406,https://rowsandall.com/rowers/workout/3073/emailcsv,https://rowsandall.com/rowers/workout/3073/emailtcx,15,4,2018-08-27 14:36:47+00:00,5855,00:14:58.700000,Bike Erg,,Europe/Prague,bike,80.0,hwt
-407,https://rowsandall.com/rowers/workout/3077/emailcsv,https://rowsandall.com/rowers/workout/3077/emailtcx,0,51,2018-09-11 05:31:02+00:00,7490,00:35:07.500000,7.5k,,Europe/Prague,water,80.0,hwt
-408,https://rowsandall.com/rowers/workout/3080/emailcsv,https://rowsandall.com/rowers/workout/3080/emailtcx,0,0,2018-09-12 04:17:04+00:00,5921,00:34:50,Sofia part II, ,Europe/Sofia,other,80.0,hwt
-409,https://rowsandall.com/rowers/workout/3079/emailcsv,https://rowsandall.com/rowers/workout/3079/emailtcx,87,60,2018-09-13 12:15:58+00:00,23476,00:59:59.700000,Mike 2,,Europe/Prague,rower,80.0,hwt
-410,https://rowsandall.com/rowers/workout/3078/emailcsv,https://rowsandall.com/rowers/workout/3078/emailtcx,94,59,2018-09-14 13:02:04+00:00,24267,00:59:57.200000,Mike,,Europe/Prague,rower,80.0,hwt
diff --git a/static/js/videogauges.js b/static/js/videogauges.js
index f6c068e4..42ac8ff9 100644
--- a/static/js/videogauges.js
+++ b/static/js/videogauges.js
@@ -1,60 +1,209 @@
-// var opts = {
-// lines: 12,
-// angle: 0.15,
-// lineWidth: 0.44,
-// pointer: {
-// length: 0.9,
-// strokeWidth: 0.035,
-// color: '#000000'
-// },
-// limitMax: 'false',
-// // percentColors: [[0.0, "#a9d70b" ], [0.50, "#a9d70b"], [1.0, "#a9d70b"]], // !!!!
-// strokeColor: '#E0E0E0',
-// generateGradient: true
-// };
-// var target = document.getElementById('angles');
-// var gauge = new Gauge(target).setOptions(opts);
-// gauge.maxValue = 90;
-// gauge.minValue = -90;
-// gauge.animationSpeed = 5;
-// gauge.set(-75);
+google.charts.load('current', {'packages':['gauge','corechart']});
+google.charts.setOnLoadCallback(drawSPMChart);
+google.charts.setOnLoadCallback(drawSpeedChart);
+google.charts.setOnLoadCallback(drawPowerChart);
+google.charts.setOnLoadCallback(drawHRChart);
+google.charts.setOnLoadCallback(drawStrokeAngleChart);
-// https://github.com/bernii/gauge.js/issues/193
+var spmdata = [
+ ['Label', 'Value'],
+ ['SPM', 21],
+];
+var speeddata = [
+ ['Label', 'Value'],
+ ['V m/s', 0],
+];
-var opts = {
- angle: 0, // The span of the gauge arc
- lineWidth: 0.2, // The line thickness
- radiusScale: 0.89, // Relative radius
- pointer: {
- length: 0.54, // // Relative to gauge radius
- strokeWidth: 0.053, // The thickness
- color: '#000000' // Fill color
- },
- limitMax: false, // If false, max value increases automatically if value > maxValue
- limitMin: false, // If true, the min value of the gauge will be fixed
- colorStart: '#6FADCF', // Colors
- colorStop: '#8FC0DA', // just experiment with them
- strokeColor: '#E0E0E0', // to see which ones work best for you
- generateGradient: true,
- highDpiSupport: true, // High resolution support
- staticZones: [
- {strokeStyle: "#00FF00", min: 0, max: 2}, // Greem
- {strokeStyle: "#0000FF", min: 2, max: 3}, // Blue`
- {strokeStyle: "#00FFFF", min: 3, max: 4}, // Cyan
- {strokeStyle: "#FFDD00", min: 4, max: 5}, // Orange
- {strokeStyle: "#FF0000", min: 5, max: 6} // Red
- ],
+var powerdata = [
+ ['Label','Value'],
+ ['PWR',150],
+]
- };
- var target = document.getElementById('basic'); // your canvas element
- var gaugeboatspeed = new Gauge(target).setOptions(opts); // create sexy gauge!
- gaugeboatspeed.maxValue = 6; // set max gauge value
- gaugeboatspeed.setMinValue(0); // Prefer setter over gauge.minValue = 0
- gaugeboatspeed.animationSpeed = 10; // set animation speed (32 is default value)
- gaugeboatspeed.set(0); // set actual value
+var hrdata = [
+ ['Label','Value'],
+ ['HR',110],
+]
-// Define set_basic(values) so that gauges can be set by metricsgroups
- function set_basic() {
- gaugeboatspeed.set(boatspeed_now);
+var angledata = [
+ ['Angle', 'deg'],
+ ['slip', 10 ],
+ ['load', 50],
+ ['unload', 50],
+ ['wash', 10],
+ ['recovery',240 ]
+]
+
+var anglesoptions = {
+ title: 'Stroke Angles',
+ legend: 'none',
+ pieHole: 0.5,
+ chartArea: { width: "100%" },
+ pieStartAngle: 35,
+ pieSliceText: 'value',
+ pieSliceTextStyle: {color:'black',fontSize:12},
+ slices: {
+ 0: { color: 'lightblue' },
+ 1: { color: 'lightgreen' },
+ 2: { color: 'yellow'},
+ 3: { color: 'orange'},
+ 4: { color: 'transparent', textStyle: {color:'transparent'}}
}
+};
+
+
+var hroptions = {
+ min: 100, max: 200,
+ width: 400, height: 120,
+ greenFrom: 100, greenTo: 135,
+ yellowFrom: 135,yellowTo: 157,
+ redFrom: 157, redTo: 200,
+ minorTicks: 5
+};
+
+
+var spmoptions = {
+ min:0, max: 50,
+ width: 400, height: 120,
+ greenFrom: 20, greenTo: 30,
+ yellowFrom: 30,yellowTo: 40,
+ redFrom: 40, redTo: 50,
+ majorTicks: ['0','10','20','30','40','50'],
+ minorTicks: 10
+};
+
+var speedoptions = {
+ min:0, max: 6,
+ width: 400, height: 120,
+ greenFrom: 2, greenTo: 4,
+ yellowFrom: 4,yellowTo: 5,
+ redFrom: 5, redTo: 6,
+ majorTicks: ['0','1','2','3','4','5','6'],
+ minorTicks: 10
+};
+
+var poweroptions = {
+ min: 0, max: 1000,
+ width: 400, height: 120,
+ greenFrom: 100, greenTo: 200,
+ yellowFrom: 200,yellowTo: 400,
+ redFrom: 400, redTo: 1000,
+ majorTicks: ['0','200','400','600','800','1000'],
+ minorTicks: 5
+};
+
+
+var dataspm = null;
+var dataspeed = null;
+var spmchart = null;
+var speedchart = null;
+var powerchart = null;
+var datapower = null;
+var dataangles = null;
+
+// SPM chart
+function drawSPMChart() {
+ console.log('first draw SPM chart');
+ dataspm = new google.visualization.arrayToDataTable(spmdata);
+
+
+ try {
+ spmchart = new google.visualization.Gauge(document.getElementById('basic_spm'));
+ spmchart.draw(dataspm,spmoptions);
+} catch(err) {
+
+}
+ // spmchart.draw(data, spmoptions);
+
+ // Define set_basic(values) so that gauges can be set by metricsgroups
+
+};
+
+// Speed Chart
+function drawSpeedChart() {
+ dataspeed = new google.visualization.arrayToDataTable(speeddata);
+
+ try {
+ speedchart = new google.visualization.Gauge(document.getElementById('basic_boatspeed'));
+ speedchart.draw(dataspeed,speedoptions);
+} catch(err) {
+
+}
+}
+
+// Power chart
+function drawPowerChart() {
+ datapower = new google.visualization.arrayToDataTable(powerdata);
+ try {
+ powerchart = new google.visualization.Gauge(document.getElementById('forcepower_power'));
+ powerchart.draw(datapower,poweroptions)
+} catch(err) {
+
+}
+
+}
+
+// HR chart
+function drawHRChart() {
+ datahr = new google.visualization.arrayToDataTable(hrdata);
+ try {
+ hrchart = new google.visualization.Gauge(document.getElementById('athlete_hr'));
+ hrchart.draw(datahr,hroptions);
+ } catch(err) {
+ console.log('no hr div');
+ }
+
+}
+
+// Stroke angle chart
+function drawStrokeAngleChart() {
+ dataangles = new google.visualization.arrayToDataTable(angledata);
+ try {
+ angleschart = new google.visualization.PieChart(document.getElementById('stroke_angles'));
+ angleschart.draw(dataangles,anglesoptions);
+ } catch(err) {
+ console.log('no angles div');
+ }
+
+}
+
+function set_basic() {
+ dataspm.setCell(0,1,spm_now);
+ spmchart.draw(dataspm, spmoptions);
+
+ dataspeed.setCell(0,1,boatspeed_now);
+ speedchart.draw(dataspeed,speedoptions);
+}
+
+function set_athlete() {
+ datahr.setCell(0,1,hr_now);
+ try {
+ hrchart.draw(datahr,hroptions);
+ } catch(err) {}
+}
+
+function set_stroke() {
+ var piestartangle = 90+catch_now;
+ var load = Math.max(-catch_now-slip_now+peakforceangle_now);
+ var unload = Math.max(finish_now-wash_now-peakforceangle_now) ;
+ var recovery = Math.max(360+catch_now-finish_now);
+ // console.log('load ',load,'; unload ',unload,'; recovery ',recovery,'; pie start angle ',piestartangle);
+ dataangles.setCell(0,1,slip_now);
+ dataangles.setCell(1,1,load);
+ dataangles.setCell(2,1,unload);
+ dataangles.setCell(3,1,wash_now);
+ dataangles.setCell(4,1,recovery);
+ anglesoptions.pieStartAngle = piestartangle;
+ try {
+ angleschart.draw(dataangles,anglesoptions);
+ } catch(err) {
+ console.log('failed: ',err);
+ }
+}
+
+function set_forcepower() {
+ datapower.setCell(0,1,power_now);
+ try {
+ powerchart.draw(datapower,poweroptions);
+} catch(err) {}
+}
diff --git a/survey/__init__.py b/survey/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/survey/admin.py b/survey/admin.py
new file mode 100644
index 00000000..29051dbc
--- /dev/null
+++ b/survey/admin.py
@@ -0,0 +1,21 @@
+from .models import Response
+from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin
+
+class ResponseInline(admin.StackedInline):
+ model = Response
+ fieldsets = (
+ ('User Details',{'fields':('plan','username','email')}),
+ ('Used Features',
+ {'fields:':
+ ('logging','technical',
+ 'trend','planning','racing','coaching','export','video','interval')}),
+ ('Paid Plan Questions',
+ {'fields':('capabilities','fallshort','considered','features')})
+ )
+
+class ResponseAdmin(admin.ModelAdmin):
+ #inlines = (ResponseInline,)
+ list_display = ('plan','id','date','capabilities')
+
+admin.site.register(Response,ResponseAdmin)
diff --git a/survey/apps.py b/survey/apps.py
new file mode 100644
index 00000000..58263d6c
--- /dev/null
+++ b/survey/apps.py
@@ -0,0 +1,4 @@
+from django.apps import AppConfig
+
+class SurveyConfig(AppConfig):
+ name = 'app'
diff --git a/survey/models.py b/survey/models.py
new file mode 100644
index 00000000..00284a9c
--- /dev/null
+++ b/survey/models.py
@@ -0,0 +1,125 @@
+from django.contrib.auth.models import User
+from django import forms
+from django.forms import ModelForm
+
+from django.conf import settings
+from django.db import models
+from django.utils import timezone
+
+from rowers.database import *
+import datetime
+
+def current_day():
+ return (datetime.datetime.now(tz=timezone.utc)).date()
+
+class Response(models.Model):
+ planchoices = (
+ ('basic','Free Athlete'),
+ ('freecoach','Free Coach'),
+ ('pro','Pro'),
+ ('plan','Self-Coach'),
+ ('coach','coach'),
+ )
+ plan = models.CharField(max_length=150,choices=planchoices,default='basic')
+ username = models.CharField(max_length=150,unique=True,verbose_name='User Name',blank=True,null=True)
+ email = models.EmailField(max_length=150,verbose_name='User Email',blank=True,null=True)
+ date = models.DateField(default=current_day,verbose_name='survey date')
+ nrworkouts = models.IntegerField(default=0,verbose_name='nr of workouts per week')
+ nrworkoutsR = models.IntegerField(default=0,verbose_name='nr of workouts per week on Rowsandall')
+
+ hearchoices = (
+ ('wordofmouth','Word of mouth'),
+ ('socialmedia','Social Media (Facebook, Twitter)'),
+ ('otherinternet','Other internet'),
+ ('coach','From my Coach/Coachee'),
+ ('other','Other')
+ )
+
+ heard = models.CharField(max_length=150,blank=True,null=True,
+ default=None,
+ choices=hearchoices,verbose_name="How did you hear about Rowsandall")
+
+ logging = models.BooleanField(default=False,verbose_name='Logging Workouts')
+ technial = models.BooleanField(default=False,verbose_name='Technical Analysis of workouts')
+ trend = models.BooleanField(default=False,verbose_name='Trend Analysis of workouts')
+ planning = models.BooleanField(default=False,verbose_name='Training planning')
+ racing = models.BooleanField(default=False,verbose_name='Online racing')
+ coaching = models.BooleanField(default=False,verbose_name='Coaching')
+ export = models.BooleanField(default=False,verbose_name='Exporting data to other sites')
+ video = models.BooleanField(default=False,verbose_name='Video Analysis')
+ interval = models.BooleanField(default=False,verbose_name='Interval editor')
+
+ capabilities = models.NullBooleanField(default=None,null=True,blank=True,
+ verbose_name='Did you get the capabilities and features that you expected out of Rowsandall')
+
+ fallshort = models.TextField(max_length=300,blank=True,verbose_name='Where did Rowsandall fall short of your expectations?')
+
+ considerchoices = (
+ ('no','No'),
+ ('pro','Yes: Pro'),
+ ('plan','Yes: Self-Coach'),
+ ('coach','Yes: Coach')
+ )
+
+ considered = models.CharField(max_length=150,choices=considerchoices,default=None,null=True,blank=True,
+ verbose_name='If you are on a Free plan, did you consider one of the paid plans?')
+
+ features = models.TextField(max_length=300,blank=True,
+ verbose_name="What combination of features would entice you to upgrade to a paid plan")
+
+ agreechoices = (
+ ('completely_disagree','Completely Disagree'),
+ ('disagree','Disagree'),
+ ('neutral','Neither agree nor disagree'),
+ ('agree','Agree'),
+ ('completely_agree','Completely Agree'),
+ )
+
+ pricing = models.CharField(
+ max_length=150,choices=agreechoices,default=None,null=True,blank=True,
+ verbose_name="The pricing for plans is clear and understandable"
+ )
+
+ subscription = models.CharField(
+ max_length=150,choices=agreechoices,default=None,null=True,blank=True,
+ verbose_name="I feel like I get a good value for the price of the subscription"
+ )
+
+ advanced = models.CharField(
+ max_length=150,choices=agreechoices,default=None,null=True,blank=True,
+ verbose_name="I feel like the advanced features of Rowsandall are easy to use"
+ )
+
+ mobile = models.CharField(
+ max_length=150,choices=agreechoices,default=None,null=True,blank=True,
+ verbose_name="It is easy to use Rowsandall from a mobile device"
+ )
+
+ developer1 = models.CharField(
+ max_length=150,choices=agreechoices,default=None,null=True,blank=True,
+ verbose_name="I feel like the developer of Rowsandall is responsive to problems and resolves them quickly"
+ )
+
+ developer2 = models.CharField(
+ max_length=150,choices=agreechoices,default=None,null=True,blank=True,
+ verbose_name="I feel like the developer of Rowsandall is responsive to ideas for new features and capabilities"
+ )
+
+ sugchoices = (
+ ('bug','Resolve a bug'),
+ ('newfeature','Add a new feature'),
+ ('improve','Improve the ease of use of the site'),
+ ('easy','Make the site easier to use on mobile devices'),
+ ('other','Other')
+ )
+
+ bug = models.BooleanField(default=False,verbose_name='Resolve a bug')
+ newfeature = models.BooleanField(default=False,verbose_name='Add a new feature')
+ improve = models.BooleanField(default=False,verbose_name='Improve the ease of use of the site')
+ easu = models.BooleanField(default=False,verbose_name='Make the site easier to use on mobile devices')
+ other = models.BooleanField(default=False,verbose_name='Other')
+
+ suggestiontext = models.TextField(
+ max_length=300,default=None,null=True,blank=True,
+ verbose_name='My suggestion is (please write a short description of your suggestion)'
+ )
diff --git a/survey/urls.py b/survey/urls.py
new file mode 100644
index 00000000..90cb2d20
--- /dev/null
+++ b/survey/urls.py
@@ -0,0 +1,10 @@
+from django.conf import settings
+from django.conf.urls import url, include
+from django.urls import path, re_path
+
+import survey.views as views
+
+urlpatterns = [
+#re_path(r'^responses/$',views.ResponseList.as_view(),name='responses_view'),
+#re_path(r'^response/(?P\d+)/$',views.ResponseDetail.as_view(),name='response_view')
+]
diff --git a/survey/views.py b/survey/views.py
new file mode 100644
index 00000000..7a3e6c99
--- /dev/null
+++ b/survey/views.py
@@ -0,0 +1,34 @@
+from django.shortcuts import render
+from django.template.loader import render_to_string
+
+from django.views.generic.edit import UpdateView,DeleteView,CreateView
+from django.views.generic import ListView,DetailView
+
+from django.http import (
+ HttpResponse, HttpResponseRedirect,
+ JsonResponse,
+ HttpResponseForbidden, HttpResponseNotAllowed,
+ HttpResponseNotFound,Http404
+ )
+from django.contrib.auth import authenticate, login, logout
+
+from survey.models import Response
+
+class ResponseList(ListView):
+ model = Response
+ template_name = 'response_list.view'
+
+class ResponseCreate(CreateView):
+ login_required = True
+ model = Response
+ template_name = 'response_create.html'
+
+class ResponseUpdate(UpdateView):
+ login_required = True
+ model = Response
+ template_name = 'response_update.html'
+
+class ResponseDetail(DetailView):
+ login_required = True
+ model = Response
+ template_name = 'response.html'
diff --git a/templates/newbase.html b/templates/newbase.html
index 3b6f4e2a..5fab2852 100644
--- a/templates/newbase.html
+++ b/templates/newbase.html
@@ -43,11 +43,13 @@
+
{% block meta %} {% endblock %}
+