Merge pull request #118 from SamR1/average-speed-in-chart

Add average speed in statistics
This commit is contained in:
Sam 2021-11-28 11:57:03 +01:00 committed by GitHub
commit 7d2248ec8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 637 additions and 229 deletions

View File

@ -1,5 +1,16 @@
# Change log # Change log
## Version 0.5.1 (unreleased)
### Issues Closed
#### New Features
* [#5](https://github.com/SamR1/FitTrackee/issues/5) - Display a chart with average speed
In this release 1 issue was closed.
## Version 0.5.0 (2021/11/14) ## Version 0.5.0 (2021/11/14)
### Issues Closed ### Issues Closed

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -1,5 +1,16 @@
# Change log # Change log
## Version 0.5.1 (unreleased)
### Issues Closed
#### New Features
* [#5](https://github.com/SamR1/FitTrackee/issues/5) - Display a chart with average speed
In this release 1 issue was closed.
## Version 0.5.0 (2021/11/14) ## Version 0.5.0 (2021/11/14)
### Issues Closed ### Issues Closed

View File

@ -76,7 +76,13 @@ Workouts
- Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance). - Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance).
- A workout with a gpx file can be displayed with map, weather (if the DarkSky API key is provided) and charts (speed and elevation). Segments can be displayed. - A workout with a gpx file can be displayed with map, weather (if the DarkSky API key is provided) and charts (speed and elevation). Segments can be displayed.
- Workout edition and deletion. User can add a note. - Workout edition and deletion. User can add a note.
- User statistics - User statistics, by time period (week, month, year) and sport:
- total distance
- total duration
- total workouts
- total ascent (**new in 0.5.0**)
- total descent (**new in 0.5.0**)
- average speed (**new in 0.5.1**)
- User records by sports: - User records by sports:
- average speed - average speed
- farest distance - farest distance

View File

