Private
Public Access
1
0
Files
rowsandall/rowers/views/statements.py
Sander Roosendaal e4676d908e changes
2020-01-06 22:53:59 +01:00

1306 lines
37 KiB
Python

import time
import colorsys
import zipfile
import bleach
import arrow
import pytz
from pytz import UnknownTimeZoneError
import operator
import warnings
import urllib
import yaml
from PIL import Image
from numbers import Number
from django.views.generic.base import TemplateView
from django.contrib.auth import views as auth_views
from django.db.models import Q
from django import template
from django.db import IntegrityError, transaction
from django.views.decorators.csrf import csrf_exempt
from matplotlib.backends.backend_agg import FigureCanvas
import gc
from pyparsing import ParseException
from uuid import uuid4
import codecs
import isodate
import re
import cgi
from icalendar import Calendar, Event
from functools import reduce
import rowers.braintreestuff as braintreestuff
import rowers.payments as payments
from rowers.opaque import encoder
from django.shortcuts import render
from django.template.loader import render_to_string
from django.views.generic.edit import UpdateView,DeleteView
from django.http import (
HttpResponse, HttpResponseRedirect,
JsonResponse,
HttpResponseForbidden, HttpResponseNotAllowed,
HttpResponseNotFound,Http404
)
from django.contrib.auth import authenticate, login, logout
from rowers.forms import (
ForceCurveOptionsForm,HistoForm,TeamMessageForm,
LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm,
TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm,
WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement,
LandingPageForm,PlannedSessionSelectForm,WorkoutSessionSelectForm,
PlannedSessionTeamForm,PlannedSessionTeamMemberForm,
VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm,
RaceResultFilterForm,PowerIntervalUpdateForm,FlexAxesForm,
FlexOptionsForm,DataFrameColumnsForm,OteWorkoutTypeForm,
MetricsForm,DisqualificationForm,disqualificationreasons,
disqualifiers,SearchForm,BillingForm,PlanSelectForm,
VideoAnalysisCreateForm,WorkoutSingleSelectForm,
VideoAnalysisMetricsForm,
)
from django.urls import reverse, reverse_lazy
from django.core.exceptions import PermissionDenied
from django.template import RequestContext
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.conf import settings
from django.utils.datastructures import MultiValueDictKeyError
from django.utils import timezone,translation
from django.core.mail import send_mail, BadHeaderError
from rowers.forms import (
SummaryStringForm,IntervalUpdateForm,StrokeDataForm,
StatsOptionsForm,PredictedPieceForm,DateRangeForm,DeltaDaysForm,
FitnessMetricForm,PredictedPieceFormNoDistance,
EmailForm, RegistrationForm, RegistrationFormTermsOfService,
RegistrationFormUniqueEmail,RegistrationFormSex,
CNsummaryForm,UpdateWindForm,
UpdateStreamForm,WorkoutMultipleCompareForm,ChartParamChoiceForm,
FusionMetricChoiceForm,BoxPlotChoiceForm,MultiFlexChoiceForm,
TrendFlexModalForm,WorkoutSplitForm,WorkoutJoinParamForm,
AnalysisOptionsForm, AnalysisChoiceForm,
PlannedSessionMultipleCloneForm,SessionDateShiftForm,RowerTeamForm,
)
from rowers.models import (
Workout, User, Rower, WorkoutForm,FavoriteChart,
PlannedSession, DeactivateUserForm,DeleteUserForm,
TrainingPlan,TrainingPlanForm,TrainingTarget,TrainingTargetForm,
TrainingMacroCycle,TrainingMesoCycle,TrainingMicroCycle,
TrainingTarget,TrainingTargetForm,
TrainingMacroCycleForm,createmacrofillers,
createmicrofillers, createmesofillers,
microcyclecheckdates,mesocyclecheckdates,macrocyclecheckdates,
TrainingMesoCycleForm, TrainingMicroCycleForm,
RaceLogo,RowerBillingAddressForm,PaidPlan,
AlertEditForm, ConditionEditForm,
PlannedSessionComment,CoachRequest,CoachOffer,checkaccessplanuser,
VideoAnalysis
)
from rowers.models import (
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
RowerPowerZonesForm,AccountRowerForm,UserForm,
Team,TeamForm,TeamInviteForm,TeamInvite,TeamRequest,
WorkoutComment,WorkoutCommentForm,RowerExportForm,
CalcAgePerformance,
PowerTimeFitnessMetric,BlogPost,
PlannedSessionForm,
PlannedSessionFormSmall,GeoCourseEditForm,VirtualRace,
VirtualRaceForm,VirtualRaceResultForm,RowerImportExportForm,
IndoorVirtualRaceResultForm,IndoorVirtualRaceResult,
IndoorVirtualRaceForm,PlannedSessionCommentForm,
Alert, Condition
)
from rowers.models import (
FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement,BasePlannedSessionFormSet,
get_course_timezone,BaseConditionFormSet,
)
from rowers.metrics import rowingmetrics,defaultfavoritecharts,nometrics,metricsgroups
from rowers import metrics as metrics
from rowers import courses as courses
import rowers.uploads as uploads
from django.forms.formsets import formset_factory
from django.forms import modelformset_factory
from django.contrib.auth.decorators import login_required #,user_passes_test
from rowers.decorators import user_passes_test
from time import strftime,strptime,mktime,time,daylight
import os,sys
import datetime
import iso8601
import rowers.c2stuff as c2stuff
from rowers.c2stuff import c2_open
from rowers.runkeeperstuff import runkeeper_open
from rowers.sporttracksstuff import sporttracks_open
from rowers.tpstuff import tp_open
from iso8601 import ParseError
import rowers.stravastuff as stravastuff
from rowers.stravastuff import strava_open
import rowers.polarstuff as polarstuff
import rowers.sporttracksstuff as sporttracksstuff
import rowers.underarmourstuff as underarmourstuff
from rowers.underarmourstuff import underarmour_open
import rowers.tpstuff as tpstuff
import rowers.runkeeperstuff as runkeeperstuff
import rowers.ownapistuff as ownapistuff
from rowers.ownapistuff import TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_REDIRECT_URI
from rowsandall_app.settings import (
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET,
STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET,
POLAR_CLIENT_ID, POLAR_REDIRECT_URI, POLAR_CLIENT_SECRET,
SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI,
SPORTTRACKS_CLIENT_SECRET,
UNDERARMOUR_CLIENT_ID, UNDERARMOUR_REDIRECT_URI,
UNDERARMOUR_CLIENT_SECRET,UNDERARMOUR_CLIENT_KEY,
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,
RECAPTCHA_SITE_KEY, RECAPTCHA_SITE_SECRET
)
#from rowers.tasks_standalone import addcomment2
from django.contrib import messages
from async_messages import messages as a_messages
from django.contrib.admin.widgets import AdminDateWidget,AdminTimeWidget,AdminSplitDateTime
import requests
import json
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rowers.rows import handle_uploaded_file,handle_uploaded_image
from rowers.plannedsessions import *
from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv
from rowers.tasks import (
handle_sendemail_unrecognized,handle_sendemailnewcomment,
handle_sendemailsummary,
handle_send_disqualification_email,
handle_sendemailfile,
handle_sendemailkml,
handle_sendemailnewresponse, handle_updatedps,
handle_updatecp,long_test_task,long_test_task2,
handle_zip_file,handle_getagegrouprecords,
handle_updatefitnessmetric,
handle_update_empower,
handle_sendemailics,
handle_sendemail_userdeleted,
handle_sendemail_raceregistration,
handle_sendemail_racesubmission,
handle_sendemail_ical,
)
from scipy.signal import savgol_filter
#from django.shortcuts import render_to_response
try:
from Cookie import SimpleCookie
except ModuleNotFoundError:
from http.cookies import SimpleCookie
from shutil import copyfile,move
import rowers.mytypes as mytypes
from rowingdata import rower as rrower
from rowingdata import main as rmain
from rowingdata import rowingdata as rrdata
from rowingdata import make_cumvalues
from rowingdata import summarydata
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from rowers.emails import send_template_email,htmlstrip
from rowers.alerts import *
from pytz import timezone as tz,utc
from timezonefinder import TimezoneFinder
import dateutil
import mpld3
from mpld3 import plugins
import stravalib
from stravalib.exc import ActivityUploadFailed,TimeoutExceeded
from rowers.weather import get_wind_data,get_airport_code,get_metar_data
from oauth2_provider.models import Application,Grant,AccessToken
import django_rq
queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('low')
import redis
import threading
from redis import StrictRedis,Redis
from rq.exceptions import NoSuchJobError
from rq.registry import StartedJobRegistry
from rq import Queue,cancel_job
from django.core.cache import cache
from django_mailbox.models import Message,Mailbox,MessageAttachment
# Utility to get stroke data in a JSON response
class JSONResponse(HttpResponse):
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
def getfavorites(r,row):
workouttype = 'ote'
if row.workouttype in mytypes.otwtypes:
workouttype = 'otw'
matchworkouttypes = [workouttype,'all']
workoutsource = row.workoutsource
if 'speedcoach2' in row.workoutsource:
workoutsource = 'speedcoach2'
favorites = FavoriteChart.objects.filter(user=r,
workouttype__in=matchworkouttypes).order_by("id")
favorites2 = FavoriteChart.objects.filter(user=r,
workouttype__in=[workoutsource]).order_by("id")
favorites = favorites | favorites2
maxfav = len(favorites)-1
return favorites,maxfav
def get_workout_default_page(request,id):
if request.user.is_anonymous:
return reverse('workout_view',kwargs={'id':id})
else:
r = Rower.objects.get(user=request.user)
if r.defaultlandingpage == 'workout_edit_view':
return reverse('workout_edit_view',kwargs={'id':id})
else:
return reverse('workout_workflow_view',kwargs={'id':id})
def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
userid = int(userid)
rowerid = int(rowerid)
if notpermanent == False:
if rowerid == 0 and 'rowerid' in request.session:
rowerid = request.session['rowerid']
if userid != 0:
rowerid = 0
try:
if rowerid != 0:
r = Rower.objects.get(id=rowerid)
elif userid != 0:
u = User.objects.get(id=userid)
r = getrower(u)
else:
r = getrower(request.user)
except Rower.DoesNotExist:
raise Http404("Rower doesn't exist")
if not checkaccessuser(request.user,r):
raise PermissionDenied("You have no access to this user")
if notpermanent == False:
request.session['rowerid'] = r.id
return r
def getrequestplanrower(request,rowerid=0,userid=0,notpermanent=False):
userid = int(userid)
rowerid = int(rowerid)
if notpermanent == False:
if rowerid == 0 and 'rowerid' in request.session:
rowerid = request.session['rowerid']
if userid != 0:
rowerid = 0
try:
if rowerid != 0:
r = Rower.objects.get(id=rowerid)
elif userid != 0:
u = User.objects.get(id=userid)
r = getrower(u)
else:
r = getrower(request.user)
except Rower.DoesNotExist:
raise Http404("Rower doesn't exist")
if not checkaccessplanuser(request.user,r):
raise PermissionDenied("You have no access to this user")
if notpermanent == False:
request.session['rowerid'] = r.id
return r
def getrower(user):
try:
if user.is_anonymous:
return None
except AttributeError:
if User.objects.get(id=user).is_anonymous:
return None
try:
r = Rower.objects.get(user=user)
except Rower.DoesNotExist:
r = Rower(user=user)
r.save()
return r
def get_workout(id):
try:
id = encoder.decode_hex(id)
w = Workout.objects.get(id=id)
except Workout.DoesNotExist:
raise Http404("Workout doesn't exist")
return w
def get_workout_permitted(user,id):
w = get_workout(id)
if (checkworkoutuser(user,w)==False):
raise PermissionDenied("Access denied")
return w
def get_workout_permittedview(user,id):
w = get_workout(id)
if (checkworkoutuserview(user,w)==False):
raise PermissionDenied("Access denied")
return w
def getvalue(data):
perc = 0
total = 1
done = 0
id = 0
session_key = 'noot'
for i in data.iteritems():
if i[0] == 'total':
total = float(i[1])
if i[0] == 'done':
done = float(i[1])
if i[0] == 'id':
id = i[1]
if i[0] == 'session_key':
session_key = i[1]
return total,done,id,session_key
class SessionTaskListener(threading.Thread):
def __init__(self, r, channels):
threading.Thread.__init__(self)
self.redis = r
self.pubsub = self.redis.pubsub()
self.pubsub.subscribe(channels)
def work(self, item):
try:
data = json.loads(item['data'])
total,done,id,session_key = getvalue(data)
perc = int(100.*done/total)
cache.set(id,perc,3600)
except TypeError:
pass
def run(self):
for item in self.pubsub.listen():
if item['data'] == "KILL":
self.pubsub.unsubscribe()
print(self, "unsubscribed and finished")
break
else:
self.work(item)
queuefailed = Queue("failed",connection=Redis())
redis_connection = StrictRedis()
r = Redis()
# this doesn't yet work on production
#if settings.DEBUG:
# client = SessionTaskListener(r,['tasks'])
# client.start()
rq_registry = StartedJobRegistry(queue.name,connection=redis_connection)
rq_registryhigh = StartedJobRegistry(queuehigh.name,connection=redis_connection)
rq_registrylow = StartedJobRegistry(queuelow.name,connection=redis_connection)
from rq.job import Job
try:
from rest_framework_swagger.views import get_swagger_view
except ImportError:
pass
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rowers.serializers import RowerSerializer,WorkoutSerializer
try:
from rest_framework import status,permissions,generics
except ImportError:
pass
from rest_framework.decorators import api_view, renderer_classes
from rowers.permissions import IsOwnerOrNot
import rowers.plots as plots
import rowers.mailprocessing as mailprocessing
from io import BytesIO
from scipy.special import lambertw
from rowers.dataprep import timedeltaconv
from rowers.dataprep import getsmallrowdata_db
from scipy.interpolate import griddata
#LOCALTIMEZONE = tz('Etc/UTC')
USER_LANGUAGE = 'en-US'
from rowers.interactiveplots import *
from rowers.celery import result as celery_result
# Define the API documentation
try:
schema_view = get_swagger_view(title='Rowsandall API')
except NameError:
pass
def remove_asynctask(request,id):
try:
oldtasks = request.session['async_tasks']
except KeyError:
oldtasks = []
newtasks = []
for task in oldtasks:
if id not in task[0]:
newtasks += [(task[0],task[1])]
request.session['async_tasks'] = newtasks
def get_job_result(jobid):
if settings.TESTING:
return None
elif settings.CELERY:
result = celery_result.AsyncResult(jobid).result
else:
running_job_ids = rq_registry.get_job_ids()
if len(running_job_ids) and jobid in running_job_ids:
# job is running
return None
else:
# job is ready
try:
job = Job.fetch(jobid,connection=redis_connection)
result = job.result
except NoSuchJobError:
return None
return result
verbose_job_status = {
'updatecp': 'Critical Power Calculation for Ergometer Workouts',
'updatecpwater': 'Critical Power Calculation for OTW Workouts',
'otwsetpower': 'Rowing Physics OTW Power Calculation',
'agegrouprecords': 'Calculate age group records',
'make_plot': 'Create static chart',
'long_test_task': 'Long Test Task',
'long_test_task2': 'Long Test Task 2',
'update_empower': 'Correct Empower Inflated Power Bug',
'submit_race': 'Checking Race Course Result',
}
def get_job_status(jobid):
if settings.TESTING:
summary = {
'status': 'failed',
'result': 0,
'finished': True,
'failed': True,
'started_at':None,
}
return summary
elif settings.CELERY:
job = celery_result.AsyncResult(jobid)
jobresult = job.result
if 'fail' in job.status.lower():
jobresult = '0'
summary = {
'status': job.status,
'result': jobresult,
'started_at': None
}
else:
try:
job = Job.fetch(jobid,connection=redis_connection)
try:
status = job.status
except AttributeError:
status = job.get_status()
summary = {
'status':status,
'result':job.result,
'started_at':job.started_at
}
except NoSuchJobError:
summary = {
'status': 'success',
'result': 1,
'started_at':None,
}
try:
if 'fail' in summary['status'].lower():
summary['failed'] = True
else:
summary['failed'] = False
if 'success' in summary['status'].lower():
summary['finished'] = True
elif 'finished' in summary['status'].lower():
summary['finished'] = True
else:
summary['finished'] = False
except AttributeError:
summary = {
'status': 'failed',
'result': 0,
'finished': True,
'failed': True,
'started_at':None,
}
return summary
def kill_async_job(request,id='aap'):
if settings.CELERY:
job = celery_result.AsyncResult(id)
job.revoke()
else:
try:
cancel_job(id,connection=redis_connection)
except NoSuchJobError:
pass
remove_asynctask(request,id)
cache.delete(id)
url = reverse(session_jobs_status)
return HttpResponseRedirect(url)
@login_required()
def raise_500(request):
if request.user.is_superuser:
raise ValueError
else:
return HttpResponse("invalid")
#@login_required()
#def test_job_view(request,aantal=100):
#
# session_key = request.session._session_key
#
# job = myqueue(queuehigh,long_test_task,int(aantal),
# session_key=session_key)
#
#
# try:
# request.session['async_tasks'] += [(job.id,'long_test_task')]
# except KeyError:
# request.session['async_tasks'] = [(job.id,'long_test_task')]
#
# url = reverse(session_jobs_status)
#
# return HttpResponseRedirect(url)
#@login_required()
#def test_job_view2(request,aantal=100):
#
#
# job = myqueue(queuehigh,long_test_task2,int(aantal),
# secret=settings.PROGRESS_CACHE_SECRET)#
#
#
# try:
# request.session['async_tasks'] += [(job.id,'long_test_task2')]
# except KeyError:
# request.session['async_tasks'] = [(job.id,'long_test_task2')]
#
# url = reverse(session_jobs_status)
#
# return HttpResponseRedirect(url)
@csrf_exempt
def post_progress(request,id=None,value=0):
if request.method == 'POST':
try:
secret = request.POST['secret']
except KeyError:
return HttpResponse('Access Denied',status=401)
if secret == settings.PROGRESS_CACHE_SECRET:
if not id:
try:
id = request.POST['id']
except KeyError:
return HttpResponse('Invalid request',400)
try:
value = request.POST['value']
except KeyError:
pass
cache.set(id,value,3600)
# test
result = cache.get(id)
return HttpResponse('progress cached '+str(result),
status=201)
else: # secret not given
return HttpResponse('access denied',status=401)
else: # request method is not POST
return HttpResponse('GET method not allowed',status=405)
def get_all_queued_jobs(userid=0):
r = StrictRedis()
jobs = []
celerykeys = r.keys('celery*')
for key in celerykeys:
id= key[17:]
job = celery_result.AsyncResult(id)
jobresult = job.result
if 'fail' in job.status.lower():
jobresult = '0'
jobs.append(
(id,{
'status':job.status,
'result':jobresult,
'function':'',
'meta':job.info,
}))
ids = [j.id for j in queue.jobs]
ids += [j.id for j in queuehigh.jobs]
ids += [j.id for j in queuelow.jobs]
ids += [j.id for j in queuefailed.jobs]
for id in ids:
job = Job.fetch(id,connection=redis_connection)
jobs.append(
(id,{
'status':job.get_status(),
'result':job.result,
'function':job.func_name,
'meta':job.meta,
}))
return jobs
def get_stored_tasks_status(request):
try:
taskids = request.session['async_tasks']
except KeyError:
taskids = []
taskstatus = []
for id,func_name in reversed(taskids):
progress = 0
try:
cached_progress = cache.get(id)
if cached_progress is not None:
cached_progress = int(cached_progress)
else:
cached_progress = 0
except ValueError:
cached_progress = 0
finished = get_job_status(id)['finished']
if finished:
cache.set(id,100)
progress = 100
elif cached_progress is not None and cached_progress>0:
progress = cached_progress
else:
progress = 0
this_task_status = {
'id':id,
'status':get_job_status(id)['status'],
'failed':get_job_status(id)['failed'],
'finished':get_job_status(id)['finished'],
'func_name':func_name,
'verbose': verbose_job_status[func_name],
'progress': progress,
}
taskstatus.append(this_task_status)
return taskstatus
@login_required()
def get_thumbnails(request,id):
row = get_workout_permitted(request.user,id)
r = getrower(request.user)
result = request.user.is_authenticated and ispromember(request.user)
if result:
promember=1
if request.user == row.user.user:
mayedit=1
comments = WorkoutComment.objects.filter(workout=row)
aantalcomments = len(comments)
favorites,maxfav = getfavorites(r,row)
charts = []
charts = thumbnails_set(r,encoder.decode_hex(id),favorites)
try:
if charts[0]['script'] == '':
charts = []
except IndexError:
charts = []
return JSONResponse(charts)
def get_blog_posts(request):
blogposts = BlogPost.objects.all().order_by("-date")
jsondata = []
if blogposts:
for blogpost in blogposts[0:3]:
thedict = {
'title':blogpost.title,
'link':blogpost.link,
}
jsondata.append(thedict)
return JSONResponse(jsondata)
def get_blog_posts_old(request):
try:
response = requests.get(
'https://analytics.rowsandall.com/wp-json/wp/v2/posts?per_page=3')
if response.status_code == 200:
blogs_json = response.json()
# with open('blogs.txt','w') as o:
# o.write(json.dumps(blogs_json,indent=2,sort_keys=True))
else:
blogs_json = []
except ConnectionError:
pass
blogposts = []
for postdata in blogs_json[0:3]:
try:
title = postdata['title']['rendered'].encode(
'ascii','xmlcharrefreplace')
except TypeError:
title = postdata['title']['rendered'].encode(
'ascii','xmlcharrefreplace').decode('utf-8')
thedict = {
'title': title,
# 'author': '',
# 'image': image_url,
# 'excerpt': excerpt_first,
'link': postdata['link'],
}
blogposts.append(thedict)
return JSONResponse(blogposts)
@login_required()
def get_testscript(request,id):
row = get_workout_permitted(request.user,id)
r = getrower(request.user)
object = {
"script":"""
<div id="id_script">
<script>alert("hi")</script>
</div>
""",
"div":"""
<div id="id_div">
Hoi
</div>
"""
}
return JSONResponse([object,object])
@login_required()
def session_jobs_view(request):
taskstatus = get_stored_tasks_status(request)
return HttpResponse(json.dumps(taskstatus))
@login_required()
def session_jobs_status(request):
taskstatus = get_stored_tasks_status(request)
return render(request,
'async_tasks.html',
{'taskstatus':taskstatus})
# Test if row data include candidates
def rowhascoordinates(row):
# create interactive plot
f1 = row.csvfilename
u = row.user.user
r = getrower(u)
rowdata = rdata(f1)
hascoordinates = 1
if rowdata != 0:
try:
latitude = rowdata.df[' latitude']
if not latitude.std():
hascoordinates = 0
except (KeyError,AttributeError):
hascoordinates = 0
else:
hascoordinates = 0
return hascoordinates
# Wrapper around the rowingdata call to catch some exceptions
# Checks for CSV file, then for gzipped CSV file, and if all fails, returns 0
def rdata(file,rower=rrower()):
try:
res = rrdata(csvfile=file,rower=rower)
except (IOError, IndexError, EOFError):
try:
res = rrdata(csvfile=file+'.gz',rower=rower)
except (IOError, IndexError, EOFError):
res = 0
return res
# Query to get teams managed and member of
def get_my_teams(user):
try:
therower = Rower.objects.get(user=user)
try:
teams1 = therower.team.all()
except AttributeError:
teams1 = []
teams2 = Team.objects.filter(manager=user)
teams = list(set(teams1).union(set(teams2)))
except TypeError:
teams = []
return teams
# Used for the interval editor - translates seconds to a time object
def get_time(second):
if (second<=0) or (second>1e9):
hours = 0
minutes=0
sec=0
microsecond = 0
elif math.isnan(second):
hours = 0
minutes=0
sec=0
microsecond = 0
else:
days = int(second/(24.*3600.)) % (24*3600)
hours = int((second-24.*3600.*days)/3600.) % 24
minutes = int((second-3600.*(hours+24.*days))/60.) % 60
sec = int(second-3600.*(hours+24.*days)-60.*minutes) % 60
microsecond = int(1.0e6*(second-3600.*(hours+24.*days)-60.*minutes-sec))
return datetime.time(hours,minutes,sec,microsecond)
# get the workout ID from the SportTracks URI
def getidfromsturi(uri,length=8):
return uri[len(uri)-length:]
import re
def getidfromuri(uri):
m = re.search('/(\w.*)\/(\d+)',uri)
return m.group(2)
from rowers.utils import (
geo_distance,serialize_list,deserialize_list,uniqify,
str2bool,range_to_color_hex,absolute,myqueue,get_call,
calculate_age,rankingdistances,rankingdurations,
is_ranking_piece,my_dict_from_instance,wavg,NoTokenError
)
import rowers.datautils as datautils
from rowers.models import (
checkworkoutuser,checkaccessuser,checkviewworkouts,checkworkoutuserview
)
# Check if a user is a Coach member
def iscoachmember(user):
if not user.is_anonymous:
try:
r = Rower.objects.get(user=user)
except Rower.DoesNotExist:
r = Rower(user=user)
r.save()
result = user.is_authenticated and ('coach' in r.rowerplan)
else:
result = False
return result
def cancreateteam(user):
if user.is_anonymous:
return False
try:
r = Rower.objects.get(user=user)
except Rower.DoesNotExist:
r = Rower(user=user)
r.save()
if user.is_authenticated and ('coach' in r.rowerplan):
return True
elif user.is_athenticated() and r.rowerplan in ['plan','pro']:
ts = Team.objects.filter(manager=user)
if len(otherteams) >= 1:
return False
# Check if a user can create planned sessions
def hasplannedsessions(user):
if not user.is_anonymous:
try:
r = Rower.objects.get(user=user)
except Rower.DoesNotExist:
r = Rower(user=user)
r.save()
result = user.is_authenticated and (r.rowerplan=='coach' or r.rowerplan=='freecoach' or r.rowerplan=='plan')
if not result and r.plantrialexpires:
result = user.is_authenticated and r.plantrialexpires >= datetime.date.today()
else:
result = False
return result
from rowers.utils import ProcessorCustomerError
from rowers.utils import isprorower
# Check if a user is a Pro member
def ispromember(user):
if user and not user.is_anonymous:
try:
r = Rower.objects.get(user=user)
except Rower.DoesNotExist:
r = Rower(user=user)
r.save()
result = user.is_authenticated and isprorower(r)
else:
result = False
return result
# More User/Rower utils
def add_defaultfavorites(r):
for c in defaultfavoritecharts:
f = FavoriteChart(user=r,
yparam1=c['yparam1'],
yparam2=c['yparam2'],
xparam=c['xparam'],
plottype=c['plottype'],
workouttype=c['workouttype'],
reststrokes=c['reststrokes'],
notes=c['notes'])
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() and success:
firstname = form.cleaned_data['firstname']
lastname = form.cleaned_data['lastname']
email = form.cleaned_data['email']
subject = 'Rowsandall Contact Form:'+form.cleaned_data['subject']
message = form.cleaned_data['message']
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/')
# Create workout data from Strava or Concept2
# data and create the associated Workout object and save it
def add_workout_from_strokedata(user,importid,data,strokedata,
source='c2',splitdata=None,
workoutsource='concept2'):
try:
workouttype = data['type']
except KeyError:
workouttype = 'rower'
if workouttype not in [x[0] for x in Workout.workouttypes]:
workouttype = 'other'
try:
comments = data['comments']
except:
comments = ' '
# comments = "Imported data \n %s" % comments
# comments = "Imported data \n"+comments # str(comments)
try:
thetimezone = tz(data['timezone'])
except:
thetimezone = 'UTC'
r = getrower(user)
try:
rowdatetime = iso8601.parse_date(data['date_utc'])
except KeyError:
rowdatetime = iso8601.parse_date(data['start_date'])
except ParseError:
rowdatetime = iso8601.parse_date(data['date'])
try:
c2intervaltype = data['workout_type']
except KeyError:
c2intervaltype = ''
try:
title = data['name']
except KeyError:
title = ""
try:
t = data['comments'].split('\n', 1)[0]
title += t[:20]
except:
title = 'Imported'
starttimeunix = arrow.get(rowdatetime).timestamp
res = make_cumvalues(0.1*strokedata['t'])
cum_time = res[0]
lapidx = res[1]
unixtime = cum_time+starttimeunix
# unixtime[0] = starttimeunix
seconds = 0.1*strokedata.loc[:,'t']
nr_rows = len(unixtime)
try:
latcoord = strokedata.loc[:,'lat']
loncoord = strokedata.loc[:,'lon']
except:
latcoord = np.zeros(nr_rows)
loncoord = np.zeros(nr_rows)
try:
strokelength = strokedata.loc[:,'strokelength']
except:
strokelength = np.zeros(nr_rows)
dist2 = 0.1*strokedata.loc[:,'d']
try:
spm = strokedata.loc[:,'spm']
except KeyError:
spm = 0*dist2
try:
hr = strokedata.loc[:,'hr']
except KeyError:
hr = 0*spm
pace = strokedata.loc[:,'p']/10.
pace = np.clip(pace,0,1e4)
pace = pace.replace(0,300)
velo = 500./pace
power = 2.8*velo**3
# save csv
# Create data frame with all necessary data to write to csv
df = pd.DataFrame({'TimeStamp (sec)':unixtime,
' Horizontal (meters)': dist2,
' Cadence (stokes/min)':spm,
' HRCur (bpm)':hr,
' longitude':loncoord,
' latitude':latcoord,
' Stroke500mPace (sec/500m)':pace,
' Power (watts)':power,
' DragFactor':np.zeros(nr_rows),
' DriveLength (meters)':np.zeros(nr_rows),
' StrokeDistance (meters)':strokelength,
' DriveTime (ms)':np.zeros(nr_rows),
' StrokeRecoveryTime (ms)':np.zeros(nr_rows),
' AverageDriveForce (lbs)':np.zeros(nr_rows),
' PeakDriveForce (lbs)':np.zeros(nr_rows),
' lapIdx':lapidx,
' ElapsedTime (sec)':seconds
})
df.sort_values(by='TimeStamp (sec)',ascending=True)
timestr = strftime("%Y%m%d-%H%M%S")
# Create CSV file name and save data to CSV file
csvfilename ='media/{code}_{importid}.csv'.format(
importid=importid,
code = uuid4().hex[:16]
)
res = df.to_csv(csvfilename+'.gz',index_label='index',
compression='gzip')
# with Concept2
if source=='c2':
try:
totaldist = data['distance']
totaltime = data['time']/10.
except KeyError:
totaldist = 0
totaltime = 0
else:
totaldist = 0
totaltime = 0
id,message = dataprep.save_workout_database(
csvfilename,r,
workouttype=workouttype,
title=title,notes=comments,
# totaldist=totaldist,
# totaltime=totaltime,
workoutsource=workoutsource,
dosummary=True
)
return id,message
def keyvalue_get_default(key,options,def_options):
try:
return options[key]
except KeyError:
return def_options[key]
# Creates unix time stamp from a datetime object
def totimestamp(dt, epoch=datetime.datetime(1970,1,1,tzinfo=tz('UTC'))):
td = dt - epoch
# return td.total_seconds()
return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
# Check if a column of a dataframe has the required (aantal)
# number of elements. Also checks if the column is a numerical type
# Replaces any faulty columns with zeros
def trydf(df,aantal,column):
try:
s = df[column]
if len(s) != aantal:
return np.zeros(aantal)
if not np.issubdtype(s,np.number):
return np.zeros(aantal)
except KeyError:
s = np.zeros(aantal)
return s
import rowers.teams as teams
from rowers.models import C2WorldClassAgePerformance