Private
Public Access
1
0

Merge branch 'feature/refactoring' into develop

This commit is contained in:
Sander Roosendaal
2018-06-26 13:16:15 +02:00
19 changed files with 136 additions and 447 deletions

View File

@@ -34,7 +34,7 @@ import sys
import urllib import urllib
from requests import Request, Session from requests import Request, Session
from utils import myqueue,uniqify,isprorower from utils import myqueue,uniqify,isprorower, custom_exception_handler, NoTokenError
from rowers.types import otwtypes from rowers.types import otwtypes
@@ -46,32 +46,7 @@ queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low') queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low')
# Custom error class - to raise a NoTokenError
class C2NoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self):
return repr(self.value)
# Custom exception handler, returns a 401 HTTP message
# with exception details in the json data
def custom_exception_handler(exc,message):
response = {
"errors": [
{
"code": str(exc),
"detail": message,
}
]
}
res = HttpResponse(message)
res.status_code = 401
res.json = json.dumps(response)
return res
# Checks if user has Concept2 tokens, resets tokens if they are # Checks if user has Concept2 tokens, resets tokens if they are
# expired. # expired.
@@ -79,16 +54,16 @@ def c2_open(user):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None): if (r.c2token == '') or (r.c2token is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
raise C2NoTokenError("User has no token") raise NoTokenError("User has no token")
else: else:
if (timezone.now()>r.tokenexpirydate): if (timezone.now()>r.tokenexpirydate):
res = rower_c2_token_refresh(user) res = rower_c2_token_refresh(user)
if res == None: if res == None:
raise C2NoTokenError("User has no token") raise NoTokenError("User has no token")
if res[0] != None: if res[0] != None:
thetoken = res[0] thetoken = res[0]
else: else:
raise C2NoTokenError("User has no token") raise NoTokenError("User has no token")
else: else:
thetoken = r.c2token thetoken = r.c2token
@@ -122,7 +97,7 @@ def get_c2_workouts(rower):
try: try:
thetoken = c2_open(rower.user) thetoken = c2_open(rower.user)
except C2NoTokenError: except NoTokenError:
return 0 return 0
res = get_c2_workout_list(rower.user,page=1) res = get_c2_workout_list(rower.user,page=1)
@@ -693,7 +668,7 @@ def workout_c2_upload(user,w):
if (checkworkoutuser(user,w)): if (checkworkoutuser(user,w)):
c2userid = get_userid(r.c2token) c2userid = get_userid(r.c2token)
if not c2userid: if not c2userid:
raise C2NoTokenError raise NoTokenError
data = createc2workoutdata(w) data = createc2workoutdata(w)
if data == 0: if data == 0:

View File

@@ -46,30 +46,6 @@ from utils import geo_distance
from rowers.courseutils import coursetime_paths, coursetime_first,time_in_path from rowers.courseutils import coursetime_paths, coursetime_first,time_in_path
def get_course_timezone(course):
polygons = GeoPolygon.objects.filter(course = course)
points = GeoPoint.objects.filter(polygon = polygons[0])
lat = points[0].latitude
lon = points[0].longitude
tf = TimezoneFinder()
try:
timezone_str = tf.timezone_at(lng=lon,lat=lat)
except ValueError:
timezone_str = 'UTC'
if timezone_str is None:
timezone_str = tf.closest_timezone_at(lng=lon,lat=lat)
if timezone_str is None:
timezone_str = 'UTC'
return timezone_str
def crewnerdcourse(doc): def crewnerdcourse(doc):
courses = [] courses = []
for course in doc: for course in doc:

18
rowers/database.py Normal file
View File

@@ -0,0 +1,18 @@
from django.conf import settings
user = settings.DATABASES['default']['USER']
password = settings.DATABASES['default']['PASSWORD']
database_name = settings.DATABASES['default']['NAME']
host = settings.DATABASES['default']['HOST']
port = settings.DATABASES['default']['PORT']
database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
user=user,
password=password,
database_name=database_name,
host=host,
port=port,
)
if settings.DEBUG or user=='':
database_url = 'sqlite:///db.sqlite3'

View File

@@ -71,24 +71,8 @@ queuehigh = django_rq.get_queue('default')
from rowsandall_app.settings import SITE_URL from rowsandall_app.settings import SITE_URL
from rowers.types import otwtypes from rowers.types import otwtypes
user = settings.DATABASES['default']['USER'] from rowers.database import *
password = settings.DATABASES['default']['PASSWORD']
database_name = settings.DATABASES['default']['NAME']
host = settings.DATABASES['default']['HOST']
port = settings.DATABASES['default']['PORT']
database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
user=user,
password=password,
database_name=database_name,
host=host,
port=port,
)
# Use SQLite local database when we're in debug mode
if settings.DEBUG or user == '':
# database_url = 'sqlite:///db.sqlite3'
database_url = 'sqlite:///' + database_name
# mapping the DB column names to the CSV file column names # mapping the DB column names to the CSV file column names