@ -157,6 +157,7 @@
<span class="nt">&quot;statistics&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;statistics&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;2017&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;2017&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;3&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;3&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;average_speed&quot;</span><span class="p">:</span> <span class="mf">4.48</span><span class="p">,</span>
<span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">203.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">203.0</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">156.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">156.0</span><span class="p">,</span>
@ -166,6 +167,7 @@
<span class="p">},</span> <span class="p">},</span>
<span class="nt">&quot;2019&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;2019&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;1&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;1&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;average_speed&quot;</span><span class="p">:</span> <span class="mf">16.99</span><span class="p">,</span>
<span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">150.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">150.0</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">178.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">178.0</span><span class="p">,</span>
@ -173,6 +175,7 @@
<span class="nt">&quot;total_duration&quot;</span><span class="p">:</span> <span class="mi">9960</span> <span class="nt">&quot;total_duration&quot;</span><span class="p">:</span> <span class="mi">9960</span>
<span class="p">},</span> <span class="p">},</span>
<span class="nt">&quot;2&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;2&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;average_speed&quot;</span><span class="p">:</span> <span class="mf">15.95</span><span class="p">,</span>
<span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">46.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">46.0</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">78.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">78.0</span><span class="p">,</span>
@ -272,6 +275,7 @@
<span class="nt">&quot;data&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;data&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;statistics&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;statistics&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;1&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;1&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;average_speed&quot;</span><span class="p">:</span> <span class="mf">16.99</span><span class="p">,</span>
<span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">150.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">150.0</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">178.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">178.0</span><span class="p">,</span>
@ -279,6 +283,7 @@
<span class="nt">&quot;total_duration&quot;</span><span class="p">:</span> <span class="mi">9960</span> <span class="nt">&quot;total_duration&quot;</span><span class="p">:</span> <span class="mi">9960</span>
<span class="p">},</span> <span class="p">},</span>
<span class="nt">&quot;2&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;2&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;average_speed&quot;</span><span class="p">:</span> <span class="mf">15.95</span><span class="p">,</span>
<span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">46.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">46.0</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">78.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">78.0</span><span class="p">,</span>
@ -286,6 +291,7 @@
<span class="nt">&quot;total_duration&quot;</span><span class="p">:</span> <span class="mi">1267</span> <span class="nt">&quot;total_duration&quot;</span><span class="p">:</span> <span class="mi">1267</span>
<span class="p">},</span> <span class="p">},</span>
<span class="nt">&quot;3&quot;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&quot;3&quot;</span><span class="p">:</span> <span class="p">{</span>
<span class="nt">&quot;average_speed&quot;</span><span class="p">:</span> <span class="mf">4.46</span><span class="p">,</span>
<span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="nt">&quot;nb_workouts&quot;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">203.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">203.0</span><span class="p">,</span>
<span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">156.0</span><span class="p">,</span> <span class="nt">&quot;total_ascent&quot;</span><span class="p">:</span> <span class="mf">156.0</span><span class="p">,</span>

View File

@ -77,9 +77,16 @@
role="menu" role="menu"
aria-labelledby="dLabelLocalToc"><ul> aria-labelledby="dLabelLocalToc"><ul>
<li><a class="reference internal" href="#">Change log</a><ul> <li><a class="reference internal" href="#">Change log</a><ul>
<li><a class="reference internal" href="#version-0-5-0-2021-11-14">Version 0.5.0 (2021/11/14)</a><ul> <li><a class="reference internal" href="#version-0-5-1-unreleased">Version 0.5.1 (unreleased)</a><ul>
<li><a class="reference internal" href="#issues-closed">Issues Closed</a><ul> <li><a class="reference internal" href="#issues-closed">Issues Closed</a><ul>
<li><a class="reference internal" href="#new-features">New Features</a></li> <li><a class="reference internal" href="#new-features">New Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-5-0-2021-11-14">Version 0.5.0 (2021/11/14)</a><ul>
<li><a class="reference internal" href="#id1">Issues Closed</a><ul>
<li><a class="reference internal" href="#id2">New Features</a></li>
<li><a class="reference internal" href="#bugs-fixed">Bugs Fixed</a></li> <li><a class="reference internal" href="#bugs-fixed">Bugs Fixed</a></li>
<li><a class="reference internal" href="#misc">Misc</a></li> <li><a class="reference internal" href="#misc">Misc</a></li>
</ul> </ul>
@ -88,137 +95,137 @@
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-4-9-2021-07-16">Version 0.4.9 (2021/07/16)</a><ul> <li><a class="reference internal" href="#version-0-4-9-2021-07-16">Version 0.4.9 (2021/07/16)</a><ul>
<li><a class="reference internal" href="#id1">Issues Closed</a><ul> <li><a class="reference internal" href="#id3">Issues Closed</a><ul>
<li><a class="reference internal" href="#id2">New Features</a></li> <li><a class="reference internal" href="#id4">New Features</a></li>
<li><a class="reference internal" href="#id3">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-8-2021-07-03">Version 0.4.8 (2021/07/03)</a><ul>
<li><a class="reference internal" href="#id4">Issues Closed</a><ul>
<li><a class="reference internal" href="#id5">Bugs Fixed</a></li> <li><a class="reference internal" href="#id5">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-4-7-2021-04-07">Version 0.4.7 (2021/04/07)</a><ul> <li><a class="reference internal" href="#version-0-4-8-2021-07-03">Version 0.4.8 (2021/07/03)</a><ul>
<li><a class="reference internal" href="#id6">Issues Closed</a><ul> <li><a class="reference internal" href="#id6">Issues Closed</a><ul>
<li><a class="reference internal" href="#id7">Bugs Fixed</a></li> <li><a class="reference internal" href="#id7">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#id8">Misc</a></li> </ul>
</li>
<li><a class="reference internal" href="#version-0-4-7-2021-04-07">Version 0.4.7 (2021/04/07)</a><ul>
<li><a class="reference internal" href="#id8">Issues Closed</a><ul>
<li><a class="reference internal" href="#id9">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id10">Misc</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-4-6-2021-02-21">Version 0.4.6 (2021/02/21)</a><ul> <li><a class="reference internal" href="#version-0-4-6-2021-02-21">Version 0.4.6 (2021/02/21)</a><ul>
<li><a class="reference internal" href="#id9">Issues Closed</a><ul>
<li><a class="reference internal" href="#id10">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-5-2021-02-17">Version 0.4.5 (2021/02/17)</a><ul>
<li><a class="reference internal" href="#id11">Issues Closed</a><ul> <li><a class="reference internal" href="#id11">Issues Closed</a><ul>
<li><a class="reference internal" href="#id12">Bugs Fixed</a></li> <li><a class="reference internal" href="#id12">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-4-4-2021-01-31">Version 0.4.4 (2021/01/31)</a><ul> <li><a class="reference internal" href="#version-0-4-5-2021-02-17">Version 0.4.5 (2021/02/17)</a><ul>
<li><a class="reference internal" href="#id13">Issues Closed</a><ul> <li><a class="reference internal" href="#id13">Issues Closed</a><ul>
<li><a class="reference internal" href="#id14">Bugs Fixed</a></li> <li><a class="reference internal" href="#id14">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#id15">Misc</a></li> </ul>
</li>
<li><a class="reference internal" href="#version-0-4-4-2021-01-31">Version 0.4.4 (2021/01/31)</a><ul>
<li><a class="reference internal" href="#id15">Issues Closed</a><ul>
<li><a class="reference internal" href="#id16">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id17">Misc</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-4-3-2021-01-10">Version 0.4.3 (2021/01/10)</a><ul> <li><a class="reference internal" href="#version-0-4-3-2021-01-10">Version 0.4.3 (2021/01/10)</a><ul>
<li><a class="reference internal" href="#id16">Issues Closed</a><ul> <li><a class="reference internal" href="#id18">Issues Closed</a><ul>
<li><a class="reference internal" href="#id17">New Features</a></li> <li><a class="reference internal" href="#id19">New Features</a></li>
<li><a class="reference internal" href="#id18">Bugs Fixed</a></li> <li><a class="reference internal" href="#id20">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-4-2-2021-01-03">Version 0.4.2 (2021/01/03)</a><ul> <li><a class="reference internal" href="#version-0-4-2-2021-01-03">Version 0.4.2 (2021/01/03)</a><ul>
<li><a class="reference internal" href="#id19">Misc</a></li> <li><a class="reference internal" href="#id21">Misc</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-4-1-2020-12-31">Version 0.4.1 (2020/12/31)</a><ul> <li><a class="reference internal" href="#version-0-4-1-2020-12-31">Version 0.4.1 (2020/12/31)</a><ul>
<li><a class="reference internal" href="#id20">Issues Closed</a><ul>
<li><a class="reference internal" href="#id21">New Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-4-0-fittrackee-on-pypi-2020-09-19">Version 0.4.0 - FitTrackee on PyPI (2020/09/19)</a><ul>
<li><a class="reference internal" href="#id22">Issues Closed</a><ul> <li><a class="reference internal" href="#id22">Issues Closed</a><ul>
<li><a class="reference internal" href="#id23">New Features</a></li> <li><a class="reference internal" href="#id23">New Features</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-3-0-administration-2020-07-15">Version 0.3.0 - Administration (2020/07/15)</a><ul> <li><a class="reference internal" href="#version-0-4-0-fittrackee-on-pypi-2020-09-19">Version 0.4.0 - FitTrackee on PyPI (2020/09/19)</a><ul>
<li><a class="reference internal" href="#id24">Issues Closed</a><ul> <li><a class="reference internal" href="#id24">Issues Closed</a><ul>
<li><a class="reference internal" href="#id25">New Features</a></li> <li><a class="reference internal" href="#id25">New Features</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-3-0-administration-2020-07-15">Version 0.3.0 - Administration (2020/07/15)</a><ul>
<li><a class="reference internal" href="#id26">Issues Closed</a><ul>
<li><a class="reference internal" href="#id27">New Features</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-5-fix-and-improvements-2020-01-31">Version 0.2.5 - Fix and improvements (2020/01/31)</a><ul> <li><a class="reference internal" href="#version-0-2-5-fix-and-improvements-2020-01-31">Version 0.2.5 - Fix and improvements (2020/01/31)</a><ul>
<li><a class="reference internal" href="#id26">Misc</a></li> <li><a class="reference internal" href="#id28">Misc</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-2-4-minor-fix-2020-01-30">Version 0.2.4 - Minor fix (2020/01/30)</a><ul> <li><a class="reference internal" href="#version-0-2-4-minor-fix-2020-01-30">Version 0.2.4 - Minor fix (2020/01/30)</a><ul>
<li><a class="reference internal" href="#id27">Issues Closed</a><ul> <li><a class="reference internal" href="#id29">Issues Closed</a><ul>
<li><a class="reference internal" href="#id28">Bugs Fixed</a></li> <li><a class="reference internal" href="#id30">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-2-3-fittrackee-available-in-french-2019-12-29">Version 0.2.3 - FitTrackee available in French (2019/12/29)</a><ul> <li><a class="reference internal" href="#version-0-2-3-fittrackee-available-in-french-2019-12-29">Version 0.2.3 - FitTrackee available in French (2019/12/29)</a><ul>
<li><a class="reference internal" href="#id29">Issues Closed</a><ul> <li><a class="reference internal" href="#id31">Issues Closed</a><ul>
<li><a class="reference internal" href="#id30">New Features</a></li> <li><a class="reference internal" href="#id32">New Features</a></li>
<li><a class="reference internal" href="#id31">Bugs Fixed</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#version-0-2-2-statistics-fix-2019-09-23">Version 0.2.2 - Statistics fix (2019/09/23)</a><ul>
<li><a class="reference internal" href="#id32">Issues Closed</a><ul>
<li><a class="reference internal" href="#id33">Bugs Fixed</a></li> <li><a class="reference internal" href="#id33">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-2-1-fix-and-improvements-2019-09-01">Version 0.2.1 - Fix and improvements (2019/09/01)</a><ul> <li><a class="reference internal" href="#version-0-2-2-statistics-fix-2019-09-23">Version 0.2.2 - Statistics fix (2019/09/23)</a><ul>
<li><a class="reference internal" href="#id34">Issues Closed</a><ul> <li><a class="reference internal" href="#id34">Issues Closed</a><ul>
<li><a class="reference internal" href="#id35">New Features</a></li> <li><a class="reference internal" href="#id35">Bugs Fixed</a></li>
<li><a class="reference internal" href="#id36">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#id37">Misc</a></li> </ul>
</li>
<li><a class="reference internal" href="#version-0-2-1-fix-and-improvements-2019-09-01">Version 0.2.1 - Fix and improvements (2019/09/01)</a><ul>
<li><a class="reference internal" href="#id36">Issues Closed</a><ul>
<li><a class="reference internal" href="#id37">New Features</a></li>
<li><a class="reference internal" href="#id38">Bugs Fixed</a></li>
</ul>
</li>
<li><a class="reference internal" href="#id39">Misc</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-2-0-statistics-2019-07-07">Version 0.2.0 - Statistics (2019/07/07)</a><ul> <li><a class="reference internal" href="#version-0-2-0-statistics-2019-07-07">Version 0.2.0 - Statistics (2019/07/07)</a><ul>
<li><a class="reference internal" href="#id38">Issues Closed</a><ul> <li><a class="reference internal" href="#id40">Issues Closed</a><ul>
<li><a class="reference internal" href="#id39">New Features</a></li> <li><a class="reference internal" href="#id41">New Features</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#id40">Misc</a></li> <li><a class="reference internal" href="#id42">Misc</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-1-1-fix-and-improvements-2019-02-07">Version 0.1.1 - Fix and improvements (2019/02/07)</a><ul> <li><a class="reference internal" href="#version-0-1-1-fix-and-improvements-2019-02-07">Version 0.1.1 - Fix and improvements (2019/02/07)</a><ul>
<li><a class="reference internal" href="#id41">Issues Closed</a><ul> <li><a class="reference internal" href="#id43">Issues Closed</a><ul>
<li><a class="reference internal" href="#id42">New Features</a></li> <li><a class="reference internal" href="#id44">New Features</a></li>
<li><a class="reference internal" href="#id43">Bugs Fixed</a></li> <li><a class="reference internal" href="#id45">Bugs Fixed</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#version-0-1-0-first-release-2018-07-04">Version 0.1.0 - First release 🎉 (2018-07-04)</a><ul> <li><a class="reference internal" href="#version-0-1-0-first-release-2018-07-04">Version 0.1.0 - First release 🎉 (2018-07-04)</a><ul>
<li><a class="reference internal" href="#id44">Issues Closed</a><ul> <li><a class="reference internal" href="#id46">Issues Closed</a><ul>
<li><a class="reference internal" href="#id45">New Features</a></li> <li><a class="reference internal" href="#id47">New Features</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -270,13 +277,26 @@
<section id="change-log"> <section id="change-log">
<h1>Change log<a class="headerlink" href="#change-log" title="Permalink to this headline"></a></h1> <h1>Change log<a class="headerlink" href="#change-log" title="Permalink to this headline"></a></h1>
<section id="version-0-5-0-2021-11-14"> <section id="version-0-5-1-unreleased">
<h2>Version 0.5.0 (2021/11/14)<a class="headerlink" href="#version-0-5-0-2021-11-14" title="Permalink to this headline"></a></h2> <h2>Version 0.5.1 (unreleased)<a class="headerlink" href="#version-0-5-1-unreleased" title="Permalink to this headline"></a></h2>
<section id="issues-closed"> <section id="issues-closed">
<h3>Issues Closed<a class="headerlink" href="#issues-closed" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#issues-closed" title="Permalink to this headline"></a></h3>
<section id="new-features"> <section id="new-features">
<h4>New Features<a class="headerlink" href="#new-features" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#new-features" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/5">#5</a> - Display a chart with average speed</p></li>
</ul>
<p>In this release 1 issue was closed.</p>
</section>
</section>
</section>
<section id="version-0-5-0-2021-11-14">
<h2>Version 0.5.0 (2021/11/14)<a class="headerlink" href="#version-0-5-0-2021-11-14" title="Permalink to this headline"></a></h2>
<section id="id1">
<h3>Issues Closed<a class="headerlink" href="#id1" title="Permalink to this headline"></a></h3>
<section id="id2">
<h4>New Features<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/99">#99</a> - Display workout with imperial units</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/99">#99</a> - Display workout with imperial units</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/91">#91</a> - Display elevation chart with min and max altitude of workout</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/91">#91</a> - Display elevation chart with min and max altitude of workout</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/90">#90</a> - Add user sports preferences</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/90">#90</a> - Add user sports preferences</p></li>
@ -314,17 +334,17 @@
</section> </section>
<section id="version-0-4-9-2021-07-16"> <section id="version-0-4-9-2021-07-16">
<h2>Version 0.4.9 (2021/07/16)<a class="headerlink" href="#version-0-4-9-2021-07-16" title="Permalink to this headline"></a></h2> <h2>Version 0.4.9 (2021/07/16)<a class="headerlink" href="#version-0-4-9-2021-07-16" title="Permalink to this headline"></a></h2>
<section id="id1"> <section id="id3">
<h3>Issues Closed<a class="headerlink" href="#id1" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h3>
<section id="id2"> <section id="id4">
<h4>New Features<a class="headerlink" href="#id2" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id4" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/83">#83</a> - allow using configured tile server to generate static maps<br /><strong>Note</strong>: to keep using the default tile server, set environment variable <code class="docutils literal notranslate"><span class="pre">DEFAULT_STATICMAP</span></code> to <code class="docutils literal notranslate"><span class="pre">True</span></code></p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/83">#83</a> - allow using configured tile server to generate static maps<br /><strong>Note</strong>: to keep using the default tile server, set environment variable <code class="docutils literal notranslate"><span class="pre">DEFAULT_STATICMAP</span></code> to <code class="docutils literal notranslate"><span class="pre">True</span></code></p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/81">#81</a> - display remaining characters in textarea</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/81">#81</a> - display remaining characters in textarea</p></li>
</ul> </ul>
</section> </section>
<section id="id3"> <section id="id5">
<h4>Bugs Fixed<a class="headerlink" href="#id3" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id5" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/82">#82</a> - a user can not modify his birth day</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/82">#82</a> - a user can not modify his birth day</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/80">#80</a> - can not save notes with control characters</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/80">#80</a> - can not save notes with control characters</p></li>
@ -335,10 +355,10 @@
</section> </section>
<section id="version-0-4-8-2021-07-03"> <section id="version-0-4-8-2021-07-03">
<h2>Version 0.4.8 (2021/07/03)<a class="headerlink" href="#version-0-4-8-2021-07-03" title="Permalink to this headline"></a></h2> <h2>Version 0.4.8 (2021/07/03)<a class="headerlink" href="#version-0-4-8-2021-07-03" title="Permalink to this headline"></a></h2>
<section id="id4"> <section id="id6">
<h3>Issues Closed<a class="headerlink" href="#id4" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id6" title="Permalink to this headline"></a></h3>
<section id="id5"> <section id="id7">
<h4>Bugs Fixed<a class="headerlink" href="#id5" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id7" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/79">#79</a> - Fails to start after make rebuild</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/79">#79</a> - Fails to start after make rebuild</p></li>
</ul> </ul>
@ -348,17 +368,17 @@
</section> </section>
<section id="version-0-4-7-2021-04-07"> <section id="version-0-4-7-2021-04-07">
<h2>Version 0.4.7 (2021/04/07)<a class="headerlink" href="#version-0-4-7-2021-04-07" title="Permalink to this headline"></a></h2> <h2>Version 0.4.7 (2021/04/07)<a class="headerlink" href="#version-0-4-7-2021-04-07" title="Permalink to this headline"></a></h2>
<section id="id6"> <section id="id8">
<h3>Issues Closed<a class="headerlink" href="#id6" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id8" title="Permalink to this headline"></a></h3>
<section id="id7"> <section id="id9">
<h4>Bugs Fixed<a class="headerlink" href="#id7" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id9" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/75">#75</a> - Workouts on the same day are not displayed in right order</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/75">#75</a> - Workouts on the same day are not displayed in right order</p></li>
</ul> </ul>
</section> </section>
</section> </section>
<section id="id8"> <section id="id10">
<h3>Misc<a class="headerlink" href="#id8" title="Permalink to this headline"></a></h3> <h3>Misc<a class="headerlink" href="#id10" title="Permalink to this headline"></a></h3>
<ul class="simple"> <ul class="simple">
<li><p>Update Python and Javascript dependencies<br /><strong>IMPORTANT</strong>: Due to <a class="reference external" href="https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html#change-3687655465c25a39b968b4f5f6e9170b">SQLAlchemy update (1.4+)</a>, engine URLs starting with <code class="docutils literal notranslate"><span class="pre">postgres://</span></code> are no longer supported. Please update <code class="docutils literal notranslate"><span class="pre">DATABASE_URL</span></code> with <code class="docutils literal notranslate"><span class="pre">postgresql://</span></code>.</p></li> <li><p>Update Python and Javascript dependencies<br /><strong>IMPORTANT</strong>: Due to <a class="reference external" href="https://docs.sqlalchemy.org/en/14/changelog/changelog_14.html#change-3687655465c25a39b968b4f5f6e9170b">SQLAlchemy update (1.4+)</a>, engine URLs starting with <code class="docutils literal notranslate"><span class="pre">postgres://</span></code> are no longer supported. Please update <code class="docutils literal notranslate"><span class="pre">DATABASE_URL</span></code> with <code class="docutils literal notranslate"><span class="pre">postgresql://</span></code>.</p></li>
</ul> </ul>
@ -367,10 +387,10 @@
</section> </section>
<section id="version-0-4-6-2021-02-21"> <section id="version-0-4-6-2021-02-21">
<h2>Version 0.4.6 (2021/02/21)<a class="headerlink" href="#version-0-4-6-2021-02-21" title="Permalink to this headline"></a></h2> <h2>Version 0.4.6 (2021/02/21)<a class="headerlink" href="#version-0-4-6-2021-02-21" title="Permalink to this headline"></a></h2>
<section id="id9"> <section id="id11">
<h3>Issues Closed<a class="headerlink" href="#id9" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id11" title="Permalink to this headline"></a></h3>
<section id="id10"> <section id="id12">
<h4>Bugs Fixed<a class="headerlink" href="#id10" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id12" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/72">#72</a> - Error message when file exceeding size is incorrect</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/72">#72</a> - Error message when file exceeding size is incorrect</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/71">#71</a> - max size or max number of files must be greater than 0</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/71">#71</a> - max size or max number of files must be greater than 0</p></li>
@ -382,10 +402,10 @@
</section> </section>
<section id="version-0-4-5-2021-02-17"> <section id="version-0-4-5-2021-02-17">
<h2>Version 0.4.5 (2021/02/17)<a class="headerlink" href="#version-0-4-5-2021-02-17" title="Permalink to this headline"></a></h2> <h2>Version 0.4.5 (2021/02/17)<a class="headerlink" href="#version-0-4-5-2021-02-17" title="Permalink to this headline"></a></h2>
<section id="id11"> <section id="id13">
<h3>Issues Closed<a class="headerlink" href="#id11" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id13" title="Permalink to this headline"></a></h3>
<section id="id12"> <section id="id14">
<h4>Bugs Fixed<a class="headerlink" href="#id12" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id14" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/66">#66</a> - invalid gpx limit used when importing zip archive</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/66">#66</a> - invalid gpx limit used when importing zip archive</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/64">#64</a> - Only 50 workouts per month shown in calendar</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/64">#64</a> - Only 50 workouts per month shown in calendar</p></li>
@ -396,17 +416,17 @@
</section> </section>
<section id="version-0-4-4-2021-01-31"> <section id="version-0-4-4-2021-01-31">
<h2>Version 0.4.4 (2021/01/31)<a class="headerlink" href="#version-0-4-4-2021-01-31" title="Permalink to this headline"></a></h2> <h2>Version 0.4.4 (2021/01/31)<a class="headerlink" href="#version-0-4-4-2021-01-31" title="Permalink to this headline"></a></h2>
<section id="id13"> <section id="id15">
<h3>Issues Closed<a class="headerlink" href="#id13" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id15" title="Permalink to this headline"></a></h3>
<section id="id14"> <section id="id16">
<h4>Bugs Fixed<a class="headerlink" href="#id14" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id16" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/62">#62</a> - Error when sending reset password email</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/62">#62</a> - Error when sending reset password email</p></li>
</ul> </ul>
</section> </section>
</section> </section>
<section id="id15"> <section id="id17">
<h3>Misc<a class="headerlink" href="#id15" title="Permalink to this headline"></a></h3> <h3>Misc<a class="headerlink" href="#id17" title="Permalink to this headline"></a></h3>
<ul class="simple"> <ul class="simple">
<li><p>Refactoring before introducing new features.</p></li> <li><p>Refactoring before introducing new features.</p></li>
<li><p>Add docker files for evaluation purposes.</p></li> <li><p>Add docker files for evaluation purposes.</p></li>
@ -416,16 +436,16 @@
</section> </section>
<section id="version-0-4-3-2021-01-10"> <section id="version-0-4-3-2021-01-10">
<h2>Version 0.4.3 (2021/01/10)<a class="headerlink" href="#version-0-4-3-2021-01-10" title="Permalink to this headline"></a></h2> <h2>Version 0.4.3 (2021/01/10)<a class="headerlink" href="#version-0-4-3-2021-01-10" title="Permalink to this headline"></a></h2>
<section id="id16"> <section id="id18">
<h3>Issues Closed<a class="headerlink" href="#id16" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id18" title="Permalink to this headline"></a></h3>
<section id="id17"> <section id="id19">
<h4>New Features<a class="headerlink" href="#id17" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id19" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/58">#58</a> - Standardize terms used for workouts<br /><strong>Note:</strong> Database model, upload directory for workouts and API endpoints are also updated.</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/58">#58</a> - Standardize terms used for workouts<br /><strong>Note:</strong> Database model, upload directory for workouts and API endpoints are also updated.</p></li>
</ul> </ul>
</section> </section>
<section id="id18"> <section id="id20">
<h4>Bugs Fixed<a class="headerlink" href="#id18" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id20" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/59">#59</a> - No message displayed on uploading image error</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/59">#59</a> - No message displayed on uploading image error</p></li>
</ul> </ul>
@ -435,18 +455,18 @@
</section> </section>
<section id="version-0-4-2-2021-01-03"> <section id="version-0-4-2-2021-01-03">
<h2>Version 0.4.2 (2021/01/03)<a class="headerlink" href="#version-0-4-2-2021-01-03" title="Permalink to this headline"></a></h2> <h2>Version 0.4.2 (2021/01/03)<a class="headerlink" href="#version-0-4-2-2021-01-03" title="Permalink to this headline"></a></h2>
<section id="id19"> <section id="id21">
<h3>Misc<a class="headerlink" href="#id19" title="Permalink to this headline"></a></h3> <h3>Misc<a class="headerlink" href="#id21" title="Permalink to this headline"></a></h3>
<p>No new features in this release, only some refactorings before introducing <p>No new features in this release, only some refactorings before introducing
new features.</p> new features.</p>
</section> </section>
</section> </section>
<section id="version-0-4-1-2020-12-31"> <section id="version-0-4-1-2020-12-31">
<h2>Version 0.4.1 (2020/12/31)<a class="headerlink" href="#version-0-4-1-2020-12-31" title="Permalink to this headline"></a></h2> <h2>Version 0.4.1 (2020/12/31)<a class="headerlink" href="#version-0-4-1-2020-12-31" title="Permalink to this headline"></a></h2>
<section id="id20"> <section id="id22">
<h3>Issues Closed<a class="headerlink" href="#id20" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id22" title="Permalink to this headline"></a></h3>
<section id="id21"> <section id="id23">
<h4>New Features<a class="headerlink" href="#id21" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id23" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/57">#57</a> - Use uuid for activities</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/57">#57</a> - Use uuid for activities</p></li>
</ul> </ul>
@ -462,10 +482,10 @@ new features.</p>
<li><p>Its now possible to change the tile provider for maps. The default tile server is now <strong>OpenStreetMap</strong>s standard tile layer (replacing <strong>ThunderForest Outdoors</strong>), <li><p>Its now possible to change the tile provider for maps. The default tile server is now <strong>OpenStreetMap</strong>s standard tile layer (replacing <strong>ThunderForest Outdoors</strong>),
see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#map-tile-server">Map tile server in documentation</a>.</p></li> see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#map-tile-server">Map tile server in documentation</a>.</p></li>
</ul> </ul>
<section id="id22"> <section id="id24">
<h3>Issues Closed<a class="headerlink" href="#id22" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id24" title="Permalink to this headline"></a></h3>
<section id="id23"> <section id="id25">
<h4>New Features<a class="headerlink" href="#id23" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id25" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/54">#54</a> - Tile server can be changed</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/54">#54</a> - Tile server can be changed</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/53">#53</a> - Simplify FitTrackee installation</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/53">#53</a> - Simplify FitTrackee installation</p></li>
@ -481,10 +501,10 @@ see <a class="reference external" href="https://samr1.github.io/FitTrackee/insta
<li><p>FitTrackee administration is now available (see <a class="reference external" href="https://samr1.github.io/FitTrackee/features.html#administration">documentation</a>)<br />⚠️ Warning: some application parameters move from environment variables to database (see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#environment-variables">installation</a>).</p></li> <li><p>FitTrackee administration is now available (see <a class="reference external" href="https://samr1.github.io/FitTrackee/features.html#administration">documentation</a>)<br />⚠️ Warning: some application parameters move from environment variables to database (see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#environment-variables">installation</a>).</p></li>
<li><p>in order to send emails, Redis is now a mandatory dependency</p></li> <li><p>in order to send emails, Redis is now a mandatory dependency</p></li>
</ul> </ul>
<section id="id24"> <section id="id26">
<h3>Issues Closed<a class="headerlink" href="#id24" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id26" title="Permalink to this headline"></a></h3>
<section id="id25"> <section id="id27">
<h4>New Features<a class="headerlink" href="#id25" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id27" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/50">#50</a> - A user can reset his password</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/50">#50</a> - A user can reset his password</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/17">#17</a> - A user can delete his account</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/17">#17</a> - A user can delete his account</p></li>
@ -496,8 +516,8 @@ see <a class="reference external" href="https://samr1.github.io/FitTrackee/insta
</section> </section>
<section id="version-0-2-5-fix-and-improvements-2020-01-31"> <section id="version-0-2-5-fix-and-improvements-2020-01-31">
<h2>Version 0.2.5 - Fix and improvements (2020/01/31)<a class="headerlink" href="#version-0-2-5-fix-and-improvements-2020-01-31" title="Permalink to this headline"></a></h2> <h2>Version 0.2.5 - Fix and improvements (2020/01/31)<a class="headerlink" href="#version-0-2-5-fix-and-improvements-2020-01-31" title="Permalink to this headline"></a></h2>
<section id="id26"> <section id="id28">
<h3>Misc<a class="headerlink" href="#id26" title="Permalink to this headline"></a></h3> <h3>Misc<a class="headerlink" href="#id28" title="Permalink to this headline"></a></h3>
<p>This version contains minor fix and improvements on client side:</p> <p>This version contains minor fix and improvements on client side:</p>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/commit/4c3fc343d51b9c27d3ebab71df648bcf7d7bae59">4c3fc34</a> - empty user data on logout</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/commit/4c3fc343d51b9c27d3ebab71df648bcf7d7bae59">4c3fc34</a> - empty user data on logout</p></li>
@ -510,10 +530,10 @@ add URL interceptors to simplify routes definition</p></li>
</section> </section>
<section id="version-0-2-4-minor-fix-2020-01-30"> <section id="version-0-2-4-minor-fix-2020-01-30">
<h2>Version 0.2.4 - Minor fix (2020/01/30)<a class="headerlink" href="#version-0-2-4-minor-fix-2020-01-30" title="Permalink to this headline"></a></h2> <h2>Version 0.2.4 - Minor fix (2020/01/30)<a class="headerlink" href="#version-0-2-4-minor-fix-2020-01-30" title="Permalink to this headline"></a></h2>
<section id="id27"> <section id="id29">
<h3>Issues Closed<a class="headerlink" href="#id27" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id29" title="Permalink to this headline"></a></h3>
<section id="id28"> <section id="id30">
<h4>Bugs Fixed<a class="headerlink" href="#id28" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id30" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/47">#47</a> - timezone drop-down is not displayed correctly</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/47">#47</a> - timezone drop-down is not displayed correctly</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/46">#46</a> - calendar cannot display more than 5 or 6 activities on the same day</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/46">#46</a> - calendar cannot display more than 5 or 6 activities on the same day</p></li>
@ -524,17 +544,17 @@ add URL interceptors to simplify routes definition</p></li>
</section> </section>
<section id="version-0-2-3-fittrackee-available-in-french-2019-12-29"> <section id="version-0-2-3-fittrackee-available-in-french-2019-12-29">
<h2>Version 0.2.3 - FitTrackee available in French (2019/12/29)<a class="headerlink" href="#version-0-2-3-fittrackee-available-in-french-2019-12-29" title="Permalink to this headline"></a></h2> <h2>Version 0.2.3 - FitTrackee available in French (2019/12/29)<a class="headerlink" href="#version-0-2-3-fittrackee-available-in-french-2019-12-29" title="Permalink to this headline"></a></h2>
<section id="id29"> <section id="id31">
<h3>Issues Closed<a class="headerlink" href="#id29" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id31" title="Permalink to this headline"></a></h3>
<section id="id30"> <section id="id32">
<h4>New Features<a class="headerlink" href="#id30" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id32" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/43">#43</a> - Display weekend days with a different background color on calendar</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/43">#43</a> - Display weekend days with a different background color on calendar</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/40">#40</a> - Localize FitTrackee (i18n)</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/40">#40</a> - Localize FitTrackee (i18n)</p></li>
</ul> </ul>
</section> </section>
<section id="id31"> <section id="id33">
<h4>Bugs Fixed<a class="headerlink" href="#id31" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id33" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/44">#44</a> - Cannot edit an activity that does not have a gpx file</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/44">#44</a> - Cannot edit an activity that does not have a gpx file</p></li>
</ul> </ul>
@ -544,10 +564,10 @@ add URL interceptors to simplify routes definition</p></li>
</section> </section>
<section id="version-0-2-2-statistics-fix-2019-09-23"> <section id="version-0-2-2-statistics-fix-2019-09-23">
<h2>Version 0.2.2 - Statistics fix (2019/09/23)<a class="headerlink" href="#version-0-2-2-statistics-fix-2019-09-23" title="Permalink to this headline"></a></h2> <h2>Version 0.2.2 - Statistics fix (2019/09/23)<a class="headerlink" href="#version-0-2-2-statistics-fix-2019-09-23" title="Permalink to this headline"></a></h2>
<section id="id32"> <section id="id34">
<h3>Issues Closed<a class="headerlink" href="#id32" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id34" title="Permalink to this headline"></a></h3>
<section id="id33"> <section id="id35">
<h4>Bugs Fixed<a class="headerlink" href="#id33" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id35" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/41">#41</a> - User statistics are incorrect</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/41">#41</a> - User statistics are incorrect</p></li>
</ul> </ul>
@ -557,10 +577,10 @@ add URL interceptors to simplify routes definition</p></li>
</section> </section>
<section id="version-0-2-1-fix-and-improvements-2019-09-01"> <section id="version-0-2-1-fix-and-improvements-2019-09-01">
<h2>Version 0.2.1 - Fix and improvements (2019/09/01)<a class="headerlink" href="#version-0-2-1-fix-and-improvements-2019-09-01" title="Permalink to this headline"></a></h2> <h2>Version 0.2.1 - Fix and improvements (2019/09/01)<a class="headerlink" href="#version-0-2-1-fix-and-improvements-2019-09-01" title="Permalink to this headline"></a></h2>
<section id="id34"> <section id="id36">
<h3>Issues Closed<a class="headerlink" href="#id34" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id36" title="Permalink to this headline"></a></h3>
<section id="id35"> <section id="id37">
<h4>New Features<a class="headerlink" href="#id35" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id37" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/4">#4</a> - Show points on the map when mouse over the chart</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/4">#4</a> - Show points on the map when mouse over the chart</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/14">#14</a> - Display segments informations</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/14">#14</a> - Display segments informations</p></li>
@ -571,15 +591,15 @@ add URL interceptors to simplify routes definition</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/37">#37</a> - Display map on activities list</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/37">#37</a> - Display map on activities list</p></li>
</ul> </ul>
</section> </section>
<section id="id36"> <section id="id38">
<h4>Bugs Fixed<a class="headerlink" href="#id36" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id38" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/34">#34</a> - Weather is not displayed anymore</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/34">#34</a> - Weather is not displayed anymore</p></li>
</ul> </ul>
</section> </section>
</section> </section>
<section id="id37"> <section id="id39">
<h3>Misc<a class="headerlink" href="#id37" title="Permalink to this headline"></a></h3> <h3>Misc<a class="headerlink" href="#id39" title="Permalink to this headline"></a></h3>
<ul class="simple"> <ul class="simple">
<li><p><strong><a class="reference external" href="https://poetry.eustace.io/">Poetry</a></strong> replaces <strong><a class="reference external" href="https://docs.pipenv.org">pipenv</a></strong> for Python packages management</p></li> <li><p><strong><a class="reference external" href="https://poetry.eustace.io/">Poetry</a></strong> replaces <strong><a class="reference external" href="https://docs.pipenv.org">pipenv</a></strong> for Python packages management</p></li>
</ul> </ul>
@ -588,17 +608,17 @@ add URL interceptors to simplify routes definition</p></li>
</section> </section>
<section id="version-0-2-0-statistics-2019-07-07"> <section id="version-0-2-0-statistics-2019-07-07">
<h2>Version 0.2.0 - Statistics (2019/07/07)<a class="headerlink" href="#version-0-2-0-statistics-2019-07-07" title="Permalink to this headline"></a></h2> <h2>Version 0.2.0 - Statistics (2019/07/07)<a class="headerlink" href="#version-0-2-0-statistics-2019-07-07" title="Permalink to this headline"></a></h2>
<section id="id38"> <section id="id40">
<h3>Issues Closed<a class="headerlink" href="#id38" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id40" title="Permalink to this headline"></a></h3>
<section id="id39"> <section id="id41">
<h4>New Features<a class="headerlink" href="#id39" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id41" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/13">#13</a> - Detailed statistics</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/13">#13</a> - Detailed statistics</p></li>
</ul> </ul>
</section> </section>
</section> </section>
<section id="id40"> <section id="id42">
<h3>Misc<a class="headerlink" href="#id40" title="Permalink to this headline"></a></h3> <h3>Misc<a class="headerlink" href="#id42" title="Permalink to this headline"></a></h3>
<ul class="simple"> <ul class="simple">
<li><p>Update dependencies</p></li> <li><p>Update dependencies</p></li>
</ul> </ul>
@ -607,17 +627,17 @@ add URL interceptors to simplify routes definition</p></li>
</section> </section>
<section id="version-0-1-1-fix-and-improvements-2019-02-07"> <section id="version-0-1-1-fix-and-improvements-2019-02-07">
<h2>Version 0.1.1 - Fix and improvements (2019/02/07)<a class="headerlink" href="#version-0-1-1-fix-and-improvements-2019-02-07" title="Permalink to this headline"></a></h2> <h2>Version 0.1.1 - Fix and improvements (2019/02/07)<a class="headerlink" href="#version-0-1-1-fix-and-improvements-2019-02-07" title="Permalink to this headline"></a></h2>
<section id="id41"> <section id="id43">
<h3>Issues Closed<a class="headerlink" href="#id41" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id43" title="Permalink to this headline"></a></h3>
<section id="id42"> <section id="id44">
<h4>New Features<a class="headerlink" href="#id42" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id44" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/25">#25</a> - Display records on calendar</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/25">#25</a> - Display records on calendar</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/22">#22</a> - Add a total on current month statistics</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/22">#22</a> - Add a total on current month statistics</p></li>
</ul> </ul>
</section> </section>
<section id="id43"> <section id="id45">
<h4>Bugs Fixed<a class="headerlink" href="#id43" title="Permalink to this headline"></a></h4> <h4>Bugs Fixed<a class="headerlink" href="#id45" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/31">#31</a> - Use moving duration for stats</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/31">#31</a> - Use moving duration for stats</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/29">#29</a> - Pause duration calculation with segments</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/29">#29</a> - Pause duration calculation with segments</p></li>
@ -666,10 +686,10 @@ add URL interceptors to simplify routes definition</p></li>
<li><p>no administration for now</p></li> <li><p>no administration for now</p></li>
</ul> </ul>
<p>➡️ more informations: see <a class="reference external" href="https://samr1.github.io/FitTrackee/">documentation</a> and <a class="reference external" href="https://github.com/SamR1/FitTrackee/issues">current issues</a></p> <p>➡️ more informations: see <a class="reference external" href="https://samr1.github.io/FitTrackee/">documentation</a> and <a class="reference external" href="https://github.com/SamR1/FitTrackee/issues">current issues</a></p>
<section id="id44"> <section id="id46">
<h3>Issues Closed<a class="headerlink" href="#id44" title="Permalink to this headline"></a></h3> <h3>Issues Closed<a class="headerlink" href="#id46" title="Permalink to this headline"></a></h3>
<section id="id45"> <section id="id47">
<h4>New Features<a class="headerlink" href="#id45" title="Permalink to this headline"></a></h4> <h4>New Features<a class="headerlink" href="#id47" title="Permalink to this headline"></a></h4>
<ul class="simple"> <ul class="simple">
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/11">#11</a> - Timezone support</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/11">#11</a> - Timezone support</p></li>
<li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/10">#10</a> - Add a note to an activity</p></li> <li><p><a class="reference external" href="https://github.com/SamR1/FitTrackee/issues/10">#10</a> - Add a note to an activity</p></li>

View File

@ -240,7 +240,18 @@
<li><p>Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance).</p></li> <li><p>Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance).</p></li>
<li><p>A workout with a gpx file can be displayed with map, weather (if the DarkSky API key is provided) and charts (speed and elevation). Segments can be displayed.</p></li> <li><p>A workout with a gpx file can be displayed with map, weather (if the DarkSky API key is provided) and charts (speed and elevation). Segments can be displayed.</p></li>
<li><p>Workout edition and deletion. User can add a note.</p></li> <li><p>Workout edition and deletion. User can add a note.</p></li>
<li><p>User statistics</p></li> <li><dl class="simple">
<dt>User statistics, by time period (week, month, year) and sport:</dt><dd><ul>
<li><p>total distance</p></li>
<li><p>total duration</p></li>
<li><p>total workouts</p></li>
<li><p>total ascent (<strong>new in 0.5.0</strong>)</p></li>
<li><p>total descent (<strong>new in 0.5.0</strong>)</p></li>
<li><p>average speed (<strong>new in 0.5.1</strong>)</p></li>
</ul>
</dd>
</dl>
</li>
<li><dl class="simple"> <li><dl class="simple">
<dt>User records by sports:</dt><dd><ul> <dt>User records by sports:</dt><dd><ul>
<li><p>average speed</p></li> <li><p>average speed</p></li>

