Merge pull request #358 from jat255/max_speed_preference
Add user preference for filtering of GPX speed data
This commit is contained in:
Vendored
+1
-1
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"/><link rel="stylesheet" href="/static/css/leaflet.css"/><title>FitTrackee</title><script defer="defer" src="/static/js/chunk-vendors.a33476ea.js"></script><script defer="defer" src="/static/js/app.464dd65e.js"></script><link href="/static/css/app.fa4567f8.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"/><link rel="stylesheet" href="/static/css/leaflet.css"/><title>FitTrackee</title><script defer="defer" src="/static/js/chunk-vendors.a33476ea.js"></script><script defer="defer" src="/static/js/app.f72ca9c7.js"></script><link href="/static/css/app.3193986e.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -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 ###
|
||||
+18
@@ -59,6 +59,24 @@ 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')
|
||||
|
||||
@@ -1459,6 +1459,7 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
|
||||
imperial_units=True,
|
||||
display_ascent=False,
|
||||
start_elevation_at_zero=False,
|
||||
use_raw_gpx_speed=True,
|
||||
date_format='yyyy-MM-dd',
|
||||
)
|
||||
),
|
||||
@@ -1471,6 +1472,7 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
|
||||
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'
|
||||
|
||||
@@ -54,7 +54,7 @@ class TestStoppedSpeedThreshold:
|
||||
)
|
||||
|
||||
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 +88,7 @@ class TestStoppedSpeedThreshold:
|
||||
)
|
||||
|
||||
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
|
||||
@@ -98,6 +98,43 @@ class TestStoppedSpeedThreshold:
|
||||
)
|
||||
|
||||
|
||||
class TestUseRawGpxSpeed:
|
||||
@pytest.mark.parametrize('input_use_raw_gpx_speed', [True, False])
|
||||
def test_it_calls_get_moving_data_with_user_use_raw_gpx_speed_preference(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
gpx_file_storage: FileStorage,
|
||||
sport_1_cycling: Sport,
|
||||
input_use_raw_gpx_speed: bool,
|
||||
) -> None:
|
||||
user_1.use_raw_gpx_speed = input_use_raw_gpx_speed
|
||||
with patch(
|
||||
'fittrackee.workouts.utils.workouts.get_new_file_path',
|
||||
return_value='/tmp/fitTrackee/uploads/test.png',
|
||||
), patch(
|
||||
'gpxpy.gpx.GPXTrackSegment.get_moving_data',
|
||||
return_value=moving_data,
|
||||
) as gpx_track_segment_mock:
|
||||
process_files(
|
||||
auth_user=user_1,
|
||||
folders=folders,
|
||||
workout_data={'sport_id': sport_1_cycling.id},
|
||||
workout_file=gpx_file_storage,
|
||||
)
|
||||
|
||||
assert gpx_track_segment_mock.call_args_list[0] == call(
|
||||
stopped_speed_threshold=sport_1_cycling.stopped_speed_threshold,
|
||||
raw=input_use_raw_gpx_speed,
|
||||
)
|
||||
gpx_track_segment_mock.assert_called_with(
|
||||
sport_1_cycling.stopped_speed_threshold, # stopped_speed_threshold
|
||||
False, # raw
|
||||
IGNORE_TOP_SPEED_PERCENTILES, # speed_extreemes_percentiles
|
||||
True, # ignore_nonstandard_distances
|
||||
)
|
||||
|
||||
|
||||
class TestGetGpxInfoStopTime:
|
||||
def test_stop_time_equals_to_0_when_gpx_file_contains_one_segment(
|
||||
self, gpx_file: str
|
||||
|
||||
@@ -279,6 +279,37 @@ class TestPostWorkoutWithGpx(ApiTestCaseMixin, CallArgsMixin):
|
||||
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,
|
||||
|
||||
@@ -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]:
|
||||
:<json string language: language preferences
|
||||
:<json boolean start_elevation_at_zero: do elevation plots start at zero?
|
||||
:<json string timezone: user time zone
|
||||
:<json boolean use_raw_gpx_speed: Use unfiltered gpx to calculate speeds
|
||||
:<json boolean weekm: does week start on Monday?
|
||||
|
||||
:reqheader Authorization: OAuth 2.0 Bearer Token
|
||||
@@ -915,6 +917,7 @@ def edit_user_preferences(auth_user: User) -> 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()
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ 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'<User {self.username!r}>'
|
||||
@@ -216,6 +217,7 @@ class User(BaseModel):
|
||||
'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,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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: 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
|
||||
|
||||
@@ -299,10 +299,12 @@ def process_one_gpx_file(
|
||||
absolute_gpx_filepath = None
|
||||
absolute_map_filepath = None
|
||||
try:
|
||||
gpx_data, map_data, weather_data = get_gpx_info(
|
||||
params['file_path'], stopped_speed_threshold
|
||||
)
|
||||
auth_user = params['auth_user']
|
||||
gpx_data, map_data, weather_data = get_gpx_info(
|
||||
gpx_file=params['file_path'],
|
||||
stopped_speed_threshold=stopped_speed_threshold,
|
||||
use_raw_gpx_speed=auth_user.use_raw_gpx_speed,
|
||||
)
|
||||
workout_date, _ = get_workout_datetime(
|
||||
workout_date=gpx_data['start'],
|
||||
date_str_format=None if gpx_data else '%Y-%m-%d %H:%M',
|
||||
|
||||
@@ -20,7 +20,31 @@
|
||||
<dt>{{ $t('user.PROFILE.ASCENT_DATA') }}:</dt>
|
||||
<dd>{{ $t(`common.${display_ascent}`) }}</dd>
|
||||
<dt>{{ $t('user.PROFILE.ELEVATION_CHART_START.LABEL') }}:</dt>
|
||||
<dd>{{ $t(`user.PROFILE.ELEVATION_CHART_START.${user.start_elevation_at_zero ? 'ZERO' : 'MIN_ALT'}`) }}</dd>
|
||||
<dd>
|
||||
{{
|
||||
$t(
|
||||
`user.PROFILE.ELEVATION_CHART_START.${
|
||||
user.start_elevation_at_zero ? 'ZERO' : 'MIN_ALT'
|
||||
}`
|
||||
)
|
||||
}}
|
||||
</dd>
|
||||
<dt>{{ $t('user.PROFILE.USE_RAW_GPX_SPEED.LABEL') }}:</dt>
|
||||
<dd>
|
||||
{{
|
||||
$t(
|
||||
`user.PROFILE.USE_RAW_GPX_SPEED.${
|
||||
user.use_raw_gpx_speed ? 'RAW_SPEED' : 'FILTERED_SPEED'
|
||||
}`
|
||||
)
|
||||
}}
|
||||
</dd>
|
||||
<div class="info-box raw-speed-help">
|
||||
<span>
|
||||
<i class="fa fa-info-circle" aria-hidden="true" />
|
||||
{{ $t('user.PROFILE.USE_RAW_GPX_SPEED.HELP') }}
|
||||
</span>
|
||||
</div>
|
||||
</dl>
|
||||
<div class="profile-buttons">
|
||||
<button @click="$router.push('/profile/edit/preferences')">
|
||||
|
||||
@@ -104,7 +104,10 @@
|
||||
{{ $t('user.PROFILE.ELEVATION_CHART_START.LABEL') }}
|
||||
</span>
|
||||
<div class="checkboxes">
|
||||
<label v-for="status in startElevationAtZeroData" :key="status.label">
|
||||
<label
|
||||
v-for="status in startElevationAtZeroData"
|
||||
:key="status.label"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
:id="status.label"
|
||||
@@ -119,6 +122,32 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-items form-checkboxes">
|
||||
<span class="checkboxes-label">
|
||||
{{ $t('user.PROFILE.USE_RAW_GPX_SPEED.LABEL') }}
|
||||
</span>
|
||||
<div class="checkboxes">
|
||||
<label v-for="status in useRawGpxSpeed" :key="status.label">
|
||||
<input
|
||||
type="radio"
|
||||
:id="status.label"
|
||||
:name="status.label"
|
||||
:checked="status.value === userForm.use_raw_gpx_speed"
|
||||
:disabled="loading"
|
||||
@input="updateUseRawGpxSpeed(status.value)"
|
||||
/>
|
||||
<span class="checkbox-label">
|
||||
{{ $t(`user.PROFILE.USE_RAW_GPX_SPEED.${status.label}`) }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="info-box raw-speed-help">
|
||||
<span>
|
||||
<i class="fa fa-info-circle" aria-hidden="true" />
|
||||
{{ $t('user.PROFILE.USE_RAW_GPX_SPEED.HELP') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-buttons">
|
||||
<button class="confirm" type="submit">
|
||||
{{ $t('buttons.SUBMIT') }}
|
||||
@@ -193,12 +222,22 @@
|
||||
const startElevationAtZeroData = [
|
||||
{
|
||||
label: 'ZERO',
|
||||
value: true
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: 'MIN_ALT',
|
||||
value: false
|
||||
}
|
||||
value: false,
|
||||
},
|
||||
]
|
||||
const useRawGpxSpeed = [
|
||||
{
|
||||
label: 'FILTERED_SPEED',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
label: 'RAW_SPEED',
|
||||
value: true,
|
||||
},
|
||||
]
|
||||
const loading = computed(
|
||||
() => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]
|
||||
@@ -222,7 +261,12 @@
|
||||
|
||||
function updateUserForm(user: IAuthUserProfile) {
|
||||
userForm.display_ascent = user.display_ascent
|
||||
userForm.start_elevation_at_zero = user.start_elevation_at_zero ? user.start_elevation_at_zero : false
|
||||
userForm.start_elevation_at_zero = user.start_elevation_at_zero
|
||||
? user.start_elevation_at_zero
|
||||
: false
|
||||
userForm.use_raw_gpx_speed = user.use_raw_gpx_speed
|
||||
? user.use_raw_gpx_speed
|
||||
: false
|
||||
userForm.imperial_units = user.imperial_units ? user.imperial_units : false
|
||||
userForm.language = user.language ? user.language : 'en'
|
||||
userForm.timezone = user.timezone ? user.timezone : 'Europe/Paris'
|
||||
@@ -238,6 +282,9 @@
|
||||
function updateStartElevationAtZero(value: boolean) {
|
||||
userForm.start_elevation_at_zero = value
|
||||
}
|
||||
function updateUseRawGpxSpeed(value: boolean) {
|
||||
userForm.use_raw_gpx_speed = value
|
||||
}
|
||||
function updateAscentDisplay(value: boolean) {
|
||||
userForm.display_ascent = value
|
||||
}
|
||||
|
||||
@@ -116,6 +116,11 @@
|
||||
"IMPERIAL": "Imperiales System (ft, mi, mph, °F)",
|
||||
"LABEL": "Einheiten für die Distanz",
|
||||
"METRIC": "Metrisches System (m, km, m/s, °C)"
|
||||
},
|
||||
"USE_RAW_GPX_SPEED": {
|
||||
"FILTERED_SPEED": "Gefiltert",
|
||||
"LABEL": "Höchstgeschwindigkeitsstrategie",
|
||||
"RAW_SPEED": "Rau"
|
||||
}
|
||||
},
|
||||
"READ_AND_ACCEPT_PRIVACY_POLICY": "Ich habe die {0} gelesen und stimme ihr zu.",
|
||||
|
||||
@@ -68,12 +68,12 @@
|
||||
"EDIT": "Edit profile",
|
||||
"EDIT_PREFERENCES": "Edit preferences",
|
||||
"EDIT_SPORTS_PREFERENCES": "Edit sports preferences",
|
||||
"ERRORED_EMAIL_UPDATE": "Please {0} to change your email address again or contact the administrator",
|
||||
"ELEVATION_CHART_START": {
|
||||
"LABEL": "Elevation chart starts at",
|
||||
"ZERO": "Zero",
|
||||
"MIN_ALT": "Minimum altitude"
|
||||
"MIN_ALT": "Minimum altitude",
|
||||
"ZERO": "Zero"
|
||||
},
|
||||
"ERRORED_EMAIL_UPDATE": "Please {0} to change your email address again or contact the administrator",
|
||||
"FIRST_DAY_OF_WEEK": "First day of week",
|
||||
"FIRST_NAME": "First name",
|
||||
"LANGUAGE": "Language",
|
||||
@@ -116,6 +116,12 @@
|
||||
"IMPERIAL": "Imperial system (ft, mi, mph, °F)",
|
||||
"LABEL": "Units for distance",
|
||||
"METRIC": "Metric system (m, km, m/s, °C)"
|
||||
},
|
||||
"USE_RAW_GPX_SPEED": {
|
||||
"FILTERED_SPEED": "Filtered",
|
||||
"HELP": "If filtered, it excludes extreme values (which may be GPS errors) when calculating the maximum speed.",
|
||||
"LABEL": "GPX max speed strategy",
|
||||
"RAW_SPEED": "Raw"
|
||||
}
|
||||
},
|
||||
"READ_AND_ACCEPT_PRIVACY_POLICY": "I have read and agree to the {0}.",
|
||||
|
||||
@@ -116,6 +116,11 @@
|
||||
"IMPERIAL": "Sistema Imperial (ft, mi, mph, ºF)",
|
||||
"LABEL": "Unidades de distancia",
|
||||
"METRIC": "Sistema Métrico (m, km, m/s, ºC)"
|
||||
},
|
||||
"USE_RAW_GPX_SPEED": {
|
||||
"FILTERED_SPEED": "Filtrado",
|
||||
"LABEL": "Estrategia de velocidad máxima",
|
||||
"RAW_SPEED": "Crudo"
|
||||
}
|
||||
},
|
||||
"READ_AND_ACCEPT_PRIVACY_POLICY": "He leído y aceptado la {0}.",
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
"EDIT_SPORTS_PREFERENCES": "Modifier les préférences des sports",
|
||||
"ELEVATION_CHART_START": {
|
||||
"LABEL": "Début de l'axe pour le graphe affichant l'altitude",
|
||||
"ZERO": "0",
|
||||
"MIN_ALT": "Altitude minimale"
|
||||
"MIN_ALT": "Altitude minimale",
|
||||
"ZERO": "0"
|
||||
},
|
||||
"ERRORED_EMAIL_UPDATE": "Veuillez vous {0} pour changer de nouveau votre adresse électronique ou contacter l'administrateur",
|
||||
"FIRST_DAY_OF_WEEK": "Premier jour de la semaine",
|
||||
@@ -116,6 +116,12 @@
|
||||
"IMPERIAL": "Système impérial (ft, mi, mph, °F)",
|
||||
"LABEL": "Unités pour les distances",
|
||||
"METRIC": "Système métrique (m, km, m/s, °C)"
|
||||
},
|
||||
"USE_RAW_GPX_SPEED": {
|
||||
"FILTERED_SPEED": "Filtré",
|
||||
"HELP": "Si filtré, les valeurs extrêmes (qui peuvent être des erreurs GPS) sont exclues lors du calcul de la vitesse maximale.",
|
||||
"LABEL": "Stratégie de vitesse maximale",
|
||||
"RAW_SPEED": "Brut"
|
||||
}
|
||||
},
|
||||
"READ_AND_ACCEPT_PRIVACY_POLICY": "J'ai lu et accepte la {0}.",
|
||||
|
||||
@@ -116,6 +116,11 @@
|
||||
"IMPERIAL": "Sistema Imperial (ft, mi, mph, ºF)",
|
||||
"LABEL": "Unidades de distancia",
|
||||
"METRIC": "Sistema Métrico (m, km, m/s, ºC)"
|
||||
},
|
||||
"USE_RAW_GPX_SPEED": {
|
||||
"FILTERED_SPEED": "Filtrado",
|
||||
"LABEL": "Estratexia de velocidade máxima",
|
||||
"RAW_SPEED": "Cru"
|
||||
}
|
||||
},
|
||||
"READ_AND_ACCEPT_PRIVACY_POLICY": "Lin e acepto a {0}.",
|
||||
|
||||
@@ -97,6 +97,11 @@
|
||||
"IMPERIAL": "Sistema imperiale (ft, mi, mph, °F)",
|
||||
"LABEL": "Unità per la distanza",
|
||||
"METRIC": "Sistema metrico (m, km, m/s, °C)"
|
||||
},
|
||||
"USE_RAW_GPX_SPEED": {
|
||||
"FILTERED_SPEED": "Filtrato",
|
||||
"LABEL": "Strategia di massima velocità",
|
||||
"RAW_SPEED": "Greggio"
|
||||
}
|
||||
},
|
||||
"REGISTER": "Registra",
|
||||
|
||||
@@ -47,7 +47,12 @@
|
||||
"TABS": {
|
||||
"PROFILE": "profil"
|
||||
},
|
||||
"TIMEZONE": "Tidssone"
|
||||
"TIMEZONE": "Tidssone",
|
||||
"USE_RAW_GPX_SPEED": {
|
||||
"FILTERED_SPEED": "Filtrert",
|
||||
"LABEL": "Maks hastighet strategi",
|
||||
"RAW_SPEED": "Rå"
|
||||
}
|
||||
},
|
||||
"RESET_PASSWORD": "Tilbakestill passordet ditt",
|
||||
"SHOW_PASSWORD": "vis passord",
|
||||
|
||||
@@ -116,6 +116,11 @@
|
||||
"IMPERIAL": "Imperialistisch systeem (ft, mi, mph, °F)",
|
||||
"LABEL": "Eenheid voor afstand",
|
||||
"METRIC": "Metrisch systeem (m, km, m/s, °C)"
|
||||
},
|
||||
"USE_RAW_GPX_SPEED": {
|
||||
"FILTERED_SPEED": "Gefilterd",
|
||||
"LABEL": "Strategie voor maximale snelheid",
|
||||
"RAW_SPEED": "Rauw"
|
||||
}
|
||||
},
|
||||
"READ_AND_ACCEPT_PRIVACY_POLICY": "Ik heb het {0} gelezen en goedgekeurd.",
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface IAuthUserProfile extends IUserProfile {
|
||||
display_ascent: boolean
|
||||
imperial_units: boolean
|
||||
start_elevation_at_zero: boolean
|
||||
use_raw_gpx_speed: boolean
|
||||
language: string | null
|
||||
timezone: string
|
||||
date_format: string
|
||||
@@ -65,6 +66,7 @@ export interface IAdminUserPayload {
|
||||
export interface IUserPreferencesPayload {
|
||||
display_ascent: boolean
|
||||
start_elevation_at_zero: boolean
|
||||
use_raw_gpx_speed: boolean
|
||||
imperial_units: boolean
|
||||
language: string
|
||||
timezone: string
|
||||
|
||||
Reference in New Issue
Block a user