View File

@@ -133,34 +133,8 @@ def rdata(file,rower=rrower()):
return res return res
from utils import totaltime_sec_to_string
def totaltime_sec_to_string(totaltime):
hours = int(totaltime / 3600.)
if hours > 23:
message = 'Warning: The workout duration was longer than 23 hours. '
hours = 23
minutes = int((totaltime - 3600. * hours) / 60.)
if minutes > 59:
minutes = 59
if not message:
message = 'Warning: there is something wrong with the workout duration'
seconds = int(totaltime - 3600. * hours - 60. * minutes)
if seconds > 59:
seconds = 59
if not message:
message = 'Warning: there is something wrong with the workout duration'
tenths = int(10 * (totaltime - 3600. * hours - 60. * minutes - seconds))
if tenths > 9:
tenths = 9
if not message:
message = 'Warning: there is something wrong with the workout duration'
duration = "%s:%s:%s.%s" % (hours, minutes, seconds, tenths)
return duration
# Creates C2 stroke data # Creates C2 stroke data
def create_c2_stroke_data_db( def create_c2_stroke_data_db(

View File

@@ -49,22 +49,7 @@ tweetapi = twitter.Api(consumer_key=TWEET_CONSUMER_KEY,
access_token_key=TWEET_ACCESS_TOKEN_KEY, access_token_key=TWEET_ACCESS_TOKEN_KEY,
access_token_secret=TWEET_ACCESS_TOKEN_SECRET) access_token_secret=TWEET_ACCESS_TOKEN_SECRET)
user = settings.DATABASES['default']['USER'] from rowers.database import *
password = settings.DATABASES['default']['PASSWORD']
database_name = settings.DATABASES['default']['NAME']
host = settings.DATABASES['default']['HOST']
port = settings.DATABASES['default']['PORT']
database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
user=user,
password=password,
database_name=database_name,
host=host,
port=port,
)
if settings.DEBUG or user=='':
database_url = 'sqlite:///db.sqlite3'
timezones = ( timezones = (
(x,x) for x in pytz.common_timezones (x,x) for x in pytz.common_timezones

View File

@@ -2,43 +2,8 @@ from matplotlib.ticker import MultipleLocator,FuncFormatter,NullFormatter
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
from rows import format_pace_tick, format_pace, format_time, format_time_tick
# Make pace ticks for pace axis '2:00', '1:50', etc
def format_pace_tick(x,pos=None):
min=int(x/60)
sec=int(x-min*60.)
sec_str=str(sec).zfill(2)
template='%d:%s'
return template % (min,sec_str)
# Returns a pace string from a pace in seconds/500m, '1:45.4'
def format_pace(x,pos=None):
if isinf(x) or isnan(x):
x=0
min=int(x/60)
sec=(x-min*60.)
str1 = "{min:0>2}:{sec:0>4.1f}".format(
min = min,
sec = sec
)
return str1
# Returns a time string from a time in seconds
def format_time(x,pos=None):
min = int(x/60.)
sec = int(x-min*60)
str1 = "{min:0>2}:{sec:0>4.1f}".format(
min=min,
sec=sec,
)
return str1
# Formatting the distance tick marks # Formatting the distance tick marks
def format_dist_tick(x,pos=None): def format_dist_tick(x,pos=None):
@@ -46,13 +11,6 @@ def format_dist_tick(x,pos=None):
template='%6.3f' template='%6.3f'
return template % (km) return template % (km)
# Formatting the time tick marks (h:mm)
def format_time_tick(x,pos=None):
hour=int(x/3600)
min=int((x-hour*3600.)/60)
min_str=str(min).zfill(2)
template='%d:%s'
return template % (hour,min_str)
# Utility to select reasonable y axis range # Utility to select reasonable y axis range
# Basically the data range plus some padding, but with ultimate # Basically the data range plus some padding, but with ultimate

View File

@@ -50,32 +50,8 @@ from rowsandall_app.settings import (
#baseurl = 'https://polaraccesslink.com/v3-example' #baseurl = 'https://polaraccesslink.com/v3-example'
baseurl = 'https://polaraccesslink.com/v3' baseurl = 'https://polaraccesslink.com/v3'
# Custom exception handler, returns a 401 HTTP message
# with exception details in the json data
def custom_exception_handler(exc,message):
response = { from utils import NoTokenError, custom_exception_handler
"errors": [
{
"code": str(exc),
"detail": message,
}
]
}
res = HttpResponse(message)
res.status_code = 401
res.json = json.dumps(response)
return res
# Custom error class - to raise a NoTokenError
class PolarNoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self):
return repr(self.value)
# Exchange access code for long-lived access token # Exchange access code for long-lived access token

View File

@@ -36,63 +36,15 @@ from rowsandall_app.settings import (
RUNKEEPER_CLIENT_ID, RUNKEEPER_CLIENT_SECRET,RUNKEEPER_REDIRECT_URI, RUNKEEPER_CLIENT_ID, RUNKEEPER_CLIENT_SECRET,RUNKEEPER_REDIRECT_URI,
) )
# Custom error class - to raise a NoTokenError from utils import geo_distance,ewmovingaverage,NoTokenError, custom_exception_handler
class RunKeeperNoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self):
return repr(self.value)
# Exponentially weighted moving average
# Used for data smoothing of the jagged data obtained by Strava
# See bitbucket issue 72
def ewmovingaverage(interval,window_size):
# Experimental code using Exponential Weighted moving average
try:
intervaldf = pd.DataFrame({'v':interval})
idf_ewma1 = intervaldf.ewm(span=window_size)
idf_ewma2 = intervaldf[::-1].ewm(span=window_size)
i_ewma1 = idf_ewma1.mean().ix[:,'v']
i_ewma2 = idf_ewma2.mean().ix[:,'v']
interval2 = np.vstack((i_ewma1,i_ewma2[::-1]))
interval2 = np.mean( interval2, axis=0) # average
except ValueError:
interval2 = interval
return interval2
from utils import geo_distance
# Custom exception handler, returns a 401 HTTP message
# with exception details in the json data
def custom_exception_handler(exc,message):
response = {
"errors": [
{
"code": str(exc),
"detail": message,
}
]
}
res = HttpResponse(message)
res.status_code = 401
res.json = json.dumps(response)
return res
# Checks if user has SportTracks token, renews them if they are expired # Checks if user has SportTracks token, renews them if they are expired
def runkeeper_open(user): def runkeeper_open(user):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.runkeepertoken == '') or (r.runkeepertoken is None): if (r.runkeepertoken == '') or (r.runkeepertoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
raise RunKeeperNoTokenError("User has no token") raise NoTokenError("User has no token")
else: else:
thetoken = r.runkeepertoken thetoken = r.runkeepertoken

View File

@@ -34,40 +34,15 @@ from rowers.models import Rower,Workout,checkworkoutuser
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, SPORTTRACKS_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_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, SPORTTRACKS_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI
# Custom error class - to raise a NoTokenError from utils import NoTokenError, custom_exception_handler
class SportTracksNoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self):
return repr(self.value)
# Custom exception handler, returns a 401 HTTP message
# with exception details in the json data
def custom_exception_handler(exc,message):
response = {
"errors": [
{
"code": str(exc),
"detail": message,
}
]
}
res = HttpResponse(message)
res.status_code = 401
res.json = json.dumps(response)
return res
# Checks if user has SportTracks token, renews them if they are expired # Checks if user has SportTracks token, renews them if they are expired
def sporttracks_open(user): def sporttracks_open(user):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
raise SportTracksNoTokenError("User has no token") raise NoTokenError("User has no token")
else: else:
if (timezone.now()>r.sporttrackstokenexpirydate): if (timezone.now()>r.sporttrackstokenexpirydate):
thetoken = rower_sporttracks_token_refresh(user) thetoken = rower_sporttracks_token_refresh(user)