View File

@ -185,6 +185,7 @@ Map</a>.</div>
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a><ul> <li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a><ul>
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-5-1-unreleased">Version 0.5.1 (unreleased)</a></li>
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-5-0-2021-11-14">Version 0.5.0 (2021/11/14)</a></li> <li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-5-0-2021-11-14">Version 0.5.0 (2021/11/14)</a></li>
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-4-9-2021-07-16">Version 0.4.9 (2021/07/16)</a></li> <li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-4-9-2021-07-16">Version 0.4.9 (2021/07/16)</a></li>
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-4-8-2021-07-03">Version 0.4.8 (2021/07/03)</a></li> <li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-4-8-2021-07-03">Version 0.4.8 (2021/07/03)</a></li>

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -76,7 +76,13 @@ Workouts
- Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance). - Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance).
- A workout with a gpx file can be displayed with map, weather (if the DarkSky API key is provided) and charts (speed and elevation). Segments can be displayed. - A workout with a gpx file can be displayed with map, weather (if the DarkSky API key is provided) and charts (speed and elevation). Segments can be displayed.
- Workout edition and deletion. User can add a note. - Workout edition and deletion. User can add a note.
- User statistics - User statistics, by time period (week, month, year) and sport:
- total distance
- total duration
- total workouts
- total ascent (**new in 0.5.0**)
- total descent (**new in 0.5.0**)
- average speed (**new in 0.5.1**)
- User records by sports: - User records by sports:
- average speed - average speed
- farest distance - farest distance

