From 8ca9446e486fc98909a383832b26bfff11db85f4 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 15 Apr 2021 18:06:30 +0200 Subject: [PATCH 1/8] further cleanupp --- rowers/templates/alert_delete_confirm.html | 6 +- rowers/tests/test_analysis.py | 597 ++---- rowers/tests/test_permissions.py | 8 +- rowers/tests/test_urls.py | 73 - rowers/tests/viewnames.csv | 9 - rowers/urls.py | 19 - rowers/views/analysisviews.py | 2035 +------------------- 7 files changed, 147 insertions(+), 2600 deletions(-) diff --git a/rowers/templates/alert_delete_confirm.html b/rowers/templates/alert_delete_confirm.html index 8871a27d..39a7646f 100644 --- a/rowers/templates/alert_delete_confirm.html +++ b/rowers/templates/alert_delete_confirm.html @@ -6,20 +6,20 @@ {% block main %}

Confirm Delete

This will permanently delete the alert

- +
  • {% csrf_token %}

    Are you sure you want to delete {{ object }}?

    - +

- + {% endblock %} diff --git a/rowers/tests/test_analysis.py b/rowers/tests/test_analysis.py index 5deb71b9..b79abbd4 100644 --- a/rowers/tests/test_analysis.py +++ b/rowers/tests/test_analysis.py @@ -75,104 +75,6 @@ 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,surveydone=True, - gdproptindate=timezone.now(), - rowerplan='coach') - - self.c = Client() - self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) - - self.factory = RequestFactory() - self.password = faker.word() - self.u.set_password(self.password) - self.u.save() - - def tearDown(self): - for workout in self.user_workouts: - try: - os.remove(workout.csvfilename) - except (IOError, FileNotFoundError,OSError): - pass - - @patch('rowers.dataprep.create_engine') - @patch('rowers.dataprep.getsmallrowdata_db') - def test_workouts_boxplot(self, mocked_sqlalchemy, - mocked_getsmallrowdata_db): - - login = self.c.login(username=self.u.username, password=self.password) - self.assertTrue(login) - - url = '/rowers/user-boxplot-select/' - - response = self.c.get(url) - self.assertEqual(response.status_code,200) - - @patch('rowers.dataprep.create_engine') - @patch('rowers.dataprep.getsmallrowdata_db') - @patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multi) - def donot_test_workouts_boxplot_submit(self, mocked_sqlalchemy, - mocked_getsmallrowdata_db, - mocked_df): - - login = self.c.login(username=self.u.username,password=self.password) - self.assertTrue(login) - - form_data = { - 'workouts':['1','2','3'], - 'includereststrokes':False, - 'spmmax':55.0, - 'spmmin':15.0, - 'workmax':1500.0, - 'workmin':0.0, - 'yparam':'spm', - } - - form = WorkoutMultipleCompareForm(form_data) - chartform = BoxPlotChoiceForm(form_data) - - self.assertTrue(form.is_valid()) - self.assertTrue(chartform.is_valid()) - - response = self.c.get('/rowers/user-boxplot/',follow=True) - self.assertEqual(response.status_code,200) - self.assertRedirects(response, - expected_url='/rowers/user-boxplot-select/user/1/', - status_code=302,target_status_code=200) - - response = self.c.post('/rowers/user-boxplot/',form_data) - - self.assertEqual(response.status_code,200) - - options = {} - options['spmmin'] = 15 - options['spmmax'] = 55 - options['workmin'] = 0 - options['workmax'] = 5500 - options['ids'] = [1,2,3] - options['userid'] = 1 - options['plotfield'] = 'spm' - options['rankingonly'] = False - options['cpfit'] = 'data' - options['piece'] = 4 - - session = self.c.session - session['options'] = options - session.save() - response = self.c.get('/') - - sessionoptions = session['options'] - self.assertEqual(sessionoptions['ids'],[1,2,3]) - - response = self.c.get('/rowers/user-boxplot-data/') - - - self.assertEqual(response.status_code,200) class ListWorkoutTest(TestCase): @@ -316,382 +218,6 @@ class ForcecurveTest(TestCase): response = self.c.get(url) self.assertEqual(response.status_code,200) -class CumStatsTest(TestCase): - def setUp(self): - self.u = UserFactory() - - self.r = Rower.objects.create(user=self.u, - birthdate=faker.profile()['birthdate'], - gdproptin=True,surveydone=True, - gdproptindate=timezone.now(), - rowerplan='coach') - - self.c = Client() - self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) - self.factory = RequestFactory() - self.password = faker.word() - self.u.set_password(self.password) - self.u.save() - - def tearDown(self): - for workout in self.user_workouts: - try: - os.remove(workout.csvfilename) - except (IOError, FileNotFoundError,OSError): - pass - - @patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multistats) - def test_cumstats(self, mocked_df): - login = self.c.login(username=self.u.username, password=self.password) - self.assertTrue(login) - - startdate = (self.user_workouts[0].startdatetime-datetime.timedelta(days=3)).date() - enddate = (self.user_workouts[0].startdatetime+datetime.timedelta(days=3)).date() - - # make sure the dates are not naive - try: - startdate = pytz.utc.localize(startdate) - except (ValueError, AttributeError): - pass - try: - enddate = pytz.utc.localize(enddate) - except (ValueError, AttributeError): - pass - - url = '/rowers/cumstats/' - 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,surveydone=True, - gdproptindate=timezone.now(), - rowerplan='coach') - - self.c = Client() - self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) - self.factory = RequestFactory() - self.password = faker.word() - self.u.set_password(self.password) - self.u.save() - - def tearDown(self): - for workout in self.user_workouts: - try: - os.remove(workout.csvfilename) - except (IOError, FileNotFoundError,OSError): - pass - - @patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multiflex) - def test_cumflex(self, mocked_df): - login = self.c.login(username=self.u.username, password=self.password) - self.assertTrue(login) - - startdate = (self.user_workouts[0].startdatetime-datetime.timedelta(days=3)).date() - enddate = (self.user_workouts[0].startdatetime+datetime.timedelta(days=3)).date() - - # make sure the dates are not naive - try: - startdate = pytz.utc.localize(startdate) - except (ValueError, AttributeError): - pass - try: - enddate = pytz.utc.localize(enddate) - except (ValueError, AttributeError): - pass - - waterboattype = [u'1x', - u'2x', - u'2x+', - u'2-', - u'2+', - u'3x+', - u'3x-', - u'4x', - u'4x+', - u'4-', - u'4+', - u'8+', - u'8x+'] - - form_data = { - 'startdate':startdate, - 'enddate':enddate, - 'modality':u'all', - 'waterboattype': waterboattype, - 'xaxis':'spm', - 'yaxis1':'hr', - 'yaxis2':'power', - } - - form = TrendFlexModalForm(form_data) - self.assertTrue(form.is_valid()) - - self.factory.user = self.u - form = FlexAxesForm(self.factory,form_data) - - - url = '/rowers/flexall/' - - 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 = {'enddatestring': '2019-01-14', - 'includereststrokes': False, - 'modality': u'water', - 'rankingonly': False, - 'startdatestring': '2018-12-15', - 'theuser': 2, - 'waterboattype': [u'1x', - u'2x', - u'2x+', - u'2-', - u'2+', - u'3x+', - u'3x-', - u'4x', - u'4x+', - u'4-', - u'4+', - u'8+', - u'8x+'], - 'xparam': u'spm', - 'yparam1': u'hr', - 'yparam2': u'power'} - - session = self.c.session - 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,surveydone=True, - gdproptindate=timezone.now(), - rowerplan='coach') - - self.c = Client() - self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) - self.factory = RequestFactory() - self.password = faker.word() - self.u.set_password(self.password) - self.u.save() - - def tearDown(self): - for workout in self.user_workouts: - try: - os.remove(workout.csvfilename) - except (IOError, FileNotFoundError,OSError): - pass - - @patch('rowers.dataprep.read_cols_df_sql', side_effect = mocked_read_df_cols_sql_multiflex) - def test_multiflex(self, mocked_df): - login = self.c.login(username=self.u.username, password=self.password) - self.assertTrue(login) - - startdate = (self.user_workouts[0].startdatetime-datetime.timedelta(days=3)).date() - enddate = (self.user_workouts[0].startdatetime+datetime.timedelta(days=3)).date() - - # make sure the dates are not naive - try: - startdate = pytz.utc.localize(startdate) - except (ValueError, AttributeError): - pass - try: - enddate = pytz.utc.localize(enddate) - except (ValueError, AttributeError): - pass - - waterboattype = [u'1x', - u'2x', - u'2x+', - u'2-', - u'2+', - u'3x+', - u'3x-', - u'4x', - u'4x+', - u'4-', - u'4+', - u'8+', - u'8x+'] - - form_data = { - 'startdate':startdate, - 'enddate':enddate, - 'modality':u'all', - 'waterboattype': waterboattype, - 'binsize':u'1', - 'palette':u'monochrome_blue', - 'spmmax':55, - 'spmmin':15, - 'workmax':1500, - 'workmin':0, - 'workouts':[1,2,3,4,5], - 'workoutselectform':'Create Chart', - 'xparam':'spm', - 'yparam':'power', - 'groupby':'spm', - } - - form = MultiFlexChoiceForm(form_data) - self.assertTrue(form.is_valid()) - - url = '/rowers/user-multiflex-select/' - - response = self.c.get(url) - self.assertEqual(response.status_code,200) - - url = '/rowers/user-multiflex/user/1/' - reponse = self.c.post(url, form_data,follow=True) - self.assertEqual(response.status_code, 200) - - options={ - 'includereststrokes':False, - 'ploterrorbars':True, - 'userid':0, - 'palette': 'monochrome_blue', - 'groupby': 'power', - 'binsize': 1, - 'xparam': 'spm', - 'yparam': 'power', - 'spmmin': 15, - 'spmmax': 55, - 'workmin': 400, - 'workmax': 1500, - 'ids': [1,2,3,4,5], - 'ploterrorbars':False, - } - - session = self.c.session - 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,surveydone=True, - gdproptindate=timezone.now(), - rowerplan='coach') - - self.c = Client() - self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) - self.factory = RequestFactory() - self.password = faker.word() - self.u.set_password(self.password) - self.u.save() - - def tearDown(self): - for workout in self.user_workouts: - try: - os.remove(workout.csvfilename) - except (IOError, FileNotFoundError,OSError): - pass - - @patch('rowers.dataprep.create_engine') - @patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getpowerdata_db) - def test_histo_workouts(self, mocked_sqlalchemy, - mocked_getsmallrowdata_db): - - login = self.c.login(username=self.u.username, password=self.password) - self.assertTrue(login) - - startdate = (self.user_workouts[0].startdatetime-datetime.timedelta(days=3)).date() - enddate = (self.user_workouts[0].startdatetime+datetime.timedelta(days=3)).date() - - # make sure the dates are not naive - try: - startdate = pytz.utc.localize(startdate) - except (ValueError, AttributeError): - pass - try: - enddate = pytz.utc.localize(enddate) - except (ValueError, AttributeError): - pass - - waterboattype = [u'1x', - u'2x', - u'2x+', - u'2-', - u'2+', - u'3x+', - u'3x-', - u'4x', - u'4x+', - u'4-', - u'4+', - u'8+', - u'8x+'] - - form_data = { - 'startdate':startdate, - 'enddate':enddate, - 'modality':u'all', - 'histoparam':'power', - 'rankingonly': False, - 'includereststrokes':False, - 'workouttypes': ['water'], - 'waterboattype': waterboattype - } - - 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, - 'modality':'all', - 'waterboattype':waterboattype, - 'theuser':0, - 'enddatestring':enddate.strftime("%Y-%m-%d"), - 'startdatestring':startdate.strftime("%Y-%m-%d"), - } - - session = self.c.session - session['options'] = options - session.save() - response = self.c.get('/') - - sessionoptions = session['options'] - - response = self.c.get('/rowers/histodata/') - self.assertEqual(response.status_code,200) - - - #-------------------------------------------------- - - class WorkoutCompareTestNew(TestCase): def setUp(self): @@ -1642,3 +1168,126 @@ class MarkerPerformanceTest(TestCase): response = self.c.post(url,form_data) self.assertEqual(response.status_code,200) + +class AlertTest(TestCase): + def setUp(self): + self.u = UserFactory() + + self.r = Rower.objects.create(user=self.u, + birthdate=faker.profile()['birthdate'], + gdproptin=True,surveydone=True, + gdproptindate=timezone.now(), + rowerplan='coach') + + self.c = Client() + self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) + self.factory = RequestFactory() + self.password = faker.word() + self.u.set_password(self.password) + self.u.save() + + # need a 2k, 5k, 1h row + self.werg2k = WorkoutFactory( + user=self.r, + duration=datetime.time(hour=0,minute=7,second=0), + distance=2000, + workouttype='rower', + rankingpiece=True, + ) + + # need a 2k, 5k, 1h row + self.werg5k = WorkoutFactory( + user=self.r, + duration=datetime.time(hour=0,minute=18,second=0), + distance=5000, + workouttype='rower', + rankingpiece=True, + ) + + # need a 2k, 5k, 1h row + self.werg1h = WorkoutFactory( + user=self.r, + duration=datetime.time(hour=1,minute=0,second=0), + distance=15000, + workouttype='rower', + rankingpiece=True, + ) + + def tearDown(self): + for workout in self.user_workouts: + try: + os.remove(workout.csvfilename) + except (IOError, FileNotFoundError, OSError): + pass + + @patch('rowers.dataprep.create_engine') + @patch('rowers.alerts.getsmallrowdata_db') + def test_alerts(self, mocked_sqlalchemy, + mocked_getsmallrowdata_db): + login = self.c.login(username=self.u.username,password=self.password) + self.assertTrue(login) + + startdate = (self.user_workouts[0].startdatetime-datetime.timedelta(days=3)).date() + enddate = (self.user_workouts[0].startdatetime+datetime.timedelta(days=3)).date() + + url = reverse('alerts_view') + response = self.c.get(url) + self.assertEqual(response.status_code,200) + + # create alert + url = reverse('alert_create_view') + response = self.c.get(url) + self.assertEqual(response.status_code,200) + + data = { + 'name': 'Ss', + 'period':7, + 'emailalert': True, + 'boattype':'1x', + 'workouttype':'water', + 'reststrokes':False, + 'metric':'spm', + 'condition':'<', + 'value1':20, + 'value2':22, + # management_form data + 'form-INITIAL_FORMS': '0', + 'form-TOTAL_FORMS': '1', + 'form-MAX_NUM_FORMS': '', + + # First condition data + 'form-0-metric': 'hr', + 'form-0-condition': '>', + 'form-0-value1': 120, + 'form-0-value2': 130 + } + + + form = AlertEditForm(data) + self.assertTrue(form.is_valid()) + + response = self.c.post(url,data,follow=True) + expected_url = reverse('alert_edit_view',kwargs={'id':1}) + self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200) + + url = expected_url + response = self.c.post(url,data) + self.assertEqual(response.status_code,200) + + data = {} + + url = reverse('alert_report_view',kwargs={'id':1,'userid':self.u.id}) + response = self.c.get(url) + self.assertEqual(response.status_code,200) + + # delete + url = '/rowers/alerts/1/delete/' + response = self.c.get(url) + self.assertEqual(response.status_code,200) + + + response = self.c.post(url,data,follow=True) + expected_url = reverse('alerts_view') + self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200) + + # diff --git a/rowers/tests/test_permissions.py b/rowers/tests/test_permissions.py index e2a093db..5f4bcdd2 100644 --- a/rowers/tests/test_permissions.py +++ b/rowers/tests/test_permissions.py @@ -857,7 +857,7 @@ class PermissionsViewTests(TestCase): self.assertTrue(login) - url = reverse('cumstats', + url = reverse('analysis_new', kwargs={ 'userid':self.ubasic.id, } @@ -877,7 +877,7 @@ class PermissionsViewTests(TestCase): self.assertTrue(login) - url = reverse('cumstats', + url = reverse('analysis_new', kwargs={ 'userid':self.ubasic.id, } @@ -1153,7 +1153,7 @@ class PermissionsViewTests(TestCase): self.assertTrue(login) - url = reverse('cumstats', + url = reverse('analysis_new', kwargs={ 'userid':self.ubasic.id, } @@ -1276,7 +1276,7 @@ class PermissionsViewTests(TestCase): self.assertTrue(login) - url = reverse('cumstats', + url = reverse('analysis_new', kwargs={ 'userid':self.ubasic.id, } diff --git a/rowers/tests/test_urls.py b/rowers/tests/test_urls.py index 6a75c617..c34057d8 100644 --- a/rowers/tests/test_urls.py +++ b/rowers/tests/test_urls.py @@ -68,10 +68,6 @@ class URLTests(TestCase): '/rowers/404/', '/rowers/500/', '/rowers/502/', -# '/rowers/1/list-workouts/', -# '/rowers/1/list-workouts/2016-01-01/2016-12-31/', -# '/rowers/1/ote-bests/', -# '/rowers/1/ote-bests2/2016-01-01/2016-12-31/', '/rowers/about/', '/rowers/workout/addmanual/', '/rowers/agegroupcp/30/', @@ -86,29 +82,10 @@ class URLTests(TestCase): '/rowers/courses/upload/', '/rowers/createplan/', '/rowers/createplan/user/1/', - '/rowers/cumstats/', -# '/rowers/cumstats/2016-01-01/2016-12-31/', - '/rowers/cumstats/user/1/', -# '/rowers/cumstats/user/1/2016-01-01/2016-12-31/', '/rowers/developers/', '/rowers/email/', '/rowers/email/thankyou/', -# '/rowers/fitness-progress/', -# '/rowers/fitness-progress/user/1/', -# '/rowers/fitness-progress/user/1/rower/', - '/rowers/flexall/', - '/rowers/flexall/spm/hr/None/', -# '/rowers/flexall/spm/hr/None/2016-01-01/2016-12-31/', -# '/rowers/flexall/spm/hr/None/2016-01-01/2016-12-31/user/1/', - '/rowers/flexall/user/1/', - '/rowers/flexalldata/', '/rowers/help/', - '/rowers/histo/', - '/rowers/histo/user/1/', -# '/rowers/histo/user/1/2016-01-01/2016-12-31/', - '/rowers/histodata/', -# '/rowers/job-kill/1/', -# '/rowers/jobs-status/', '/rowers/laboratory/', '/rowers/laboratory/user/1/', '/rowers/legal/', @@ -116,8 +93,6 @@ class URLTests(TestCase): '/rowers/list-graphs/', '/rowers/list-jobs/', '/rowers/list-workouts/', -# '/rowers/list-workouts/2016-01-01/2016-12-31/', -# '/rowers/list-workouts/2016-01-01/2016-12-31/user/1/', '/rowers/list-workouts/ranking/', '/rowers/list-workouts/user/1/', '/rowers/me/calcdps/', @@ -135,65 +110,23 @@ class URLTests(TestCase): '/rowers/me/workflowconfig2/', '/rowers/me/workflowconfig2/user/1/', '/rowers/me/workflowdefault/', -# '/rowers/multi-compare/', -# '/rowers/ote-bests/', -# '/rowers/ote-bests/2016-01-01/2016-12-31/', -# '/rowers/ote-bests/user/1/', -# '/rowers/ote-bests/user/1/2016-01-01/2016-12-31/', '/rowers/ote-bests2/', -# '/rowers/ote-bests2/2016-01-01/2016-12-31/', '/rowers/ote-bests2/user/1/', -# '/rowers/ote-ranking/', -# '/rowers/ote-ranking/2016-01-01/2016-12-31/', -# '/rowers/ote-ranking/user/1/', -# '/rowers/ote-ranking/user/1/2016-01-01/2016-12-31/', -# '/rowers/otw-bests/', -# '/rowers/otw-bests/2016-01-01/2016-12-31/', -# '/rowers/otw-bests/user/1/2016-01-01/2016-12-31/', '/rowers/partners/', '/rowers/physics/', '/rowers/planrequired/', -# '/rowers/promembership/', '/rowers/register/', '/rowers/register/thankyou/', '/rowers/sessions/', -# '/rowers/sessions/2016-01-01/2016-12-31/', -# '/rowers/sessions/2016-01-01/2016-12-31/user/1/', '/rowers/sessions/coach/', -# '/rowers/sessions/coach/user/1/', '/rowers/sessions/create/', -# '/rowers/sessions/create/user/1/', '/rowers/sessions/manage/', -# '/rowers/sessions/manage/user/1/', '/rowers/sessions/multiclone/', -# '/rowers/sessions/multiclone/user/1/', '/rowers/sessions/multicreate/', -# '/rowers/sessions/multicreate/user/1/', '/rowers/sessions/print/', -# '/rowers/sessions/print/user/1/', '/rowers/sessions/teamcreate/', -# '/rowers/sessions/user/1/', '/rowers/team-compare-select/', '/rowers/team-compare-select/workout/'+encoded1+'/', -# '/rowers/team-compare-select/2016-01-01/2016-12-31/', -# '/rowers/test-job/2/', -# '/rowers/test-job2/2/', -# '/rowers/test_callback/', -# '/rowers/updatefitness/', -# '/rowers/updatefitness/rower/', -# '/rowers/updatefitness/rower/50/', -# '/rowers/user-boxplot/', -# '/rowers/user-boxplot-data/', -# '/rowers/user-boxplot-select/', -# '/rowers/user-boxplot-select/user/1/', -# '/rowers/user-boxplot/user/1/', -# '/rowers/user-multiflex-data/', -# '/rowers/user-multiflex-select/', -# '/rowers/user-multiflex-select/2016-01-01/2016-12-31/', -# '/rowers/user-multiflex-select/user/1/', -# '/rowers/user-multiflex-select/user/1/2016-01-01/2016-12-31/', -# '/rowers/user-multiflex/', -# '/rowers/user-multiflex/user/1/', '/rowers/workout/'+encoded1+'/', '/rowers/workout/'+encoded1+'/adddistanceplot/', '/rowers/workout/'+encoded1+'/adddistanceplot2/', @@ -224,27 +157,21 @@ class URLTests(TestCase): '/rowers/workout/'+encoded1+'/split/', '/rowers/workout/'+encoded1+'/stats/', '/rowers/workout/'+encoded1+'/stream/', -# '/rowers/workout/'+encoded1+'/task/', -# '/rowers/workout/'+encoded1+'/teststrokedata/', '/rowers/workout/'+encoded1+'/toggle-ranking/', '/rowers/workout/'+encoded1+'/undosmoothenpace/', '/rowers/workout/'+encoded1+'/unsubscribe/', -# '/rowers/workout/'+encoded1+'/updatecp/', '/rowers/workout/'+encoded1+'/view/', '/rowers/workout/'+encoded1+'/wind/', '/rowers/workout/'+encoded1+'/workflow/', '/rowers/workout/fusion/'+encoded1+'/', -# '/rowers/workout/fusion/'+encoded1+'/2016-01-01/2016-12-31/', '/rowers/workout/upload/', '/rowers/workout/upload/team/', '/rowers/workouts-join/', '/rowers/workouts-join-select/', -# '/rowers/workouts-join-select/2016-01-01/2016-12-31/', ] - # urlstotest = ['/rowers/createplan/user/1/'] lijst = [] for url in urlstotest: diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv index a8f12ac7..8d399ca0 100644 --- a/rowers/tests/viewnames.csv +++ b/rowers/tests/viewnames.csv @@ -26,9 +26,7 @@ 25,27,team_comparison_select,compare with a team member workout,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,TRUE,TRUE,TRUE,TRUE, 26,28,workouts_join_view,join workouts,TRUE,302,pro,302,302,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, 27,29,workouts_join_select,select workouts to join,TRUE,404,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, -28,30,user_boxplot_select,select boxplots,TRUE,302,pro,200,302,pro,403,403,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE, 29,31,analysis_new,analysis front page,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE, -30,32,user_multiflex_select,select multiflex data,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE, 31,33,session_jobs_view,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 32,34,session_jobs_status,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 33,35,kill_async_job,kill job,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, @@ -38,9 +36,6 @@ 41,43,cum_flex,flex all chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 42,44,analysis_view_data,redirects to analysis direct,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 43,47,cum_flex_data,flex all chart data (json),TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -44,48,histo,histogram view,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE, -45,49,histo_data,histogram data,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, -46,51,cumstats,cumulative statistics,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE,TRUE, 47,53,graph_show_view,show a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 48,54,GraphDelete,delete a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 49,55,get_thumbnails,get thumbnails,TRUE,403,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE, @@ -114,10 +109,6 @@ 119,148,alert_edit_view,edit alert,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 120,150,alert_create_view,create alert,TRUE,302,pro,200,403,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 121,152,alert_report_view,view alerts report,TRUE,302,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,FALSE,FALSE,FALSE, -122,155,boxplot_view,View boxplot,TRUE,302,pro,302,403,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, -123,157,boxplot_view_data,data for boxplot,TRUE,302,pro,200,403,pro,200,403,coach,200,403,FALSE,FALSE,FALSE,FALSE,FALSE, -124,158,multiflex_view,view multiflex,TRUE,302,pro,302,403,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE,TRUE, -125,160,multiflex_data,data for multiflex,TRUE,302,pro,200,403,pro,200,403,coach,200,403,FALSE,FALSE,FALSE,FALSE,FALSE, 126,161,deactivate_user,deactivate a user,TRUE,302,basic,200,302,FALSE,403,403,FALSE,403,403,FALSE,FALSE,FALSE,TRUE,TRUE, 127,162,remove_user,remove a user,TRUE,302,basic,200,302,FALSE,403,403,FALSE,403,403,FALSE,FALSE,FALSE,TRUE,TRUE, 128,163,user_gdpr_confirm,GDPR confirmation,TRUE,302,basic,302,302,FALSE,403,403,FALSE,403,403,FALSE,FALSE,FALSE,TRUE,TRUE, diff --git a/rowers/urls.py b/rowers/urls.py index eb62075a..3df7665a 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -325,8 +325,6 @@ urlpatterns = [ re_path(r'^workouts-join/user/(?P\d+)$',views.workouts_join_view,name='workouts_join_view'), re_path(r'^workouts-join-select/$',views.workouts_join_select,name='workouts_join_select'), re_path(r'^workouts-join-select/user/(?P\d+)/$',views.workouts_join_select,name='workouts_join_select'), - re_path(r'^user-boxplot-select/user/(?P\d+)/$',views.user_boxplot_select,name='user_boxplot_select'), - re_path(r'^user-boxplot-select/$',views.user_boxplot_select,name='user_boxplot_select'), re_path(r'^user-analysis-select/(?P\w.*)/workout/(?P\b[0-9A-Fa-f]+\b)/$',views.analysis_new,name='analysis_new'), re_path(r'^user-analysis-select/(?P\w.*)/user/(?P\d+)/$',views.analysis_new,name='analysis_new'), re_path(r'^user-analysis-select/(?P\w.*)/team/(?P\d+)/$',views.analysis_new,name='analysis_new'), @@ -334,8 +332,6 @@ urlpatterns = [ re_path(r'^user-analysis-select/team/(?P\d+)/$',views.analysis_new,name='analysis_new'), re_path(r'^user-analysis-select/(?P\w.*)/$',views.analysis_new,name='analysis_new'), re_path(r'^user-analysis-select/$',views.analysis_new,name='analysis_new'), - re_path(r'^user-multiflex-select/user/(?P\d+)/$',views.user_multiflex_select,name='user_multiflex_select'), - re_path(r'^user-multiflex-select/$',views.user_multiflex_select,name='user_multiflex_select'), re_path(r'^list-jobs/$',views.session_jobs_view,name='session_jobs_view'), re_path(r'^jobs-status/$',views.session_jobs_status,name='session_jobs_status'), re_path(r'^job-kill/(?P.*)/$',views.kill_async_job), @@ -356,16 +352,7 @@ urlpatterns = [ re_path(r'^performancemanager/user/(?P\d+)/(?P\w+.*)/$',views.performancemanager_view,name='performancemanager_view'), re_path(r'^ote-bests2/user/(?P\d+)/$',views.rankings_view2,name='rankings_view2'), re_path(r'^ote-bests2/$',views.rankings_view2,name='rankings_view2'), - re_path(r'^flexall/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)/$',views.cum_flex,name='cum_flex'), re_path(r'^analysisdata/$',views.analysis_view_data,name='analysis_view_data'), - re_path(r'^flexall/user/(?P\d+)/$',views.cum_flex,name='cum_flex'), - re_path(r'^flexall/$',views.cum_flex,name='cum_flex'), - re_path(r'^flexalldata/$',views.cum_flex_data,name='cum_flex_data'), - re_path(r'^histo/user/(?P\d+)/$',views.histo,name='histo'), - re_path(r'^histodata/$',views.histo_data,name='histo_data'), - re_path(r'^histo/$',views.histo,name='histo'), - re_path(r'^cumstats/user/(?P\d+)/$',views.cumstats,name='cumstats'), - re_path(r'^cumstats/$',views.cumstats,name='cumstats'), re_path(r'^graph/(?P\d+)/$',views.graph_show_view,name='graph_show_view'), 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, @@ -541,12 +528,6 @@ urlpatterns = [ re_path(r'^alerts/(?P\d+)/report/user/(?P\d+)/$',views.alert_report_view,name='alert_report_view'), re_path(r'^alerts/(?P\d+)/report/(?P\d+)/user/(?P\d+)/$',views.alert_report_view,name='alert_report_view'), re_path(r'^alerts/(?P\d+)/report/$',views.alert_report_view,name='alert_report_view'), - re_path(r'^user-boxplot/user/(?P\d+)/$',views.boxplot_view,name='boxplot_view'), - re_path(r'^user-boxplot/$',views.boxplot_view,name='boxplot_view'), - re_path(r'^user-boxplot-data/$',views.boxplot_view_data,name='boxplot_view_data'), - re_path(r'^user-multiflex/user/(?P\d+)/$',views.multiflex_view,name='multiflex_view'), - re_path(r'^user-multiflex/$',views.multiflex_view,name='multiflex_view'), - 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'), diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index 848b1820..b945f96f 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -954,606 +954,6 @@ def analysis_view_data(request,userid=0): }) -# Histogram for a date/time range -@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) -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def histo(request,userid=0, - startdate=timezone.now()-datetime.timedelta(days=365), - enddate=timezone.now(), - deltadays=-1, - enddatestring=timezone.now().strftime("%Y-%m-%d"), - startdatestring=(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), - options={ - 'includereststrokes':False, - 'workouttypes':[i[0] for i in mytypes.workouttypes], - 'waterboattype':mytypes.waterboattype, - 'rankingonly': False, - 'histoparam':'power' - }): - - r = getrequestrower(request,userid=userid) - theuser = r.user - - if 'histoparam' in request.session: # pragma: no cover - histoparam = request.session['histoparam'] - else: - histoparam = 'power' - - if 'waterboattype' in request.session: # pragma: no cover - waterboattype = request.session['waterboattype'] - else: - waterboattype = mytypes.waterboattype - - - if 'rankingonly' in request.session: # pragma: no cover - rankingonly = request.session['rankingonly'] - else: - rankingonly = False - - if 'modalities' in request.session: # pragma: no cover - modalities = request.session['modalities'] - if len(modalities) > 1: - modality = 'all' - else: # pragma: no cover - modality = modalities[0] - else: - modalities = [m[0] for m in mytypes.workouttypes] - modality = 'all' - - - try: - rankingonly = options['rankingonly'] - except KeyError: # pragma: no cover - rankingonly = False - - try: - includereststrokes = options['includereststrokes'] - except KeyError: # pragma: no cover - includereststrokes = False - - - workstrokesonly = not includereststrokes - - waterboattype = mytypes.waterboattype - - - if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) - - if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) - - if enddate < startdate: # pragma: no cover - s = enddate - enddate = startdate - startdate = s - - - # get all indoor rows of in date range - - # process form - if request.method == 'POST': - form = DateRangeForm(request.POST) - modalityform = TrendFlexModalForm(request.POST) - histoform = HistoForm(request.POST) - if form.is_valid(): - startdate = form.cleaned_data['startdate'] - enddate = form.cleaned_data['enddate'] - if startdate > enddate: # pragma: no cover - s = enddate - enddate = startdate - startdate = s - startdatestring = startdate.strftime('%Y-%m-%d') - enddatestring = enddate.strftime('%Y-%m-%d') - if modalityform.is_valid(): - modality = modalityform.cleaned_data['modality'] - waterboattype = modalityform.cleaned_data['waterboattype'] - rankingonly = modalityform.cleaned_data['rankingonly'] - if modality == 'all': - modalities = [m[0] for m in mytypes.workouttypes] - else: # pragma: no cover - modalities = [modality] - - if modality != 'water': - waterboattype = [b[0] for b in mytypes.boattypes] - - - request.session['modalities'] = modalities - request.session['waterboattype'] = waterboattype - request.session['rankingonly'] = rankingonly - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - if histoform.is_valid(): - includereststrokes = histoform.cleaned_data['includereststrokes'] - histoparam = histoform.cleaned_data['histoparam'] - request.session['histoparam'] = histoparam - request.session['includereststrokes'] = includereststrokes - else: - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - includereststrokes = False - - workstrokesonly = not includereststrokes - modalityform = TrendFlexModalForm( - initial={ - 'modality':modality, - 'waterboattype':waterboattype, - 'rankingonly':rankingonly, - } - ) - histoform = HistoForm(initial={ - 'includereststrokes':False, - 'histoparam':histoparam - }) - - negtypes = [] - for b in mytypes.boattypes: - if b[0] not in waterboattype: # pragma: no cover - negtypes.append(b[0]) - - - - script = '' - div = get_call() - js_resources = '' - css_resources = '' - - - - - options = { - 'modality': modality, - 'theuser': theuser.id, - 'waterboattype':waterboattype, - 'startdatestring':startdatestring, - 'enddatestring':enddatestring, - 'rankingonly':rankingonly, - 'includereststrokes':includereststrokes, - 'histoparam':histoparam, - } - - request.session['options'] = options - - promember=0 - mayedit=0 - if not request.user.is_anonymous: - result = request.user.is_authenticated and ispromember(request.user) - if result: - promember = 1 - - - request.session['options'] = options - - breadcrumbs = [ - { - 'url':'/rowers/analysis', - 'name':'Analysis' - }, - { - 'url':reverse('histo'), - 'name': 'Histogram' - } - ] - - return render(request, 'histo.html', - {'interactiveplot':script, - 'the_div':div, - 'breadcrumbs':breadcrumbs, - 'id':theuser, - 'active':'nav-analysis', - 'theuser':theuser, - 'rower':r, - 'startdate':startdate, - 'enddate':enddate, - 'form':form, - 'optionsform':modalityform, - 'histoform':histoform, - 'teams':get_my_teams(request.user), - }) - -# The Flex plot for a large selection of workouts -@login_required() -def cum_flex_data( - request, - options={ - 'includereststrokes':False, - 'rankingonly':False, - 'modality':'all', - 'waterboattype':mytypes.waterboattype, - 'theuser':0, - 'xparam':'spm', - 'yparam1':'power', - 'yparam2':'None', - 'enddatestring':timezone.now().strftime("%Y-%m-%d"), - 'startdatestring':(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), - 'deltadays':-1, - }): - - def_options = options - - if 'options' in request.session: - options = request.session['options'] - - - modality = keyvalue_get_default('modality',options,def_options) - rankingonly = keyvalue_get_default('rankingonly',options,def_options) - includereststrokes = keyvalue_get_default('includereststrokes',options,def_options) - waterboattype = keyvalue_get_default('waterboattype',options,def_options) - workstrokesonly = not includereststrokes - theuser = keyvalue_get_default('theuser',options,def_options) - xparam = keyvalue_get_default('xparam',options,def_options) - yparam1 = keyvalue_get_default('yparam1',options,def_options) - yparam2 = keyvalue_get_default('yparam2',options,def_options) - startdatestring = keyvalue_get_default('startdatestring',options,def_options) - enddatestring = keyvalue_get_default('enddatestring',options,def_options) - - - if modality == 'all': - modalities = [m[0] for m in mytypes.workouttypes] - else: # pragma: no cover - modalities = [modality] - - try: - startdate = iso8601.parse_date(startdatestring) - except ParseError: # pragma: no cover - startdate = timezone.now()-datetime.timedelta(days=7) - - try: - enddate = iso8601.parse_date(enddatestring) - except ParseError: # pragma: no cover - enddate = timezone.now() - - - if enddate < startdate: # pragma: no cover - s = enddate - enddate = startdate - startdate = s - - promember=0 - if theuser == 0: - theuser = request.user.id - - if not request.user.is_anonymous: - r = getrower(request.user) - result = request.user.is_authenticated and ispromember(request.user) - if result: - promember=1 - - r2 = getrower(theuser) - - if rankingonly: # pragma: no cover - rankingpiece = [True,] - else: - rankingpiece = [True,False] - - allworkouts = Workout.objects.filter(user=r2, - workouttype__in=modalities, - boattype__in=waterboattype, - startdatetime__gte=startdate, - startdatetime__lte=enddate, - rankingpiece__in=rankingpiece) - - if allworkouts: - res = interactive_cum_flex_chart2(allworkouts,xparam=xparam, - yparam1=yparam1, - yparam2=yparam2, - promember=promember, - workstrokesonly=workstrokesonly, - ) - script = res[0] - div = res[1] - else: - script = '' - div = '

