From a98057c936cad18709234e4b26ebe301f78365a0 Mon Sep 17 00:00:00 2001 From: Joshua Taillon Date: Sun, 14 May 2023 22:40:03 -0600 Subject: [PATCH 1/9] Add pref for use_raw_gpx_speed; still need to do tests and client UI bits --- ...2_eff1c16c43eb_add_gpx_speed_preference.py | 34 +++++++++++++++++++ fittrackee/tests/users/test_auth_api.py | 2 ++ fittrackee/users/auth.py | 5 +++ fittrackee/users/models.py | 4 +++ fittrackee/workouts/utils/gpx.py | 4 ++- fittrackee/workouts/utils/workouts.py | 6 ++-- 6 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 fittrackee/migrations/versions/32_eff1c16c43eb_add_gpx_speed_preference.py diff --git a/fittrackee/migrations/versions/32_eff1c16c43eb_add_gpx_speed_preference.py b/fittrackee/migrations/versions/32_eff1c16c43eb_add_gpx_speed_preference.py new file mode 100644 index 000000000..733482908 --- /dev/null +++ b/fittrackee/migrations/versions/32_eff1c16c43eb_add_gpx_speed_preference.py @@ -0,0 +1,34 @@ +"""Add user prefrence for gpx speed calculation + +Revision ID: eff1c16c43eb +Revises: db58d195c5bf +Create Date: 2023-05-14 22:12:56.244291 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'eff1c16c43eb' +down_revision = 'db58d195c5bf' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.add_column(sa.Column('use_raw_gpx_speed', sa.Boolean(), nullable=True)) + op.execute("UPDATE users SET use_raw_gpx_speed = false") + op.alter_column('users', 'use_raw_gpx_speed', nullable=False) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.drop_column('use_raw_gpx_speed') + + # ### end Alembic commands ### diff --git a/fittrackee/tests/users/test_auth_api.py b/fittrackee/tests/users/test_auth_api.py index 4b6cf5e79..d88ec55f8 100644 --- a/fittrackee/tests/users/test_auth_api.py +++ b/fittrackee/tests/users/test_auth_api.py @@ -1483,6 +1483,7 @@ def test_it_updates_user_preferences( imperial_units=True, display_ascent=False, start_elevation_at_zero=False, + use_raw_gpx_speed=True, date_format='yyyy-MM-dd', ) ), @@ -1495,6 +1496,7 @@ def test_it_updates_user_preferences( assert data['message'] == 'user preferences updated' assert data['data']['display_ascent'] is False assert data['data']['start_elevation_at_zero'] is False + assert data['data']['use_raw_gpx_speed'] is True assert data['data']['imperial_units'] is True assert data['data']['language'] == expected_language assert data['data']['timezone'] == 'America/New_York' diff --git a/fittrackee/users/auth.py b/fittrackee/users/auth.py index 00516ffc3..2f0ff2828 100644 --- a/fittrackee/users/auth.py +++ b/fittrackee/users/auth.py @@ -879,6 +879,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]: "total_ascent": 720.35, "total_distance": 67.895, "total_duration": "6:50:27", + "use_raw_gpx_speed": true, "username": "sam" "weekm": true, }, @@ -892,6 +893,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]: : Union[Dict, HttpResponse]: 'language', 'start_elevation_at_zero', 'timezone', + 'use_raw_gpx_speed', 'weekm', } if not post_data or not post_data.keys() >= user_mandatory_data: @@ -925,6 +928,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]: imperial_units = post_data.get('imperial_units') language = get_language(post_data.get('language')) start_elevation_at_zero = post_data.get('start_elevation_at_zero') + use_raw_gpx_speed = post_data.get('use_raw_gpx_speed') timezone = post_data.get('timezone') weekm = post_data.get('weekm') @@ -935,6 +939,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]: auth_user.language = language auth_user.start_elevation_at_zero = start_elevation_at_zero auth_user.timezone = timezone + auth_user.use_raw_gpx_speed = use_raw_gpx_speed auth_user.weekm = weekm db.session.commit() diff --git a/fittrackee/users/models.py b/fittrackee/users/models.py index 2c598a316..8ab7c91ee 100644 --- a/fittrackee/users/models.py +++ b/fittrackee/users/models.py @@ -62,6 +62,9 @@ class User(BaseModel): start_elevation_at_zero = db.Column( db.Boolean, default=True, nullable=False ) + use_raw_gpx_speed = db.Column( + db.Boolean, default=False, nullable=False + ) def __repr__(self) -> str: return f'' @@ -216,6 +219,7 @@ def serialize(self, current_user: 'User') -> Dict: 'language': self.language, 'start_elevation_at_zero': self.start_elevation_at_zero, 'timezone': self.timezone, + 'use_raw_gpx_speed': self.use_raw_gpx_speed, 'weekm': self.weekm, }, } diff --git a/fittrackee/workouts/utils/gpx.py b/fittrackee/workouts/utils/gpx.py index 0116fab8b..7e1428bad 100644 --- a/fittrackee/workouts/utils/gpx.py +++ b/fittrackee/workouts/utils/gpx.py @@ -73,6 +73,7 @@ def get_gpx_info( stopped_speed_threshold: float, update_map_data: Optional[bool] = True, update_weather_data: Optional[bool] = True, + use_raw_gpx_speed: Optional[bool] = False ) -> Tuple: """ Parse and return gpx, map and weather data from gpx file @@ -128,7 +129,8 @@ def get_gpx_info( if update_map_data: map_data.append([point.longitude, point.latitude]) moving_data = segment.get_moving_data( - stopped_speed_threshold=stopped_speed_threshold + stopped_speed_threshold=stopped_speed_threshold, + raw=use_raw_gpx_speed ) if moving_data: calculated_max_speed = moving_data.max_speed diff --git a/fittrackee/workouts/utils/workouts.py b/fittrackee/workouts/utils/workouts.py index c687205d4..2caed7ce7 100644 --- a/fittrackee/workouts/utils/workouts.py +++ b/fittrackee/workouts/utils/workouts.py @@ -299,10 +299,12 @@ def process_one_gpx_file( absolute_gpx_filepath = None absolute_map_filepath = None try: + auth_user = params['auth_user'] gpx_data, map_data, weather_data = get_gpx_info( - params['file_path'], stopped_speed_threshold + gpx_file=params['file_path'], + stopped_speed_threshold=stopped_speed_threshold, + use_raw_gpx_speed=auth_user.use_raw_gpx_speed ) - auth_user = params['auth_user'] workout_date, _ = get_workout_datetime( workout_date=gpx_data['start'], date_str_format=None if gpx_data else '%Y-%m-%d %H:%M', From 7e00e79386dacf68005f0b684fbccc4b22c8a816 Mon Sep 17 00:00:00 2001 From: Joshua Taillon Date: Fri, 19 May 2023 23:08:12 -0600 Subject: [PATCH 2/9] Add test for parsing max_speed with raw_speed user preference setting --- fittrackee/tests/fixtures/fixtures_users.py | 17 ++++++++++++ .../tests/workouts/test_utils/test_gpx.py | 6 +++-- .../workouts/test_workouts_api_1_post.py | 27 +++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/fittrackee/tests/fixtures/fixtures_users.py b/fittrackee/tests/fixtures/fixtures_users.py index 1f3a99778..516752230 100644 --- a/fittrackee/tests/fixtures/fixtures_users.py +++ b/fittrackee/tests/fixtures/fixtures_users.py @@ -59,6 +59,23 @@ def user_1_full() -> User: return user +@pytest.fixture() +def user_1_raw_speed() -> User: + user = User(username='test', email='test@test.com', password='12345678') + user.first_name = 'John' + user.last_name = 'Doe' + user.bio = 'just a random guy' + user.location = 'somewhere' + user.language = 'en' + user.timezone = 'America/New_York' + user.birth_date = datetime.datetime.strptime('01/01/1980', '%d/%m/%Y') + user.is_active = True + user.use_raw_gpx_speed = True + user.accepted_policy = datetime.datetime.utcnow() + db.session.add(user) + db.session.commit() + return user + @pytest.fixture() def user_1_paris() -> User: user = User(username='test', email='test@test.com', password='12345678') diff --git a/fittrackee/tests/workouts/test_utils/test_gpx.py b/fittrackee/tests/workouts/test_utils/test_gpx.py index 058218aea..6195a430f 100644 --- a/fittrackee/tests/workouts/test_utils/test_gpx.py +++ b/fittrackee/tests/workouts/test_utils/test_gpx.py @@ -54,7 +54,8 @@ def test_it_calls_get_moving_data_with_threshold_depending_on_sport( ) assert gpx_track_segment_mock.call_args_list[0] == call( - stopped_speed_threshold=expected_threshold + stopped_speed_threshold=expected_threshold, + raw=False ) gpx_track_segment_mock.assert_called_with( expected_threshold, # stopped_speed_threshold @@ -88,7 +89,8 @@ def test_it_calls_get_moving_data_with_threshold_depending_from_user_preference( ) assert gpx_track_segment_mock.call_args_list[0] == call( - stopped_speed_threshold=expected_threshold + stopped_speed_threshold=expected_threshold, + raw=False ) gpx_track_segment_mock.assert_called_with( expected_threshold, # stopped_speed_threshold diff --git a/fittrackee/tests/workouts/test_workouts_api_1_post.py b/fittrackee/tests/workouts/test_workouts_api_1_post.py index 6587070bd..d2d74a2c8 100644 --- a/fittrackee/tests/workouts/test_workouts_api_1_post.py +++ b/fittrackee/tests/workouts/test_workouts_api_1_post.py @@ -278,6 +278,33 @@ def test_it_adds_a_workout_with_gpx_file( assert 'just a workout' == data['data']['workouts'][0]['title'] assert_workout_data_with_gpx(data) + def test_it_adds_a_workout_with_gpx_file_raw_speed( + self, app: Flask, user_1_raw_speed: User, sport_1_cycling: Sport, gpx_file: str + ) -> None: + client, auth_token = self.get_test_client_and_auth_token( + app, user_1_raw_speed.email + ) + + response = client.post( + '/api/workouts', + data=dict( + file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), + data='{"sport_id": 1}', + ), + headers=dict( + content_type='multipart/form-data', + Authorization=f'Bearer {auth_token}', + ), + ) + + data = json.loads(response.data.decode()) + assert response.status_code == 201 + assert 'created' in data['status'] + assert len(data['data']['workouts']) == 1 + # max speed should be slightly higher than that tested in + # assert_workout_data_with_gpx + assert data['data']['workouts'][0]['max_speed'] == pytest.approx(5.25) + def test_it_returns_ha_record_when_a_workout_without_gpx_exists( self, app: Flask, From cef28c52a2bb9dec9c84a76606870767a6b9505f Mon Sep 17 00:00:00 2001 From: Joshua Taillon Date: Sun, 21 May 2023 10:35:18 -0600 Subject: [PATCH 3/9] Add user preference UI bits for raw gpx speed processing --- .../User/ProfileDisplay/UserPreferences.vue | 2 ++ .../ProfileEdition/UserPreferencesEdition.vue | 34 +++++++++++++++++++ fittrackee_client/src/locales/de/user.json | 5 +++ fittrackee_client/src/locales/en/user.json | 5 +++ fittrackee_client/src/locales/es/user.json | 5 +++ fittrackee_client/src/locales/fr/user.json | 5 +++ fittrackee_client/src/locales/gl/user.json | 5 +++ fittrackee_client/src/locales/it/user.json | 5 +++ fittrackee_client/src/locales/nb/user.json | 7 +++- fittrackee_client/src/locales/nl/user.json | 5 +++ fittrackee_client/src/types/user.ts | 2 ++ 11 files changed, 79 insertions(+), 1 deletion(-) diff --git a/fittrackee_client/src/components/User/ProfileDisplay/UserPreferences.vue b/fittrackee_client/src/components/User/ProfileDisplay/UserPreferences.vue index fb64337e2..6bccddd5e 100644 --- a/fittrackee_client/src/components/User/ProfileDisplay/UserPreferences.vue +++ b/fittrackee_client/src/components/User/ProfileDisplay/UserPreferences.vue @@ -21,6 +21,8 @@
{{ $t(`common.${display_ascent}`) }}
{{ $t('user.PROFILE.ELEVATION_CHART_START.LABEL') }}:
{{ $t(`user.PROFILE.ELEVATION_CHART_START.${user.start_elevation_at_zero ? 'ZERO' : 'MIN_ALT'}`) }}
+
{{ $t('user.PROFILE.USE_RAW_GPX_SPEED.LABEL') }}:
+
{{ $t(`user.PROFILE.USE_RAW_GPX_SPEED.${user.use_raw_gpx_speed ? 'RAW_SPEED' : 'FILTERED_SPEED'}`) }}
+
+ + {{ $t('user.PROFILE.USE_RAW_GPX_SPEED.LABEL') }} + +
+ +
+