View File

@ -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><link href="/static/css/admin.babfd43e.css" rel="prefetch"><link href="/static/css/main.7f7a365e.css" rel="prefetch"><link href="/static/css/main~workouts.0edb3403.css" rel="prefetch"><link href="/static/css/profile.05400f70.css" rel="prefetch"><link href="/static/css/reset.46776e72.css" rel="prefetch"><link href="/static/css/workouts.84cbed34.css" rel="prefetch"><link href="/static/js/admin.2f1d393d.js" rel="prefetch"><link href="/static/js/chunk-2d0c9189.c81458cc.js" rel="prefetch"><link href="/static/js/chunk-2d0cf391.020c75ea.js" rel="prefetch"><link href="/static/js/chunk-2d0da8f3.c8c3e7e8.js" rel="prefetch"><link href="/static/js/chunk-2d2248b6.d84473c1.js" rel="prefetch"><link href="/static/js/chunk-2d22523a.4b710d99.js" rel="prefetch"><link href="/static/js/main.aa7fcffc.js" rel="prefetch"><link href="/static/js/main~workouts.6afa0411.js" rel="prefetch"><link href="/static/js/profile.62578012.js" rel="prefetch"><link href="/static/js/reset.518e646f.js" rel="prefetch"><link href="/static/js/workouts.ca9449b1.js" rel="prefetch"><link href="/static/css/app.2b8c39ab.css" rel="preload" as="style"><link href="/static/js/app.6471a147.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.caa4fc1c.js" rel="preload" as="script"><link href="/static/css/app.2b8c39ab.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><script src="/static/js/chunk-vendors.caa4fc1c.js"></script><script src="/static/js/app.6471a147.js"></script></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><link href="/static/css/admin.babfd43e.css" rel="prefetch"><link href="/static/css/main.4a1640fb.css" rel="prefetch"><link href="/static/css/main~workouts.0edb3403.css" rel="prefetch"><link href="/static/css/profile.05400f70.css" rel="prefetch"><link href="/static/css/reset.46776e72.css" rel="prefetch"><link href="/static/css/workouts.84cbed34.css" rel="prefetch"><link href="/static/js/admin.2f1d393d.js" rel="prefetch"><link href="/static/js/chunk-2d0c9189.c81458cc.js" rel="prefetch"><link href="/static/js/chunk-2d0cf391.020c75ea.js" rel="prefetch"><link href="/static/js/chunk-2d0da8f3.c8c3e7e8.js" rel="prefetch"><link href="/static/js/chunk-2d2248b6.d84473c1.js" rel="prefetch"><link href="/static/js/chunk-2d22523a.4b710d99.js" rel="prefetch"><link href="/static/js/main.8ecc731b.js" rel="prefetch"><link href="/static/js/main~workouts.6afa0411.js" rel="prefetch"><link href="/static/js/profile.62578012.js" rel="prefetch"><link href="/static/js/reset.518e646f.js" rel="prefetch"><link href="/static/js/workouts.ca9449b1.js" rel="prefetch"><link href="/static/css/app.2b8c39ab.css" rel="preload" as="style"><link href="/static/js/app.aa3fc8a8.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.caa4fc1c.js" rel="preload" as="script"><link href="/static/css/app.2b8c39ab.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><script src="/static/js/chunk-vendors.caa4fc1c.js"></script><script src="/static/js/app.aa3fc8a8.js"></script></body></html>

