~cypheon/trakka

f4b6ad3476a203d09e9fe80ed2a84c1465ca38a0 — Johann Rudloff 2 years ago c0de2f4
Implement calculation of actual "moving time"
2 files changed, 27 insertions(+), 6 deletions(-)

M activities/activity.py
M activities/tests.py
M activities/activity.py => activities/activity.py +15 -6
@@ 200,6 200,10 @@ def guess_type(analysis) -> str:
    except:
        return 'Exercise'

# Speed (in m/s) that is considered "moving", lower speeds are considered
# "stopped"
MOVING_THRESHOLD = 0.05

def analyse(track: Track, athlete_data: Mapping[str, float], raw: bool = False):
    pos = track.positions
    raw_hr = track.hr


@@ 224,6 228,16 @@ def analyse(track: Track, athlete_data: Mapping[str, float], raw: bool = False):
        dist[i][1] = length_acc
        # print(pos[i])

    # since time values in the `dist` array are relative to the start, elapsed
    # time is just the last time value from the array
    elapsed_seconds = dist[-1][0]

    time_deltas = np.diff(dist[:, 0])
    dist_deltas = np.diff(dist[:, 1])
    speed = dist_deltas / time_deltas
    moving_seconds = np.dot(np.greater(speed, MOVING_THRESHOLD), time_deltas)
    assert moving_seconds <= elapsed_seconds

    hr = np.zeros((raw_hr.shape[0], 2))
    if raw_hr.shape[0] > 0:
        hr[:, 1] = raw_hr[:, 1]


@@ 248,9 262,6 @@ def analyse(track: Track, athlete_data: Mapping[str, float], raw: bool = False):
        max_hr = None
        min_hr = None

    # elapsed_seconds = (pos[-1][0] - pos[0][0]).item().total_seconds()
    elapsed_seconds = dist[-1][0]

    weight = athlete_data.get('weight')
    if weight is not None:
        energy = round(estimate_energy(dist[-1][1],


@@ 260,12 271,10 @@ def analyse(track: Track, athlete_data: Mapping[str, float], raw: bool = False):
    else:
        energy = None



    result = {
        'distance': dist[-1][1],
        'elapsed_seconds': elapsed_seconds,
        'moving_seconds': elapsed_seconds, # TODO: real "moving time" calculation
        'moving_seconds': moving_seconds,
        'start_date': pos[0][0].item(),
        'avg_hr': avg_hr,
        'max_hr': max_hr,

M activities/tests.py => activities/tests.py +12 -0
@@ 51,6 51,18 @@ class TestFitImport(SimpleTestCase):
        npt.assert_allclose(a['elapsed_seconds'], 1533)
        npt.assert_allclose(a['distance'], 4790, atol=1)

class TestAnalysis(SimpleTestCase):
    def setUp(self):
        with open('test/data/sample_walk.fit', 'rb') as f:
            content = f.read()
        self.track = from_fit_bytes(content)

    def test_moving_time(self):
        a = analyse(self.track, {})

        npt.assert_allclose(a['elapsed_seconds'], 51 * 60 + 23, atol=1)
        npt.assert_allclose(a['moving_seconds'], 50 * 60, atol=10)

class TestStravaImport(SimpleTestCase):

    def test_import(self):