View File

@@ -40,7 +40,7 @@ from rowers.models import Rower,Workout
from rowers.models import checkworkoutuser from rowers.models import checkworkoutuser
import dataprep import dataprep
from dataprep import columndict from dataprep import columndict
from utils import uniqify,isprorower,myqueue from utils import uniqify,isprorower,myqueue,NoTokenError, custom_exception_handler
from uuid import uuid4 from uuid import uuid4
import stravalib import stravalib
from stravalib.exc import ActivityUploadFailed,TimeoutExceeded from stravalib.exc import ActivityUploadFailed,TimeoutExceeded
@@ -63,32 +63,6 @@ except ImportError:
from utils import geo_distance,ewmovingaverage from utils import geo_distance,ewmovingaverage
# Custom exception handler, returns a 401 HTTP message
# with exception details in the json data
def custom_exception_handler(exc,message):
response = {
"errors": [
{
"code": str(exc),
"detail": message,
}
]
}
res = HttpResponse(message)
res.status_code = 401
res.json = json.dumps(response)
return res
# Custom error class - to raise a NoTokenError
class StravaNoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self):
return repr(self.value)
# Exchange access code for long-lived access token # Exchange access code for long-lived access token
@@ -275,6 +249,7 @@ def create_async_workout(alldata,user,stravaid):
return w.id return w.id
from utils import get_strava_stream
# Get a Strava workout summary data and stroke data by ID # Get a Strava workout summary data and stroke data by ID
def get_strava_workout(user,stravaid): def get_strava_workout(user,stravaid):
@@ -297,18 +272,12 @@ def get_strava_workout(user,stravaid):
workoutsummary['timezone'] = "Etc/UTC" workoutsummary['timezone'] = "Etc/UTC"
startdatetime = workoutsummary['start_date'] startdatetime = workoutsummary['start_date']
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/cadence?resolution="+fetchresolution+"&series_type="+series_type spmjson = get_strava_stream(r,'cadence',stravaid)
spmjson = requests.get(url,headers=headers) hrjson = get_strava_stream(r,'heartrate',stravaid)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/heartrate?resolution="+fetchresolution+"&series_type="+series_type timejson = get_strava_stream(r,'time',stravaid)
hrjson = requests.get(url,headers=headers) velojson = get_strava_stream(r,'velocity_smooth',stravaid)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/time?resolution="+fetchresolution+"&series_type="+series_type distancejson = get_strava_stream(r,'distance',stravaid)
timejson = requests.get(url,headers=headers) latlongjson = get_strava_stream(r,'latlng',stravaid)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/velocity_smooth?resolution="+fetchresolution+"&series_type="+series_type
velojson = requests.get(url,headers=headers)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/distance?resolution="+fetchresolution+"&series_type="+series_type
distancejson = requests.get(url,headers=headers)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/latlng?resolution="+fetchresolution+"&series_type="+series_type
latlongjson = requests.get(url,headers=headers)
try: try:
t = np.array(timejson.json()[0]['data']) t = np.array(timejson.json()[0]['data'])
@@ -467,7 +436,7 @@ def workout_strava_upload(user,w):
res = -1 res = -1
if (r.stravatoken == '') or (r.stravatoken is None): if (r.stravatoken == '') or (r.stravatoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
raise StravaNoTokenError("Your hovercraft is full of eels") raise NoTokenError("Your hovercraft is full of eels")
else: else:
if (checkworkoutuser(user,w)): if (checkworkoutuser(user,w)):
try: try:

View File

@@ -67,6 +67,8 @@ import requests
import longtask import longtask
import arrow import arrow
from utils import get_strava_stream
siteurl = SITE_URL siteurl = SITE_URL
# testing task # testing task
@@ -98,20 +100,13 @@ def handle_strava_import_stroke_data(stravatoken,
workoutsummary['timezone'] = "Etc/UTC" workoutsummary['timezone'] = "Etc/UTC"
startdatetime = workoutsummary['start_date'] startdatetime = workoutsummary['start_date']
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/cadence?resolution="+fetchresolution+"&series_type="+series_type spmjson = get_strava_stream(r,'cadence',stravaid)
spmjson = requests.get(url,headers=headers) hrjson = get_strava_stream(r,'heartrate',stravaid)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/heartrate?resolution="+fetchresolution+"&series_type="+series_type timejson = get_strava_stream(r,'time',stravaid)
hrjson = requests.get(url,headers=headers) velojson = get_strava_stream(r,'velocity_smooth',stravaid)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/time?resolution="+fetchresolution+"&series_type="+series_type distancejson = get_strava_stream(r,'distance',stravaid)
timejson = requests.get(url,headers=headers) latlongjson = get_strava_stream(r,'latlng',stravaid)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/velocity_smooth?resolution="+fetchresolution+"&series_type="+series_type wattsjson = get_strava_stream(r,'watts',stravaid)
velojson = requests.get(url,headers=headers)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/distance?resolution="+fetchresolution+"&series_type="+series_type
distancejson = requests.get(url,headers=headers)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/latlng?resolution="+fetchresolution+"&series_type="+series_type
latlongjson = requests.get(url,headers=headers)
url = "https://www.strava.com/api/v3/activities/"+str(stravaid)+"/streams/watts?resolution="+fetchresolution+"&series_type="+series_type
wattsjson = requests.get(url,headers=headers)
try: try:
t = np.array(timejson.json()[0]['data']) t = np.array(timejson.json()[0]['data'])

View File

@@ -20,7 +20,7 @@ from time import strftime,strptime,mktime,time,daylight
import os import os
from rowers.tasks import handle_makeplot from rowers.tasks import handle_makeplot
from rowers.utils import serialize_list,deserialize_list from rowers.utils import serialize_list,deserialize_list
from rowers.c2stuff import C2NoTokenError from rowers.utils import NoTokenError
from shutil import copyfile from shutil import copyfile
from minimocktest import MockTestCase from minimocktest import MockTestCase
@@ -424,8 +424,8 @@ class C2Tests(TestCase):
def c2_notokentest(self): def c2_notokentest(self):
thetoken = c2_open(self.u) thetoken = c2_open(self.u)
# should raise C2NoTokenError # should raise NoTokenError
self.assertRaises(C2NoTokenError) self.assertRaises(NoTokenError)
class DataTest(TestCase): class DataTest(TestCase):
def setUp(self): def setUp(self):

View File

@@ -52,63 +52,17 @@ from async_messages import message_user,messages
# Custom error class - to raise a NoTokenError
class TPNoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self): from utils import geo_distance, NoTokenError,ewmovingaverage, custom_exception_handler
return repr(self.value)
# Exponentially weighted moving average
# Used for data smoothing of the jagged data obtained by Strava
# See bitbucket issue 72
def ewmovingaverage(interval,window_size):
# Experimental code using Exponential Weighted moving average
try:
intervaldf = pd.DataFrame({'v':interval})
idf_ewma1 = intervaldf.ewm(span=window_size)
idf_ewma2 = intervaldf[::-1].ewm(span=window_size)
i_ewma1 = idf_ewma1.mean().ix[:,'v']
i_ewma2 = idf_ewma2.mean().ix[:,'v']
interval2 = np.vstack((i_ewma1,i_ewma2[::-1]))
interval2 = np.mean( interval2, axis=0) # average
except ValueError:
interval2 = interval
return interval2
from utils import geo_distance
# Custom exception handler, returns a 401 HTTP message
# with exception details in the json data
def custom_exception_handler(exc,message):
response = {
"errors": [
{
"code": str(exc),
"detail": message,
}
]
}
res = HttpResponse(message)
res.status_code = 401
res.json = json.dumps(response)
return res
# Checks if user has UnderArmour token, renews them if they are expired # Checks if user has UnderArmour token, renews them if they are expired
def tp_open(user): def tp_open(user):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.tptoken == '') or (r.tptoken is None): if (r.tptoken == '') or (r.tptoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
raise TPNoTokenError("User has no token") raise NoTokenError("User has no token")
else: else:
if (timezone.now()>r.tptokenexpirydate): if (timezone.now()>r.tptokenexpirydate):
res = do_refresh_token(r.tprefreshtoken) res = do_refresh_token(r.tprefreshtoken)
@@ -120,7 +74,7 @@ def tp_open(user):
r.save() r.save()
thetoken = r.tptoken thetoken = r.tptoken
else: else:
raise TPNoTokenError("Refresh token invalid") raise NoTokenError("Refresh token invalid")
else: else:
thetoken = r.tptoken thetoken = r.tptoken

View File

@@ -20,7 +20,7 @@ from time import strftime,strptime,mktime,time,daylight
import os import os
from rowers.tasks import handle_makeplot from rowers.tasks import handle_makeplot
from rowers.utils import serialize_list,deserialize_list from rowers.utils import serialize_list,deserialize_list
from rowers.c2stuff import C2NoTokenError
from shutil import copyfile from shutil import copyfile
from minimocktest import MockTestCase from minimocktest import MockTestCase

View File

@@ -39,63 +39,18 @@ from rowsandall_app.settings import (
UNDERARMOUR_REDIRECT_URI,UNDERARMOUR_CLIENT_KEY, UNDERARMOUR_REDIRECT_URI,UNDERARMOUR_CLIENT_KEY,
) )
# Custom error class - to raise a NoTokenError from utils import NoTokenError,ewmovingaverage
class UnderArmourNoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self): from utils import geo_distance, custom_exception_handler
return repr(self.value)
# Exponentially weighted moving average
# Used for data smoothing of the jagged data obtained by Strava
# See bitbucket issue 72
def ewmovingaverage(interval,window_size):
# Experimental code using Exponential Weighted moving average
try:
intervaldf = pd.DataFrame({'v':interval})
idf_ewma1 = intervaldf.ewm(span=window_size)
idf_ewma2 = intervaldf[::-1].ewm(span=window_size)
i_ewma1 = idf_ewma1.mean().ix[:,'v']
i_ewma2 = idf_ewma2.mean().ix[:,'v']
interval2 = np.vstack((i_ewma1,i_ewma2[::-1]))
interval2 = np.mean( interval2, axis=0) # average
except ValueError:
interval2 = interval
return interval2
from utils import geo_distance
# Custom exception handler, returns a 401 HTTP message
# with exception details in the json data
def custom_exception_handler(exc,message):
response = {
"errors": [
{
"code": str(exc),
"detail": message,
}
]
}
res = HttpResponse(message)
res.status_code = 401
res.json = json.dumps(response)
return res
# Checks if user has UnderArmour token, renews them if they are expired # Checks if user has UnderArmour token, renews them if they are expired
def underarmour_open(user): def underarmour_open(user):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.underarmourtoken == '') or (r.underarmourtoken is None): if (r.underarmourtoken == '') or (r.underarmourtoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
raise UnderArmourNoTokenError("User has no token") raise NoTokenError("User has no token")
else: else:
if (timezone.now()>r.underarmourtokenexpirydate): if (timezone.now()>r.underarmourtokenexpirydate):
res = do_refresh_token( res = do_refresh_token(

View File

@@ -36,7 +36,7 @@ except:
from rowers.utils import ( from rowers.utils import (
geo_distance,serialize_list,deserialize_list,uniqify, geo_distance,serialize_list,deserialize_list,uniqify,
str2bool,range_to_color_hex,absolute,myqueue str2bool,range_to_color_hex,absolute,myqueue,NoTokenError
) )
def cleanbody(body): def cleanbody(body):
@@ -379,7 +379,7 @@ def do_sync(w,options):
if ('upload_to_C2' in options and options['upload_to_C2']) or (w.user.c2_auto_export and isprorower(w.user)): if ('upload_to_C2' in options and options['upload_to_C2']) or (w.user.c2_auto_export and isprorower(w.user)):
try: try:
message,id = c2stuff.workout_c2_upload(w.user.user,w) message,id = c2stuff.workout_c2_upload(w.user.user,w)
except c2stuff.C2NoTokenError: except NoTokenError:
id = 0 id = 0
message = "Something went wrong with the Concept2 sync" message = "Something went wrong with the Concept2 sync"
@@ -388,7 +388,7 @@ def do_sync(w,options):
message,id = stravastuff.workout_strava_upload( message,id = stravastuff.workout_strava_upload(
w.user.user,w w.user.user,w
) )
except stravastuff.StravaNoTokenError: except NoTokenError:
id = 0 id = 0
message = "Please connect to Strava first" message = "Please connect to Strava first"
@@ -398,7 +398,7 @@ def do_sync(w,options):
message,id = sporttracksstuff.workout_sporttracks_upload( message,id = sporttracksstuff.workout_sporttracks_upload(
w.user.user,w w.user.user,w
) )
except sporttracksstuff.SportTracksNoTokenError: except NoTokenError:
message = "Please connect to SportTracks first" message = "Please connect to SportTracks first"
id = 0 id = 0
@@ -408,7 +408,7 @@ def do_sync(w,options):
message,id = runkeeperstuff.workout_runkeeper_upload( message,id = runkeeperstuff.workout_runkeeper_upload(
w.user.user,w w.user.user,w
) )
except runkeeperstuff.RunKeeperNoTokenError: except NoTokenError:
message = "Please connect to Runkeeper first" message = "Please connect to Runkeeper first"
id = 0 id = 0
@@ -417,7 +417,7 @@ def do_sync(w,options):
message,id = underarmourstuff.workout_ua_upload( message,id = underarmourstuff.workout_ua_upload(
w.user.user,w w.user.user,w
) )
except underarmourstuff.UnderArmourNoTokenError: except NoTokenError:
message = "Please connect to MapMyFitness first" message = "Please connect to MapMyFitness first"
id = 0 id = 0
@@ -427,7 +427,7 @@ def do_sync(w,options):
message,id = tpstuff.workout_tp_upload( message,id = tpstuff.workout_tp_upload(
w.user.user,w w.user.user,w
) )
except tpstuff.TPNoTokenError: except NoTokenError:
message = "Please connect to TrainingPeaks first" message = "Please connect to TrainingPeaks first"
id = 0 id = 0

View File

@@ -7,6 +7,7 @@ from django.conf import settings
import uuid import uuid
import datetime import datetime
import requests
lbstoN = 4.44822 lbstoN = 4.44822
@@ -398,3 +399,47 @@ def ewmovingaverage(interval,window_size):
interval2 = interval interval2 = interval
return interval2 return interval2
# Exceptions
# Custom error class - to raise a NoTokenError
class NoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self):
return repr(self.value)
# Custom exception handler, returns a 401 HTTP message
# with exception details in the json data
def custom_exception_handler(exc,message):
response = {
"errors": [
{
"code": str(exc),
"detail": message,
}
]
}
res = HttpResponse(message)
res.status_code = 401
res.json = json.dumps(response)
return res
def get_strava_stream(r,metric,stravaid,series_type='time',fetchresolution='high'):
authorizationstring = str('Bearer ' + r.stravatoken)
headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal',
'Content-Type': 'application/json',
'resolution': 'medium',}
url = "https://www.strava.com/api/v3/activities/{stravaid}/streams/{metric}?resolution={fetchresolutions}&series_type={series_type}".format(
stravaid=stravid,
fetchresolution=fetchresolution,
series_type=series_type,
metric=metric
)
return requests.get(url,headers=headers)

View File

@@ -90,18 +90,16 @@ import os,sys
import datetime import datetime
import iso8601 import iso8601
import c2stuff import c2stuff
from c2stuff import C2NoTokenError,c2_open from c2stuff import c2_open
from runkeeperstuff import RunKeeperNoTokenError,runkeeper_open from runkeeperstuff import runkeeper_open
from sporttracksstuff import SportTracksNoTokenError,sporttracks_open from sporttracksstuff import sporttracks_open
from tpstuff import TPNoTokenError,tp_open from tpstuff import tp_open
from iso8601 import ParseError from iso8601 import ParseError
import stravastuff import stravastuff
import polarstuff import polarstuff
from polarstuff import PolarNoTokenError
from stravastuff import StravaNoTokenError
import sporttracksstuff import sporttracksstuff
import underarmourstuff import underarmourstuff
from underarmourstuff import UnderArmourNoTokenError,underarmour_open from underarmourstuff import underarmour_open
import tpstuff import tpstuff
import runkeeperstuff import runkeeperstuff
import ownapistuff import ownapistuff
@@ -887,7 +885,7 @@ from utils import (
geo_distance,serialize_list,deserialize_list,uniqify, geo_distance,serialize_list,deserialize_list,uniqify,
str2bool,range_to_color_hex,absolute,myqueue,get_call, str2bool,range_to_color_hex,absolute,myqueue,get_call,
calculate_age,rankingdistances,rankingdurations, calculate_age,rankingdistances,rankingdurations,
is_ranking_piece,my_dict_from_instance,wavg is_ranking_piece,my_dict_from_instance,wavg,NoTokenError
) )
import datautils import datautils
@@ -2065,7 +2063,7 @@ def workout_tp_upload_view(request,id=0):
res = -1 res = -1
try: try:
thetoken = tp_open(r.user) thetoken = tp_open(r.user)
except TPNoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/tpauthorize/") return HttpResponseRedirect("/rowers/me/tpauthorize/")
# ready to upload. Hurray # ready to upload. Hurray
@@ -2216,7 +2214,7 @@ def workout_c2_upload_view(request,id=0):
try: try:
message,c2id = c2stuff.workout_c2_upload(request.user,w) message,c2id = c2stuff.workout_c2_upload(request.user,w)
except C2NoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
if message and c2id <=0: if message and c2id <=0:
@@ -2241,7 +2239,7 @@ def workout_runkeeper_upload_view(request,id=0):
try: try:
thetoken = runkeeper_open(r.user) thetoken = runkeeper_open(r.user)
except RunKeeperNoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") return HttpResponseRedirect("/rowers/me/runkeeperauthorize/")
# ready to upload. Hurray # ready to upload. Hurray
@@ -2303,7 +2301,7 @@ def workout_underarmour_upload_view(request,id=0):
try: try:
thetoken = underarmour_open(r.user) thetoken = underarmour_open(r.user)
except UnderArmourNoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/underarmourauthorize/") return HttpResponseRedirect("/rowers/me/underarmourauthorize/")
# ready to upload. Hurray # ready to upload. Hurray
@@ -2367,7 +2365,7 @@ def workout_sporttracks_upload_view(request,id=0):
try: try:
thetoken = sporttracks_open(r.user) thetoken = sporttracks_open(r.user)
except SportTracksNoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")
@@ -8950,7 +8948,7 @@ def workout_export_view(request,id=0, message="", successmessage=""):
try: try:
thetoken = c2_open(request.user) thetoken = c2_open(request.user)
except C2NoTokenError: except NoTokenError:
thetoken = 0 thetoken = 0
if (checkworkoutuser(request.user,row)) and thetoken: if (checkworkoutuser(request.user,row)) and thetoken:
@@ -8960,7 +8958,7 @@ def workout_export_view(request,id=0, message="", successmessage=""):
try: try:
rktoken = runkeeper_open(request.user) rktoken = runkeeper_open(request.user)
except RunKeeperNoTokenError: except NoTokenError:
rktoken = 0 rktoken = 0
if (checkworkoutuser(request.user,row)) and rktoken: if (checkworkoutuser(request.user,row)) and rktoken:
@@ -9940,7 +9938,7 @@ def workout_sporttracksimport_view(request,message=""):
def c2listdebug_view(request,page=1,message=""): def c2listdebug_view(request,page=1,message=""):
try: try:
thetoken = c2_open(request.user) thetoken = c2_open(request.user)
except C2NoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
r = getrower(request.user) r = getrower(request.user)
@@ -9983,7 +9981,7 @@ def c2listdebug_view(request,page=1,message=""):
def workout_getc2workout_all(request,page=1,message=""): def workout_getc2workout_all(request,page=1,message=""):
try: try:
thetoken = c2_open(request.user) thetoken = c2_open(request.user)
except C2NoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
res = c2stuff.get_c2_workout_list(request.user,page=page) res = c2stuff.get_c2_workout_list(request.user,page=page)
@@ -10016,7 +10014,7 @@ def workout_getc2workout_all(request,page=1,message=""):
def workout_c2import_view(request,page=1,message=""): def workout_c2import_view(request,page=1,message=""):
try: try:
thetoken = c2_open(request.user) thetoken = c2_open(request.user)
except C2NoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
res = c2stuff.get_c2_workout_list(request.user,page=page) res = c2stuff.get_c2_workout_list(request.user,page=page)
@@ -10242,7 +10240,7 @@ def workout_getstravaworkout_all(request):
def workout_getc2workout_view(request,c2id): def workout_getc2workout_view(request,c2id):
try: try:
thetoken = c2_open(request.user) thetoken = c2_open(request.user)
except C2NoTokenError: except NoTokenError:
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
res = c2stuff.get_c2_workout(request.user,c2id) res = c2stuff.get_c2_workout(request.user,c2id)
@@ -10643,7 +10641,7 @@ def workout_upload_view(request,
if (upload_to_c2) or (w.user.c2_auto_export and isprorower(w.user)): if (upload_to_c2) or (w.user.c2_auto_export and isprorower(w.user)):
try: try:
message,id = c2stuff.workout_c2_upload(request.user,w) message,id = c2stuff.workout_c2_upload(request.user,w)
except C2NoTokenError: except NoTokenError:
id = 0 id = 0
message = "Something went wrong with the Concept2 sync" message = "Something went wrong with the Concept2 sync"
if id>1: if id>1:
@@ -10656,7 +10654,7 @@ def workout_upload_view(request,
message,id = stravastuff.workout_strava_upload( message,id = stravastuff.workout_strava_upload(
request.user,w request.user,w
) )
except StravaNoTokenError: except NoTokenError:
id = 0 id = 0
message = "Please connect to Strava first" message = "Please connect to Strava first"
if id>1: if id>1:
@@ -10669,7 +10667,7 @@ def workout_upload_view(request,
message,id = sporttracksstuff.workout_sporttracks_upload( message,id = sporttracksstuff.workout_sporttracks_upload(
request.user,w request.user,w
) )
except SportTracksNoTokenError: except NoTokenError:
message = "Please connect to SportTracks first" message = "Please connect to SportTracks first"
id = 0 id = 0
if id>1: if id>1:
@@ -10682,7 +10680,7 @@ def workout_upload_view(request,
message,id = runkeeperstuff.workout_runkeeper_upload( message,id = runkeeperstuff.workout_runkeeper_upload(
request.user,w request.user,w
) )
except RunKeeperNoTokenError: except NoTokenError:
message = "Please connect to Runkeeper first" message = "Please connect to Runkeeper first"
id = 0 id = 0
@@ -10697,7 +10695,7 @@ def workout_upload_view(request,
message,id = underarmourstuff.workout_ua_upload( message,id = underarmourstuff.workout_ua_upload(
request.user,w request.user,w
) )
except UnderArmourNoTokenError: except NoTokenError:
message = "Please connect to MapMyFitness first" message = "Please connect to MapMyFitness first"
id = 0 id = 0
@@ -10712,7 +10710,7 @@ def workout_upload_view(request,
message,id = tpstuff.workout_tp_upload( message,id = tpstuff.workout_tp_upload(
request.user,w request.user,w
) )
except TPNoTokenError: except NoTokenError:
message = "Please connect to TrainingPeaks first" message = "Please connect to TrainingPeaks first"
id = 0 id = 0