View File

@ -64,7 +64,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/img/workouts/mountains.svg" "url": "/img/workouts/mountains.svg"
}, },
{ {
"revision": "f34e801fbe4c2fd5b262da59fa3396f2", "revision": "daeb08eb2247d9fbbfce6f460f1066be",
"url": "/index.html" "url": "/index.html"
}, },
{ {
@ -80,7 +80,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/css/admin.babfd43e.css" "url": "/static/css/admin.babfd43e.css"
}, },
{ {
"revision": "34b8f17a1f53ad3f88b0", "revision": "4fefe86bda62538fef01",
"url": "/static/css/app.2b8c39ab.css" "url": "/static/css/app.2b8c39ab.css"
}, },
{ {
@ -92,8 +92,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/css/leaflet.css" "url": "/static/css/leaflet.css"
}, },
{ {
"revision": "1832b6aed4a370727f35", "revision": "475d71e5fe5bd682eeec",
"url": "/static/css/main.7f7a365e.css" "url": "/static/css/main.4a1640fb.css"
}, },
{ {
"revision": "ac1280c03a31a5894834", "revision": "ac1280c03a31a5894834",
@ -196,8 +196,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/js/admin.2f1d393d.js" "url": "/static/js/admin.2f1d393d.js"
}, },
{ {
"revision": "34b8f17a1f53ad3f88b0", "revision": "4fefe86bda62538fef01",
"url": "/static/js/app.6471a147.js" "url": "/static/js/app.aa3fc8a8.js"
}, },
{ {
"revision": "bd7d183c9f68e5f4027d", "revision": "bd7d183c9f68e5f4027d",
@ -224,8 +224,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/js/chunk-vendors.caa4fc1c.js" "url": "/static/js/chunk-vendors.caa4fc1c.js"
}, },
{ {
"revision": "1832b6aed4a370727f35", "revision": "475d71e5fe5bd682eeec",
"url": "/static/js/main.aa7fcffc.js" "url": "/static/js/main.8ecc731b.js"
}, },
{ {
"revision": "ac1280c03a31a5894834", "revision": "ac1280c03a31a5894834",

View File

@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts( importScripts(
"/precache-manifest.b2fffe2480dec51855b1b6caf598a8e0.js" "/precache-manifest.eb56f78718c678088fa66ae97922cb98.js"
); );
workbox.core.setCacheNameDetails({prefix: "fittrackee_client"}); workbox.core.setCacheNameDetails({prefix: "fittrackee_client"});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -51,6 +51,14 @@ def sport_2_running() -> Sport:
return sport return sport
def update_workout(workout: Workout) -> None:
workout.ave_speed = float(workout.distance) / (
workout.duration.seconds / 3600
)
workout.max_speed = workout.ave_speed
workout.moving = workout.duration
@pytest.fixture() @pytest.fixture()
def workout_cycling_user_1() -> Workout: def workout_cycling_user_1() -> Workout:
workout = Workout( workout = Workout(
@ -60,9 +68,7 @@ def workout_cycling_user_1() -> Workout:
distance=10, distance=10,
duration=datetime.timedelta(seconds=3600), duration=datetime.timedelta(seconds=3600),
) )
workout.max_speed = 10 update_workout(workout)
workout.ave_speed = 10
workout.moving = workout.duration
db.session.add(workout) db.session.add(workout)
db.session.commit() db.session.commit()
return workout return workout
@ -94,7 +100,7 @@ def workout_running_user_1() -> Workout:
distance=12, distance=12,
duration=datetime.timedelta(seconds=6000), duration=datetime.timedelta(seconds=6000),
) )
workout.moving = workout.duration update_workout(workout)
db.session.add(workout) db.session.add(workout)
db.session.commit() db.session.commit()
return workout return workout
@ -109,8 +115,7 @@ def seven_workouts_user_1() -> Workout:
distance=5, distance=5,
duration=datetime.timedelta(seconds=1024), duration=datetime.timedelta(seconds=1024),
) )
workout.ave_speed = float(workout.distance) / (1024 / 3600) update_workout(workout)
workout.moving = workout.duration
workout.ascent = 120 workout.ascent = 120
workout.descent = 200 workout.descent = 200
db.session.add(workout) db.session.add(workout)
@ -123,8 +128,7 @@ def seven_workouts_user_1() -> Workout:
distance=10, distance=10,
duration=datetime.timedelta(seconds=3456), duration=datetime.timedelta(seconds=3456),
) )
workout.ave_speed = float(workout.distance) / (3456 / 3600) update_workout(workout)
workout.moving = workout.duration
workout.ascent = 100 workout.ascent = 100
workout.descent = 80 workout.descent = 80
db.session.add(workout) db.session.add(workout)
@ -137,8 +141,7 @@ def seven_workouts_user_1() -> Workout:
distance=10, distance=10,
duration=datetime.timedelta(seconds=1024), duration=datetime.timedelta(seconds=1024),
) )
workout.ave_speed = float(workout.distance) / (1024 / 3600) update_workout(workout)
workout.moving = workout.duration
workout.ascent = 80 workout.ascent = 80
workout.descent = 100 workout.descent = 100
db.session.add(workout) db.session.add(workout)
@ -151,8 +154,7 @@ def seven_workouts_user_1() -> Workout:
distance=1, distance=1,
duration=datetime.timedelta(seconds=600), duration=datetime.timedelta(seconds=600),
) )
workout.ave_speed = float(workout.distance) / (600 / 3600) update_workout(workout)
workout.moving = workout.duration
workout.ascent = 120 workout.ascent = 120
workout.descent = 180 workout.descent = 180
db.session.add(workout) db.session.add(workout)
@ -165,8 +167,7 @@ def seven_workouts_user_1() -> Workout:
distance=10, distance=10,
duration=datetime.timedelta(seconds=1000), duration=datetime.timedelta(seconds=1000),
) )
workout.ave_speed = float(workout.distance) / (1000 / 3600) update_workout(workout)
workout.moving = workout.duration
workout.ascent = 100 workout.ascent = 100
workout.descent = 200 workout.descent = 200
db.session.add(workout) db.session.add(workout)
@ -179,8 +180,7 @@ def seven_workouts_user_1() -> Workout:
distance=8, distance=8,
duration=datetime.timedelta(seconds=6000), duration=datetime.timedelta(seconds=6000),
) )
workout.ave_speed = float(workout.distance) / (6000 / 3600) update_workout(workout)
workout.moving = workout.duration
workout.ascent = 40 workout.ascent = 40
workout.descent = 20 workout.descent = 20
db.session.add(workout) db.session.add(workout)
@ -193,8 +193,7 @@ def seven_workouts_user_1() -> Workout:
distance=10, distance=10,
duration=datetime.timedelta(seconds=3000), duration=datetime.timedelta(seconds=3000),
) )
workout.ave_speed = float(workout.distance) / (3000 / 3600) update_workout(workout)
workout.moving = workout.duration
db.session.add(workout) db.session.add(workout)
db.session.commit() db.session.commit()
return workout return workout
@ -209,7 +208,7 @@ def workout_cycling_user_2() -> Workout:
distance=15, distance=15,
duration=datetime.timedelta(seconds=3600), duration=datetime.timedelta(seconds=3600),
) )
workout.moving = workout.duration update_workout(workout)
db.session.add(workout) db.session.add(workout)
db.session.commit() db.session.commit()
return workout return workout

View File

@ -558,7 +558,7 @@ class TestUserProfile(ApiTestCaseMixin):
assert data['data']['imperial_units'] is False assert data['data']['imperial_units'] is False
assert data['data']['nb_sports'] == 2 assert data['data']['nb_sports'] == 2
assert data['data']['nb_workouts'] == 2 assert data['data']['nb_workouts'] == 2
assert len(data['data']['records']) == 6 assert len(data['data']['records']) == 8
assert data['data']['sports_list'] == [1, 2] assert data['data']['sports_list'] == [1, 2]
assert data['data']['total_distance'] == 22 assert data['data']['total_distance'] == 22
assert data['data']['total_duration'] == '2:40:00' assert data['data']['total_duration'] == '2:40:00'

View File

@ -83,7 +83,7 @@ class TestGetUser(ApiTestCaseMixin):
assert user['timezone'] is None assert user['timezone'] is None
assert user['weekm'] is False assert user['weekm'] is False
assert user['language'] is None assert user['language'] is None
assert len(user['records']) == 6 assert len(user['records']) == 8
assert user['nb_sports'] == 2 assert user['nb_sports'] == 2
assert user['nb_workouts'] == 2 assert user['nb_workouts'] == 2
assert user['sports_list'] == [1, 2] assert user['sports_list'] == [1, 2]
@ -206,7 +206,7 @@ class TestGetUsers(ApiTestCaseMixin):
assert data['data']['users'][0]['weekm'] is False assert data['data']['users'][0]['weekm'] is False
assert data['data']['users'][0]['nb_sports'] == 2 assert data['data']['users'][0]['nb_sports'] == 2
assert data['data']['users'][0]['nb_workouts'] == 2 assert data['data']['users'][0]['nb_workouts'] == 2
assert len(data['data']['users'][0]['records']) == 6 assert len(data['data']['users'][0]['records']) == 8
assert data['data']['users'][0]['sports_list'] == [1, 2] assert data['data']['users'][0]['sports_list'] == [1, 2]
assert data['data']['users'][0]['total_distance'] == 22.0 assert data['data']['users'][0]['total_distance'] == 22.0
assert data['data']['users'][0]['total_duration'] == '2:40:00' assert data['data']['users'][0]['total_duration'] == '2:40:00'
@ -215,7 +215,7 @@ class TestGetUsers(ApiTestCaseMixin):
assert data['data']['users'][1]['weekm'] is False assert data['data']['users'][1]['weekm'] is False
assert data['data']['users'][1]['nb_sports'] == 1 assert data['data']['users'][1]['nb_sports'] == 1
assert data['data']['users'][1]['nb_workouts'] == 1 assert data['data']['users'][1]['nb_workouts'] == 1
assert len(data['data']['users'][1]['records']) == 2 assert len(data['data']['users'][1]['records']) == 4
assert data['data']['users'][1]['sports_list'] == [1] assert data['data']['users'][1]['sports_list'] == [1]
assert data['data']['users'][1]['total_distance'] == 15 assert data['data']['users'][1]['total_distance'] == 15
assert data['data']['users'][1]['total_duration'] == '1:00:00' assert data['data']['users'][1]['total_duration'] == '1:00:00'

View File

