2018-05-09 18:23:17 +02:00
|
|
|
import os
|
2018-05-11 13:45:54 +02:00
|
|
|
import tempfile
|
2018-05-09 18:23:17 +02:00
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
2018-05-01 17:51:38 +02:00
|
|
|
import gpxpy.gpx
|
2018-05-09 18:23:17 +02:00
|
|
|
from flask import current_app
|
2018-05-12 23:38:33 +02:00
|
|
|
from mpwo_api import appLog
|
2018-05-09 18:23:17 +02:00
|
|
|
from werkzeug.utils import secure_filename
|
|
|
|
|
|
|
|
from .models import Activity
|
|
|
|
|
|
|
|
|
2018-05-10 10:21:58 +02:00
|
|
|
def create_activity(
|
2018-05-11 13:45:54 +02:00
|
|
|
auth_user_id, activity_data, gpx_data=None
|
2018-05-10 10:21:58 +02:00
|
|
|
):
|
|
|
|
activity_date = gpx_data['start'] if gpx_data else datetime.strptime(
|
|
|
|
activity_data.get('activity_date'), '%Y-%m-%d %H:%M')
|
2018-05-12 23:38:33 +02:00
|
|
|
duration = gpx_data['duration'] if gpx_data \
|
2018-05-10 10:21:58 +02:00
|
|
|
else timedelta(seconds=activity_data.get('duration'))
|
2018-05-11 17:55:46 +02:00
|
|
|
distance = gpx_data['distance'] if gpx_data \
|
|
|
|
else activity_data.get('distance')
|
2018-05-09 18:23:17 +02:00
|
|
|
|
|
|
|
new_activity = Activity(
|
|
|
|
user_id=auth_user_id,
|
|
|
|
sport_id=activity_data.get('sport_id'),
|
2018-05-10 10:21:58 +02:00
|
|
|
activity_date=activity_date,
|
2018-05-11 17:55:46 +02:00
|
|
|
distance=distance,
|
2018-05-10 10:21:58 +02:00
|
|
|
duration=duration
|
2018-05-09 18:23:17 +02:00
|
|
|
)
|
2018-05-10 10:21:58 +02:00
|
|
|
|
|
|
|
if gpx_data:
|
2018-05-11 13:45:54 +02:00
|
|
|
new_activity.gpx = gpx_data['filename']
|
2018-05-12 23:38:33 +02:00
|
|
|
new_activity.pauses = gpx_data['stop_time']
|
|
|
|
new_activity.moving = gpx_data['moving_time']
|
2018-05-10 10:21:58 +02:00
|
|
|
new_activity.min_alt = gpx_data['elevation_min']
|
|
|
|
new_activity.max_alt = gpx_data['elevation_max']
|
|
|
|
new_activity.descent = gpx_data['downhill']
|
|
|
|
new_activity.ascent = gpx_data['uphill']
|
|
|
|
new_activity.max_speed = gpx_data['max_speed']
|
|
|
|
new_activity.ave_speed = gpx_data['average_speed']
|
|
|
|
else:
|
|
|
|
new_activity.moving = duration
|
|
|
|
new_activity.ave_speed = new_activity.distance / (
|
|
|
|
duration.seconds / 3600)
|
|
|
|
new_activity.max_speed = new_activity.ave_speed
|
2018-05-09 18:23:17 +02:00
|
|
|
return new_activity
|
2018-05-01 17:51:38 +02:00
|
|
|
|
|
|
|
|
2018-05-11 17:55:46 +02:00
|
|
|
def edit_activity(activity, activity_data):
|
2018-05-09 20:45:01 +02:00
|
|
|
activity.sport_id = activity_data.get('sport_id')
|
2018-05-11 17:55:46 +02:00
|
|
|
if not activity.gpx:
|
|
|
|
if activity_data.get('activity_date'):
|
|
|
|
activity.activity_date = datetime.strptime(
|
|
|
|
activity_data.get('activity_date'), '%Y-%m-%d %H:%M')
|
|
|
|
if activity_data.get('duration'):
|
|
|
|
activity.duration = timedelta(seconds=activity_data.get('duration')) # noqa
|
|
|
|
activity.moving = activity.duration
|
|
|
|
if activity_data.get('distance'):
|
|
|
|
activity.distance = activity_data.get('distance')
|
|
|
|
activity.ave_speed = activity.distance / (
|
|
|
|
activity.duration.seconds / 3600)
|
|
|
|
activity.max_speed = activity.ave_speed
|
2018-05-09 20:45:01 +02:00
|
|
|
return activity
|
|
|
|
|
|
|
|
|
2018-05-12 23:38:33 +02:00
|
|
|
def get_gpx_data(parsed_gpx, max_speed, start):
|
2018-05-01 17:51:38 +02:00
|
|
|
|
2018-05-12 23:38:33 +02:00
|
|
|
gpx_data = {'max_speed': (max_speed / 1000) * 3600, 'start': start}
|
2018-05-01 17:51:38 +02:00
|
|
|
|
2018-05-12 23:38:33 +02:00
|
|
|
duration = parsed_gpx.get_duration()
|
|
|
|
gpx_data['duration'] = timedelta(seconds=duration)
|
2018-05-01 17:51:38 +02:00
|
|
|
|
2018-05-12 23:38:33 +02:00
|
|
|
ele = parsed_gpx.get_elevation_extremes()
|
2018-05-01 17:51:38 +02:00
|
|
|
gpx_data['elevation_max'] = ele.maximum
|
|
|
|
gpx_data['elevation_min'] = ele.minimum
|
|
|
|
|
2018-05-12 23:38:33 +02:00
|
|
|
hill = parsed_gpx.get_uphill_downhill()
|
2018-05-01 17:51:38 +02:00
|
|
|
gpx_data['uphill'] = hill.uphill
|
|
|
|
gpx_data['downhill'] = hill.downhill
|
|
|
|
|
2018-05-12 23:38:33 +02:00
|
|
|
mv = parsed_gpx.get_moving_data()
|
|
|
|
gpx_data['moving_time'] = timedelta(seconds=mv.moving_time)
|
|
|
|
gpx_data['stop_time'] = timedelta(seconds=mv.stopped_time)
|
2018-05-01 17:51:38 +02:00
|
|
|
distance = mv.moving_distance + mv.stopped_distance
|
2018-05-12 23:38:33 +02:00
|
|
|
gpx_data['distance'] = distance / 1000
|
2018-05-01 17:51:38 +02:00
|
|
|
|
2018-05-12 23:38:33 +02:00
|
|
|
average_speed = distance / mv.moving_time
|
2018-05-01 17:51:38 +02:00
|
|
|
gpx_data['average_speed'] = (average_speed / 1000) * 3600
|
|
|
|
|
|
|
|
return gpx_data
|
2018-05-09 18:23:17 +02:00
|
|
|
|
|
|
|
|
2018-05-12 23:38:33 +02:00
|
|
|
def get_gpx_info(gpx_file):
|
|
|
|
|
|
|
|
gpx_file = open(gpx_file, 'r')
|
|
|
|
|
|
|
|
try:
|
|
|
|
gpx = gpxpy.parse(gpx_file)
|
|
|
|
except gpxpy.gpx.GPXXMLSyntaxException as e:
|
|
|
|
appLog.error(e)
|
|
|
|
return None
|
|
|
|
|
|
|
|
# handle only one track per file
|
|
|
|
if len(gpx.tracks) == 0:
|
|
|
|
return None
|
|
|
|
|
|
|
|
gpx_data = {
|
|
|
|
'name': gpx.tracks[0].name,
|
|
|
|
'segments': []}
|
|
|
|
max_speed = 0
|
|
|
|
start = 0
|
|
|
|
|
|
|
|
for segment_idx, segment in enumerate(gpx.tracks[0].segments):
|
|
|
|
segment_max_speed = 0
|
|
|
|
segment_start = 0
|
|
|
|
for point_idx, point in enumerate(segment.points):
|
|
|
|
if point_idx == 0:
|
|
|
|
segment_start = point.time
|
|
|
|
if start == 0:
|
|
|
|
start = segment_start
|
|
|
|
segment_speed = segment.get_speed(point_idx)
|
|
|
|
if segment_speed > segment_max_speed:
|
|
|
|
segment_max_speed = segment_speed
|
|
|
|
if segment_max_speed > max_speed:
|
|
|
|
max_speed = segment_max_speed
|
|
|
|
|
|
|
|
segment_data = get_gpx_data(
|
|
|
|
segment, segment_max_speed, segment_start
|
|
|
|
)
|
|
|
|
segment_data['idx'] = segment_idx
|
|
|
|
gpx_data['segments'].append(segment_data)
|
|
|
|
|
|
|
|
gull_gpx_data = get_gpx_data(gpx, max_speed, start)
|
|
|
|
gpx_data = {**gpx_data, **gull_gpx_data}
|
|
|
|
bounds = gpx.get_bounds()
|
|
|
|
gpx_data['bounds'] = [
|
|
|
|
bounds.min_latitude,
|
|
|
|
bounds.min_longitude,
|
|
|
|
bounds.max_latitude,
|
|
|
|
bounds.max_longitude
|
|
|
|
]
|
|
|
|
|
|
|
|
return gpx_data
|
|
|
|
|
|
|
|
|
2018-05-09 18:23:17 +02:00
|
|
|
def get_file_path(auth_user_id, activity_file):
|
|
|
|
filename = secure_filename(activity_file.filename)
|
|
|
|
dir_path = os.path.join(
|
2018-05-11 13:45:54 +02:00
|
|
|
current_app.config['UPLOAD_FOLDER'],
|
|
|
|
'activities',
|
|
|
|
str(auth_user_id),
|
|
|
|
'tmp')
|
2018-05-09 18:23:17 +02:00
|
|
|
if not os.path.exists(dir_path):
|
|
|
|
os.makedirs(dir_path)
|
|
|
|
file_path = os.path.join(dir_path, filename)
|
|
|
|
return file_path
|
2018-05-11 13:45:54 +02:00
|
|
|
|
|
|
|
|
|
|
|
def get_new_file_path(auth_user_id, activity_date, activity_file, sport):
|
|
|
|
old_filename = secure_filename(activity_file.filename)
|
|
|
|
extension = '.{}'.format(old_filename.rsplit('.', 1)[1].lower())
|
2018-05-11 17:55:46 +02:00
|
|
|
_, new_filename = tempfile.mkstemp(
|
2018-05-11 13:45:54 +02:00
|
|
|
prefix='{}_{}_'.format(activity_date, sport),
|
|
|
|
suffix=extension
|
|
|
|
)
|
|
|
|
dir_path = os.path.join(
|
|
|
|
current_app.config['UPLOAD_FOLDER'], 'activities', str(auth_user_id))
|
|
|
|
if not os.path.exists(dir_path):
|
|
|
|
os.makedirs(dir_path)
|
2018-05-11 17:55:46 +02:00
|
|
|
file_path = os.path.join(dir_path, new_filename.replace('/tmp/', '')) # noqa
|
2018-05-11 13:45:54 +02:00
|
|
|
return file_path
|