From fd5ce16e4b6acddcd296556e422046a0747690db Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 16 Jan 2023 19:58:26 +0100 Subject: [PATCH] now working and with a test --- rowers/tests/test_api.py | 72 ++++++++++++++++++++++++++++++++ rowers/urls.py | 2 + rowers/views/apiviews.py | 90 +++++++++++++++++++--------------------- 3 files changed, 116 insertions(+), 48 deletions(-) diff --git a/rowers/tests/test_api.py b/rowers/tests/test_api.py index f1a6f73b..32fc2af6 100644 --- a/rowers/tests/test_api.py +++ b/rowers/tests/test_api.py @@ -180,3 +180,75 @@ class OwnApi(TestCase): response = strokedatajson_v2(request,id=w.id) self.assertEqual(response.status_code,200) + + def test_strokedataform_v3(self): + login = self.c.login(username=self.u.username, password=self.password) + self.assertTrue(login) + + w = self.user_workouts[1] + + url = reverse('strokedatajson_v3') + + request = self.factory.get(url) + request.user = self.u + force_authenticate(request, user=self.u) + response = strokedatajson_v3(request) + self.assertEqual(response.status_code,405) + + + strokedata = { + "data": [ + { + "time": 3200.0000476837, + "pace": 155068.4885951763, + "hr": 85.7857142857, + "power": 84.6531131591, + "distance": 23, + "spm": 16.380952381 + }, + { + "time": 6700.0000476837, + "pace" : 144402.6407586741, + "hr": 91.2142857143, + "power": 117.458827834, + "distance": 36, + "spm": 21.1666666667 + }, + { + "time": 10099.9999046326, + "pace": 138830.8712654931, + "hr": 95.7142857143, + "power": 141.31057207, + "distance": 48, + "spm": 19.8095238095 + } + ] + } + + form_data = { + "totalDistance": 100, + "elapsedTime": 29000, + "title": "Test Workout (GO)", + "startdatetime": "2023-01-16 17:54:35.588838+00:00", + "workouttype": "water", + "boattype": "1x", + "notes": "some\nnotes", + "strokes": strokedata, + } + + + url = reverse('strokedatajson_v3') + + request = self.factory.post(url,form_data,format='json') + request.user = self.u + request.data = json.dumps(form_data) + + force_authenticate(request, user=self.u) + with patch('rowers.dataprep.getrowdata_db') as mock_getrowdata: + mock_getrowdata.return_value = (pd.DataFrame(),None) + response = strokedatajson_v3(request) + + self.assertEqual(response.status_code,200) + response = json.loads(response.content) + x = response['workout id'] + diff --git a/rowers/urls.py b/rowers/urls.py index 9c59e802..c9760f9a 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -247,6 +247,8 @@ urlpatterns = [ name='strokedatajson'), re_path(r'^api/v2/workouts/(?P\b[0-9A-Fa-f]+\b)/strokedata/$', views.strokedatajson_v2, name='strokedatajson_v2'), + re_path(r'^api/v3/workouts/$', views.strokedatajson_v3, + name='strokedatajson_v3'), re_path(r'^500v/$', views.error500_view, name='error500_view'), re_path(r'^500q/$', views.servererror_view, name='servererror_view'), path('502/', TemplateView.as_view(template_name='502.html'), name='502'), diff --git a/rowers/views/apiviews.py b/rowers/views/apiviews.py index fc1226f8..88efe374 100644 --- a/rowers/views/apiviews.py +++ b/rowers/views/apiviews.py @@ -3,6 +3,8 @@ from rowers.tasks import handle_calctrimp from rowers.opaque import encoder import arrow +import pendulum +from rowsandall_app.settings import UPLOAD_SERVICE_SECRET, UPLOAD_SERVICE_URL # Stroke data form to test API upload @@ -210,49 +212,35 @@ def strokedatajson_v3(request): POST: Add Stroke data to workout GET: Get stroke data of workout This v2 API works on stroke based data dict: - {"startdatetime":"2023-01-16 12:34:45", - "totalDistance":11233, - "elapsedTime":"65:23.10", - "summary":"Some summary", - "timezone":"UTC", - "workouttype":"rower", - "boattype":"1x", - "notes":"some notes", - "title":"Workout title", - "rpe":4, - "data": - [ - {"hr": 110, "p": 3600, "spm": 53, "d": 6, "t": 12, "latitude": 52.343, "longitude": -6.342}, - {"hr": 111, "p": 3600, "spm": 53, "d": 6, "t": 12, "latitude": 52.343, "longitude": -6.342}, - {"hr": 111, "p": 3600, "spm": 64, "d": 6, "t": 22, "latitude": 52.343, "longitude": -6.342}, - {"hr": 110, "p": 3600, "spm": 16, "d": 14, "t": 55, "latitude": 52.343, "longitude": -6.342}, - {"hr": 110, "p": 3600, "spm": 16, "d": 14, "t": 82, "latitude": 52.343, "longitude": -6.342}, - {"hr": 107, "p": 3600, "spm": 12, "d": 22, "t": 109, "latitude": 52.343, "longitude": -6.342}, - {"hr": 107, "p": 3600, "spm": 12, "d": 22, "t": 133, "latitude": 52.343, "longitude": -6.342}, - {"hr": 108, "p": 3600, "spm": 12, "d": 32, "t": 157, "latitude": 52.343, "longitude": -6.342}, - {"hr": 108, "p": 3577, "spm": 12, "d": 32, "t": 157, "latitude": 52.343, "longitude": -6.342}, - {"hr": 108, "p": 3411, "spm": 12, "d": 32, "t": 157, "latitude": 52.343, "longitude": -6.342}, - {"hr": 108, "p": 2649, "spm": 12, "d": 32, "t": 157, "latitude": 52.343, "longitude": -6.342}, - {"hr": 108, "p": 3099, "spm": 12, "d": 32, "t": 157, "latitude": 52.343, "longitude": -6.342}, - {"hr": 108, "p": 3600, "spm": 12, "d": 32, "t": 157, "latitude": 52.343, "longitude": -6.342}, - {"hr": 100, "p": 3600, "spm": 44, "d": 115, "t": 292, "latitude": 52.343, "longitude": -6.342}, - {"hr": 99, "p": 3600, "spm": 27, "d": 129, "t": 305, "latitude": 52.343, "longitude": -6.342}, - {"hr": 97, "p": 3600, "spm": 34, "d": 161, "t": 330, "latitude": 52.343, "longitude": -6.342}, - {"hr": 96, "p": 3600, "spm": 25, "d": 177, "t": 344, "latitude": 52.343, "longitude": -6.342}, - {"hr": 96, "p": 3494, "spm": 43, "d": 196, "t": 357, "latitude": 52.343, "longitude": -6.342}, - {"hr": 98, "p": 2927, "spm": 26, "d": 235, "t": 377, "latitude": 52.343, "longitude": -6.342}, - {"hr": 102, "p": 2718, "spm": 27, "d": 380, "t": 455, "latitude": 52.343, "longitude": -6.342}, - {"hr": 102, "p": 2753, "spm": 9, "d": 398, "t": 472, "latitude": 52.343, "longitude": -6.342}, - {"hr": 102, "p": 2864, "spm": 61, "d": 406, "t": 477, "latitude": 52.343, "longitude": -6.342}, - {"hr": 101, "p": 2780, "spm": 15, "d": 484, "t": 515, "latitude": 52.343, "longitude": -6.342}, - {"hr": 101, "p": 2365, "spm": 16, "d": 583, "t": 554, "latitude": 52.343, "longitude": -6.342}, - {"hr": 103, "p": 1965, "spm": 16, "d": 681, "t": 592, "latitude": 52.343, "longitude": -6.342}, - ] - } + { + "totalDistance": 100, + "elapsedTime": 592, + "title": "Test Workout (GO)", + "startdatetime": "2023-01-16 17:54:35.588838+00:00", + "workouttype": "water", + "boattype": "1x", + "notes": "some\nnotes", + "strokes": {"data": [ + {"distance":5, "power": 112, "hr": 132, "pace": 145800, "spm": 11, "time": 0, "latitude":52.2264097,"longitude":6.8493638}, + {"distance":12, "power": 221, "hr": 131, "pace": 116400, "spm": 41, "time": 2200, "latitude":52.2263474,"longitude":6.8495814}, + {"distance":19, "power": 511, "hr": 131, "pace": 88100, "spm": 56, "time": 4599, "latitude":52.2262715,"longitude":6.8496975}, + {"distance":27, "power": 673, "hr": 132, "pace": 80400, "spm": 59, "time": 7000, "latitude":52.2262003,"longitude":6.8498095}, + {"distance":35, "power": 744, "hr": 133, "pace": 77700, "spm": 55, "time": 9599, "latitude":52.2261312, "longitude":6.8499267}, + {"distance":43, "power": 754, "hr": 136, "pace": 77400, "spm": 48, "time": 12000, "latitude":52.2260576,"longitude":6.8500366}, + {"distance":51, "power": 754, "hr": 139, "pace": 77400, "spm": 48, "time": 14400, "latitude":52.2259872,"longitude":6.8501561}, + {"distance":59, "power": 749, "hr": 142, "pace": 77600, "spm": 48, "time": 16799, "latitude":52.2259154,"longitude":6.8502769}, + {"distance":67, "power": 729, "hr": 145, "pace": 78300, "spm": 48, "time": 19400, "latitude":52.2257749,"longitude":6.8503918}, + {"distance":75, "power": 729, "hr": 147, "pace": 78300, "spm": 48, "time": 21799, "latitude":52.2259154,"longitude":6.8502769}, + {"distance":82, "power": 726, "hr": 150, "pace": 78400, "spm": 48, "time": 24200, "latitude":52.2259872,"longitude":6.8501561}, + {"distance":90, "power": 709, "hr": 152, "pace": 79000, "spm": 48, "time": 26599, "latitude":52.2260576,"longitude":6.8500366}, + {"distance":100, "power": 707, "hr": 153, "pace": 79100, "spm": 49, "time": 29000, "latitude":52.2261312,"longitude":6.8499267}]} + +} + """ if request.method != 'POST': - return HttpResponse("Not allowed", status=409) + return HttpResponseNotAllowed("Method not supported") # pragma: no cover dologging('apilog.log', request.user.username+" (strokedatajson_v3 POST)") @@ -265,17 +253,23 @@ def strokedatajson_v3(request): totalDistance = request.data['totalDistance'] except KeyError: return HttpResponse("Missing Total Distance", status=400) - summary = request.data.get('summary','') - timezone = request.data.get('timezone','UTC') + timeZone = request.data.get('timezone','UTC') workouttype = request.data.get('workouttype','rower') boattype = request.data.get('boattype','1x') notes = request.data.get('notes','') rpe = request.data.get('rpe',0) + startdatetime = request.data.get('startdatetime',"%s" % timezone.now()) + + startdatetime = pendulum.parse(startdatetime) df = pd.DataFrame() + try: + strokes = request.data['strokes'] + except KeyError: + return HttpResponse("No Stroke Data in JSON", status=400) try: - df = pd.DataFrame(request.data['data']) + df = pd.DataFrame(strokes['data']) except KeyError: try: df = pd.DataFrame(request.data['strokedata']) @@ -291,22 +285,21 @@ def strokedatajson_v3(request): return HttpResponse(comment, status=status) - csvfilename = 'media/{code}.csv'.format(code=uuid4().hex[:16]) - _ = data.to_csv(csvfilename+'.gz', index_label='index', compression='gzip') + csvfilename = 'media/{code}.csv.gz'.format(code=uuid4().hex[:16]) + _ = data.to_csv(csvfilename, index_label='index', compression='gzip') uploadoptions = { 'secret': UPLOAD_SERVICE_SECRET, - 'user': userid, + 'user': request.user.id, 'file': csvfilename, 'title': title, 'workouttype': workouttype, 'boattype': boattype, - 'summary': summary, 'elapsedTime': elapsedTime/1000., # in seconds 'totalDistance': totalDistance, 'rpe': rpe, 'notes': notes, - 'timezone': timezone, + 'timezone': timeZone, } session = requests.session() newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'} @@ -324,6 +317,7 @@ def strokedatajson_v3(request): return JsonResponse( {"workout public id": encoder.encode_hex(workoutid), + "workout id": workoutid, "status": "success", })