@ -109,6 +109,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2017': { '2017': {
'1': { '1': {
'average_speed': 14.0,
'nb_workouts': 2, 'nb_workouts': 2,
'total_ascent': 220.0, 'total_ascent': 220.0,
'total_descent': 280.0, 'total_descent': 280.0,
@ -118,6 +119,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018': { '2018': {
'1': { '1': {
'average_speed': 18.79,
'nb_workouts': 5, 'nb_workouts': 5,
'total_ascent': 340.0, 'total_ascent': 340.0,
'total_descent': 500.0, 'total_descent': 500.0,
@ -125,6 +127,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 11624, 'total_duration': 11624,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -156,6 +159,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2018': { '2018': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -163,6 +167,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -195,6 +200,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2018': { '2018': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -202,6 +208,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -233,6 +240,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2017': { '2017': {
'1': { '1': {
'average_speed': 14.0,
'nb_workouts': 2, 'nb_workouts': 2,
'total_ascent': 220.0, 'total_ascent': 220.0,
'total_descent': 280.0, 'total_descent': 280.0,
@ -242,6 +250,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018': { '2018': {
'1': { '1': {
'average_speed': 18.79,
'nb_workouts': 5, 'nb_workouts': 5,
'total_ascent': 340.0, 'total_ascent': 340.0,
'total_descent': 500.0, 'total_descent': 500.0,
@ -249,6 +258,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 11624, 'total_duration': 11624,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -280,6 +290,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2018': { '2018': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -287,6 +298,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -319,6 +331,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2018': { '2018': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -326,6 +339,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -357,6 +371,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2017-03': { '2017-03': {
'1': { '1': {
'average_speed': 17.58,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 120.0, 'total_ascent': 120.0,
'total_descent': 200.0, 'total_descent': 200.0,
@ -366,6 +381,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2017-06': { '2017-06': {
'1': { '1': {
'average_speed': 10.42,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 100.0, 'total_ascent': 100.0,
'total_descent': 80.0, 'total_descent': 80.0,
@ -375,6 +391,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-01': { '2018-01': {
'1': { '1': {
'average_speed': 35.16,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 80.0, 'total_ascent': 80.0,
'total_descent': 100.0, 'total_descent': 100.0,
@ -384,6 +401,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-02': { '2018-02': {
'1': { '1': {
'average_speed': 21.0,
'nb_workouts': 2, 'nb_workouts': 2,
'total_ascent': 220.0, 'total_ascent': 220.0,
'total_descent': 380.0, 'total_descent': 380.0,
@ -393,6 +411,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-04': { '2018-04': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -400,6 +419,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -409,6 +429,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-05': { '2018-05': {
'1': { '1': {
'average_speed': 12.0,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -440,6 +461,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2017-03': { '2017-03': {
'1': { '1': {
'average_speed': 17.58,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 120.0, 'total_ascent': 120.0,
'total_descent': 200.0, 'total_descent': 200.0,
@ -449,6 +471,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2017-06': { '2017-06': {
'1': { '1': {
'average_speed': 10.42,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 100.0, 'total_ascent': 100.0,
'total_descent': 80.0, 'total_descent': 80.0,
@ -458,6 +481,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-01': { '2018-01': {
'1': { '1': {
'average_speed': 35.16,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 80.0, 'total_ascent': 80.0,
'total_descent': 100.0, 'total_descent': 100.0,
@ -467,6 +491,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-02': { '2018-02': {
'1': { '1': {
'average_speed': 21.0,
'nb_workouts': 2, 'nb_workouts': 2,
'total_ascent': 220.0, 'total_ascent': 220.0,
'total_descent': 380.0, 'total_descent': 380.0,
@ -476,6 +501,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-04': { '2018-04': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -483,6 +509,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -492,6 +519,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-05': { '2018-05': {
'1': { '1': {
'average_speed': 12.0,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -523,6 +551,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2018-04': { '2018-04': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -530,6 +559,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -561,6 +591,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2017-03-19': { '2017-03-19': {
'1': { '1': {
'average_speed': 17.58,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 120.0, 'total_ascent': 120.0,
'total_descent': 200.0, 'total_descent': 200.0,
@ -570,6 +601,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2017-05-28': { '2017-05-28': {
'1': { '1': {
'average_speed': 10.42,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 100.0, 'total_ascent': 100.0,
'total_descent': 80.0, 'total_descent': 80.0,
@ -579,6 +611,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2017-12-31': { '2017-12-31': {
'1': { '1': {
'average_speed': 35.16,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 80.0, 'total_ascent': 80.0,
'total_descent': 100.0, 'total_descent': 100.0,
@ -588,6 +621,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-02-18': { '2018-02-18': {
'1': { '1': {
'average_speed': 21.0,
'nb_workouts': 2, 'nb_workouts': 2,
'total_ascent': 220.0, 'total_ascent': 220.0,
'total_descent': 380.0, 'total_descent': 380.0,
@ -597,6 +631,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-04-01': { '2018-04-01': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -604,6 +639,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -613,6 +649,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-05-06': { '2018-05-06': {
'1': { '1': {
'average_speed': 12.0,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -644,6 +681,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2018-04-01': { '2018-04-01': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -651,6 +689,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -682,6 +721,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2017-03-20': { '2017-03-20': {
'1': { '1': {
'average_speed': 17.58,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 120.0, 'total_ascent': 120.0,
'total_descent': 200.0, 'total_descent': 200.0,
@ -691,6 +731,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2017-05-29': { '2017-05-29': {
'1': { '1': {
'average_speed': 10.42,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 100.0, 'total_ascent': 100.0,
'total_descent': 80.0, 'total_descent': 80.0,
@ -700,6 +741,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-01-01': { '2018-01-01': {
'1': { '1': {
'average_speed': 35.16,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 80.0, 'total_ascent': 80.0,
'total_descent': 100.0, 'total_descent': 100.0,
@ -709,6 +751,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-02-19': { '2018-02-19': {
'1': { '1': {
'average_speed': 21.0,
'nb_workouts': 2, 'nb_workouts': 2,
'total_ascent': 220.0, 'total_ascent': 220.0,
'total_descent': 380.0, 'total_descent': 380.0,
@ -718,6 +761,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-03-26': { '2018-03-26': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -725,6 +769,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -734,6 +779,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
}, },
'2018-05-07': { '2018-05-07': {
'1': { '1': {
'average_speed': 12.0,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -765,6 +811,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'2018-03-26': { '2018-03-26': {
'1': { '1': {
'average_speed': 4.8,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 40.0, 'total_ascent': 40.0,
'total_descent': 20.0, 'total_descent': 20.0,
@ -772,6 +819,7 @@ class TestGetStatsByTime(ApiTestCaseMixin):
'total_duration': 6000, 'total_duration': 6000,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -804,6 +852,7 @@ class TestGetStatsBySport(ApiTestCaseMixin):
assert 'success' in data['status'] assert 'success' in data['status']
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'1': { '1': {
'average_speed': 17.42,
'nb_workouts': 7, 'nb_workouts': 7,
'total_ascent': 560.0, 'total_ascent': 560.0,
'total_descent': 780.0, 'total_descent': 780.0,
@ -811,6 +860,7 @@ class TestGetStatsBySport(ApiTestCaseMixin):
'total_duration': 16104, 'total_duration': 16104,
}, },
'2': { '2': {
'average_speed': 7.2,
'nb_workouts': 1, 'nb_workouts': 1,
'total_ascent': 0.0, 'total_ascent': 0.0,
'total_descent': 0.0, 'total_descent': 0.0,
@ -840,6 +890,7 @@ class TestGetStatsBySport(ApiTestCaseMixin):
assert 'success' in data['status'] assert 'success' in data['status']
assert data['data']['statistics'] == { assert data['data']['statistics'] == {
'1': { '1': {
'average_speed': 17.42,
'nb_workouts': 7, 'nb_workouts': 7,
'total_ascent': 560.0, 'total_ascent': 560.0,
'total_descent': 780.0, 'total_descent': 780.0,

View File

@ -0,0 +1,32 @@
from statistics import mean
from typing import List
import pytest
from fittrackee.workouts.utils import get_average_speed
class TestWorkoutAverageSpeed:
@pytest.mark.parametrize(
'ave_speeds_list',
[
([0]),
([10]),
([0, 0]),
([10, 20]),
([10, 0, 20, 10]),
([1.5, 2, 3.7, 4.2]),
],
)
def test_it_calculates_average_speed(self, ave_speeds_list: List) -> None:
nb_workouts = len(ave_speeds_list)
total_average_speed = (
sum(ave_speeds_list[:-1]) / (len(ave_speeds_list) - 1)
if len(ave_speeds_list) > 1
else ave_speeds_list[0]
)
workout_average_speed = ave_speeds_list[-1]
assert get_average_speed(
nb_workouts, total_average_speed, workout_average_speed
) == mean(ave_speeds_list)

View File

@ -16,7 +16,11 @@ from fittrackee.users.decorators import authenticate, authenticate_as_admin
from fittrackee.users.models import User from fittrackee.users.models import User
from .models import Sport, Workout from .models import Sport, Workout
from .utils import get_datetime_from_request_args, get_upload_dir_size from .utils import (
get_average_speed,
get_datetime_from_request_args,
get_upload_dir_size,
)
from .utils_format import convert_timedelta_to_integer from .utils_format import convert_timedelta_to_integer
stats_blueprint = Blueprint('stats', __name__) stats_blueprint = Blueprint('stats', __name__)
@ -64,6 +68,7 @@ def get_workouts(
sport_id = workout.sport_id sport_id = workout.sport_id
if sport_id not in workouts_list_by_sport: if sport_id not in workouts_list_by_sport:
workouts_list_by_sport[sport_id] = { workouts_list_by_sport[sport_id] = {
'average_speed': 0.0,
'nb_workouts': 0, 'nb_workouts': 0,
'total_distance': 0.0, 'total_distance': 0.0,
'total_duration': 0, 'total_duration': 0,
@ -71,6 +76,13 @@ def get_workouts(
'total_descent': 0.0, 'total_descent': 0.0,
} }
workouts_list_by_sport[sport_id]['nb_workouts'] += 1 workouts_list_by_sport[sport_id]['nb_workouts'] += 1
workouts_list_by_sport[sport_id][
'average_speed'
] = get_average_speed(
workouts_list_by_sport[sport_id]['nb_workouts'], # type: ignore # noqa
workouts_list_by_sport[sport_id]['average_speed'],
workout.ave_speed,
)
workouts_list_by_sport[sport_id]['total_distance'] += float( workouts_list_by_sport[sport_id]['total_distance'] += float(
workout.distance workout.distance
) )
@ -117,6 +129,7 @@ def get_workouts(
workouts_list_by_time[time_period] = {} workouts_list_by_time[time_period] = {}
if sport_id not in workouts_list_by_time[time_period]: if sport_id not in workouts_list_by_time[time_period]:
workouts_list_by_time[time_period][sport_id] = { workouts_list_by_time[time_period][sport_id] = {
'average_speed': 0.0,
'nb_workouts': 0, 'nb_workouts': 0,
'total_distance': 0.0, 'total_distance': 0.0,
'total_duration': 0, 'total_duration': 0,
@ -126,6 +139,17 @@ def get_workouts(
workouts_list_by_time[time_period][sport_id][ workouts_list_by_time[time_period][sport_id][
'nb_workouts' 'nb_workouts'
] += 1 ] += 1
workouts_list_by_time[time_period][sport_id][
'average_speed'
] = get_average_speed(
workouts_list_by_time[time_period][sport_id][
'nb_workouts'
],
workouts_list_by_time[time_period][sport_id][
'average_speed'
],
workout.ave_speed,
)
workouts_list_by_time[time_period][sport_id][ workouts_list_by_time[time_period][sport_id][
'total_distance' 'total_distance'
] += float(workout.distance) ] += float(workout.distance)
@ -189,6 +213,7 @@ def get_workouts_by_time(
"statistics": { "statistics": {
"2017": { "2017": {
"3": { "3": {
"average_speed": 4.48,
"nb_workouts": 2, "nb_workouts": 2,
"total_ascent": 203.0, "total_ascent": 203.0,
"total_ascent": 156.0, "total_ascent": 156.0,
@ -198,6 +223,7 @@ def get_workouts_by_time(
}, },
"2019": { "2019": {
"1": { "1": {
"average_speed": 16.99,
"nb_workouts": 3, "nb_workouts": 3,
"total_ascent": 150.0, "total_ascent": 150.0,
"total_ascent": 178.0, "total_ascent": 178.0,
@ -205,6 +231,7 @@ def get_workouts_by_time(
"total_duration": 9960 "total_duration": 9960
}, },
"2": { "2": {
"average_speed": 15.95,
"nb_workouts": 1, "nb_workouts": 1,
"total_ascent": 46.0, "total_ascent": 46.0,
"total_ascent": 78.0, "total_ascent": 78.0,
@ -292,6 +319,7 @@ def get_workouts_by_sport(
"data": { "data": {
"statistics": { "statistics": {
"1": { "1": {
"average_speed": 16.99,
"nb_workouts": 3, "nb_workouts": 3,
"total_ascent": 150.0, "total_ascent": 150.0,
"total_ascent": 178.0, "total_ascent": 178.0,
@ -299,6 +327,7 @@ def get_workouts_by_sport(
"total_duration": 9960 "total_duration": 9960
}, },
"2": { "2": {
"average_speed": 15.95,
"nb_workouts": 1, "nb_workouts": 1,
"total_ascent": 46.0, "total_ascent": 46.0,
"total_ascent": 78.0, "total_ascent": 78.0,
@ -306,6 +335,7 @@ def get_workouts_by_sport(
"total_duration": 1267 "total_duration": 1267
}, },
"3": { "3": {
"average_speed": 4.46,
"nb_workouts": 2, "nb_workouts": 2,
"total_ascent": 203.0, "total_ascent": 203.0,
"total_ascent": 156.0, "total_ascent": 156.0,

View File

@ -448,3 +448,16 @@ def get_upload_dir_size() -> int:
fp = os.path.join(dir_path, f) fp = os.path.join(dir_path, f)
total_size += os.path.getsize(fp) total_size += os.path.getsize(fp)
return total_size return total_size
def get_average_speed(
nb_workouts: int, total_average_speed: float, workout_average_speed: float
) -> float:
return round(
(
(total_average_speed * (nb_workouts - 1))
+ float(workout_average_speed)
)
/ nb_workouts,
2,
)

View File

@ -77,7 +77,7 @@
}, },
}, },
y: { y: {
stacked: true, stacked: props.displayedData !== 'average_speed',
grid: { grid: {
drawOnChartArea: false, drawOnChartArea: false,
}, },
@ -101,15 +101,37 @@
datalabels: { datalabels: {
anchor: 'end', anchor: 'end',
align: 'end', align: 'end',
color: function (context) {
return props.displayedData === 'average_speed' &&
context.dataset.backgroundColor
? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
context.dataset.backgroundColor[0]
: '#666666'
},
rotation: function (context) { rotation: function (context) {
return props.fullStats && context.chart.chartArea.width < 580 return props.fullStats && context.chart.chartArea.width < 580
? 310 ? 310
: 0 : 0
}, },
display: function (context) { display: function (context) {
return !(props.fullStats && context.chart.chartArea.width < 300) return props.fullStats && context.chart.chartArea.width < 300
? false
: props.displayedData === 'average_speed'
? props.displayedSportIds.length == 1
? 'auto'
: false
: true
}, },
formatter: function (value, context) { formatter: function (value, context) {
if (props.displayedData === 'average_speed') {
return formatTooltipValue(
props.displayedData,
value,
props.useImperialUnits,
false
)
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
const total: number = context.chart.data.datasets const total: number = context.chart.data.datasets
@ -124,6 +146,7 @@
false false
) )
: null : null
}
}, },
}, },
legend: { legend: {
@ -133,6 +156,8 @@
interaction: { interaction: {
intersect: true, intersect: true,
mode: 'index', mode: 'index',
position:
props.displayedData === 'average_speed' ? 'nearest' : 'average',
}, },
filter: function (tooltipItem) { filter: function (tooltipItem) {
return tooltipItem.formattedValue !== '0' return tooltipItem.formattedValue !== '0'
@ -153,6 +178,9 @@
return label return label
}, },
footer: function (tooltipItems) { footer: function (tooltipItems) {
if (props.displayedData === 'average_speed') {
return ''
}
let sum = 0 let sum = 0
tooltipItems.map((tooltipItem) => { tooltipItems.map((tooltipItem) => {
sum += tooltipItem.parsed.y sum += tooltipItem.parsed.y

View File

@ -32,6 +32,15 @@
/> />
{{ $t('workouts.WORKOUT', 2) }} {{ $t('workouts.WORKOUT', 2) }}
</label> </label>
<label v-if="fullStats">
<input
type="radio"
name="average_speed"
:checked="displayedData === 'average_speed'"
@click="updateDisplayData"
/>
{{ $t('workouts.AVERAGE_SPEED') }}
</label>
<label v-if="fullStats"> <label v-if="fullStats">
<input <input
type="radio" type="radio"

View File

@ -4,6 +4,8 @@ export interface IChartDataset {
borderColor?: string[] borderColor?: string[]
borderWidth?: number borderWidth?: number
fill?: boolean fill?: boolean
data: number[] data: (number | null)[]
yAxisID?: string yAxisID?: string
type?: string
spanGaps?: boolean
} }

View File

@ -19,6 +19,7 @@ export interface IStatisticsDateParams {
} }
export type TStatisticsDatasetKeys = export type TStatisticsDatasetKeys =
| 'average_speed'
| 'nb_workouts' | 'nb_workouts'
| 'total_duration' | 'total_duration'
| 'total_distance' | 'total_distance'

View File

@ -43,6 +43,7 @@ const dateFormats: Record<string, Record<string, string>> = {
} }
export const datasetKeys: TStatisticsDatasetKeys[] = [ export const datasetKeys: TStatisticsDatasetKeys[] = [
'average_speed',
'nb_workouts', 'nb_workouts',
'total_duration', 'total_duration',
'total_distance', 'total_distance',
@ -67,17 +68,25 @@ export const getDateKeys = (
const getStatisticsChartDataset = ( const getStatisticsChartDataset = (
sportLabel: string, sportLabel: string,
color: string color: string,
isLineChart = false
): IChartDataset => { ): IChartDataset => {
return { const dataset: IChartDataset = {
label: sportLabel, label: sportLabel,
backgroundColor: [color], backgroundColor: [color],
data: [], data: [],
} }
if (isLineChart) {
dataset.type = 'line'
dataset.borderColor = [color]
dataset.spanGaps = true
}
return dataset
} }
export const getDatasets = (displayedSports: ISport[]): TStatisticsDatasets => { export const getDatasets = (displayedSports: ISport[]): TStatisticsDatasets => {
const datasets: TStatisticsDatasets = { const datasets: TStatisticsDatasets = {
average_speed: [],
nb_workouts: [], nb_workouts: [],
total_distance: [], total_distance: [],
total_duration: [], total_duration: [],
@ -86,6 +95,9 @@ export const getDatasets = (displayedSports: ISport[]): TStatisticsDatasets => {
} }
displayedSports.map((sport) => { displayedSports.map((sport) => {
const color = sport.color ? sport.color : sportColors[sport.label] const color = sport.color ? sport.color : sportColors[sport.label]
datasets.average_speed.push(
getStatisticsChartDataset(sport.label, color, true)
)
datasets.nb_workouts.push(getStatisticsChartDataset(sport.label, color)) datasets.nb_workouts.push(getStatisticsChartDataset(sport.label, color))
datasets.total_distance.push(getStatisticsChartDataset(sport.label, color)) datasets.total_distance.push(getStatisticsChartDataset(sport.label, color))
datasets.total_duration.push(getStatisticsChartDataset(sport.label, color)) datasets.total_duration.push(getStatisticsChartDataset(sport.label, color))
@ -101,11 +113,12 @@ export const convertStatsValue = (
useImperialUnits: boolean useImperialUnits: boolean
): number => { ): number => {
switch (datasetKey) { switch (datasetKey) {
case 'average_speed':
case 'total_distance': case 'total_distance':
case 'total_ascent': case 'total_ascent':
case 'total_descent': case 'total_descent':
return convertStatsDistance( return convertStatsDistance(
datasetKey === 'total_distance' ? 'km' : 'm', ['average_speed', 'total_distance'].includes(datasetKey) ? 'km' : 'm',
value, value,
useImperialUnits useImperialUnits
) )
@ -151,6 +164,8 @@ export const formatStats = (
apiStats[date][sportsId[dataset.label]][datasetKey], apiStats[date][sportsId[dataset.label]][datasetKey],
useImperialUnits useImperialUnits
) )
: datasetKey === 'average_speed'
? null
: 0 : 0
) )
}) })

View File

@ -11,6 +11,8 @@ export const formatTooltipValue = (
const unitFrom = 'km' const unitFrom = 'km'
const unitTo = useImperialUnits ? units[unitFrom].defaultTarget : unitFrom const unitTo = useImperialUnits ? units[unitFrom].defaultTarget : unitFrom
switch (displayedData) { switch (displayedData) {
case 'average_speed':
return `${value.toFixed(2)} ${unitTo}/h`
case 'total_duration': case 'total_duration':
return formatDuration(value, formatWithUnits) return formatDuration(value, formatWithUnits)
case 'total_distance': case 'total_distance':

View File

@ -167,6 +167,32 @@ describe('getDateKeys (week starting Monday)', () => {
describe('getDatasets', () => { describe('getDatasets', () => {
it('returns chart datasets (when no displayed data provided)', () => { it('returns chart datasets (when no displayed data provided)', () => {
const expected: TStatisticsDatasets = { const expected: TStatisticsDatasets = {
average_speed: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#4c9792'],
borderColor: ['#4c9792'],
data: [],
type: 'line',
spanGaps: true,
},
{
label: 'Cycling (Transport)',
backgroundColor: ['#000000'],
borderColor: ['#000000'],
data: [],
type: 'line',
spanGaps: true,
},
{
label: 'Hiking',
backgroundColor: ['#bb757c'],
borderColor: ['#bb757c'],
data: [],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Sport)', label: 'Cycling (Sport)',
@ -257,6 +283,16 @@ describe('getDatasets', () => {
}) })
it('returns chart datasets with only displayed sports', () => { it('returns chart datasets with only displayed sports', () => {
const expected: TStatisticsDatasets = { const expected: TStatisticsDatasets = {
average_speed: [
{
label: 'Cycling (Transport)',
backgroundColor: ['#000000'],
borderColor: ['#000000'],
data: [],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Transport)', label: 'Cycling (Transport)',
@ -308,6 +344,7 @@ describe('formatStats', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['05/2021', '06/2021', '07/2021'], labels: ['05/2021', '06/2021', '07/2021'],
datasets: { datasets: {
average_speed: [],
nb_workouts: [], nb_workouts: [],
total_distance: [], total_distance: [],
total_duration: [], total_duration: [],
@ -331,6 +368,16 @@ describe('formatStats', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['05/2021', '06/2021', '07/2021'], labels: ['05/2021', '06/2021', '07/2021'],
datasets: { datasets: {
average_speed: [
{
label: 'Cycling (Transport)',
backgroundColor: ['#000000'],
borderColor: ['#000000'],
data: [null, null, null],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Transport)', label: 'Cycling (Transport)',
@ -378,6 +425,7 @@ describe('formatStats', () => {
const inputStats: TStatisticsFromApi = { const inputStats: TStatisticsFromApi = {
'2021-05': { '2021-05': {
1: { 1: {
average_speed: 12,
nb_workouts: 1, nb_workouts: 1,
total_distance: 10, total_distance: 10,
total_duration: 3000, total_duration: 3000,
@ -387,6 +435,7 @@ describe('formatStats', () => {
}, },
'2021-06': { '2021-06': {
1: { 1: {
average_speed: 18,
nb_workouts: 1, nb_workouts: 1,
total_distance: 15, total_distance: 15,
total_duration: 3500, total_duration: 3500,
@ -394,6 +443,7 @@ describe('formatStats', () => {
total_descent: 150, total_descent: 150,
}, },
2: { 2: {
average_speed: 24,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -403,6 +453,7 @@ describe('formatStats', () => {
}, },
'2021-07': { '2021-07': {
3: { 3: {
average_speed: 8.64,
nb_workouts: 2, nb_workouts: 2,
total_distance: 12, total_distance: 12,
total_duration: 5000, total_duration: 5000,
@ -419,6 +470,7 @@ describe('formatStats', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['05/2021', '06/2021', '07/2021'], labels: ['05/2021', '06/2021', '07/2021'],
datasets: { datasets: {
average_speed: [],
nb_workouts: [], nb_workouts: [],
total_distance: [], total_distance: [],
total_duration: [], total_duration: [],
@ -436,6 +488,7 @@ describe('formatStats', () => {
const inputStats: TStatisticsFromApi = { const inputStats: TStatisticsFromApi = {
'2021-05': { '2021-05': {
1: { 1: {
average_speed: 12,
nb_workouts: 1, nb_workouts: 1,
total_distance: 10, total_distance: 10,
total_duration: 3000, total_duration: 3000,
@ -445,6 +498,7 @@ describe('formatStats', () => {
}, },
'2021-06': { '2021-06': {
1: { 1: {
average_speed: 18,
nb_workouts: 1, nb_workouts: 1,
total_distance: 15, total_distance: 15,
total_duration: 3500, total_duration: 3500,
@ -452,6 +506,7 @@ describe('formatStats', () => {
total_descent: 150, total_descent: 150,
}, },
2: { 2: {
average_speed: 24,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -461,6 +516,7 @@ describe('formatStats', () => {
}, },
'2021-07': { '2021-07': {
3: { 3: {
average_speed: 8.64,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -477,6 +533,16 @@ describe('formatStats', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['05/2021', '06/2021', '07/2021'], labels: ['05/2021', '06/2021', '07/2021'],
datasets: { datasets: {
average_speed: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#4c9792'],
borderColor: ['#4c9792'],
data: [12, 18, null],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Sport)', label: 'Cycling (Sport)',
@ -526,6 +592,7 @@ describe('formatStats (duration)', () => {
const inputStats: TStatisticsFromApi = { const inputStats: TStatisticsFromApi = {
'2020': { '2020': {
1: { 1: {
average_speed: 12,
nb_workouts: 1, nb_workouts: 1,
total_distance: 10, total_distance: 10,
total_duration: 3000, total_duration: 3000,
@ -535,6 +602,7 @@ describe('formatStats (duration)', () => {
}, },
'2021': { '2021': {
1: { 1: {
average_speed: 18,
nb_workouts: 1, nb_workouts: 1,
total_distance: 15, total_distance: 15,
total_duration: 3500, total_duration: 3500,
@ -542,6 +610,7 @@ describe('formatStats (duration)', () => {
total_descent: 150, total_descent: 150,
}, },
2: { 2: {
average_speed: 14,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -551,6 +620,7 @@ describe('formatStats (duration)', () => {
}, },
'2022': { '2022': {
3: { 3: {
average_speed: 14,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -567,6 +637,16 @@ describe('formatStats (duration)', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['2020', '2021'], labels: ['2020', '2021'],
datasets: { datasets: {
average_speed: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#4c9792'],
borderColor: ['#4c9792'],
data: [12, 18],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Sport)', label: 'Cycling (Sport)',
@ -613,6 +693,7 @@ describe('formatStats (duration)', () => {
const inputStats: TStatisticsFromApi = { const inputStats: TStatisticsFromApi = {
'2020': { '2020': {
1: { 1: {
average_speed: 12,
nb_workouts: 1, nb_workouts: 1,
total_distance: 10, total_distance: 10,
total_duration: 3000, total_duration: 3000,
@ -622,6 +703,7 @@ describe('formatStats (duration)', () => {
}, },
'2021': { '2021': {
1: { 1: {
average_speed: 18,
nb_workouts: 1, nb_workouts: 1,
total_distance: 15, total_distance: 15,
total_duration: 3500, total_duration: 3500,
@ -629,6 +711,7 @@ describe('formatStats (duration)', () => {
total_descent: 150, total_descent: 150,
}, },
2: { 2: {
average_speed: 24,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -638,6 +721,7 @@ describe('formatStats (duration)', () => {
}, },
'2022': { '2022': {
3: { 3: {
average_speed: 8.64,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -654,6 +738,16 @@ describe('formatStats (duration)', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['2020', '2021'], labels: ['2020', '2021'],
datasets: { datasets: {
average_speed: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#4c9792'],
borderColor: ['#4c9792'],
data: [12, 18],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Sport)', label: 'Cycling (Sport)',
@ -701,6 +795,7 @@ describe('formatStats (duration)', () => {
const inputStats: TStatisticsFromApi = { const inputStats: TStatisticsFromApi = {
'2021-10-03': { '2021-10-03': {
1: { 1: {
average_speed: 12,
nb_workouts: 1, nb_workouts: 1,
total_distance: 10, total_distance: 10,
total_duration: 3000, total_duration: 3000,
@ -710,6 +805,7 @@ describe('formatStats (duration)', () => {
}, },
'2021-10-10': { '2021-10-10': {
1: { 1: {
average_speed: 18,
nb_workouts: 1, nb_workouts: 1,
total_distance: 15, total_distance: 15,
total_duration: 3500, total_duration: 3500,
@ -717,6 +813,7 @@ describe('formatStats (duration)', () => {
total_descent: 150, total_descent: 150,
}, },
2: { 2: {
average_speed: 24,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -726,6 +823,7 @@ describe('formatStats (duration)', () => {
}, },
'2021-10-17': { '2021-10-17': {
3: { 3: {
average_speed: 8.64,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -742,6 +840,16 @@ describe('formatStats (duration)', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['03/10/2021', '10/10/2021', '17/10/2021'], labels: ['03/10/2021', '10/10/2021', '17/10/2021'],
datasets: { datasets: {
average_speed: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#4c9792'],
borderColor: ['#4c9792'],
data: [12, 18, null],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Sport)', label: 'Cycling (Sport)',
@ -789,6 +897,7 @@ describe('formatStats (duration)', () => {
const inputStats: TStatisticsFromApi = { const inputStats: TStatisticsFromApi = {
'2021-10-04': { '2021-10-04': {
1: { 1: {
average_speed: 12,
nb_workouts: 1, nb_workouts: 1,
total_distance: 10, total_distance: 10,
total_duration: 3000, total_duration: 3000,
@ -798,6 +907,7 @@ describe('formatStats (duration)', () => {
}, },
'2021-10-11': { '2021-10-11': {
1: { 1: {
average_speed: 18,
nb_workouts: 1, nb_workouts: 1,
total_distance: 15, total_distance: 15,
total_duration: 3500, total_duration: 3500,
@ -805,6 +915,7 @@ describe('formatStats (duration)', () => {
total_descent: 150, total_descent: 150,
}, },
2: { 2: {
average_speed: 24,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -814,6 +925,7 @@ describe('formatStats (duration)', () => {
}, },
'2021-10-18': { '2021-10-18': {
3: { 3: {
average_speed: 8.64,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -830,6 +942,16 @@ describe('formatStats (duration)', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['04/10/2021', '11/10/2021', '18/10/2021'], labels: ['04/10/2021', '11/10/2021', '18/10/2021'],
datasets: { datasets: {
average_speed: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#4c9792'],
borderColor: ['#4c9792'],
data: [12, 18, null],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Sport)', label: 'Cycling (Sport)',
@ -877,6 +999,7 @@ describe('formatStats (duration)', () => {
const inputStats: TStatisticsFromApi = { const inputStats: TStatisticsFromApi = {
'2021-10-03': { '2021-10-03': {
1: { 1: {
average_speed: 12,
nb_workouts: 1, nb_workouts: 1,
total_distance: 10, total_distance: 10,
total_duration: 3000, total_duration: 3000,
@ -886,6 +1009,7 @@ describe('formatStats (duration)', () => {
}, },
'2021-10-10': { '2021-10-10': {
1: { 1: {
average_speed: 18,
nb_workouts: 1, nb_workouts: 1,
total_distance: 15, total_distance: 15,
total_duration: 3500, total_duration: 3500,
@ -893,6 +1017,7 @@ describe('formatStats (duration)', () => {
total_descent: 150, total_descent: 150,
}, },
2: { 2: {
average_speed: 24,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -902,6 +1027,7 @@ describe('formatStats (duration)', () => {
}, },
'2021-10-17': { '2021-10-17': {
3: { 3: {
average_speed: 8.64,
nb_workouts: 2, nb_workouts: 2,
total_distance: 20, total_distance: 20,
total_duration: 3000, total_duration: 3000,
@ -918,6 +1044,16 @@ describe('formatStats (duration)', () => {
const expected: IStatisticsChartData = { const expected: IStatisticsChartData = {
labels: ['03/10/2021', '10/10/2021', '17/10/2021'], labels: ['03/10/2021', '10/10/2021', '17/10/2021'],
datasets: { datasets: {
average_speed: [
{
label: 'Cycling (Sport)',
backgroundColor: ['#4c9792'],
borderColor: ['#4c9792'],
data: [7.46, 11.18, null],
type: 'line',
spanGaps: true,
},
],
nb_workouts: [ nb_workouts: [
{ {
label: 'Cycling (Sport)', label: 'Cycling (Sport)',

View File

@ -5,33 +5,39 @@ import { formatTooltipValue } from '@/utils/tooltip'
describe('formatTooltipValue', () => { describe('formatTooltipValue', () => {
const testsParams = [ const testsParams = [
{
description: 'returns 3 if input is average speed',
inputDisplayedData: datasetKeys[0], // 'average_speed'
inputValue: 30,
expectedResult: '30.00 km/h',
},
{ {
description: 'returns 3 if input is workouts count', description: 'returns 3 if input is workouts count',
inputDisplayedData: datasetKeys[0], // 'nb_workouts' inputDisplayedData: datasetKeys[1], // 'nb_workouts'
inputValue: 30, inputValue: 30,
expectedResult: '30', expectedResult: '30',
}, },
{ {
description: 'returns 00m:03s if input is total duration', description: 'returns 00m:03s if input is total duration',
inputDisplayedData: datasetKeys[1], // 'total_duration' inputDisplayedData: datasetKeys[2], // 'total_duration'
inputValue: 30, inputValue: 30,
expectedResult: '00m 30s', expectedResult: '00m 30s',
}, },
{ {
description: 'returns 3.00 km if input is total distance', description: 'returns 3.00 km if input is total distance',
inputDisplayedData: datasetKeys[2], // 'total_distance' inputDisplayedData: datasetKeys[3], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '30.00 km', expectedResult: '30.00 km',
}, },
{ {
description: 'returns 0.003 km if input is total ascent', description: 'returns 0.003 km if input is total ascent',
inputDisplayedData: datasetKeys[3], // 'total_distance' inputDisplayedData: datasetKeys[4], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '0.03 km', expectedResult: '0.03 km',
}, },
{ {
description: 'returns 0.003 km if input is total descent', description: 'returns 0.003 km if input is total descent',
inputDisplayedData: datasetKeys[4], // 'total_distance' inputDisplayedData: datasetKeys[5], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '0.03 km', expectedResult: '0.03 km',
}, },
@ -53,33 +59,39 @@ describe('formatTooltipValue', () => {
describe('formatTooltipValue after conversion to imperial units', () => { describe('formatTooltipValue after conversion to imperial units', () => {
const testsParams = [ const testsParams = [
{
description: 'returns 30 if input is average speed',
inputDisplayedData: datasetKeys[0], // 'average_speed'
inputValue: 30,
expectedResult: '30.00 mi/h',
},
{ {
description: 'returns 30 if input is workouts count', description: 'returns 30 if input is workouts count',
inputDisplayedData: datasetKeys[0], // 'nb_workouts' inputDisplayedData: datasetKeys[1], // 'nb_workouts'
inputValue: 30, inputValue: 30,
expectedResult: '30', expectedResult: '30',
}, },
{ {
description: 'returns 00m:03s if input is total duration', description: 'returns 00m:03s if input is total duration',
inputDisplayedData: datasetKeys[1], // 'total_duration' inputDisplayedData: datasetKeys[2], // 'total_duration'
inputValue: 30, inputValue: 30,
expectedResult: '00m 30s', expectedResult: '00m 30s',
}, },
{ {
description: 'returns 30 mi if input is total distance', description: 'returns 30 mi if input is total distance',
inputDisplayedData: datasetKeys[2], // 'total_distance' inputDisplayedData: datasetKeys[3], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '30.00 mi', expectedResult: '30.00 mi',
}, },
{ {
description: 'returns 0.03 mi if input is total ascent', description: 'returns 0.03 mi if input is total ascent',
inputDisplayedData: datasetKeys[3], // 'total_distance' inputDisplayedData: datasetKeys[4], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '0.03 mi', expectedResult: '0.03 mi',
}, },
{ {
description: 'returns 0.03 mi if input is total descent', description: 'returns 0.03 mi if input is total descent',
inputDisplayedData: datasetKeys[4], // 'total_distance' inputDisplayedData: datasetKeys[5], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '0.03 mi', expectedResult: '0.03 mi',
}, },
@ -101,33 +113,39 @@ describe('formatTooltipValue after conversion to imperial units', () => {
describe('formatTooltipValue (formatWithUnits = false)', () => { describe('formatTooltipValue (formatWithUnits = false)', () => {
const testsParams = [ const testsParams = [
{
description: 'returns 3 if input is average speed',
inputDisplayedData: datasetKeys[0], // 'average_speed'
inputValue: 30,
expectedResult: '30.00 km/h',
},
{ {
description: 'returns 3 if input is workouts count', description: 'returns 3 if input is workouts count',
inputDisplayedData: datasetKeys[0], // 'nb_workouts' inputDisplayedData: datasetKeys[1], // 'nb_workouts'
inputValue: 30, inputValue: 30,
expectedResult: '30', expectedResult: '30',
}, },
{ {
description: 'returns 00:03 if input is total duration', description: 'returns 00:03 if input is total duration',
inputDisplayedData: datasetKeys[1], // 'total_duration' inputDisplayedData: datasetKeys[2], // 'total_duration'
inputValue: 30, inputValue: 30,
expectedResult: '00:30', expectedResult: '00:30',
}, },
{ {
description: 'returns 3.00 km if input is total distance', description: 'returns 3.00 km if input is total distance',
inputDisplayedData: datasetKeys[2], // 'total_distance' inputDisplayedData: datasetKeys[3], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '30.00 km', expectedResult: '30.00 km',
}, },
{ {
description: 'returns 0.003 km if input is total ascent', description: 'returns 0.003 km if input is total ascent',
inputDisplayedData: datasetKeys[3], // 'total_distance' inputDisplayedData: datasetKeys[4], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '0.03 km', expectedResult: '0.03 km',
}, },
{ {
description: 'returns 0.003 km if input is total descent', description: 'returns 0.003 km if input is total descent',
inputDisplayedData: datasetKeys[4], // 'total_distance' inputDisplayedData: datasetKeys[5], // 'total_distance'
inputValue: 30, inputValue: 30,
expectedResult: '0.03 km', expectedResult: '0.03 km',
}, },