excluding strava from analysis
This commit is contained in:
@@ -217,6 +217,9 @@ def workout_goldmedalstandard(workout, reset=False):
|
||||
|
||||
def check_marker(workout):
|
||||
r = workout.user
|
||||
if workout.workoutsource == 'strava':
|
||||
return None
|
||||
|
||||
gmstandard, gmseconds = workout_goldmedalstandard(workout)
|
||||
if gmseconds < 60:
|
||||
return None
|
||||
|
||||
@@ -550,7 +550,7 @@ def goldmedalscorechart(user, startdate=None, enddate=None):
|
||||
workouts = Workout.objects.filter(user=user.rower, date__gte=startdate,
|
||||
date__lte=enddate,
|
||||
workouttype__in=mytypes.rowtypes,
|
||||
duplicate=False).order_by('date')
|
||||
duplicate=False).order_by('date').exclude(workoutsource='strava')
|
||||
|
||||
markerworkouts = workouts.filter(rankingpiece=True)
|
||||
outids = [w.id for w in markerworkouts]
|
||||
|
||||
@@ -1423,9 +1423,26 @@ parchoicesy1 = list(sorted(favchartlabelsy1.items(), key=lambda x: x[1]))
|
||||
parchoicesy2 = list(sorted(favchartlabelsy2.items(), key=lambda x: x[1]))
|
||||
parchoicesx = list(sorted(favchartlabelsx.items(), key=lambda x: x[1]))
|
||||
|
||||
# special filter for workouts to exclude strava workouts by default
|
||||
class WorkoutQuerySet(models.QuerySet):
|
||||
def filter(self, *args, exclude_strava=True, **kwargs):
|
||||
queryset = super().filter(*args, **kwargs)
|
||||
if exclude_strava:
|
||||
queryset = queryset.exclude(workoutsource='strava')
|
||||
|
||||
return queryset
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
queryset = self
|
||||
|
||||
return super().get(*args, **kwargs)
|
||||
|
||||
|
||||
class WorkoutManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
return WorkoutQuerySet(self.model, using=self._db)
|
||||
|
||||
# Saving a chart as a favorite chart
|
||||
|
||||
|
||||
class FavoriteChart(models.Model):
|
||||
workouttypechoices = [
|
||||
('ote', 'Erg/SkiErg'),
|
||||
@@ -3704,6 +3721,9 @@ class Workout(models.Model):
|
||||
default=False, verbose_name='Duplicate Workout')
|
||||
impeller = models.BooleanField(default=False, verbose_name='Impeller')
|
||||
|
||||
# attach the WorkoutManager
|
||||
#objects = WorkoutManager()
|
||||
|
||||
def url(self):
|
||||
str = '/rowers/workout/{id}/'.format(
|
||||
id=encoder.encode_hex(self.id)
|
||||
|
||||
@@ -451,6 +451,11 @@ def is_workout_user(user, workout):
|
||||
except AttributeError: # pragma: no cover
|
||||
return False
|
||||
|
||||
if workout.privacy == 'hidden':
|
||||
return user == workout.user.user
|
||||
if workout.workoutsource == 'strava':
|
||||
return user == workout.user.user
|
||||
|
||||
if workout.user == r:
|
||||
return True
|
||||
|
||||
@@ -469,6 +474,11 @@ def is_workout_team(user, workout):
|
||||
except AttributeError: # pragma: no cover
|
||||
return False
|
||||
|
||||
if workout.privacy == 'hidden':
|
||||
return user == workout.user.user
|
||||
if workout.workoutsource == 'strava':
|
||||
return user == workout.user.user
|
||||
|
||||
if workout.user == r:
|
||||
return True
|
||||
|
||||
|
||||
@@ -102,13 +102,17 @@ class StravaPrivacy(TestCase):
|
||||
|
||||
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
|
||||
for w in self.user_workouts:
|
||||
if w.id <= 3:
|
||||
if w.id <= 2:
|
||||
w.workoutsource = 'strava'
|
||||
w.privacy = 'hidden'
|
||||
elif w.id == 3: # user can change privacy but cannot change workoutsource
|
||||
w.workoutsource = 'strava'
|
||||
w.privacy = 'visible'
|
||||
else:
|
||||
w.workoutsource = 'concept2'
|
||||
w.privacy = 'visible'
|
||||
w.team.add(self.team)
|
||||
w.csvfilename = get_random_file(filename='rowers/tests/testdata/thyro.csv')['filename']
|
||||
w.save()
|
||||
|
||||
# r2 coaches r
|
||||
@@ -116,6 +120,13 @@ class StravaPrivacy(TestCase):
|
||||
|
||||
self.factory = APIRequestFactory()
|
||||
|
||||
def tearDown(self):
|
||||
for workout in self.user_workouts:
|
||||
try:
|
||||
os.remove(workout.csvfilename)
|
||||
except (OSError, FileNotFoundError, IOError):
|
||||
pass
|
||||
|
||||
# Test if workout with workoutsource strava and privacy hidden can be seen by coach
|
||||
def test_privacy_coach(self):
|
||||
login = self.c.login(username=self.u2.username, password=self.password2)
|
||||
@@ -126,6 +137,16 @@ class StravaPrivacy(TestCase):
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,403)
|
||||
|
||||
# Same test as above but for 'workout_edit_view'
|
||||
def test_privacy_coach_edit(self):
|
||||
login = self.c.login(username=self.u2.username, password=self.password2)
|
||||
self.assertTrue(login)
|
||||
|
||||
w = self.user_workouts[0]
|
||||
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,403)
|
||||
|
||||
# Test if workout with workoutsource strava and privacy hidden can be seen by team member
|
||||
def test_privacy_member(self):
|
||||
login = self.c.login(username=self.u3.username, password=self.password3)
|
||||
@@ -136,6 +157,16 @@ class StravaPrivacy(TestCase):
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,403)
|
||||
|
||||
# Same test as above but for 'workout_edit_view'
|
||||
def test_privacy_member_edit(self):
|
||||
login = self.c.login(username=self.u3.username, password=self.password3)
|
||||
self.assertTrue(login)
|
||||
|
||||
w = self.user_workouts[0]
|
||||
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,403)
|
||||
|
||||
# same test as above but with user r and the response code should be 200
|
||||
def test_privacy_owner(self):
|
||||
login = self.c.login(username=self.u.username, password=self.password)
|
||||
@@ -146,6 +177,16 @@ class StravaPrivacy(TestCase):
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,200)
|
||||
|
||||
# same test as above but for 'workout_edit_view'
|
||||
def test_privacy_owner_edit(self):
|
||||
login = self.c.login(username=self.u.username, password=self.password)
|
||||
self.assertTrue(login)
|
||||
|
||||
w = self.user_workouts[0]
|
||||
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,200)
|
||||
|
||||
|
||||
|
||||
# test if list_workouts returns all workouts for user r
|
||||
@@ -169,6 +210,7 @@ class StravaPrivacy(TestCase):
|
||||
|
||||
self.assertEqual(len(workouts),5)
|
||||
|
||||
|
||||
# same test as above but list_workouts with team id = self.team.id
|
||||
def test_list_workouts_team(self):
|
||||
login = self.c.login(username=self.u.username, password=self.password)
|
||||
@@ -211,6 +253,27 @@ class StravaPrivacy(TestCase):
|
||||
|
||||
self.assertEqual(len(workouts),2)
|
||||
|
||||
# same test as above but with without the teamid kwarg but with a rowerid=self.r.id
|
||||
def test_list_workouts_team_coach2(self):
|
||||
login = self.c.login(username=self.u2.username, password=self.password2)
|
||||
self.assertTrue(login)
|
||||
|
||||
url = reverse('workouts_view',kwargs={'rowerid':self.r.id})
|
||||
response = self.c.get(url)
|
||||
self.assertEqual(response.status_code,200)
|
||||
|
||||
# the response.content is html, so we need to parse it
|
||||
soup = BeautifulSoup(response.content, 'html.parser')
|
||||
# the workouts look like <a href="/rowers/workout/{id}/...">...</a> and there should be 5 unique ids
|
||||
# the id is a hex string
|
||||
workouts = set([a['href'].split('/')[3] for a in soup.find_all('a') if a['href'].startswith('/rowers/workout/')])
|
||||
|
||||
# throw out "c2import", "nkimport", "stravaimport", "concept2import", "sporttracksimport" from the set
|
||||
workouts = set([w for w in workouts if w not in [
|
||||
'upload', 'addmanual', 'c2import', 'polarimport', 'rp3import', 'nkimport', 'stravaimport', 'concept2import', 'sporttracksimport']])
|
||||
|
||||
self.assertEqual(len(workouts),2)
|
||||
|
||||
# same test as the previous one but with self.r3 and the number of workouts found should 0
|
||||
def test_list_workouts_team_member(self):
|
||||
login = self.c.login(username=self.u3.username, password=self.password3)
|
||||
@@ -307,8 +370,9 @@ class StravaPrivacy(TestCase):
|
||||
|
||||
|
||||
# test some analysis, should only use the workouts with workoutsource != strava
|
||||
@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||
def test_workouts_analysis(self, mocked_read_data):
|
||||
#@patch('rowers.dataprep.read_data', side_effect=mocked_read_data)
|
||||
#def test_workouts_analysis(self, mocked_read_data):
|
||||
def test_workouts_analysis(self):
|
||||
login = self.c.login(username=self.u.username, password=self.password)
|
||||
self.assertTrue(login)
|
||||
|
||||
@@ -388,7 +452,7 @@ class StravaPrivacy(TestCase):
|
||||
self.assertTrue(data.startswith('data = ['))
|
||||
self.assertTrue(data.endswith(']'))
|
||||
# count the number of commas between the brackets
|
||||
self.assertEqual(data.count(','),1377)
|
||||
self.assertEqual(data.count(','),2062)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -199,14 +199,14 @@ def analysis_new(request,
|
||||
startdatetime__lte=enddate,
|
||||
workouttype__in=modalities,
|
||||
rankingpiece__in=rankingtypes,
|
||||
)
|
||||
).exclude(workoutsource='strava')
|
||||
elif theteam is not None and theteam.viewing == 'coachonly': # pragma: no cover
|
||||
workouts = Workout.objects.filter(team=theteam, user=r,
|
||||
startdatetime__gte=startdate,
|
||||
startdatetime__lte=enddate,
|
||||
workouttype__in=modalities,
|
||||
rankingpiece__in=rankingtypes,
|
||||
)
|
||||
).exclude(workoutsource='strava')
|
||||
elif thesession is not None:
|
||||
workouts = get_workouts_session(r, thesession)
|
||||
else:
|
||||
@@ -363,6 +363,7 @@ def trendflexdata(workouts, options, userid=0):
|
||||
|
||||
savedata = options.get('savedata',False)
|
||||
|
||||
workouts = workouts.exclude(workoutsource='strava')
|
||||
|
||||
fieldlist, fielddict = dataprep.getstatsfields()
|
||||
fieldlist = [xparam, yparam, groupby,
|
||||
@@ -566,6 +567,8 @@ def flexalldata(workouts, options):
|
||||
trendline = options['trendline']
|
||||
promember = True
|
||||
|
||||
workouts = workouts.exclude(workoutsource='strava')
|
||||
|
||||
workstrokesonly = not includereststrokes
|
||||
|
||||
userid = options['userid']
|
||||
@@ -612,6 +615,9 @@ def histodata(workouts, options):
|
||||
workmax = options['workmax']
|
||||
userid = options['userid']
|
||||
|
||||
workouts = workouts.exclude(workoutsource='strava')
|
||||
|
||||
|
||||
if userid == 0: # pragma: no cover
|
||||
extratitle = ''
|
||||
else:
|
||||
@@ -646,6 +652,7 @@ def cpdata(workouts, options):
|
||||
u = User.objects.get(id=userid)
|
||||
r = u.rower
|
||||
|
||||
|
||||
delta, cpvalue, avgpower, workoutnames, urls = dataprep.fetchcp_new(
|
||||
r, workouts)
|
||||
|
||||
@@ -798,6 +805,8 @@ def cpdata(workouts, options):
|
||||
|
||||
|
||||
def statsdata(workouts, options):
|
||||
workouts = workouts.exclude(workoutsource='strava')
|
||||
|
||||
includereststrokes = options['includereststrokes']
|
||||
ids = options['ids']
|
||||
|
||||
@@ -872,6 +881,7 @@ def statsdata(workouts, options):
|
||||
|
||||
|
||||
def comparisondata(workouts, options):
|
||||
workouts = workouts.exclude(workoutsource='strava')
|
||||
includereststrokes = options['includereststrokes']
|
||||
xparam = options['xaxis']
|
||||
yparam1 = options['yaxis1']
|
||||
@@ -915,6 +925,7 @@ def comparisondata(workouts, options):
|
||||
|
||||
|
||||
def boxplotdata(workouts, options):
|
||||
workouts = workouts.exclude(workoutsource='strava')
|
||||
|
||||
includereststrokes = options['includereststrokes']
|
||||
spmmin = options['spmmin']
|
||||
@@ -1020,11 +1031,14 @@ def analysis_view_data(request, userid=0):
|
||||
|
||||
for id in ids:
|
||||
try:
|
||||
workouts.append(Workout.objects.get(id=id))
|
||||
w = Workout.objects.get(id=id)
|
||||
if w.workoutsource != 'strava':
|
||||
workouts.append(w)
|
||||
except Workout.DoesNotExist: # pragma: no cover
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if function == 'boxplot':
|
||||
script, div = boxplotdata(workouts, options)
|
||||
elif function == 'trendflex': # pragma: no cover
|
||||
@@ -1069,7 +1083,7 @@ def create_marker_workouts_view(request, userid=0,
|
||||
workouts = Workout.objects.filter(user=theuser.rower, date__gte=startdate,
|
||||
date__lte=enddate,
|
||||
workouttype__in=mytypes.rowtypes,
|
||||
duplicate=False).order_by('date')
|
||||
duplicate=False).order_by('date').exclude(workoutsource='strava')
|
||||
|
||||
for workout in workouts:
|
||||
_ = dataprep.check_marker(workout)
|
||||
@@ -1113,7 +1127,7 @@ def goldmedalscores_view(request, userid=0,
|
||||
theuser, startdate=startdate, enddate=enddate,
|
||||
)
|
||||
|
||||
bestworkouts = Workout.objects.filter(id__in=ids).order_by('-date')
|
||||
bestworkouts = Workout.objects.filter(id__in=ids).order_by('-date').exclude(workoutsource='strava')
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
@@ -1311,7 +1325,7 @@ def performancemanager_view(request, userid=0, mode='rower',
|
||||
user = therower, date__gte=startdate-datetime.timedelta(days=90),
|
||||
date__lte=enddate,
|
||||
duplicate=False,
|
||||
rankingpiece=True, workouttype__in=mytypes.rowtypes).order_by('date')
|
||||
rankingpiece=True, workouttype__in=mytypes.rowtypes).order_by('date').exclude(workoutsource='strava')
|
||||
|
||||
ids = [w.id for w in markerworkouts]
|
||||
form = PerformanceManagerForm(initial={
|
||||
@@ -1323,7 +1337,7 @@ def performancemanager_view(request, userid=0, mode='rower',
|
||||
|
||||
ids = pd.Series(ids, dtype='int').dropna().values
|
||||
|
||||
bestworkouts = Workout.objects.filter(id__in=ids).order_by('-date')
|
||||
bestworkouts = Workout.objects.filter(id__in=ids).order_by('-date').exclude(workoutsource='strava')
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ from rest_framework.response import Response
|
||||
from rq.job import Job
|
||||
from rules.contrib.views import permission_required, objectgetter
|
||||
from django.core.cache import cache
|
||||
from django.db import models
|
||||
from django.utils.crypto import get_random_string
|
||||
from rq.registry import StartedJobRegistry
|
||||
from rq.exceptions import NoSuchJobError
|
||||
|
||||
@@ -2204,25 +2204,25 @@ def workouts_view(request, message='', successmessage='',
|
||||
team=theteam,
|
||||
startdatetime__gte=startdate,
|
||||
startdatetime__lte=enddate,
|
||||
privacy='visible').order_by("-date", "-starttime")
|
||||
privacy='visible').order_by("-date", "-starttime").exclude(workoutsource='strava')
|
||||
g_workouts = Workout.objects.filter(
|
||||
team=theteam,
|
||||
startdatetime__gte=activity_startdate,
|
||||
startdatetime__lte=activity_enddate,
|
||||
duplicate=False,
|
||||
privacy='visible').order_by("-date", "-starttime")
|
||||
privacy='visible').order_by("-date", "-starttime").exclude(workoutsource='strava')
|
||||
elif theteam.viewing == 'coachonly': # pragma: no cover
|
||||
workouts = Workout.objects.filter(
|
||||
team=theteam, user=r,
|
||||
startdatetime__gte=startdate,
|
||||
startdatetime__lte=enddate,
|
||||
privacy='visible').order_by("-startdatetime")
|
||||
privacy='visible').order_by("-startdatetime").exclude(workoutsource='strava')
|
||||
g_workouts = Workout.objects.filter(
|
||||
team=theteam, user=r,
|
||||
startdatetime__gte=activity_startdate,
|
||||
startdatetime__lte=activity_enddate,
|
||||
duplicate=False,
|
||||
privacy='visible').order_by("-startdatetime")
|
||||
privacy='visible').order_by("-startdatetime").exclude(workoutsource='strava')
|
||||
|
||||
elif request.user != r.user:
|
||||
theteam = None
|
||||
@@ -2230,13 +2230,13 @@ def workouts_view(request, message='', successmessage='',
|
||||
user=r,
|
||||
startdatetime__gte=startdate,
|
||||
startdatetime__lte=enddate,
|
||||
privacy='visible').order_by("-date", "-starttime")
|
||||
privacy='visible').order_by("-date", "-starttime").exclude(workoutsource='strava')
|
||||
g_workouts = Workout.objects.filter(
|
||||
user=r,
|
||||
startdatetime__gte=activity_startdate,
|
||||
startdatetime__lte=activity_enddate,
|
||||
duplicate=False,
|
||||
privacy='visible').order_by("-startdatetime")
|
||||
privacy='visible').order_by("-startdatetime").exclude(workoutsource='strava')
|
||||
else:
|
||||
theteam = None
|
||||
workouts = Workout.objects.filter(
|
||||
@@ -2252,7 +2252,7 @@ def workouts_view(request, message='', successmessage='',
|
||||
if g_workouts.count() == 0:
|
||||
g_workouts = Workout.objects.filter(
|
||||
user=r,
|
||||
startdatetime__gte=timezone.now()-timedelta(days=15)).order_by("-startdatetime")
|
||||
startdatetime__gte=timezone.now()-timedelta(days=15)).order_by("-startdatetime").exclude(workoutsource='strava')
|
||||
g_enddate = timezone.now()
|
||||
g_startdate = (timezone.now()-timedelta(days=15))
|
||||
|
||||
@@ -2266,7 +2266,8 @@ def workouts_view(request, message='', successmessage='',
|
||||
reduce(operator.and_,
|
||||
(Q(name__icontains=q) for q in query_list)) |
|
||||
reduce(operator.and_,
|
||||
(Q(notes__icontains=q) for q in query_list))
|
||||
(Q(notes__icontains=q) for q in query_list)),
|
||||
exclude_strava=False,
|
||||
)
|
||||
searchform = SearchForm(initial={'q': query})
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user