No pieces uploaded for this date range.

' - - scripta = script.split('\n')[2:-1] - script = ''.join(scripta) - - data = { - "script":script, - "div":div, - } - - return JSONResponse(data) - -# The Flex plot for a large selection of workouts -@login_required() -def histo_data( - request, - options={ - 'includereststrokes':False, - 'rankingonly':False, - 'modality':'all', - 'waterboattype':mytypes.waterboattype, - 'theuser':0, - 'enddatestring':timezone.now().strftime("%Y-%m-%d"), - 'startdatestring':(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), - 'deltadays':-1, - 'histoparam':'power', - }): - - def_options = options - - - if 'options' in request.session: - options = request.session['options'] - - modality = keyvalue_get_default('modality',options,def_options) - rankingonly = keyvalue_get_default('rankingonly',options,def_options) - includereststrokes = keyvalue_get_default('includereststrokes',options,def_options) - waterboattype = keyvalue_get_default('waterboattype',options,def_options) - workstrokesonly = not includereststrokes - theuser = keyvalue_get_default('theuser',options,def_options) - startdatestring = keyvalue_get_default('startdatestring',options,def_options) - enddatestring = keyvalue_get_default('enddatestring',options,def_options) - histoparam = keyvalue_get_default('histoparam',options,def_options) - - if modality == 'all': - modalities = [m[0] for m in mytypes.workouttypes] - else: # pragma: no cover - modalities = [modality] - - try: - startdate = iso8601.parse_date(startdatestring) - except ParseError: # pragma: no cover - startdate = timezone.now()-datetime.timedelta(days=7) - - try: - enddate = iso8601.parse_date(enddatestring) - except ParseError: # pragma: no cover - enddate = timezone.now() - - - if enddate < startdate: # pragma: no cover - s = enddate - enddate = startdate - startdate = s - - promember=0 - if theuser == 0: - theuser = request.user.id - - if not request.user.is_anonymous: - r = getrower(request.user) - result = request.user.is_authenticated and ispromember(request.user) - if result: - promember=1 - - r2 = getrower(theuser) - - if rankingonly: # pragma: no cover - rankingpiece = [True,] - else: - rankingpiece = [True,False] - - allworkouts = Workout.objects.filter(user=r2, - workouttype__in=modalities, - boattype__in=waterboattype, - startdatetime__gte=startdate, - startdatetime__lte=enddate, - rankingpiece__in=rankingpiece) - - if allworkouts: - res = interactive_histoall(allworkouts,histoparam,includereststrokes) - script = res[0] - div = res[1] - else: - script = '' - div = '

No pieces uploaded for this date range.

' - - scripta = script.split('\n')[2:-1] - script = ''.join(scripta) - - data = { - "script":script, - "div":div, - } - - return JSONResponse(data) - - - - -@login_required() -def cum_flex(request,theuser=0, - xparam='spm', - yparam1='power', - yparam2='None', - startdate=timezone.now()-datetime.timedelta(days=10), - enddate=timezone.now(), - deltadays=-1, - enddatestring=timezone.now().strftime("%Y-%m-%d"), - startdatestring=(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), - options={ - 'includereststrokes':False, - 'workouttypes':[i[0] for i in mytypes.workouttypes], - 'waterboattype':mytypes.waterboattype, - 'rankingonly':False, - }): - - - r = getrequestrower(request,userid=theuser) - theuser = r.user - - if 'waterboattype' in request.session: # pragma: no cover - waterboattype = request.session['waterboattype'] - else: - waterboattype = mytypes.waterboattype - - - if 'rankingonly' in request.session: # pragma: no cover - rankingonly = request.session['rankingonly'] - else: - rankingonly = False - - if 'modalities' in request.session: # pragma: no cover - modalities = request.session['modalities'] - if len(modalities) > 1: - modality = 'all' - else: - modality = modalities[0] - else: - modalities = [m[0] for m in mytypes.workouttypes] - modality = 'all' - - - try: - rankingonly = options['rankingonly'] - except KeyError: # pragma: no cover - rankingonly = False - - try: - includereststrokes = options['includereststrokes'] - except KeyError: # pragma: no cover - includereststrokes = False - - - workstrokesonly = not includereststrokes - - waterboattype = mytypes.waterboattype - - - if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) - - if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) - - if enddate < startdate: # pragma: no cover - s = enddate - enddate = startdate - startdate = s - - - # get all indoor rows of in date range - - # process form - if request.method == 'POST': - form = DateRangeForm(request.POST) - modalityform = TrendFlexModalForm(request.POST) - flexaxesform = FlexAxesForm(request,request.POST) - if form.is_valid(): - startdate = form.cleaned_data['startdate'] - enddate = form.cleaned_data['enddate'] - if startdate > enddate: # pragma: no cover - s = enddate - enddate = startdate - startdate = s - startdatestring = startdate.strftime('%Y-%m-%d') - enddatestring = enddate.strftime('%Y-%m-%d') - if modalityform.is_valid(): - modality = modalityform.cleaned_data['modality'] - waterboattype = modalityform.cleaned_data['waterboattype'] - rankingonly = modalityform.cleaned_data['rankingonly'] - if modality == 'all': - modalities = [m[0] for m in mytypes.workouttypes] - else: # pragma: no cover - modalities = [modality] - - if modality != 'water': - waterboattype = [b[0] for b in mytypes.boattypes] - - - request.session['modalities'] = modalities - request.session['waterboattype'] = waterboattype - request.session['rankingonly'] = rankingonly - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - if flexaxesform.is_valid(): - xparam = flexaxesform.cleaned_data['xaxis'] - yparam1 = flexaxesform.cleaned_data['yaxis1'] - yparam2 = flexaxesform.cleaned_data['yaxis2'] - else: - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - includereststrokes = False - - workstrokesonly = not includereststrokes - modalityform = TrendFlexModalForm( - initial={ - 'modality':modality, - 'waterboattype':waterboattype, - 'rankingonly':rankingonly, - } - ) - initial = { - 'xaxis':xparam, - 'yaxis1':yparam1, - 'yaxis2':yparam2 - } - flexaxesform = FlexAxesForm(request,initial=initial) - - negtypes = [] - for b in mytypes.boattypes: - if b[0] not in waterboattype: # pragma: no cover - negtypes.append(b[0]) - - - - script = '' - div = get_call() - js_resources = '' - css_resources = '' - - - - - options = { - 'xparam': xparam, - 'yparam1': yparam1, - 'yparam2': yparam2, - 'modality': modality, - 'theuser': theuser.id, - 'waterboattype':waterboattype, - 'startdatestring':startdatestring, - 'enddatestring':enddatestring, - 'rankingonly':rankingonly, - 'includereststrokes':includereststrokes, - } - - request.session['options'] = options - - promember=0 - mayedit=0 - if not request.user.is_anonymous: - result = request.user.is_authenticated and ispromember(request.user) - if result: - promember = 1 - - - request.session['options'] = options - - - return render(request, 'cum_flex.html', - {'interactiveplot':script, - 'the_div':div, - 'js_res': js_resources, - 'css_res':css_resources, - 'id':theuser, - 'rower':r, - 'active':'nav-analysis', - 'theuser':theuser, - 'startdate':startdate, - 'enddate':enddate, - 'form':form, - 'optionsform':modalityform, - 'xparam':xparam, - 'yparam1':yparam1, - 'yparam2':yparam2, - 'promember':promember, - 'teams':get_my_teams(request.user), - 'flexaxesform':flexaxesform, - }) def planrequired_view(request): @@ -1895,7 +1295,7 @@ def rankings_view2(request,userid=0, if dateform.is_valid(): startdate = dateform.cleaned_data['startdate'] enddate = dateform.cleaned_data['enddate'] - if startdate > enddate: + if startdate > enddate: # pragma: no cover s = enddate enddate = startdate startdate = s @@ -1928,7 +1328,7 @@ def rankings_view2(request,userid=0, # get all 2k (if any) - this rower, in date range try: r = getrower(theuser) - except Rower.DoesNotExist: + except Rower.DoesNotExist: # pragma: no cover allergworkouts = [] r=0 @@ -2012,7 +1412,7 @@ def rankings_view2(request,userid=0, message = res[5] try: testcalc = pd.Series(res[6])*3 - except TypeError: + except TypeError: # pragma: no cover age = 0 else: @@ -2085,7 +1485,7 @@ def rankings_view2(request,userid=0, pwr3 = 50. velo3 = (pwr3/2.8)**(1./3.) - if np.isnan(velo3) or velo3 <= 0: + if np.isnan(velo3) or velo3 <= 0: # pragma: no cover velo3 = 1.0 t3 = rankingdistance/velo3 @@ -2206,21 +1606,21 @@ def otecp_toadmin_view(request,theuser=0, enddate=timezone.now(), startdatestring="", enddatestring="", - ): + ): # pragma: no cover - if startdatestring != "": + if startdatestring != "": # pragma: no cover try: startdate = iso8601.parse_date(startdatestring) except ParseError: pass - if enddatestring != "": + if enddatestring != "": # pragma: no cover try: enddate = iso8601.parse_date(enddatestring) except ParseError: pass - if theuser == 0: + if theuser == 0: # pragma: no cover theuser = request.user.id u = User.objects.get(id=theuser) @@ -2280,7 +1680,7 @@ def otwcp_toadmin_view(request,theuser=0, enddate=timezone.now(), startdatestring="", enddatestring="", - ): + ): # pragma: no cover if startdatestring != "": try: @@ -2345,1407 +1745,6 @@ def otwcp_toadmin_view(request,theuser=0, return response - -# Multi Flex Chart with Grouping -@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) -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def user_multiflex_select(request, - startdatestring="", - enddatestring="", - message='', - successmessage='', - startdate=timezone.now()-datetime.timedelta(days=30), - enddate=timezone.now(), - userid=0): - - r = getrequestrower(request,userid=userid) - user = r.user - - if 'options' in request.session: - options = request.session['options'] - else: - options = {} - - try: - palette = request.session['palette'] - except KeyError: - palette = 'monochrome_blue' - - try: - includereststrokes = request.session['includereststrokes'] - except KeyError: - includereststrokes = False - - try: - ploterrorbars = request.session['ploterrorbars'] - except: - ploterrorbars = False - - if 'startdate' in request.session: - startdate = iso8601.parse_date(request.session['startdate']) - - - if 'enddate' in request.session: - enddate = iso8601.parse_date(request.session['enddate']) - - try: - waterboattype = request.session['waterboattype'] - except KeyError: - waterboattype = mytypes.waterboattype - else: - waterboattype = mytypes.waterboattype - - if 'rankingonly' in request.session: - rankingonly = request.session['rankingonly'] - else: - rankingonly = False - - - if 'modalities' in request.session: - modalities = request.session['modalities'] - if len(modalities) > 1: - modality = 'all' - else: - modality = modalities[0] - else: - modalities = [m[0] for m in mytypes.workouttypes] - modality = 'all' - - if request.method == 'POST': - dateform = DateRangeForm(request.POST) - if dateform.is_valid(): - startdate = dateform.cleaned_data['startdate'] - enddate = dateform.cleaned_data['enddate'] - startdatestring = startdate.strftime('%Y-%m-%d') - enddatestring = enddate.strftime('%Y-%m-%d') - request.session['startdate'] = startdatestring - request.session['enddate'] = enddatestring - modalityform = TrendFlexModalForm(request.POST) - if modalityform.is_valid(): - modality = modalityform.cleaned_data['modality'] - waterboattype = modalityform.cleaned_data['waterboattype'] - rankingonly = modalityform.cleaned_data['rankingonly'] - if modality == 'all': - modalities = [m[0] for m in mytypes.workouttypes] - else: - modalities = [modality] - - if modality != 'water': - waterboattype = [b[0] for b in mytypes.boattypes] - - - request.session['modalities'] = modalities - request.session['waterboattype'] = waterboattype - request.session['rankingonly'] = rankingonly - else: - dateform = DateRangeForm(initial={ - 'startdate':startdate, - 'enddate':enddate, - }) - - - startdate = datetime.datetime.combine(startdate,datetime.time()) - enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) - #enddate = enddate+datetime.timedelta(days=1) - - if startdatestring: - startdate = iso8601.parse_date(startdatestring) - if enddatestring: - enddate = iso8601.parse_date(enddatestring) - - if enddate < startdate: - s = enddate - enddate = startdate - startdate = s - - - negtypes = [] - for b in mytypes.boattypes: - if b[0] not in waterboattype: - negtypes.append(b[0]) - - if rankingonly: - rankingpiece = [True] - else: - rankingpiece = [True,False] - - # make sure the dates are not naive - try: - startdate = pytz.utc.localize(startdate) - except (ValueError, AttributeError): - pass - try: - enddate = pytz.utc.localize(enddate) - except (ValueError, AttributeError): - pass - - workouts = Workout.objects.filter( - user=r, - startdatetime__gte=startdate, - startdatetime__lte=enddate, - workouttype__in=modalities, - rankingpiece__in=rankingpiece - ).order_by( - "-date", "-starttime" - ).exclude( - boattype__in=negtypes - ) - - query = request.GET.get('q') - if query: - query_list = query.split() - workouts = workouts.filter( - reduce(operator.and_, - (Q(name__icontains=q) for q in query_list)) | - reduce(operator.and_, - (Q(notes__icontains=q) for q in query_list)) - ) - searchform = SearchForm(initial={'q':query}) - else: - searchform = SearchForm() - - form = WorkoutMultipleCompareForm() - form.fields["workouts"].queryset = workouts - - chartform = MultiFlexChoiceForm(initial={ - 'palette':palette, - 'ploterrorbars':ploterrorbars, - 'includereststrokes':includereststrokes, - }) - - modalityform = TrendFlexModalForm(initial={ - 'modality':modality, - 'waterboattype':waterboattype, - 'rankingonly':rankingonly, - }) - - messages.info(request,successmessage) - messages.error(request,message) - - startdatestring = startdate.strftime('%Y-%m-%d') - enddatestring = enddate.strftime('%Y-%m-%d') - request.session['startdate'] = startdatestring - request.session['enddate'] = enddatestring - - request.session['waterboattype'] = waterboattype - request.session['rankingonly'] = rankingonly - request.session['modalities'] = modalities - - - breadcrumbs = [ - { - 'url':'/rowers/analysis', - 'name':'Analysis' - }, - { - 'url':reverse(user_multiflex_select,kwargs={'userid':userid}), - 'name': 'Compare Select' - }, - { - 'url':reverse('multi_compare_view'), - 'name': 'Comparison Chart' - } - ] - - return render(request, 'user_multiflex_select.html', - {'workouts': workouts, - 'dateform':dateform, - 'breadcrumbs':breadcrumbs, - 'startdate':startdate, - 'enddate':enddate, - 'theuser':user, - 'rower':r, - 'form':form, - 'chartform':chartform, - 'searchform':searchform, - 'modalityform':modalityform, - 'teams':get_my_teams(request.user), - }) - -@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) -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def multiflex_data(request,userid=0, - options={ - 'includereststrokes':False, - 'ploterrorbars':False, - 'userid':0, - 'palette': 'monochrome_blue', - 'groupby': 'spm', - 'binsize': 1, - 'xparam': 'hr', - 'yparam': 'pace', - 'spmmin': 15, - 'spmmax': 55, - 'workmin': 400, - 'workmax': 1500, - 'ids': [], - 'ploterrorbars':False, - }): - - def_options = options - - if 'options' in request.session: - options = request.session['options'] - - try: - includereststrokes = options['includereststrokes'] - except KeyError: - includereststrokes = False - - try: - ploterrorbars = options['ploterrorbars'] - except KeyError: - ploterrorbars = False - - try: - palette = request.session['palette'] - except KeyError: - palette = 'monochrome_blue' - - workstrokesonly = not includereststrokes - - if userid==0: - userid = request.user.id - - - palette = keyvalue_get_default('palette',options, def_options) - groupby = keyvalue_get_default('groupby',options, def_options) - binsize = keyvalue_get_default('binsize',options, def_options) - xparam = keyvalue_get_default('xparam',options, def_options) - yparam = keyvalue_get_default('yparam',options, def_options) - spmmin = keyvalue_get_default('spmmin',options, def_options) - spmmax = keyvalue_get_default('spmmax',options, def_options) - workmin = keyvalue_get_default('workmin',options, def_options) - workmax = keyvalue_get_default('workmax',options, def_options) - ids = keyvalue_get_default('ids',options, def_options) - - workouts = [] - - for id in ids: - try: - workouts.append(Workout.objects.get(id=id)) - except Workout.DoesNotExist: - pass - - labeldict = { - int(w.id): w.__str__() for w in workouts - } - - fieldlist,fielddict = dataprep.getstatsfields() - fieldlist = [xparam,yparam,groupby, - 'workoutid','spm','driveenergy', - 'workoutstate'] - - # prepare data frame - datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist) - - if xparam == groupby: - datadf['groupby'] = datadf[xparam] - groupy = 'groupby' - - datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) - - - datadf = dataprep.filter_df(datadf,'spm',spmmin, - largerthan=True) - datadf = dataprep.filter_df(datadf,'spm',spmmax, - largerthan=False) - - datadf = dataprep.filter_df(datadf,'driveenergy',workmin, - largerthan=True) - datadf = dataprep.filter_df(datadf,'driveneergy',workmax, - largerthan=False) - - - datadf.dropna(axis=0,how='any',inplace=True) - - - datemapping = { - w.id:w.date for w in workouts - } - - datadf['date'] = datadf['workoutid'] - datadf['date'].replace(datemapping,inplace=True) - - today = datetime.date.today() - try: - datadf['days ago'] = map(lambda x : x.days, datadf.date - today) - except TypeError: - datadf['days ago'] = 0 - - if groupby != 'date': - try: - bins = np.arange(datadf[groupby].min()-binsize, - datadf[groupby].max()+binsize, - binsize) - groups = datadf.groupby(pd.cut(datadf[groupby],bins,labels=False)) - except (ValueError, AttributeError): - messages.error( - request, - "Unable to compete. Probably not enough data selected" - ) - url = reverse(user_multiflex_select) - return HttpResponseRedirect(url) - else: - bins = np.arange(datadf['days ago'].min()-binsize, - datadf['days ago'].max()+binsize, - binsize, - ) - groups = datadf.groupby(pd.cut(datadf['days ago'], bins, - labels=False)) - - - xvalues = groups.mean()[xparam] - yvalues = groups.mean()[yparam] - xerror = groups.std()[xparam] - yerror = groups.std()[yparam] - groupsize = groups.count()[xparam] - - mask = groupsize <= min([0.01*groupsize.sum(),0.2*groupsize.mean()]) - xvalues.loc[mask] = np.nan - - yvalues.loc[mask] = np.nan - xerror.loc[mask] = np.nan - yerror.loc[mask] = np.nan - groupsize.loc[mask] = np.nan - - xvalues.dropna(inplace=True) - yvalues.dropna(inplace=True) - xerror.dropna(inplace=True) - yerror.dropna(inplace=True) - groupsize.dropna(inplace=True) - - if len(groupsize) == 0: - messages.error(request,'No data in selection') - url = reverse(user_multiflex_select) - return HttpResponseRedirect(url) - else: - groupsize = 30.*np.sqrt(groupsize/float(groupsize.max())) - - df = pd.DataFrame({ - xparam:xvalues, - yparam:yvalues, - 'x':xvalues, - 'y':yvalues, - 'xerror':xerror, - 'yerror':yerror, - 'groupsize':groupsize, - }) - - - if yparam == 'pace': - df['y'] = dataprep.paceformatsecs(df['y']/1.0e3) - - aantal = len(df) - - if groupby != 'date': - try: - df['groupval'] = groups.mean()[groupby] - df['groupval'].loc[mask] = np.nan - - groupcols = df['groupval'] - except (ValueError, AttributeError): - df['groupval'] = groups.mean()[groupby].fillna(value=0) - df['groupval'].loc[mask] = np.nan - groupcols = df['groupval'] - except KeyError: - messages.error(request,'Data selection error') - url = reverse(user_multiflex_select) - return HttpResponseRedirect(url) - else: - try: - dates = groups.min()[groupby] - dates.loc[mask] = np.nan - dates.dropna(inplace=True) - df['groupval'] = [x.strftime("%Y-%m-%d") for x in dates] - df['groupval'].loc[mask] = np.nan - groupcols = 100.*np.arange(aantal)/float(aantal) - except AttributeError: - df['groupval'] = groups.mean()['days ago'].fillna(value=0) - groupcols = 100.*np.arange(aantal)/float(aantal) - - - groupcols = (groupcols-groupcols.min())/(groupcols.max()-groupcols.min()) - - if aantal == 1: - groupcols = np.array([1.]) - - - colors = range_to_color_hex(groupcols,palette=palette) - - df['color'] = colors - - clegendx = np.arange(0,1.2,.2) - legcolors = range_to_color_hex(clegendx,palette=palette) - if groupby != 'date': - clegendy = df['groupval'].min()+clegendx*(df['groupval'].max()-df['groupval'].min()) - else: - clegendy = df.index.min()+clegendx*(df.index.max()-df.index.min()) - - - - colorlegend = zip(range(6),clegendy,legcolors) - - - if userid == 0: - extratitle = '' - else: - u = User.objects.get(id=userid) - extratitle = ' '+u.first_name+' '+u.last_name - - - - script,div = interactive_multiflex(df,xparam,yparam, - groupby, - extratitle=extratitle, - ploterrorbars=ploterrorbars, - binsize=binsize, - colorlegend=colorlegend, - spmmin=spmmin,spmmax=spmmax, - workmin=workmin,workmax=workmax) - - scripta= script.split('\n')[2:-1] - script = ''.join(scripta) - - - return JSONResponse({ - "script":script, - "div":div, - }) - - -@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) -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def multiflex_view(request,userid=0, - options={ - 'includereststrokes':False, - 'ploterrorbars':False, - }): - - if 'options' in request.session: - options = request.session['options'] - - try: - includereststrokes = options['includereststrokes'] - except KeyError: - includereststrokes = False - - try: - ploterrorbars = options['ploterrorbars'] - except KeyError: - ploterrorbars = False - - try: - palette = request.session['palette'] - except KeyError: - palette = 'monochrome_blue' - - if 'startdate' in request.session: - startdate = iso8601.parse_date(request.session['startdate']) - - - if 'enddate' in request.session: - enddate = iso8601.parse_date(request.session['enddate']) - - workstrokesonly = not includereststrokes - - if userid==0: - userid = request.user.id - - if request.method == 'POST' and 'workouts' in request.POST: - form = WorkoutMultipleCompareForm(request.POST) - chartform = MultiFlexChoiceForm(request.POST) - if form.is_valid() and chartform.is_valid(): - cd = form.cleaned_data - workouts = cd['workouts'] - xparam = chartform.cleaned_data['xparam'] - yparam = chartform.cleaned_data['yparam'] - includereststrokes = chartform.cleaned_data['includereststrokes'] - ploterrorbars = chartform.cleaned_data['ploterrorbars'] - - workstrokesonly = not includereststrokes - palette = chartform.cleaned_data['palette'] - - groupby = chartform.cleaned_data['groupby'] - binsize = chartform.cleaned_data['binsize'] - if binsize <= 0: - binsize = 1 - if groupby == 'pace': - binsize *= 1000 - - spmmin = chartform.cleaned_data['spmmin'] - spmmax = chartform.cleaned_data['spmmax'] - workmin = chartform.cleaned_data['workmin'] - workmax = chartform.cleaned_data['workmax'] - - ids = [int(w.id) for w in workouts] - request.session['ids'] = ids - - else: - return HttpResponse("Form is not valid") - elif request.method == 'POST' and 'ids' in request.session: - chartform = MultiFlexChoiceForm(request.POST) - if chartform.is_valid(): - xparam = chartform.cleaned_data['xparam'] - yparam = chartform.cleaned_data['yparam'] - includereststrokes = chartform.cleaned_data['includereststrokes'] - ploterrorbars = chartform.cleaned_data['ploterrorbars'] - request.session['ploterrorbars'] = ploterrorbars - request.session['includereststrokes'] = includereststrokes - workstrokesonly = not includereststrokes - palette = chartform.cleaned_data['palette'] - - groupby = chartform.cleaned_data['groupby'] - binsize = chartform.cleaned_data['binsize'] - if binsize <= 0: - binsize = 1 - if groupby == 'pace': - binsize *= 1000. - - spmmin = chartform.cleaned_data['spmmin'] - spmmax = chartform.cleaned_data['spmmax'] - workmin = chartform.cleaned_data['workmin'] - workmax = chartform.cleaned_data['workmax'] - - ids = request.session['ids'] - request.session['ids'] = ids - workouts = dataprep.get_workouts(ids,userid) - if not workouts: - message = 'Error: Workouts in session storage do not belong to this user.' - messages.error(request,message) - url = reverse(user_multiflex_select, - kwargs={ - 'userid':userid, - } - ) - return HttpResponseRedirect(url) - - # workouts = [Workout.objects.get(id=id) for id in ids] - - - else: - return HttpResponse("invalid form") - else: - url = reverse(user_multiflex_select) - return HttpResponseRedirect(url) - - div = get_call() - - options['includereststrokes'] = includereststrokes - options['ploterrorbars'] = ploterrorbars - options['userid'] = userid - options['palette'] = palette - options['groupby'] = groupby - options['binsize'] = binsize - options['xparam'] = xparam - options['yparam'] = yparam - options['spmmin'] = spmmin - options['spmmax'] = spmmax - options['workmin'] = workmin - options['workmax'] = workmax - options['idso'] = ids - - - request.session['options'] = options - - r = getrequestrower(request,userid=userid) - - breadcrumbs = [ - { - 'url':'/rowers/analysis', - 'name':'Analysis' - }, - { - 'url':reverse(user_multiflex_select,kwargs={'userid':userid}), - 'name': 'Trend Flex Select' - }, - { - 'url':reverse(multiflex_view), - 'name': 'Trend Flex Chart' - } - ] - - - return render(request,'multiflex.html', - {'interactiveplot':'', - 'active':'nav-analysis', - 'rower':r, - 'breadcrumbs':breadcrumbs, - 'the_div':div, - 'active':'nav-analysis', - 'chartform':chartform, - 'userid':userid, - 'teams':get_my_teams(request.user), - }) - - -# Box plots -@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) -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def user_boxplot_select(request, - startdatestring="", - enddatestring="", - message='', - successmessage='', - startdate=timezone.now()-datetime.timedelta(days=30), - enddate=timezone.now(), - options={ - 'includereststrokes':False, - 'workouttypes':['rower','dynamic','slides'], - 'waterboattype':mytypes.waterboattype, - 'rankingonly':False, - }, - userid=0): - - r = getrequestrower(request,userid=userid) - user = r.user - userid = user.id - - if 'options' in request.session: - options = request.session['options'] - - - try: - workouttypes = options['workouttypes'] - except KeyError: - workouttypes = ['rower','dynamic','slides'] - - try: - rankingonly = options['rankingonly'] - except KeyError: - rankingonly = False - - try: - includereststrokes = options['includereststrokes'] - except KeyError: - includereststrokes = False - - if 'startdate' in request.session: - startdate = iso8601.parse_date(request.session['startdate']) - - - if 'enddate' in request.session: - enddate = iso8601.parse_date(request.session['enddate']) - - workstrokesonly = not includereststrokes - - waterboattype = mytypes.waterboattype - - - if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) - - if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) - - if enddate < startdate: - s = enddate - enddate = startdate - startdate = s - - - if request.method == 'POST': - dateform = DateRangeForm(request.POST) - if dateform.is_valid(): - startdate = dateform.cleaned_data['startdate'] - enddate = dateform.cleaned_data['enddate'] - startdatestring = startdate.strftime('%Y-%m-%d') - enddatestring = enddate.strftime('%Y-%m-%d') - request.session['startdate'] = startdatestring - request.session['enddate'] = enddatestring - optionsform = TrendFlexModalForm(request.POST) - if optionsform.is_valid(): - modality = optionsform.cleaned_data['modality'] - waterboattype = optionsform.cleaned_data['waterboattype'] - if modality == 'all': - modalities = [m[0] for m in mytypes.workouttypes] - else: - modalities = [modality] - if modality != 'water': - waterboattype = [b[0] for b in mytypes.boattypes] - - - if 'rankingonly' in optionsform.cleaned_data: - rankingonly = optionsform.cleaned_data['rankingonly'] - else: - rankingonly = False - - request.session['modalities'] = modalities - request.session['waterboattype'] = waterboattype - else: - dateform = DateRangeForm(initial={ - 'startdate':startdate, - 'enddate':enddate, - }) - - if 'modalities' in request.session: - modalities = request.session['modalities'] - if len(modalities) > 1: - modality = 'all' - else: - modality = modalities[0] - else: - modalities = [m[0] for m in mytypes.workouttypes] - modality = 'all' - - - - - negtypes = [] - for b in mytypes.boattypes: - if b[0] not in waterboattype: - negtypes.append(b[0]) - - - startdate = datetime.datetime.combine(startdate,datetime.time()) - enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) - #enddate = enddate+datetime.timedelta(days=1) - - if startdatestring: - startdate = iso8601.parse_date(startdatestring) - if enddatestring: - enddate = iso8601.parse_date(enddatestring) - - if enddate < startdate: - s = enddate - enddate = startdate - startdate = s - - negtypes = [] - for b in mytypes.boattypes: - if b[0] not in waterboattype: - negtypes.append(b[0]) - - # make sure the dates are not naive - try: - startdate = pytz.utc.localize(startdate) - except (ValueError, AttributeError): - pass - try: - enddate = pytz.utc.localize(enddate) - except (ValueError, AttributeError): - pass - - workouts = Workout.objects.filter(user=r, - startdatetime__gte=startdate, - startdatetime__lte=enddate, - workouttype__in=modalities, - ).order_by( - "-date", "-starttime" - ).exclude(boattype__in=negtypes) - # workouttypes = [w for w in workouttypes if w not in mytypes.otwtypes] - - if rankingonly: - workouts = workouts.exclude(rankingpiece=False) - - query = request.GET.get('q') - if query: - query_list = query.split() - workouts = workouts.filter( - reduce(operator.and_, - (Q(name__icontains=q) for q in query_list)) | - reduce(operator.and_, - (Q(notes__icontains=q) for q in query_list)) - ) - searchform = SearchForm(initial={'q':query}) - else: - searchform = SearchForm() - - form = WorkoutMultipleCompareForm() - form.fields["workouts"].queryset = workouts - - chartform = BoxPlotChoiceForm() - optionsform = TrendFlexModalForm(initial={ - 'modality':modality, - 'waterboattype':waterboattype, - 'rankingonly':rankingonly, - }) - - messages.info(request,successmessage) - messages.error(request,message) - - startdatestring = startdate.strftime('%Y-%m-%d') - enddatestring = enddate.strftime('%Y-%m-%d') - request.session['startdate'] = startdatestring - request.session['enddate'] = enddatestring - - - breadcrumbs = [ - { - 'url':'/rowers/analysis', - 'name':'Analysis' - }, - { - 'url':reverse(user_boxplot_select,kwargs={'userid':userid}), - 'name': 'BoxPlot Select' - }, - ] - return render(request, 'user_boxplot_select.html', - {'workouts': workouts, - 'dateform':dateform, - 'startdate':startdate, - 'enddate':enddate, - 'rower':r, - 'breadcrumbs':breadcrumbs, - 'theuser':user, - 'form':form, - 'active':'nav-analysis', - 'chartform':chartform, - 'searchform':searchform, - 'optionsform':optionsform, - 'teams':get_my_teams(request.user), - }) - -@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) -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def boxplot_view_data(request,userid=0, - options={ - 'includereststrokes':False, - 'spmmin':15, - 'spmmax':55, - 'workmin':0, - 'workmax':1500, - 'ids':[], - 'userid':0, - 'plotfield':'spm', - }): - - if 'options' in request.session: - options = request.session['options'] - - try: - includereststrokes = options['includereststrokes'] - spmmin = options['spmmin'] - spmmax = options['spmmax'] - workmin = options['workmin'] - workmax = options['workmax'] - ids = options['ids'] - userid = options['userid'] - plotfield = options['plotfield'] - except KeyError: - includereststrokes = False - spmmin = 15 - spmmax = 55 - workmin = 0 - workmax = 55 - ids = [] - userid = 0 - plotfield = 'spm' - - - workstrokesonly = not includereststrokes - - if userid==0: - userid = request.user.id - - workouts = [] - - - if not ids: - return JSONResponse({ - "script":'', - "div":'No data found' - }) - - for id in ids: - try: - workouts.append(Workout.objects.get(id=id)) - except Workout.DoesNotExist: - pass - - labeldict = { - int(w.id): w.__str__() for w in workouts - } - - - datemapping = { - w.id:w.date for w in workouts - } - - - - fieldlist,fielddict = dataprep.getstatsfields() - fieldlist = [plotfield,'workoutid','spm','driveenergy', - 'workoutstate'] - - # prepare data frame - datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist) - - - - datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) - - datadf = dataprep.filter_df(datadf,'spm',spmmin, - largerthan=True) - datadf = dataprep.filter_df(datadf,'spm',spmmax, - largerthan=False) - datadf = dataprep.filter_df(datadf,'driveenergy',workmin, - largerthan=True) - datadf = dataprep.filter_df(datadf,'driveneergy',workmax, - largerthan=False) - - datadf.dropna(axis=0,how='any',inplace=True) - - - datadf['workoutid'].replace(datemapping,inplace=True) - datadf.rename(columns={"workoutid":"date"},inplace=True) - datadf = datadf.sort_values(['date']) - - if userid == 0: - extratitle = '' - else: - u = User.objects.get(id=userid) - extratitle = ' '+u.first_name+' '+u.last_name - - - - script,div = interactive_boxchart(datadf,plotfield, - extratitle=extratitle, - spmmin=spmmin,spmmax=spmmax,workmin=workmin,workmax=workmax) - - scripta = script.split('\n')[2:-1] - script = ''.join(scripta) - - - return JSONResponse({ - "script":script, - "div":div, - }) - -@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) -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def boxplot_view(request,userid=0, - options={ - 'includereststrokes':False, - 'rankingonly':False, - }): - - if 'options' in request.session: - options = request.session['options'] - else: - options = {} - - try: - includereststrokes = options['includereststrokes'] - except KeyError: - includereststrokes = False - options['includereststrokes'] = False - - try: - rankingonly = options['rankingonly'] - except KeyError: - rankingonly = False - options['rankingonly'] = False - - workstrokesonly = not includereststrokes - - if userid==0: - userid = request.user.id - - - if request.method == 'POST' and 'workouts' in request.POST: - form = WorkoutMultipleCompareForm(request.POST) - chartform = BoxPlotChoiceForm(request.POST) - if form.is_valid() and chartform.is_valid(): - cd = form.cleaned_data - workouts = cd['workouts'] - plotfield = chartform.cleaned_data['yparam'] - includereststrokes = chartform.cleaned_data['includereststrokes'] - request.session['includereststrokes'] = includereststrokes - workstrokesonly = not includereststrokes - - spmmin = chartform.cleaned_data['spmmin'] - spmmax = chartform.cleaned_data['spmmax'] - workmin = chartform.cleaned_data['workmin'] - workmax = chartform.cleaned_data['workmax'] - - ids = [int(w.id) for w in workouts] - request.session['ids'] = ids - - else: - url = reverse(user_boxplot_select,kwargs={'userid':userid}) - return HttpResponseRedirect(url) - elif request.method == 'POST' and 'ids' in request.session: - chartform = BoxPlotChoiceForm(request.POST) - if chartform.is_valid(): - plotfield = chartform.cleaned_data['yparam'] - includereststrokes = chartform.cleaned_data['includereststrokes'] - spmmin = chartform.cleaned_data['spmmin'] - spmmax = chartform.cleaned_data['spmmax'] - workmin = chartform.cleaned_data['workmin'] - workmax = chartform.cleaned_data['workmax'] - request.session['includereststrokes'] = includereststrokes - workstrokesonly = not includereststrokes - ids = request.session['ids'] - request.session['ids'] = ids - - - else: - url = reverse(user_boxplot_select,kwargs={'userid':userid}) - return HttpResponseRedirect(url) - else: - url = reverse(user_boxplot_select,kwargs={'userid':userid}) - return HttpResponseRedirect(url) - - div = get_call() - - - options['spmmin'] = spmmin - options['spmmax'] = spmmax - options['workmin'] = workmin - options['workmax'] = workmax - options['ids'] = ids - options['userid'] = userid - options['plotfield'] = plotfield - options['rankingonly'] = rankingonly - - - request.session['options'] = options - - r = getrequestrower(request,userid=userid) - breadcrumbs = [ - { - 'url':'/rowers/Analysis', - 'name':'Analysis' - }, - { - 'url':reverse(user_boxplot_select,kwargs={'userid':userid}), - 'name': 'BoxPlot Select' - }, - { - 'url':reverse(boxplot_view,kwargs={'userid':userid}), - 'name': 'BoxPlot Select' - }, - ] - - return render(request,'boxplot.html', - {'interactiveplot':'', - 'the_div':div, - 'rower':r, - 'breadcrumbs':breadcrumbs, - 'active':'nav-analysis', - 'chartform':chartform, - 'userid':userid, - 'teams':get_my_teams(request.user), - }) - - -# Cumulative stats page -@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) -@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) -def cumstats(request,userid=0, - startdate=timezone.now()-datetime.timedelta(days=30), - enddate=timezone.now(), - deltadays=-1, - startdatestring="", - enddatestring="", - options={ - 'includereststrokes':False, - 'workouttypes':['rower','dynamic','slides'], - 'waterboattype':mytypes.waterboattype, - 'rankingonly':False, - }): - - r = getrequestrower(request,userid=userid) - theuser = r.user - - if 'waterboattype' in request.session: - waterboattype = request.session['waterboattype'] - else: - waterboattype = mytypes.waterboattype - - - if 'rankingonly' in request.session: - rankingonly = request.session['rankingonly'] - else: - rankingonly = False - - if 'modalities' in request.session: - modalities = request.session['modalities'] - if len(modalities) > 1: - modality = 'all' - else: - modality = modalities[0] - else: - modalities = [m[0] for m in mytypes.workouttypes] - modality = 'all' - - - try: - rankingonly = options['rankingonly'] - except KeyError: - rankingonly = False - - try: - includereststrokes = options['includereststrokes'] - except KeyError: - includereststrokes = False - - - workstrokesonly = not includereststrokes - - waterboattype = mytypes.waterboattype - - - if startdatestring != "": - startdate = iso8601.parse_date(startdatestring) - - if enddatestring != "": - enddate = iso8601.parse_date(enddatestring) - - if enddate < startdate: - s = enddate - enddate = startdate - startdate = s - - - # get all indoor rows of in date range - - # process form - if request.method == 'POST': - form = DateRangeForm(request.POST) - modalityform = TrendFlexModalForm(request.POST) - if form.is_valid(): - startdate = form.cleaned_data['startdate'] - enddate = form.cleaned_data['enddate'] - if startdate > enddate: - s = enddate - enddate = startdate - startdate = s - startdatestring = startdate.strftime('%Y-%m-%d') - enddatestring = enddate.strftime('%Y-%m-%d') - if modalityform.is_valid(): - modality = modalityform.cleaned_data['modality'] - waterboattype = modalityform.cleaned_data['waterboattype'] - rankingonly = modalityform.cleaned_data['rankingonly'] - if modality == 'all': - modalities = [m[0] for m in mytypes.workouttypes] - else: - modalities = [modality] - - if modality != 'water': - waterboattype = [b[0] for b in mytypes.boattypes] - - - request.session['modalities'] = modalities - request.session['waterboattype'] = waterboattype - request.session['rankingonly'] = rankingonly - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - else: - form = DateRangeForm(initial={ - 'startdate': startdate, - 'enddate': enddate, - }) - includereststrokes = False - - workstrokesonly = not includereststrokes - modalityform = TrendFlexModalForm( - initial={ - 'modality':modality, - 'waterboattype':waterboattype, - 'rankingonly':rankingonly, - } - ) - - negtypes = [] - for b in mytypes.boattypes: - if b[0] not in waterboattype: - negtypes.append(b[0]) - - - - script = '' - div = get_call() - js_resources = '' - css_resources = '' - - options = { - 'modality': modality, - 'userid': theuser.id, - 'waterboattype':waterboattype, - 'startdatestring':startdatestring, - 'enddatestring':enddatestring, - 'rankingonly':rankingonly, - 'includereststrokes':includereststrokes, - } - - - request.session['options'] = options - - - if modality == 'all': - modalities = [m[0] for m in mytypes.workouttypes] - else: - modalities = [modality] - - try: - startdate = iso8601.parse_date(startdatestring) - except ParseError: - startdate = timezone.now()-datetime.timedelta(days=7) - - try: - enddate = iso8601.parse_date(enddatestring) - except ParseError: - enddate = timezone.now() - - - if enddate < startdate: - s = enddate - enddate = startdate - startdate = s - - promember=0 - if theuser == 0: - theuser = request.user.id - - if not request.user.is_anonymous: - r = getrower(request.user) - result = request.user.is_authenticated and ispromember(request.user) - if result: - promember=1 - - r2 = getrower(theuser) - - if rankingonly: - rankingpiece = [True,] - else: - rankingpiece = [True,False] - - allworkouts = Workout.objects.filter( - user=r2, - workouttype__in=modalities, - boattype__in=waterboattype, - startdatetime__gte=startdate, - startdatetime__lte=enddate, - rankingpiece__in=rankingpiece - ).order_by("-date", "-starttime") - - ids = [int(workout.id) for workout in allworkouts] - - datemapping = { - w.id:w.date for w in allworkouts - } - - - - fieldlist,fielddict = dataprep.getstatsfields() - - # prepare data frame - datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist) - - datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) - try: - datadf['pace'] = datadf['pace']/1000. - except KeyError: - pass - - request.session['rowerid'] = r.id - - if datadf.empty: - stats = {} - cordict = {} - - response = render(request, - 'cumstats.html', - { - 'stats':stats, - 'teams':get_my_teams(request.user), - 'options':options, - 'active':'nav-analysis', - 'rower':r, - 'id':theuser, - 'theuser':theuser, - 'startdate':startdate, - 'enddate':enddate, - 'form':form, - 'optionsform':modalityform, - 'cordict':cordict, - }) - - request.session['options'] = options - - return response - - - - # Create stats - stats = {} - try: - fielddict.pop('pace') - except KeyError: - pass - - for field,verbosename in fielddict.items(): - thedict = { - 'mean':datadf[field].mean(), - 'min': datadf[field].min(), - 'std': datadf[field].std(), - 'max': datadf[field].max(), - 'median': datadf[field].median(), - 'firstq':datadf[field].quantile(q=0.25), - 'thirdq':datadf[field].quantile(q=0.75), - 'verbosename':verbosename, - } - stats[field] = thedict - - # Create a dict with correlation values - cor = datadf.corr(method='spearman') - cor.fillna(value=0,inplace=True) - cordict = {} - for field1,verbosename1 in fielddict.items(): - thedict = {} - for field2,verbosename2 in fielddict.items(): - try: - thedict[verbosename2] = cor.loc[field1,field2] - except KeyError: - thedict[verbosename2] = 0 - - cordict[verbosename1] = thedict - - # set options form correctly - initial = {} - initial['includereststrokes'] = includereststrokes - initial['waterboattype'] = waterboattype - initial['rankingonly'] = rankingonly - - - response = render(request, - 'cumstats.html', - { - 'stats':stats, - 'teams':get_my_teams(request.user), - 'active':'nav-analysis', - 'rower':r, - 'options':options, - 'id':theuser, - 'theuser':theuser, - 'startdate':startdate, - 'enddate':enddate, - 'form':form, - 'optionsform':modalityform, - 'cordict':cordict, - }) - - request.session['options'] = options - - return response - - def agegroupcpview(request,age,normalize=0): script,div = interactive_agegroupcpchart(age,normalized=normalize) @@ -3808,7 +1807,7 @@ def alerts_view(request,userid=0): stats = [] - for alert in alerts: + for alert in alerts: # pragma: no cover stats.append(alert_get_stats(alert)) @@ -4219,7 +2218,7 @@ def history_view(request,userid=0): ddict['id'] = wtype try: ddict['wtype'] = mytypes.workouttypes_ordered[wtype] - except KeyError: + except KeyError: # pragma: no cover ddict['wtype'] = wtype ddict['distance'] = wmeters ddict['duration'] = "{whours}:{wminutes:02d}:{wseconds:02d}".format( @@ -4330,7 +2329,7 @@ def history_view_data(request,userid=0): yaxis = request.GET.get('yaxis','duration') - if yaxis.lower() not in ['duration','rscore','trimp']: + if yaxis.lower() not in ['duration','rscore','trimp']: # pragma: no cover yaxis = 'duration' g_workouts = Workout.objects.filter( @@ -4368,9 +2367,9 @@ def history_view_data(request,userid=0): a_workouts = g_workouts.filter(workouttype=wtype) wmeters, whours, wminutes,wseconds = get_totals(a_workouts) ddict = {} - try: + try: # pragma: no cover ddict['wtype'] = mytypes.workouttypes_ordered[wtype] - except KeyError: + except KeyError: # pragma: no cover ddict['wtype'] = wtype ddict['id'] = wtype @@ -4382,7 +2381,7 @@ def history_view_data(request,userid=0): ddf = getsmallrowdata_db(columns,ids=[w.id for w in a_workouts]) try: ddf['deltat'] = ddf['time'].diff().clip(lower=0) - except KeyError: + except KeyError: # pragma: no cover pass @@ -4393,7 +2392,7 @@ def history_view_data(request,userid=0): ddict['hrmean'] = int(wavg(ddf,'hr','deltat')) try: ddict['hrmax'] = ddf['hr'].max().astype(int) - except (ValueError, AttributeError): + except (ValueError, AttributeError): # pragma: no cover ddict['hrmax'] = 0 ddict['powermean'] = int(wavg(ddf,'power','deltat')) @@ -4417,7 +2416,7 @@ def history_view_data(request,userid=0): try: totalsdict['hrmean'] = int(wavg(df,'hr','deltat')) totalsdict['hrmax'] = df['hr'].max().astype(int) - except KeyError: + except KeyError: # pragma: no cover totalsdict['hrmean'] = 0 totalsdict['hrmax'] = 0 From 456e9df73ef8a8ccbd39cbf6d6b90e27100b7646 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 15 Apr 2021 18:13:41 +0200 Subject: [PATCH 2/8] removing some printing --- rowers/management/commands/processemail.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index 8a7d758d..ca92e5a5 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -65,8 +65,6 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False): # filename = os.path.abspath(fileobj.name) except AttributeError: filename = fileobj[6:] - if testing: - print('Attribute Error', filename) # test if file exists and is not empty @@ -74,12 +72,8 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False): with io.open('media/'+filename,'rb') as fop: line = fop.readline() except (IOError, UnicodeEncodeError): - if testing: - print('IOError',filename,'media/'+filename) return 0 - if testing: - print('Creating workout from email') # set user if rower.user.is_staff and 'username' in uploadoptions: @@ -134,8 +128,6 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False): except VirtualRace.DoesNotExist: pass - if testing: - print('Workout id = {workoutid}'.format(workoutid=workoutid)) return workoutid @@ -281,15 +273,6 @@ class Command(BaseCommand): else: # move attachment and make workout - if testing: - try: - print(name) - except UnicodeEncodeError: - print("Unicode Error") - try: - print(attachment.document) - except UnicodeEncodeError: - pass workoutid = processattachment( rower, attachment.document, name, uploadoptions, From b8eba290195f0f7830b963b6852e765ea4a8c6e3 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 15 Apr 2021 18:56:58 +0200 Subject: [PATCH 3/8] 100 percent coverage on analysis views --- rowers/stravastuff.py | 4 +--- rowers/views/analysisviews.py | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/rowers/stravastuff.py b/rowers/stravastuff.py index d0914b77..c1b319ae 100644 --- a/rowers/stravastuff.py +++ b/rowers/stravastuff.py @@ -177,8 +177,6 @@ def set_strava_athlete_id(user): r.strava_owner_id = response.json()['id'] r.save() return response.json()['id'] - else: - print(response) return 0 @@ -775,7 +773,7 @@ def workout_strava_upload(user,w, quick=False,asynchron=True): activity_type = mytypes.stravamapping[w.workouttype] except KeyError: activity_type = 'Rowing' - print(w.workouttype,activity_type) + with open(tcxfile,'rb') as f: res,mes = handle_stravaexport( f,w.name, diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index b945f96f..98406c59 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -1916,7 +1916,7 @@ def alert_create_view(request,userid=0): @permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) def alert_report_view(request,id=0,userid=0,nperiod=0): r = getrequestrower(request,userid=userid) - if userid == 0: + if userid == 0: # pragma: no cover userid = request.user.id alert = Alert.objects.get(id=id) @@ -1924,11 +1924,11 @@ def alert_report_view(request,id=0,userid=0,nperiod=0): try: alert = Alert.objects.get(id=id) - except Alert.DoesNotExist: + except Alert.DoesNotExist: # pragma: no cover raise Http404("This alert doesn't exist") - if not checkalertowner(alert,request.user): + if not checkalertowner(alert,request.user): # pragma: no cover raise PermissionDenied('You are not allowed to edit this Alert') stats = alert_get_stats(alert,nperiod=nperiod) @@ -1958,7 +1958,7 @@ def alert_report_view(request,id=0,userid=0,nperiod=0): kwargs={'userid':userid,'id':alert.id}), 'name': 'Report', }, - ] + ] # pragma: no cover return render(request,'alert_stats.html', { 'breadcrumbs':breadcrumbs, @@ -1966,7 +1966,7 @@ def alert_report_view(request,id=0,userid=0,nperiod=0): 'rower':r, 'alert':alert, 'nperiod':nperiod, - }) + }) # pragma: no cover # alert edit view @user_passes_test(ispromember, login_url="/rowers/paidplans", @@ -1978,15 +1978,15 @@ def alert_edit_view(request,id=0,userid=0): try: alert = Alert.objects.get(id=id) - except Alert.DoesNotExist: + except Alert.DoesNotExist: # pragma: no cover raise Http404("This alert doesn't exist") - if alert.manager != request.user: + if alert.manager != request.user: # pragma: no cover raise PermissionDenied('You are not allowed to edit this Alert') FilterFormSet = formset_factory(ConditionEditForm, formset=BaseConditionFormSet,extra=0) - if len(alert.filter.all()) == 0: + if len(alert.filter.all()) == 0: # pragma: no cover FilterFormSet = formset_factory(ConditionEditForm, formset=BaseConditionFormSet, extra=1) filter_data = [{'metric':m.metric, @@ -2090,7 +2090,7 @@ class AlertDelete(DeleteView): def get_context_data(self, **kwargs): context = super(AlertDelete, self).get_context_data(**kwargs) - if 'userid' in kwargs: + if 'userid' in kwargs: # pragma: no cover userid = kwargs['userid'] else: userid = 0 @@ -2128,7 +2128,7 @@ class AlertDelete(DeleteView): def get_object(self, *args, **kwargs): obj = super(AlertDelete, self).get_object(*args, **kwargs) - if obj.manager != self.request.user: + if obj.manager != self.request.user: # pragma: no cover raise PermissionDenied("You are not allowed to delete this Alert") # some checks From 2ee31d6fc378cd5fef88c951b5e39751b066fbc6 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 15 Apr 2021 21:42:43 +0200 Subject: [PATCH 4/8] coverage --- rowers/mailprocessing.py | 3 +- rowers/tasks.py | 18 ++++---- rowers/tests/mocks.py | 14 +++++- rowers/tests/test_async_tasks.py | 79 ++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 13 deletions(-) diff --git a/rowers/mailprocessing.py b/rowers/mailprocessing.py index 8714a128..c41773ab 100644 --- a/rowers/mailprocessing.py +++ b/rowers/mailprocessing.py @@ -106,8 +106,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False): path='media/')[6:] fileformat = fileformat[2] - if testing: - print('Fileformat = ',fileformat) + f,e = os.path.splitext(datafilename) diff --git a/rowers/tasks.py b/rowers/tasks.py index fe6bd1ec..a42987e8 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -282,14 +282,14 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'): @app.task -def add(x, y): +def add(x, y): # pragma: no cover return x + y @app.task def handle_c2_sync(workoutid,url,headers,data,debug=False,**kwargs): response = requests.post(url,headers=headers,data=data) - if response.status_code not in [200,201]: + if response.status_code not in [200,201]: # pragma: no cover return 0 s = response.json() @@ -302,7 +302,7 @@ def handle_c2_sync(workoutid,url,headers,data,debug=False,**kwargs): @app.task def handle_sporttracks_sync(workoutid,url,headers,data,debug=False,**kwargs): response = requests.post(url,headers=headers,data=data) - if response.status_code not in [200,201]: + if response.status_code not in [200,201]: # pragma: no cover return 0 t = response.json() @@ -319,7 +319,7 @@ def handle_sporttracks_sync(workoutid,url,headers,data,debug=False,**kwargs): @app.task def handle_runkeeper_sync(workoutid,url,headers,data,debug=False,**kwargs): response = requests.post(url,headers=headers,data=data) - if response.status_code not in [200,201]: + if response.status_code not in [200,201]: # pragma: no cover return 0 uri = response.headers["Location"] @@ -379,7 +379,7 @@ def handle_c2_import_stroke_data(c2token, starttimeunix, csvfilename,debug=True,**kwargs): - if 'workouttype' in kwargs: + if 'workouttype' in kwargs: # pragma: no cover workouttype = kwargs['workouttype'] else: workouttype = 'rower' @@ -398,7 +398,7 @@ def handle_c2_import_stroke_data(c2token, ) return 1 - else: + else: # pragma: no cover url = "https://log.concept2.com/api/users/me/results/{id}".format(id=c2id) s = requests.get(url,headers=headers) @@ -456,7 +456,7 @@ def getagegrouprecord(age,sex='male',weightcategory='hwt', duration = 60*int(duration) try: df = indf[indf['duration'] == duration] - except KeyError: + except KeyError: # pragma: no cover df = pd.DataFrame() if not df.empty: @@ -478,13 +478,13 @@ def getagegrouprecord(age,sex='male',weightcategory='hwt', #power = np.polyval(poly_coefficients,age) power = 0.5*(np.abs(power)+power) - elif age is not None: + elif age is not None: # pragma: no cover new_age = np.range([age]) ww = griddata(ages.values, powers.values, new_age,method='linear',rescale=True) power = 0.5*(np.abs(power)+power) - else: + else: # pragma: no cover power = 0 return power diff --git a/rowers/tests/mocks.py b/rowers/tests/mocks.py index 162dbc1d..c479a40c 100644 --- a/rowers/tests/mocks.py +++ b/rowers/tests/mocks.py @@ -349,9 +349,16 @@ def mocked_cpraw(*args, **kwargs): return df -def StravaActivity(): +class StravalibResponse(): + def __init__(self,*args, **kwargs): + self.id = 1 + +class StravaActivity(): def wait(*args, **kwargs): - return 1 + return StravalibResponse() + + def __init__(*args, **kwargs): + pass @@ -362,6 +369,9 @@ class MockStravalibClient(): def update_activity(*args, **kwargs): return StravaActivity() + def __init__(*args,**kwargs): + pass + # Mocked Braintree ## Higher level - unfortunately didn't succeed in mocking the gateway diff --git a/rowers/tests/test_async_tasks.py b/rowers/tests/test_async_tasks.py index 2fb6f2c1..172d2fe1 100644 --- a/rowers/tests/test_async_tasks.py +++ b/rowers/tests/test_async_tasks.py @@ -68,6 +68,85 @@ class AsyncTaskTests(TestCase): except: pass + def test_summaryfromsplitdata(self): + splitdata = [ + { + "type": "distance", + "time": 415, + "rest_time": 600, + "stroke_rate": 35, + "distance": 220, + "heart_rate": { + "ending": 160, + "rest": 60 + } + }, + { + "type": "distance", + "time": 347, + "rest_time": 600, + "stroke_rate": 45, + "distance": 220, + "heart_rate": { + "ending": 170, + "rest": 70 + } + } + ] + + data = { + "date": "2015-08-30 14:24:00", + "timezone": "Europe/London", + "distance": 440, + "time": 762, + "type": "rower", + "weight_class": "H", + "heart_rate": { + "average": 140 + }, + "workout_type": "FixedDistanceInterval", + "rest_distance": 43, + "rest_time": 1200, + "workout": { + "targets": { + "stroke_rate": 30, + "heart_rate_zone": 4, + "pace": 1050 + }, + "intervals": [ + { + "type": "distance", + "time": 415, + "rest_time": 600, + "stroke_rate": 35, + "distance": 220, + "heart_rate": { + "ending": 160, + "rest": 60 + } + }, + { + "type": "distance", + "time": 347, + "rest_time": 600, + "stroke_rate": 45, + "distance": 220, + "heart_rate": { + "ending": 170, + "rest": 70 + } + } + ] + } + } + res = tasks.summaryfromsplitdata(splitdata,data,'test.csv') + + self.assertEqual(len(res[0]),478) + + @patch('rowers.tasks.stravalib.Client', side_effect=MockStravalibClient) + def test_strava_sync(self,MockStravalibClient): + res = tasks.handle_strava_sync('aap',self.wwater.id,self.wwater.csvfilename,'aap','activitytype','aa') + self.assertEqual(res,1) def test_safetimedelta(self): x = 5 From 8f81c5fc92453f4fcedbd4783c65071fc52e9eff Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 16 Apr 2021 17:13:45 +0200 Subject: [PATCH 5/8] working NK sync tests --- rowers/dataprepnodjango.py | 2 +- rowers/tasks.py | 318 ++++++++++++++++--------------- rowers/tests/mocks.py | 67 ++++++- rowers/tests/test_async_tasks.py | 18 ++ rowers/tests/test_imports.py | 25 +-- rowers/tests/test_races.py | 14 ++ rowers/views/workoutviews.py | 2 +- 7 files changed, 265 insertions(+), 181 deletions(-) diff --git a/rowers/dataprepnodjango.py b/rowers/dataprepnodjango.py index 4c08ebb4..10b96bae 100644 --- a/rowers/dataprepnodjango.py +++ b/rowers/dataprepnodjango.py @@ -696,7 +696,7 @@ def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=pd.Series([]),deb engine = create_engine(database_url, echo=False) - with engine.connect() as conn, conn.begin(): + with engine.connect() as conn, conn.begin(): df.to_sql(table, engine, if_exists='append', index=False) conn.close() engine.dispose() diff --git a/rowers/tasks.py b/rowers/tasks.py index a42987e8..7b32ebe7 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -139,34 +139,34 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'): spm = 0 try: resttime = data['rest_time']/10. - except KeyError: + except KeyError: # pragma: no cover resttime = 0 try: restdistance = data['rest_distance'] - except KeyError: + except KeyError: # pragma: no cover restdistance = 0 try: avghr = data['heart_rate']['average'] - except KeyError: + except KeyError: # pragma: no cover avghr = 0 try: maxhr = data['heart_rate']['max'] - except KeyError: + except KeyError: # pragma: no cover maxhr = 0 try: avgpace = 500.*totaltime/totaldist - except (ZeroDivisionError,OverflowError): + except (ZeroDivisionError,OverflowError): # pragma: no cover avgpace = 0. try: restpace = 500.*resttime/restdistance - except (ZeroDivisionError,OverflowError): + except (ZeroDivisionError,OverflowError): # pragma: no cover restpace = 0. velo = totaldist/totaltime avgpower = 2.8*velo**(3.0) - if workouttype in ['bike','bikeerg']: + if workouttype in ['bike','bikeerg']: # pragma: no cover velo = velo/2. avgpower = 2.8*velo**(3.0) velo = velo*2 @@ -174,11 +174,11 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'): try: restvelo = restdistance/resttime - except (ZeroDivisionError,OverflowError): + except (ZeroDivisionError,OverflowError): # pragma: no cover restvelo = 0 restpower = 2.8*restvelo**(3.0) - if workouttype in ['bike','bikeerg']: + if workouttype in ['bike','bikeerg']: # pragma: no cover restvelo = restvelo/2. restpower = 2.8*restvelo**(3.0) restvelo = restvelo*2 @@ -213,45 +213,45 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'): try: timebased = data['workout_type'] in ['FixedTimeSplits','FixedTimeInterval'] - except KeyError: + except KeyError: # pragma: no cover timebased = False for interval in splitdata: try: idist = interval['distance'] - except KeyError: + except KeyError: # pragma: no cover idist = 0 try: itime = interval['time']/10. - except KeyError: + except KeyError: # pragma: no cover itime = 0 try: ipace = 500.*itime/idist - except (ZeroDivisionError,OverflowError): + except (ZeroDivisionError,OverflowError): # pragma: no cover ipace = 180. try: ispm = interval['stroke_rate'] - except KeyError: + except KeyError: # pragma: no cover ispm = 0 try: irest_time = interval['rest_time']/10. - except KeyError: + except KeyError: # pragma: no cover irest_time = 0 try: iavghr = interval['heart_rate']['average'] - except KeyError: + except KeyError: # pragma: no cover iavghr = 0 try: imaxhr = interval['heart_rate']['average'] - except KeyError: + except KeyError: # pragma: no cover imaxhr = 0 # create interval values iarr = [idist,'meters','work'] resarr = [itime] - if timebased: + if timebased: # pragma: no cover iarr = [itime,'seconds','work'] resarr = [idist] @@ -268,9 +268,9 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'): if itime != 0: ivelo = idist/itime ipower = 2.8*ivelo**(3.0) - if workouttype in ['bike','bikeerg']: + if workouttype in ['bike','bikeerg']: # pragma: no cover ipower = 2.8*(ivelo/2.)**(3.0) - else: + else: # pragma: no cover ivelo = 0 ipower = 0 @@ -340,23 +340,23 @@ def handle_strava_sync(stravatoken,workoutid,filename,name,activity_type,descrip act = client.upload_activity(f,'tcx.gz',name=name) try: res = act.wait(poll_interval=5.0, timeout=60) - except stravalib.exc.ActivityUploadFailed: + except stravalib.exc.ActivityUploadFailed: # pragma: no cover failed = True - except JSONDecodeError: + except JSONDecodeError: # pragma: no cover failed = True - except stravalib.exc.ObjectNotFound: + except stravalib.exc.ObjectNotFound: # pragma: no cover failed = True - except ActivityUploadFailed: + except ActivityUploadFailed: # pragma: no cover failed = True if not failed: try: act = client.update_activity(res.id,activity_type=activity_type, description=description,device_name='Rowsandall.com') - except TypeError: + except TypeError: # pragma: no cover act = client.update_activity(res.id,activity_type=activity_type, description=description) - except: + except: # pragma: no cover e = sys.exc_info()[0] t = time.localtime() timestamp = bytes('{t}'.format(t=time.strftime('%b-%d-%Y_%H%M', t)),'utf-8') @@ -368,7 +368,7 @@ def handle_strava_sync(stravatoken,workoutid,filename,name,activity_type,descrip result = update_workout_field_sql(workoutid,'uploadedtostrava',res.id,debug=debug) try: os.remove(filename) - except: + except: # pragma: no cover pass return 1 @@ -441,7 +441,7 @@ def handle_c2_import_stroke_data(c2token, return 0 - return 0 + return 0 # pragma: no cover def getagegrouprecord(age,sex='male',weightcategory='hwt', distance=2000,duration=None,indf=pd.DataFrame()): @@ -450,7 +450,7 @@ def getagegrouprecord(age,sex='male',weightcategory='hwt', if not duration: try: df = indf[indf['distance'] == distance] - except KeyError: + except KeyError: # pragma: no cover df = pd.DataFrame() else: duration = 60*int(duration) @@ -496,8 +496,9 @@ def polygon_to_path(polygon,debug=True): ) if debug: engine = create_engine(database_url_debug, echo=False) - else: + else: # pragma: no cover engine = create_engine(database_url, echo=False) + with engine.connect() as conn, conn.begin(): result = conn.execute(query) points = result.fetchall() @@ -517,45 +518,46 @@ def polygon_to_path(polygon,debug=True): def handle_check_race_course(self, f1,workoutid,courseid, recordid,useremail,userfirstname, - **kwargs): + **kwargs): # pragma: no cover logfile = 'courselog_{workoutid}_{courseid}.log'.format(workoutid=workoutid,courseid=courseid) - if 'debug' in kwargs: + + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = False - if 'splitsecond' in kwargs: + if 'splitsecond' in kwargs: # pragma: no cover splitsecond = kwargs['splitsecond'] else: splitsecond = 0 - if 'referencespeed' in kwargs: + if 'referencespeed' in kwargs: # pragma: no cover referencespeed = kwargs['referencespeed'] else: referencespeed = 5.0 - if 'coursedistance' in kwargs: + if 'coursedistance' in kwargs: # pragma: no cover coursedistance = kwargs['coursedistance'] else: coursedistance = 0 mode = 'race' - if 'mode' in kwargs: + if 'mode' in kwargs: # pragma: no cover mode = kwargs['mode'] columns = ['time',' latitude',' longitude','cum_dist'] try: row = rdata(csvfile=f1) - except IOError: + except IOError: # pragma: no cover try: row = rdata(csvfile=f1 + '.csv') - except IOError: + except IOError: # pragma: no cover try: row = rdata(csvfile=f1 + '.gz') - except IOError: + except IOError: # pragma: no cover return 0 @@ -569,7 +571,7 @@ def handle_check_race_course(self, try: s = rowdata[' latitude'] - except KeyError: + except KeyError: # pragma: no cover return 0 rowdata.rename(columns = { @@ -593,22 +595,23 @@ def handle_check_race_course(self, # initiate database engine - if debug: + if debug: # pragma: no cover engine = create_engine(database_url_debug, echo=False) else: engine = create_engine(database_url, echo=False) + # get polygons query = "SELECT id,name FROM rowers_geopolygon WHERE course_id = {courseid} ORDER BY order_in_course ASC".format( courseid=courseid ) - with engine.connect() as conn, conn.begin(): result = conn.execute(query) polygons = result.fetchall() conn.close() + engine.dispose() paths = [] @@ -621,8 +624,12 @@ def handle_check_race_course(self, # check how many times went through start polygon try: - entrytimes,entrydistances = time_in_path(rowdata,paths[0],maxmin='max',getall=True, - name=polygons[0].name,logfile=logfile) + try: + entrytimes,entrydistances = time_in_path(rowdata,paths[0],maxmin='max',getall=True, + name=polygons[0].name,logfile=logfile) + except AttributeError: # for testing + entrytimes, entrydistances = time_in_path(rowdata,paths[0],maxmin='max',getall=True, + name='Start',logfile=logfile) with open(logfile,'ab') as f: t = time.localtime() timestamp = bytes('{t}'.format(t=time.strftime('%b-%d-%Y_%H%M', t)),'utf-8') @@ -633,7 +640,7 @@ def handle_check_race_course(self, f.write(b' ') f.write(bytes('Found {n} entrytimes'.format(n=len(entrytimes)),'utf-8')) - except InvalidTrajectoryError: + except InvalidTrajectoryError: # pragma: no cover entrytimes = [] entrydistances = [] coursecompleted = False @@ -701,7 +708,7 @@ def handle_check_race_course(self, coursemeters = records[records['coursetimeseconds'] == mintime]['coursemeters'].min() startsecond = records[records['coursetimeseconds'] == mintime]['startsecond'].min() endsecond = records[records['coursetimeseconds'] == mintime]['endsecond'].min() - else: + else: # pragma: no cover coursecompleted = False points = 0 @@ -732,6 +739,7 @@ def handle_check_race_course(self, ) + with engine.connect() as conn, conn.begin(): result = conn.execute(query) @@ -742,7 +750,7 @@ def handle_check_race_course(self, return 1 - else: + else: # pragma: no cover query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 0, duration = "{duration}", distance = {distance}, workoutid = {workoutid}, startsecond = {startsecond}, endsecond = {endsecond}, points={points} WHERE id={recordid}'.format( recordid=recordid, duration=totaltime_sec_to_string(0), @@ -788,12 +796,11 @@ def handle_check_race_course(self, handle_sendemail_coursefail( useremail,userfirstname,logfile ) - os.remove(logfile) return 2 - return 0 + return 0 # pragma: no cover @app.task(bind=True) @@ -805,7 +812,7 @@ def handle_getagegrouprecords(self, wcdurations = [] wcpower = [] - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = False @@ -813,7 +820,7 @@ def handle_getagegrouprecords(self, df = pd.read_json(df) - if sex == 'not specified': + if sex == 'not specified': # pragma: no cover return 0 for distance in distances: @@ -829,7 +836,7 @@ def handle_getagegrouprecords(self, duration = distance/velo wcdurations.append(duration) wcpower.append(worldclasspower) - except ZeroDivisionError: + except ZeroDivisionError: # pragma: no cover pass @@ -847,7 +854,7 @@ def handle_getagegrouprecords(self, distance = int(60*duration*velo) wcdurations.append(60.*duration) wcpower.append(worldclasspower) - except ValueError: + except ValueError: # pragma: no cover pass update_agegroup_db(age,sex,weightcategory,wcdurations,wcpower, @@ -868,7 +875,7 @@ def handle_get_garmin_file(client_id, regex = '.*\?id=(\d+)' - try: + try: # pragma: no cover m = re.compile(regex).match(url).group(1) garminid = int(m) except AttributeError: @@ -912,14 +919,14 @@ def handle_get_garmin_file(client_id, return 1 @app.task(bind=True) -def long_test_task(self,aantal,debug=False,job=None,session_key=None): +def long_test_task(self,aantal,debug=False,job=None,session_key=None): # pragma: no cover job = self.request return longtask.longtask(aantal,jobid=job.id,debug=debug, session_key=session_key) @app.task(bind=True) -def long_test_task2(self,aantal,**kwargs): +def long_test_task2(self,aantal,**kwargs): # pragma: no cover #debug=False,job=None,jobid='aap'): job = self.request job_id = job.id @@ -942,7 +949,7 @@ def long_test_task2(self,aantal,**kwargs): def handle_update_empower(self, useremail, workoutdicts, - debug=False, **kwargs): + debug=False, **kwargs): # pragma: no cover job = self.request job_id = job.id @@ -1029,7 +1036,7 @@ def handle_calctrimp(id, hrmax, hrmin, debug=False, **kwargs): - if debug: + if debug: # pragma: no cover engine = create_engine(database_url_debug, echo=False) else: engine = create_engine(database_url, echo=False) @@ -1044,11 +1051,11 @@ def handle_calctrimp(id, # check what the real file name is if os.path.exists(csvfilename): csvfile = csvfilename - elif os.path.exists(csvfilename+'.csv'): + elif os.path.exists(csvfilename+'.csv'): # pragma: no cover csvfile = csvfilename+'.csv' - elif os.path.exists(csvfilename+'.gz'): + elif os.path.exists(csvfilename+'.gz'): # pragma: no cover csvfile = csvfilename+'.gz' - else: + else: # pragma: no cover return 0 csvfile = os.path.abspath(csvfile) @@ -1061,7 +1068,7 @@ def handle_calctrimp(id, ) as channel: try: grpc.channel_ready_future(channel).result(timeout=10) - except grpc.FutureTimeoutError: + except grpc.FutureTimeoutError: # pragma: no cover return 0 stub = metrics_pb2_grpc.MetricsStub(channel) @@ -1075,7 +1082,7 @@ def handle_calctrimp(id, ) try: response = stub.CalcMetrics(req,timeout=60) - except: + except: # pragma: no cover return 0 tss = response.tss @@ -1085,40 +1092,40 @@ def handle_calctrimp(id, normw = response.normw hrtss = response.hrtss - if np.isnan(tss): + if np.isnan(tss): # pragma: no cover tss = 0 - if np.isnan(normp): + if np.isnan(normp): # pragma: no cover normp = 0 - if np.isnan(trimp): + if np.isnan(trimp): # pragma: no cover trimp = 0 - if np.isnan(normv): + if np.isnan(normv): # pragma: no cover normv = 0 - if np.isnan(normw): + if np.isnan(normw): # pragma: no cover normw = 0 - if np.isnan(hrtss): + if np.isnan(hrtss): # pragma: no cover hrtss = 0 - if tss > 1000: + if tss > 1000: # pragma: no cover tss = 0 - if trimp > 1000: + if trimp > 1000: # pragma: no cover trimp = 0 - if normp > 2000: + if normp > 2000: # pragma: no cover normp = 0 - if normv > 2000: + if normv > 2000: # pragma: no cover normv = 0 - if normw > 10000: + if normw > 10000: # pragma: no cover normw = 0 - if hrtss > 1000: + if hrtss > 1000: # pragma: no cover hrtss = 0 @@ -1146,7 +1153,7 @@ def handle_updatedps(useremail, workoutids, debug=False,**kwargs): havedata = 1 try: rowdata = rdata(csvfile=f1) - except IOError: + except IOError: # pragma: no cover try: rowdata = rdata(csvfile=f1 + '.csv') except IOError: @@ -1166,7 +1173,7 @@ def handle_updatedps(useremail, workoutids, debug=False,**kwargs): 'Rowsandall ', [useremail]) - if 'emailbounced' in kwargs: + if 'emailbounced' in kwargs: # pragma: no cover emailbounced = kwargs['emailbounced'] else: emailbounced = False @@ -1180,11 +1187,11 @@ import math def sigdig(value, digits = 3): try: order = int(math.floor(math.log10(math.fabs(value)))) - except (ValueError,TypeError): + except (ValueError,TypeError): # pragma: no cover return value # return integers as is - if value % 1 == 0: + if value % 1 == 0: # pragma: no cover return value places = digits - order - 1 @@ -1200,12 +1207,12 @@ def sigdig(value, digits = 3): def handle_send_email_alert( useremail, userfirstname, userlastname, rowerfirstname, alertname, stats, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = False - if 'othertexts' in kwargs: + if 'othertexts' in kwargs: # pragma: no cover othertexts = kwargs['othertexts'] else: othertexts = None @@ -1213,12 +1220,12 @@ def handle_send_email_alert( report = {} try: report['Percentage'] = int(stats['percentage']) - except KeyError: + except KeyError: # pragma: no cover pass try: report['Number of workouts'] = int(stats['workouts']) - except KeyError: + except KeyError: # pragma: no cover pass try: @@ -1226,18 +1233,18 @@ def handle_send_email_alert( a = stats['nr_strokes_qualifying'], b = stats['nr_strokes'] ) - except KeyError: + except KeyError: # pragma: no cover pass try: report['Median'] = sigdig(stats['median']) - except KeyError: + except KeyError: # pragma: no cover pass try: report['Median of qualifying strokes'] = sigdig(stats['median_q']) - except KeyError: + except KeyError: # pragma: no cover pass subject = "Rowsandall.com: {alertname} ({startdate} to {enddate})".format( @@ -1270,7 +1277,7 @@ def handle_send_email_alert( def handle_send_email_transaction( username, useremail, amount, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1296,7 +1303,7 @@ def handle_send_email_transaction( def handle_send_email_failed_cancel( name, email, username, id, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1326,7 +1333,7 @@ def handle_send_email_subscription_update( username, useremail, planname, recurring, price, amount, end_of_billing_period, method, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1370,7 +1377,7 @@ def handle_send_email_subscription_create( username, useremail, planname, recurring, price, amount, end_of_billing_period, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1405,7 +1412,7 @@ def handle_send_email_subscription_create( def handle_sendemail_raceregistration( useremail, username, registeredname, racename, raceid, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1434,7 +1441,7 @@ def handle_sendemail_raceregistration( def handle_sendemail_coursefail( useremail, username, logfile, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1461,7 +1468,7 @@ def handle_sendemail_coursefail( def handle_sendemail_optout( useremail, username, registeredname, racename, raceid, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1493,7 +1500,7 @@ def handle_sendemail_optout( def handle_sendemail_racesubmission( useremail, username, registeredname, racename, raceid, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1523,7 +1530,7 @@ def handle_sendemail_racesubmission( def handle_send_disqualification_email( useremail,username,reason,message, racename, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1553,7 +1560,7 @@ def handle_send_disqualification_email( def handle_send_withdraw_email( useremail,username,reason,message, racename, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = True @@ -1583,7 +1590,7 @@ def handle_send_withdraw_email( @app.task def handle_sendemail_expired(useremail,userfirstname,userlastname,expireddate, **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = False @@ -1609,7 +1616,7 @@ def handle_sendemail_breakthrough(workoutid, useremail, btvalues=pd.DataFrame().to_json(), **kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = False @@ -1653,7 +1660,7 @@ def handle_sendemail_hard(workoutid, useremail, btvalues=pd.DataFrame().to_json(), debug=False,**kwargs): - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = False @@ -1701,7 +1708,7 @@ def handle_sendemail_userdeleted(name, email, debug=False, **kwargs): 'Rowsandall ', [fullemail]) - if 'emailbounced' in kwargs: + if 'emailbounced' in kwargs: # pragma: no cover emailbounced = kwargs['emailbounced'] else: emailbounced = False @@ -1731,10 +1738,10 @@ def handle_sendemail_unrecognized(unrecognizedfile, useremail, try: email.attach_file(unrecognizedfile) - except IOError: + except IOError: # pragma: no cover pass - if 'emailbounced' in kwargs: + if 'emailbounced' in kwargs: # pragma: no cover emailbounced = kwargs['emailbounced'] else: emailbounced = False @@ -1746,7 +1753,7 @@ def handle_sendemail_unrecognized(unrecognizedfile, useremail, # remove tcx file try: os.remove(unrecognizedfile) - except: + except: # pragma: no cover pass return 1 @@ -1844,7 +1851,7 @@ def handle_sendemailtcx(first_name, last_name, email, tcxfile,**kwargs): @app.task -def handle_zip_file(emailfrom, subject, file,**kwargs): +def handle_zip_file(emailfrom, subject, file,**kwargs): # pragma: no cover message = "... zip processing ... " try: debug = kwargs['debug'] @@ -1891,7 +1898,7 @@ def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs): try: os.remove(csvfile) - except: + except: # pragma: no cover pass return 1 @@ -1926,13 +1933,13 @@ def handle_sendemail_ical(first_name, last_name, email, url, icsfile, **kwargs): fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "Calendar File for your sessions from Rowsandall.com" - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = False siteurl = SITE_URL - if debug: + if debug: # pragma: no cover progressurl = SITE_URL_DEV siteurl = SITE_URL_DEV @@ -1978,12 +1985,12 @@ def handle_sendemailfile(first_name, last_name, email, csvfile,**kwargs): attach_file=csvfile,**kwargs) - if 'delete' in kwargs: + if 'delete' in kwargs: # pragma: no cover dodelete = kwargs['delete'] else: dodelete = False - if dodelete: + if dodelete: # pragma: no cover try: os.remove(csvfile) except: @@ -2005,16 +2012,16 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, if 'jobkey' in kwargs: job_id = kwargs.pop('jobkey') - if 'ps' in kwargs: + if 'ps' in kwargs: # pragma: no cover ps = kwargs['ps'] else: ps = [1,1,1,1] - if 'ratio' in kwargs: + if 'ratio' in kwargs: # pragma: no cover ratio = kwargs['ratio'] else: ratio = 1.0 - if 'debug' in kwargs: + if 'debug' in kwargs: # pragma: no cover debug = kwargs['debug'] else: debug = False @@ -2029,11 +2036,11 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, # check what the real file name is if os.path.exists(f1): csvfile = f1 - elif os.path.exists(f1+'.csv'): + elif os.path.exists(f1+'.csv'): # pragma: no cover csvfile = f1+'.csv' - elif os.path.exists(f1+'.gz'): + elif os.path.exists(f1+'.gz'): # pragma: no cover csvfile = f1+'.gz' - else: + else: # pragma: no cover return 0 csvfile = os.path.abspath(csvfile) @@ -2041,7 +2048,7 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, # do something with boat type try: rowdata = rdata(csvfile=csvfile) - except IOError: + except IOError: # pragma: no cover try: rowdata = rdata(csvfile=csvfile) except IOError: @@ -2049,7 +2056,7 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, # do calculation, but do not overwrite NK Empower Power data powermeasured = False - try: + try: # pragma: no cover w = rowdata.df['wash'] if w.mean() != 0: powermeasured = True @@ -2058,7 +2065,7 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, progressurl = SITE_URL siteurl = SITE_URL - if debug: + if debug: # pragma: no cover progressurl = SITE_URL_DEV siteurl = SITE_URL_DEV secret = PROGRESS_CACHE_SECRET @@ -2076,7 +2083,7 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, ) as channel: try: grpc.channel_ready_future(channel).result(timeout=10) - except grpc.FutureTimeoutError: + except grpc.FutureTimeoutError: # pragma: no cover return 0 stub = calculator_pb2_grpc.PowerStub(channel) @@ -2092,13 +2099,13 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, boatclass = boatclass, ),timeout=1200) result = response.result - if result == 0: + if result == 0: # pragma: no cover # send failure email return 0 # do something with boat type try: rowdata = rdata(csvfile=csvfile) - except IOError: + except IOError: # pragma: no cover try: rowdata = rdata(csvfile=csvfile) except IOError: @@ -2110,7 +2117,7 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, ) - rowdata.df['TimeStamp (sec)'].min() try: totaltime = totaltime + rowdata.df.loc[0, ' ElapsedTime (sec)'] - except KeyError: + except KeyError: # pragma: no cover pass df = getsmallrowdata_db( ['power', 'workoutid', 'time'], ids=[workoutid], @@ -2124,7 +2131,7 @@ def handle_otwsetpower(self,f1, boattype, boatclass, coastalbrand, weightvalue, #delta,cpvalues,avgpower = datautils.getsinglecp(rowdata.df) res, btvalues, res2 = utils.isbreakthrough( delta, cpvalues, ps[0], ps[1], ps[2], ps[3], ratio) - if res: + if res: # pragma: no cover handle_sendemail_breakthrough( workoutid, email, first_name, @@ -2155,7 +2162,7 @@ def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs): for f1 in workoutfilenames: try: rowdata = rdata(csvfile=f1) - except IOError: + except IOError: # pragma: no cover try: rowdata = rdata(csvfile=f1 + '.csv') except IOError: @@ -2180,7 +2187,7 @@ def cp_from_workoutids(workoutids,debug=False): df = getsmallrowdata_db(columns,ids=workoutids,debug=debug) df.dropna(inplace=True,axis=0) - if df.empty: + if df.empty: # pragma: no cover # change this return 0,0,0 @@ -2197,12 +2204,12 @@ def cp_from_workoutids(workoutids,debug=False): df = pd.read_parquet(cpfile) df['workout'] = str(id) data.append(df) - except: + except: # pragma: no cover pass # ignore for now - if len(data) == 0: + if len(data) == 0: # pragma: no cover return 0,0,0 - if len(data)>1: + if len(data)>1: # pragma: no cover df = pd.concat(data,axis=0) @@ -2238,7 +2245,7 @@ def cp_from_workoutids(workoutids,debug=False): t2k = 2000./velo2k pwr2k = fitfunc(p1,t2k) velo2 = (pwr2k/2.8)**(1./3.) - if np.isnan(velo2) or velo2 <= 0: + if np.isnan(velo2) or velo2 <= 0: # pragma: no cover velo2 = 1.0 t2 = 2000./velo2 @@ -2261,7 +2268,7 @@ def handle_updatecp(rower_id,workoutids,debug=False,table='cpdata',**kwargs): columns = ['power','workoutid','time'] df = getsmallrowdata_db(columns,ids=workoutids,debug=debug) - if df.empty: + if df.empty: # pragma: no cover return 0 maxt = 1.05*df['time'].max()/1000. @@ -2299,7 +2306,7 @@ def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename, hrzones=hrzones) try: row = rdata(csvfile=f2, rower=rr) - except IOError: + except IOError: # pragma: no cover row = rdata(csvfile=f2 + '.gz', rower=rr) try: @@ -2312,7 +2319,7 @@ def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename, nr_rows = len(row.df) - if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200): + if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200): # pragma: no cover bin = int(nr_rows / 1200.) df = row.df.groupby(lambda x: x / bin).mean() row.df = df @@ -2324,16 +2331,16 @@ def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename, elif (plotnr == 3): try: t += ' - Heart Rate Distribution' - except TypeError: + except TypeError: # pragma: no cover t = 'Heart Rate Distribution' fig1 = row.get_piechart(t,**kwargs) elif (plotnr == 4): - if haspower: + if haspower: # pragma: no cover fig1 = row.get_timeplot_otwempower(t,pacerange=otwrange,**kwargs) else: fig1 = row.get_timeplot_otw(t,pacerange=otwrange,**kwargs) elif (plotnr == 5): - if haspower: + if haspower: # pragma: no cover fig1 = row.get_metersplot_otwempower(t,pacerange=otwrange,**kwargs) else: fig1 = row.get_metersplot_otw(t,pacerange=otwrange,**kwargs) @@ -2350,7 +2357,7 @@ def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename, t += ' - Power Distribution' fig1 = row.get_power_piechart(t,**kwargs) - if fig1 is None: + if fig1 is None: # pragma: no cover return 0 @@ -2373,7 +2380,7 @@ def handle_sendemail_coachrequest(email,name,code,coachname, subject = 'Invitation to add {n} to your athletes'.format(n=name) from_email = 'Rowsandall ' siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV d = { @@ -2399,7 +2406,7 @@ def handle_sendemail_coachoffer_rejected(coachemail,coachname,name, subject = '{n} has rejected your offer to be his coach on rowsandall.com'.format(n=name) from_email = 'Rowsandall ' siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV d = { @@ -2422,7 +2429,7 @@ def handle_sendemail_coachrequest_rejected(email,coachname,name, subject = '{n} has rejected your coaching request on rowsandall.com'.format(n=coachname) from_email = 'Rowsandall ' siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV d = { @@ -2445,7 +2452,7 @@ def handle_sendemail_coachrequest_accepted(email,coachname,name, subject = '{n} has accepted your coaching request on rowsandall.com'.format(n=coachname) from_email = 'Rowsandall ' siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV d = { @@ -2468,7 +2475,7 @@ def handle_sendemail_coachoffer_accepted(coachemail,coachname,name, subject = '{n} has accepted your coaching offer on rowsandall.com'.format(n=name) from_email = 'Rowsandall ' siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV d = { @@ -2491,7 +2498,7 @@ def handle_sendemail_coacheerequest(email,name,code,coachname, subject = '{n} requests coach access to your data on rowsandall.com'.format(n=coachname) from_email = 'Rowsandall ' siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV d = { @@ -2514,7 +2521,7 @@ def handle_sendemail_invite(email, name, code, teamname, manager, subject = 'Invitation to join team ' + teamname siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV d = { @@ -2549,16 +2556,16 @@ def handle_sendemailnewresponse(first_name, last_name, comment = u''+comment siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV sessiontype = 'workout' - if 'sessiontype' in kwargs: + if 'sessiontype' in kwargs: # pragma: no cover sessiontype=kwargs.pop('sessiontype') commentlink = '/rowers/workout/{workoutid}/comment/'.format( workoutid=encoder.encode_hex(workoutid)) - if 'commentlink' in kwargs: + if 'commentlink' in kwargs: # pragma: no cover commentlink = kwargs.pop('commentlink') d = { @@ -2604,12 +2611,12 @@ def handle_sendemailnewcomment(first_name, siteurl = SITE_URL_DEV sessiontype = 'workout' - if 'sessiontype' in kwargs: + if 'sessiontype' in kwargs: # pragma: no cover sessiontype=kwargs.pop('sessiontype') commentlink = '/rowers/workout/{workoutid}/comment/'.format( workoutid=encoder.encode_hex(workoutid)) - if 'commentlink' in kwargs: + if 'commentlink' in kwargs: # pragma: no cover commentlink = kwargs.pop('commentlink') d = { @@ -2674,7 +2681,7 @@ def handle_sendemail_request(email, name, code, teamname, requestor, id, from_email = 'Rowsandall ' siteurl = SITE_URL - if debug: + if debug: # pragma: no cover siteurl = SITE_URL_DEV d = { @@ -2823,7 +2830,7 @@ def handle_setcp(strokesdf,filename,workoutid,debug=False,**kwargs): try: totaltime = strokesdf['time'].max() - except KeyError: + except KeyError: # pragma: no cover return 0 try: powermean = strokesdf['power'].mean() @@ -2848,7 +2855,7 @@ def handle_setcp(strokesdf,filename,workoutid,debug=False,**kwargs): df.to_parquet(filename,engine='fastparquet',compression='GZIP') return 1 - return 1 + return 1 # pragma: no cover @app.task def handle_sendemail_invite_accept(email, name, teamname, managername, @@ -2876,7 +2883,7 @@ def handle_sendemail_invite_accept(email, name, teamname, managername, # Another simple task for debugging purposes -def add2(x, y,debug=False,**kwargs): +def add2(x, y,debug=False,**kwargs): # pragma: no cover return x + y graphql_url = "https://rp3rowing-app.com/graphql" @@ -2982,8 +2989,7 @@ def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone url = NK_API_LOCATION+"api/v1/sessions/strokes" response = requests.get(url,headers=headers,params=params) - - if response.status_code != 200: + if response.status_code != 200: # pragma: no cover # error handling and logging return 0 @@ -3005,7 +3011,7 @@ def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone workoutid,error = add_workout_from_data(userid,nkid,data,df) - if debug: + if debug: # pragma: no cover engine = create_engine(database_url_debug, echo=False) else: engine = create_engine(database_url, echo=False) @@ -3026,7 +3032,7 @@ def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone with open('nkblocked.json','r') as nkblocked: jsondata = json.load(nkblocked) parkedids = jsondata['ids'] - except FileNotFoundError: + except FileNotFoundError: # pragma: no cover pass newparkedids = [id for id in parkedids if id != newnkid] diff --git a/rowers/tests/mocks.py b/rowers/tests/mocks.py index c479a40c..563c5477 100644 --- a/rowers/tests/mocks.py +++ b/rowers/tests/mocks.py @@ -165,6 +165,70 @@ def mocked_sqlalchemy(*args, **kwargs): return MockEngine() +from rowers import courses + +def mocked_sqlalchemy_courses(*args, **kwargs): + # return object with method + cs = courses.kmltocourse('rowers/tests/testdata/thyro.kml') + course = cs[0] + cname = course['name'] + cnotes = course['description'] + polygons = course['polygons'] + + lijst = [] + i=0 + for polygon in polygons: + lijst.append((i,polygon['name'])) + i = i+1 + + puntenlijst = [] + i = 0 + for p in polygons[0]['points']: + puntenlijst.append((i,p['latitude'],p['longitude'])) + i = i+1 + + + class MockEngine: + def connect(self): + return MockConnection() + + def dispose(self): + return True + + def raw_connection(self): + return True + + class QueryResultPolygons: + def fetchall(self): + return lijst + + class QueryResultPoints: + def fetchall(self): + return puntenlijst + + class MockConnection: + def begin(self): + return True + + def execute(self,query): + if 'latitude' in query: + return QueryResultPoints() + if 'polygon' in query: + return QueryResultPolygons() + return True + + def close(self): + return True + + def __exit__(self, *args, **kwargs): + return True + + def __enter__(self, *args, **kwargs): + return True + + return MockEngine() + + #@pytest.mark.django_db class DjangoTestCase(TestCase): #, MockTestCase): def _pre_setup(self): @@ -801,6 +865,7 @@ def mocked_requests(*args, **kwargs): nkstrokesregex = '.*?nkrowlink\.com\/api\/v1\/sessions\/strokes' nkstrokestester = re.compile(nkstrokesregex) + stravaathleteregex = '.*?strava\.com\/api\/v3\/athlete$' stravaathletetester = re.compile(stravaathleteregex) @@ -967,7 +1032,6 @@ def mocked_requests(*args, **kwargs): if nktester.match(args[0]): - if 'token' in args[0]: json_data = { 'access_token': 'TA3n1vrNjuQJWw0TdCDHnjSmrjIPULhTlejMIWqq', @@ -977,6 +1041,7 @@ def mocked_requests(*args, **kwargs): return MockResponse(json_data,200) if nkstrokestester.match(args[0]): params = kwargs.pop('params',{}) + if 'sessionIds' in params and params['sessionIds'] == '404': return MockResponse(nkimpellerstrokedata, 200) return MockResponse(nkstrokedata,200) diff --git a/rowers/tests/test_async_tasks.py b/rowers/tests/test_async_tasks.py index 172d2fe1..ee39dbb8 100644 --- a/rowers/tests/test_async_tasks.py +++ b/rowers/tests/test_async_tasks.py @@ -10,6 +10,8 @@ import pandas as pd nu = datetime.datetime.now() from rowers import tasks +import rowers.courses as courses + class fakejob: def __init__(self): @@ -53,6 +55,15 @@ class AsyncTaskTests(TestCase): workouttype = 'water', ) + cs = courses.kmltocourse('rowers/tests/testdata/thyro.kml') + course = cs[0] + cname = course['name'] + cnotes = course['description'] + polygons = course['polygons'] + self.ThyroBaantje = courses.createcourse(self.r,cname,polygons,notes=cnotes) + self.ThyroBaantje.save() + + def tearDown(self): for workout in self.user_workouts: try: @@ -68,6 +79,13 @@ class AsyncTaskTests(TestCase): except: pass + def test_polygons(self): + polygons = GeoPolygon.objects.all() + polygon = polygons[0] + obj = (polygon.id,polygon.name) + path = tasks.polygon_to_path(obj) + self.assertEqual(len(path),4) + def test_summaryfromsplitdata(self): splitdata = [ { diff --git a/rowers/tests/test_imports.py b/rowers/tests/test_imports.py index f0a85235..6a42f1a4 100644 --- a/rowers/tests/test_imports.py +++ b/rowers/tests/test_imports.py @@ -432,24 +432,20 @@ class NKObjects(DjangoTestCase): self.assertEqual(response.status_code,200) - @patch('rowers.nkimportutils.requests.session', side_effect=mocked_session) - @patch('rowers.tasks.requests.get', side_effects=mocked_requests) - def test_handle_nk_get_workouts(self, mocked_session, mock_get): + @patch('rowers.tasks.requests.get', side_effect=mocked_requests) + def test_handle_nk_get_workouts(self, mock_get): with open('rowers/tests/testdata/nk_list.json','r') as f: data = json.load(f) - with open('rowers/tests/testdata/nk_strokes.json','r') as f: - strokeData = json.load(f) alldata = {} for item in data: alldata[item['id']] = item - result = rowers.nkstuff.rower_nk_token_refresh(self.u) - res = tasks.handle_nk_async_workout( alldata,self.r.user.id,self.r.nktoken,469,0,'UTC' ) + self.assertTrue(res>0) @patch('rowers.nkstuff.requests.get', side_effect=mocked_requests) @@ -570,21 +566,6 @@ class StravaObjects(DjangoTestCase): ) -# @patch('rowers.stravastuff.requests.post', side_effect=mocked_requests) -# @patch('rowers.views.stravastuff.handle_stravaexport') - #@patch('rowers.dataprep.getsmallrowdata_db') - #def test_strava_upload(self, mock_post,MockStravalibClient, - # mocked_getsmallrowdata_db): - # def test_strava_upload(self,mock_post, mocked_stravaexport): - # response = self.c.get('/rowers/workout/1/stravauploadw/') - - # self.assertRedirects(response, - # expected_url = '/rowers/workout/1/edit/', - # status_code=302,target_status_code=200) - - # self.assertEqual(response.url, '/rowers/workout/1/edit/') - # self.assertEqual(response.status_code, 302) - @patch('rowers.stravastuff.requests.get', side_effect=mocked_requests) @patch('rowers.stravastuff.requests.post', side_effect=mocked_requests) def test_strava_list(self, mock_get, mockpost): diff --git a/rowers/tests/test_races.py b/rowers/tests/test_races.py index 6f31a102..c89fc888 100644 --- a/rowers/tests/test_races.py +++ b/rowers/tests/test_races.py @@ -729,6 +729,20 @@ class ChallengesTest(TestCase): self.assertEqual(response.status_code, 200) + @patch('rowers.tasks.create_engine', side_effect=mocked_sqlalchemy_courses) + def notest_virtualevent_check_view(self,mocked_sqlalchemy_courses): + + res = tasks.handle_check_race_course( + self.wthyro.csvfilename, + self.wthyro.id, + self.ThyroBaantje.id, + self.result.id, + self.wthyro.user.user.email, + self.wthyro.user.user.first_name, + mode='coursetest', + ) + + self.assertEqual(res,1) # add boat diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index 8f2a820b..9486d1a5 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -4978,7 +4978,7 @@ def workout_upload_view(request, }, raceid=0): - is_ajax = request_is_ajax + is_ajax = request_is_ajax(request) if settings.TESTING: is_ajax = False From 6331b4ff4a52307be15d6ccc10fd9be9809da24a Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 16 Apr 2021 19:32:06 +0200 Subject: [PATCH 6/8] further cleaning up --- rowers/dataprep.py | 38 ---------- rowers/interactiveplots.py | 8 +- rowers/tasks.py | 123 ++++++------------------------- rowers/tests/test_async_tasks.py | 7 -- rowers/views/workoutviews.py | 3 - 5 files changed, 26 insertions(+), 153 deletions(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index d7d7ae4b..c3ba06d2 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -997,44 +997,6 @@ def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=[]): conn.close() engine.dispose() - -def runcpupdate( - rower,type='water', - startdate=timezone.now()-datetime.timedelta(days=365), - enddate=timezone.now()+datetime.timedelta(days=5) -): - if type == 'water': - theworkouts = Workout.objects.filter( - user=rower,rankingpiece=True, - workouttype='water', - startdatetime__gte=startdate, - startdatetime__lte=enddate - ) - table = 'cpdata' - else: - theworkouts = Workout.objects.filter( - user=rower,rankingpiece=True, - workouttype__in=[ - 'rower', - 'dynamic', - 'slides' - ], - startdatetime__gte=startdate, - startdatetime__lte=enddate - ) - table = 'cpergdata' - - theids = [w.id for w in theworkouts] - - job = myqueue( - queuelow, - handle_updatecp, - rower.id, - theids, - table=table) - - return job - def fetchcperg(rower,theworkouts): theids = [int(w.id) for w in theworkouts] thefilenames = [w.csvfilename for w in theworkouts] diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index b406619d..aebb4825 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -4577,18 +4577,18 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, # test if we have drive energy nowork = 1 - try: + try: # pragma: no cover test = datadf['driveenergy'].mean() nowork = 0 - except KeyError: + except KeyError: # pragma: no cover datadf['driveenergy'] = 500. # test if we have power nopower = 1 - try: + try: # pragma: no cover test = datadf['power'].mean() nopower = 0 - except KeyError: + except KeyError: # pragma: no cover datadf['power'] = 50. diff --git a/rowers/tasks.py b/rowers/tasks.py index 7b32ebe7..36008a98 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -2182,85 +2182,6 @@ def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs): return 1 -def cp_from_workoutids(workoutids,debug=False): - columns = ['power','workoutid','time'] - df = getsmallrowdata_db(columns,ids=workoutids,debug=debug) - df.dropna(inplace=True,axis=0) - - if df.empty: # pragma: no cover - # change this - return 0,0,0 - - # df is not empty. We continue - dfgrouped = df.groupby(['workoutid']) - maxt = 1.05*df['time'].max()/1000. - - logarr = datautils.getlogarr(maxt) - data = [] - - for id in workoutids: - cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=id) - try: - df = pd.read_parquet(cpfile) - df['workout'] = str(id) - data.append(df) - except: # pragma: no cover - pass # ignore for now - - if len(data) == 0: # pragma: no cover - return 0,0,0 - if len(data)>1: # pragma: no cover - df = pd.concat(data,axis=0) - - - df = df[df['cp'] == df.groupby(['delta'])['cp'].transform('max')] - df = df.sort_values(['delta']).reset_index() - - powerdf = pd.DataFrame({ - 'Delta':df['delta'], - 'CP':df['cp'], - }) - - powerdf = powerdf[powerdf['CP']>0] - powerdf.dropna(axis=0,inplace=True) - powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True) - powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True) - - p1,fitt,fitpower,ratio = datautils.cpfit(powerdf) - # This is code duplication from datautils -- correct asap - fitfunc = lambda pars,x: abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3]))) - - powerfourmin = fitfunc(p1,240.) - powerhour = fitfunc(p1,3600.) - - # 2k power - velofourmin = (powerfourmin/2.8)**(1./3.) - dfourmin = 240.*velofourmin - dratio = 2000./dfourmin - pacefourmin = 500./velofourmin - - # assume 5 sec per doubling drop - pace2k = pacefourmin + 5.*np.log10(dratio)/np.log10(2.) - velo2k = 500./pace2k - t2k = 2000./velo2k - pwr2k = fitfunc(p1,t2k) - velo2 = (pwr2k/2.8)**(1./3.) - if np.isnan(velo2) or velo2 <= 0: # pragma: no cover - velo2 = 1.0 - - t2 = 2000./velo2 - - pwr2k = fitfunc(p1,t2) - - velo3 = (pwr2k/2.8)**(1./3.) - - t3 = 2000./velo3 - - power2k = fitfunc(p1,t3) - - - return powerfourmin,power2k,powerhour - @app.task @@ -2834,7 +2755,7 @@ def handle_setcp(strokesdf,filename,workoutid,debug=False,**kwargs): return 0 try: powermean = strokesdf['power'].mean() - except KeyError: + except KeyError: # pragma: no cover powermean = 0 @@ -3302,7 +3223,7 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu 'resolution': 'medium',} url = "https://www.strava.com/api/v3/activities/"+str(stravaid) response = requests.get(url,headers=headers) - if response.status_code != 200: + if response.status_code != 200: # pragma: no cover tstamp = time.localtime() timestamp = time.strftime('%b-%d-%Y_%H%M', tstamp) with open('strava_webhooks.log','a') as f: @@ -3329,7 +3250,7 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu try: startdatetime = workoutsummary['start_date'] - except KeyError: + except KeyError: # pragma: no cover startdatetime = timezone.now() spm = get_strava_stream(None,'cadence',stravaid,authorizationstring=authorizationstring) @@ -3352,7 +3273,7 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu if t is not None: nr_rows = len(t) - else: + else: # pragma: no cover try: duration = int(workoutsummary['elapsed_time']) except KeyError: @@ -3362,22 +3283,22 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu nr_rows = len(t) - if nr_rows == 0: + if nr_rows == 0: # pragma: no cover return 0 - if d is None: + if d is None: # pragma: no cover d = 0*t - if spm is None: + if spm is None: # pragma: no cover spm = np.zeros(nr_rows) - if power is None: + if power is None: # pragma: no cover power = np.zeros(nr_rows) - if hr is None: + if hr is None: # pragma: no cover hr = np.zeros(nr_rows) - if velo is None: + if velo is None: # pragma: no cover velo = np.zeros(nr_rows) dt = np.diff(t).mean() @@ -3389,10 +3310,10 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu try: lat = coords[:,0] lon = coords[:,1] - except IndexError: + except IndexError: # pragma: no cover lat = np.zeros(len(t)) lon = np.zeros(len(t)) - else: + else: # pragma: no cover lat = np.zeros(len(t)) lon = np.zeros(len(t)) @@ -3419,13 +3340,13 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu try: workouttype = mytypes.stravamappinginv[workoutsummary['type']] - except KeyError: + except KeyError: # pragma: no cover workouttype = 'other' - if workouttype.lower() == 'rowing': + if workouttype.lower() == 'rowing': # pragma: no cover workouttype = 'rower' - if 'summary_polyline' in workoutsummary['map'] and workouttype=='rower': + if 'summary_polyline' in workoutsummary['map'] and workouttype=='rower': # pragma: no cover workouttype = 'water' try: @@ -3442,7 +3363,7 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu rowdatetime = iso8601.parse_date(workoutsummary['date_utc']) except KeyError: rowdatetime = iso8601.parse_date(workoutsummary['start_date']) - except ParseError: + except ParseError: # pragma: no cover rowdatetime = iso8601.parse_date(workoutsummary['date']) @@ -3454,7 +3375,7 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu try: title = workoutsummary['name'] - except KeyError: + except KeyError: # pragma: no cover title = "" try: t = data['comments'].split('\n', 1)[0] @@ -3476,9 +3397,9 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu try: latcoord = strokedata.loc[:,'lat'] loncoord = strokedata.loc[:,'lon'] - if latcoord.std() == 0 and loncoord.std() == 0 and workouttype == 'water': + if latcoord.std() == 0 and loncoord.std() == 0 and workouttype == 'water': # pragma: no cover workouttype = 'rower' - except: + except: # pragma: no cover latcoord = np.zeros(nr_rows) loncoord = np.zeros(nr_rows) if workouttype == 'water': @@ -3488,19 +3409,19 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu try: strokelength = strokedata.loc[:,'strokelength'] - except: + except: # pragma: no cover strokelength = np.zeros(nr_rows) dist2 = 0.1*strokedata.loc[:,'d'] try: spm = strokedata.loc[:,'spm'] - except KeyError: + except KeyError: # pragma: no cover spm = 0*dist2 try: hr = strokedata.loc[:,'hr'] - except KeyError: + except KeyError: # pragma: no cover hr = 0*spm pace = strokedata.loc[:,'p']/10. pace = np.clip(pace,0,1e4) diff --git a/rowers/tests/test_async_tasks.py b/rowers/tests/test_async_tasks.py index ee39dbb8..745880ca 100644 --- a/rowers/tests/test_async_tasks.py +++ b/rowers/tests/test_async_tasks.py @@ -517,13 +517,6 @@ class AsyncTaskTests(TestCase): res = tasks.handle_updateergcp(1,[f1]) self.assertEqual(res,1) - @patch('rowers.dataprepnodjango.getsmallrowdata_db') - def test_cp_from_workoutids(self,mocked_getsmallrowdata_db): - ids = [1] - powerfourmin,power2k,powerhour = tasks.cp_from_workoutids(ids) - self.assertFalse(powerfourmin==0) - self.assertFalse(power2k==0) - self.assertFalse(powerhour==0) @patch('rowers.dataprepnodjango.getsmallrowdata_db') def test_handle_updatecp(self,mocked_getsmallrowdata_db): diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index 9486d1a5..a273601f 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -4415,9 +4415,6 @@ def workout_edit_view(request,id=0,message="",successmessage=""): successmessage = "Changes saved" - if rankingpiece: # pragma: no cover - dataprep.runcpupdate(row.user,type=row.workouttype) - messages.info(request,successmessage) else: form = WorkoutForm(instance=row) From b6b9f29a704e7c7b2ac1084d4577eb5294780563 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sun, 18 Apr 2021 07:51:55 +0200 Subject: [PATCH 7/8] fixing NK get_workout --- rowers/nkstuff.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/rowers/nkstuff.py b/rowers/nkstuff.py index b23887f6..1fb9c5f8 100644 --- a/rowers/nkstuff.py +++ b/rowers/nkstuff.py @@ -269,8 +269,10 @@ def get_workout(user,nkid): # get strokes url = NK_API_LOCATION+"api/v1/sessions/strokes" + response = requests.get(url,headers=headers,params=params) + if response.status_code != 200: # error handling and logging return {},pd.DataFrame() @@ -282,13 +284,21 @@ def get_workout(user,nkid): df = strokeDataToDf(strokeData) # get workout data - timestampbegin = df['timestamp'].min() - timestampend = df['timestamp'].max() + after = df['timestamp'].min() + before = df['timestamp'].max() + + after = arrow.get(after/1000.) + before = arrow.get(before/1000.) + after = after-timedelta(days=1) + before = before+timedelta(days=1) + before = str(int(before.timestamp())*1000) + after = str(int(after.timestamp())*1000) + url = NK_API_LOCATION+"api/v1/sessions/" params = { - 'after':timestampbegin-1, - 'before': timestampend+1, + 'after':after, + 'before': before, } response = requests.get(url, headers=headers,params=params) From 2deb4fcbe303a420f91dee03c2b63cb6f7cdd2d5 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sun, 18 Apr 2021 12:38:22 +0200 Subject: [PATCH 8/8] fix tests --- rowers/nkstuff.py | 3 ++- rowers/tests/mocks.py | 3 ++- rowers/views/importviews.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/rowers/nkstuff.py b/rowers/nkstuff.py index 1fb9c5f8..82a5f48d 100644 --- a/rowers/nkstuff.py +++ b/rowers/nkstuff.py @@ -272,7 +272,6 @@ def get_workout(user,nkid): response = requests.get(url,headers=headers,params=params) - if response.status_code != 200: # error handling and logging return {},pd.DataFrame() @@ -293,6 +292,7 @@ def get_workout(user,nkid): before = before+timedelta(days=1) before = str(int(before.timestamp())*1000) after = str(int(after.timestamp())*1000) + print(after) url = NK_API_LOCATION+"api/v1/sessions/" @@ -309,6 +309,7 @@ def get_workout(user,nkid): jsondata = response.json() workoutdata = {} + for w in jsondata: if str(w['id']) == str(nkid): workoutdata = w diff --git a/rowers/tests/mocks.py b/rowers/tests/mocks.py index 563c5477..845690a9 100644 --- a/rowers/tests/mocks.py +++ b/rowers/tests/mocks.py @@ -1047,7 +1047,8 @@ def mocked_requests(*args, **kwargs): return MockResponse(nkstrokedata,200) if nkworkoutlisttester.match(args[0]): params = kwargs.pop('params',{}) - if 'after' in params and params['after'] == 1267136372998: + + if 'after' in params and params['after'] == '1267049972000': return MockResponse(nkimpellerworkoutlist,200) return MockResponse(nkworkoutlist,200) diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index 69a036a8..fc19b013 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -2003,6 +2003,7 @@ def workout_getrp3importview(request,externalid): @login_required() def workout_getimportview(request,externalid,source = 'c2'): data,strokedata = importsources[source].get_workout(request.user,externalid) + if not data: messages.error(request,"No strokedata received") url = reverse('workouts_view')