@sports-alliance/sports-lib 7.0.7 → 7.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/.editorconfig +14 -0
  2. package/.eslintignore +4 -0
  3. package/.eslintrc.js +9 -0
  4. package/.prettierignore +25 -0
  5. package/.prettierrc.json +12 -0
  6. package/CODE_OF_CONDUCT.md +76 -0
  7. package/jest.config.js +23 -0
  8. package/lib/esm/index.js +12034 -152
  9. package/package.json +3 -2
  10. package/tsconfig.cjs.json +7 -0
  11. package/tsconfig.esm.json +8 -0
  12. package/tsconfig.lib.json +8 -0
  13. package/lib/esm/activities/activity-parsing-options.js +0 -19
  14. package/lib/esm/activities/activity.interface.js +0 -1
  15. package/lib/esm/activities/activity.js +0 -281
  16. package/lib/esm/activities/activity.json.interface.js +0 -1
  17. package/lib/esm/activities/activity.spec.js +0 -348
  18. package/lib/esm/activities/activity.types.js +0 -1046
  19. package/lib/esm/activities/activityt-types.spec.js +0 -16
  20. package/lib/esm/activities/devices/device.interface.js +0 -1
  21. package/lib/esm/activities/devices/device.js +0 -26
  22. package/lib/esm/activities/devices/device.json.interface.js +0 -1
  23. package/lib/esm/constants/constants.js +0 -8
  24. package/lib/esm/creators/creator.interface.js +0 -1
  25. package/lib/esm/creators/creator.js +0 -37
  26. package/lib/esm/creators/creator.json.interface.js +0 -1
  27. package/lib/esm/creators/creator.spec.js +0 -25
  28. package/lib/esm/data/data-active-lap.js +0 -4
  29. package/lib/esm/data/data-active-lengths.js +0 -4
  30. package/lib/esm/data/data-aerobic-training-effect.js +0 -8
  31. package/lib/esm/data/data-anaerobic-training-effect.js +0 -8
  32. package/lib/esm/data/data-stance-time-balance-left.js +0 -4
  33. package/lib/esm/data/data-stance-time-balance-right.js +0 -4
  34. package/lib/esm/data/data-stance-time-balance.js +0 -3
  35. package/lib/esm/data/data-store.spec.js +0 -78
  36. package/lib/esm/data/data-total-cycles.js +0 -4
  37. package/lib/esm/data/data.absolute-pressure.js +0 -5
  38. package/lib/esm/data/data.accumulated-power.js +0 -8
  39. package/lib/esm/data/data.activity-types.js +0 -7
  40. package/lib/esm/data/data.air-power-avg.js +0 -4
  41. package/lib/esm/data/data.air-power-max.js +0 -4
  42. package/lib/esm/data/data.air-power-min.js +0 -4
  43. package/lib/esm/data/data.air-power.js +0 -8
  44. package/lib/esm/data/data.alti-baro-profile.js +0 -4
  45. package/lib/esm/data/data.altitude-avg.js +0 -4
  46. package/lib/esm/data/data.altitude-gps.js +0 -5
  47. package/lib/esm/data/data.altitude-max.js +0 -4
  48. package/lib/esm/data/data.altitude-min.js +0 -4
  49. package/lib/esm/data/data.altitude-smooth.js +0 -4
  50. package/lib/esm/data/data.altitude.js +0 -8
  51. package/lib/esm/data/data.array.js +0 -13
  52. package/lib/esm/data/data.ascent-time.js +0 -4
  53. package/lib/esm/data/data.ascent.js +0 -4
  54. package/lib/esm/data/data.auto-lap-distance.js +0 -5
  55. package/lib/esm/data/data.auto-lap-duration.js +0 -4
  56. package/lib/esm/data/data.auto-lap-used.js +0 -7
  57. package/lib/esm/data/data.auto-pause-used.js +0 -7
  58. package/lib/esm/data/data.avg-stride-length.js +0 -4
  59. package/lib/esm/data/data.balance.js +0 -6
  60. package/lib/esm/data/data.bare.js +0 -4
  61. package/lib/esm/data/data.battery-charge.js +0 -8
  62. package/lib/esm/data/data.battery-consumption.js +0 -8
  63. package/lib/esm/data/data.battery-current.js +0 -8
  64. package/lib/esm/data/data.battery-life-estimation.js +0 -4
  65. package/lib/esm/data/data.battery-voltage.js +0 -8
  66. package/lib/esm/data/data.bike-pod-used.js +0 -7
  67. package/lib/esm/data/data.boolean.js +0 -9
  68. package/lib/esm/data/data.cadence-avg.js +0 -4
  69. package/lib/esm/data/data.cadence-max.js +0 -4
  70. package/lib/esm/data/data.cadence-min.js +0 -4
  71. package/lib/esm/data/data.cadence.js +0 -8
  72. package/lib/esm/data/data.cycling-dynamics.js +0 -3
  73. package/lib/esm/data/data.cycling-position.js +0 -37
  74. package/lib/esm/data/data.cycling-seated-time.js +0 -5
  75. package/lib/esm/data/data.cycling-standing-time.js +0 -5
  76. package/lib/esm/data/data.descent-time.js +0 -4
  77. package/lib/esm/data/data.descent.js +0 -4
  78. package/lib/esm/data/data.description.js +0 -4
  79. package/lib/esm/data/data.device-location.js +0 -4
  80. package/lib/esm/data/data.device-names.js +0 -7
  81. package/lib/esm/data/data.distance.js +0 -15
  82. package/lib/esm/data/data.duration.js +0 -56
  83. package/lib/esm/data/data.ehpe.js +0 -5
  84. package/lib/esm/data/data.enabled-navigation-systems.js +0 -4
  85. package/lib/esm/data/data.end-altitude.js +0 -4
  86. package/lib/esm/data/data.end-position.js +0 -4
  87. package/lib/esm/data/data.energy.js +0 -8
  88. package/lib/esm/data/data.epoc.js +0 -5
  89. package/lib/esm/data/data.event.js +0 -3
  90. package/lib/esm/data/data.evpe.js +0 -4
  91. package/lib/esm/data/data.feeling.js +0 -15
  92. package/lib/esm/data/data.foot-pod-used.js +0 -7
  93. package/lib/esm/data/data.form-power.js +0 -4
  94. package/lib/esm/data/data.fused-altitude.js +0 -7
  95. package/lib/esm/data/data.fused-location.js +0 -7
  96. package/lib/esm/data/data.gnss-distance.js +0 -4
  97. package/lib/esm/data/data.grade-adjusted-pace-avg.js +0 -15
  98. package/lib/esm/data/data.grade-adjusted-pace-max.js +0 -15
  99. package/lib/esm/data/data.grade-adjusted-pace-min.js +0 -15
  100. package/lib/esm/data/data.grade-adjusted-pace.js +0 -25
  101. package/lib/esm/data/data.grade-adjusted-speed-avg.js +0 -46
  102. package/lib/esm/data/data.grade-adjusted-speed-max.js +0 -46
  103. package/lib/esm/data/data.grade-adjusted-speed-min.js +0 -46
  104. package/lib/esm/data/data.grade-adjusted-speed.js +0 -78
  105. package/lib/esm/data/data.grade-smooth.js +0 -7
  106. package/lib/esm/data/data.grade.js +0 -7
  107. package/lib/esm/data/data.ground-time.js +0 -8
  108. package/lib/esm/data/data.heart-rate-avg.js +0 -4
  109. package/lib/esm/data/data.heart-rate-max.js +0 -4
  110. package/lib/esm/data/data.heart-rate-min.js +0 -4
  111. package/lib/esm/data/data.heart-rate-used.js +0 -7
  112. package/lib/esm/data/data.heart-rate-zone-five-duration.js +0 -4
  113. package/lib/esm/data/data.heart-rate-zone-four-duration.js +0 -4
  114. package/lib/esm/data/data.heart-rate-zone-one-duration.js +0 -4
  115. package/lib/esm/data/data.heart-rate-zone-three-duration.js +0 -4
  116. package/lib/esm/data/data.heart-rate-zone-two-duration.js +0 -4
  117. package/lib/esm/data/data.heart-rate.js +0 -8
  118. package/lib/esm/data/data.ibi.js +0 -8
  119. package/lib/esm/data/data.interface.js +0 -5
  120. package/lib/esm/data/data.js +0 -62
  121. package/lib/esm/data/data.json.interface.js +0 -1
  122. package/lib/esm/data/data.latitude-degrees.js +0 -5
  123. package/lib/esm/data/data.left-balance.js +0 -4
  124. package/lib/esm/data/data.leg-stiffness.js +0 -16
  125. package/lib/esm/data/data.longitude-degrees.js +0 -5
  126. package/lib/esm/data/data.moving-time.js +0 -4
  127. package/lib/esm/data/data.number-of-satellites.js +0 -7
  128. package/lib/esm/data/data.number-of.samples.js +0 -4
  129. package/lib/esm/data/data.number.js +0 -13
  130. package/lib/esm/data/data.pace-avg.js +0 -8
  131. package/lib/esm/data/data.pace-max.js +0 -8
  132. package/lib/esm/data/data.pace-min.js +0 -8
  133. package/lib/esm/data/data.pace.js +0 -46
  134. package/lib/esm/data/data.pause.js +0 -4
  135. package/lib/esm/data/data.peak-epoc.js +0 -7
  136. package/lib/esm/data/data.peak-training-effect.js +0 -4
  137. package/lib/esm/data/data.percent.js +0 -4
  138. package/lib/esm/data/data.pool-length.js +0 -5
  139. package/lib/esm/data/data.position.interface.js +0 -1
  140. package/lib/esm/data/data.position.js +0 -18
  141. package/lib/esm/data/data.power-avg.js +0 -4
  142. package/lib/esm/data/data.power-down.js +0 -4
  143. package/lib/esm/data/data.power-intensity-factor.js +0 -5
  144. package/lib/esm/data/data.power-left.js +0 -4
  145. package/lib/esm/data/data.power-max.js +0 -4
  146. package/lib/esm/data/data.power-min.js +0 -4
  147. package/lib/esm/data/data.power-normalized.js +0 -4
  148. package/lib/esm/data/data.power-pedal-smoothness-left.js +0 -4
  149. package/lib/esm/data/data.power-pedal-smoothness-right.js +0 -4
  150. package/lib/esm/data/data.power-pod-used.js +0 -7
  151. package/lib/esm/data/data.power-right.js +0 -4
  152. package/lib/esm/data/data.power-torque-effectiveness-left.js +0 -4
  153. package/lib/esm/data/data.power-torque-effectiveness-right.js +0 -4
  154. package/lib/esm/data/data.power-training-stress-score.js +0 -5
  155. package/lib/esm/data/data.power-up.js +0 -4
  156. package/lib/esm/data/data.power-work.js +0 -5
  157. package/lib/esm/data/data.power-zone-five-duration.js +0 -4
  158. package/lib/esm/data/data.power-zone-four-duration.js +0 -4
  159. package/lib/esm/data/data.power-zone-one-duration.js +0 -4
  160. package/lib/esm/data/data.power-zone-three-duration.js +0 -4
  161. package/lib/esm/data/data.power-zone-two-duration.js +0 -4
  162. package/lib/esm/data/data.power.js +0 -8
  163. package/lib/esm/data/data.recovery-time.js +0 -7
  164. package/lib/esm/data/data.rider-position-change-event.js +0 -8
  165. package/lib/esm/data/data.right-balance.js +0 -4
  166. package/lib/esm/data/data.rpe.js +0 -23
  167. package/lib/esm/data/data.satellite-5-best-snr.js +0 -4
  168. package/lib/esm/data/data.sea-level-pressure.js +0 -5
  169. package/lib/esm/data/data.spec.js +0 -25
  170. package/lib/esm/data/data.speed-avg.js +0 -46
  171. package/lib/esm/data/data.speed-max.js +0 -46
  172. package/lib/esm/data/data.speed-min.js +0 -46
  173. package/lib/esm/data/data.speed-zone-five-duration.js +0 -4
  174. package/lib/esm/data/data.speed-zone-four-duration.js +0 -4
  175. package/lib/esm/data/data.speed-zone-one-duration.js +0 -4
  176. package/lib/esm/data/data.speed-zone-three-duration.js +0 -4
  177. package/lib/esm/data/data.speed-zone-two-duration.js +0 -4
  178. package/lib/esm/data/data.speed.js +0 -88
  179. package/lib/esm/data/data.sport-profile-name.js +0 -4
  180. package/lib/esm/data/data.stance-time.js +0 -5
  181. package/lib/esm/data/data.start-altitude.js +0 -4
  182. package/lib/esm/data/data.start-event.js +0 -4
  183. package/lib/esm/data/data.start-position.js +0 -4
  184. package/lib/esm/data/data.step-length.js +0 -4
  185. package/lib/esm/data/data.steps-old.js +0 -4
  186. package/lib/esm/data/data.steps.js +0 -4
  187. package/lib/esm/data/data.stop-all-event.js +0 -4
  188. package/lib/esm/data/data.stop-event.js +0 -4
  189. package/lib/esm/data/data.store.export.spec.js +0 -66
  190. package/lib/esm/data/data.store.js +0 -1213
  191. package/lib/esm/data/data.string.js +0 -13
  192. package/lib/esm/data/data.stryd-altitude.js +0 -4
  193. package/lib/esm/data/data.stryd-distance.js +0 -4
  194. package/lib/esm/data/data.stryd-speed.js +0 -4
  195. package/lib/esm/data/data.swim-pace-avg.js +0 -8
  196. package/lib/esm/data/data.swim-pace-max.js +0 -8
  197. package/lib/esm/data/data.swim-pace-min.js +0 -8
  198. package/lib/esm/data/data.swim-pace.js +0 -19
  199. package/lib/esm/data/data.swolf-25m.js +0 -4
  200. package/lib/esm/data/data.swolf-50m.js +0 -4
  201. package/lib/esm/data/data.target-distance.js +0 -4
  202. package/lib/esm/data/data.target-heart-rate-zone.js +0 -4
  203. package/lib/esm/data/data.target-power-zone.js +0 -4
  204. package/lib/esm/data/data.target-speed-zone.js +0 -4
  205. package/lib/esm/data/data.target-time.js +0 -4
  206. package/lib/esm/data/data.temperature-avg.js +0 -4
  207. package/lib/esm/data/data.temperature-max.js +0 -4
  208. package/lib/esm/data/data.temperature-min.js +0 -4
  209. package/lib/esm/data/data.temperature.js +0 -8
  210. package/lib/esm/data/data.time.js +0 -6
  211. package/lib/esm/data/data.timer-time.js +0 -4
  212. package/lib/esm/data/data.vertical-oscillation.js +0 -5
  213. package/lib/esm/data/data.vertical-ratio.js +0 -5
  214. package/lib/esm/data/data.vertical-speed-avg.js +0 -53
  215. package/lib/esm/data/data.vertical-speed-max.js +0 -53
  216. package/lib/esm/data/data.vertical-speed-min.js +0 -53
  217. package/lib/esm/data/data.vertical-speed.js +0 -103
  218. package/lib/esm/data/data.vo2-max.js +0 -7
  219. package/lib/esm/data/ibi/data.ibi.filters.js +0 -52
  220. package/lib/esm/data/ibi/data.ibi.js +0 -98
  221. package/lib/esm/data/ibi/data.ibi.spec.js +0 -66
  222. package/lib/esm/duration/duration.class.abstract.js +0 -36
  223. package/lib/esm/duration/duration.class.interface.js +0 -1
  224. package/lib/esm/errors/duration-exceeded-event-lib.error.js +0 -9
  225. package/lib/esm/errors/empty-event-sports-libs.error.js +0 -9
  226. package/lib/esm/errors/event-lib.error.js +0 -8
  227. package/lib/esm/errors/lib.error.js +0 -6
  228. package/lib/esm/errors/parsing-event-lib.error.js +0 -9
  229. package/lib/esm/events/adapters/exporters/exporter.gpx.js +0 -75
  230. package/lib/esm/events/adapters/exporters/exporter.interface.js +0 -1
  231. package/lib/esm/events/adapters/exporters/exporter.json.js +0 -20
  232. package/lib/esm/events/adapters/file-type.enum.js +0 -7
  233. package/lib/esm/events/adapters/importers/fit/importer.fit.ant-plus.device.names.js +0 -25
  234. package/lib/esm/events/adapters/importers/fit/importer.fit.coros.device.names.js +0 -5
  235. package/lib/esm/events/adapters/importers/fit/importer.fit.development.device.names.js +0 -4
  236. package/lib/esm/events/adapters/importers/fit/importer.fit.garmin.device.names.js +0 -462
  237. package/lib/esm/events/adapters/importers/fit/importer.fit.garmin.profile.data.js +0 -877
  238. package/lib/esm/events/adapters/importers/fit/importer.fit.garmin.profile.mapper.js +0 -106
  239. package/lib/esm/events/adapters/importers/fit/importer.fit.garmin.profile.mapper.spec.js +0 -32
  240. package/lib/esm/events/adapters/importers/fit/importer.fit.hammerhead.device.names.js +0 -4
  241. package/lib/esm/events/adapters/importers/fit/importer.fit.integration.spec.js +0 -44
  242. package/lib/esm/events/adapters/importers/fit/importer.fit.js +0 -978
  243. package/lib/esm/events/adapters/importers/fit/importer.fit.lezyne.device.names.js +0 -3
  244. package/lib/esm/events/adapters/importers/fit/importer.fit.magellan.device.names.js +0 -5
  245. package/lib/esm/events/adapters/importers/fit/importer.fit.mapper.js +0 -231
  246. package/lib/esm/events/adapters/importers/fit/importer.fit.saris.device.names.js +0 -3
  247. package/lib/esm/events/adapters/importers/fit/importer.fit.spec.js +0 -326
  248. package/lib/esm/events/adapters/importers/fit/importer.fit.srm.device.names.js +0 -7
  249. package/lib/esm/events/adapters/importers/fit/importer.fit.suunto.device.names.js +0 -16
  250. package/lib/esm/events/adapters/importers/fit/importer.fit.wahoo.device.names.js +0 -10
  251. package/lib/esm/events/adapters/importers/gpx/gx-parser.js +0 -36
  252. package/lib/esm/events/adapters/importers/gpx/importer.gpx.integration.spec.js +0 -44
  253. package/lib/esm/events/adapters/importers/gpx/importer.gpx.js +0 -102
  254. package/lib/esm/events/adapters/importers/gpx/importer.gpx.mapper.js +0 -142
  255. package/lib/esm/events/adapters/importers/gpx/importer.gpx.spec.js +0 -71
  256. package/lib/esm/events/adapters/importers/json/importer.json.js +0 -160
  257. package/lib/esm/events/adapters/importers/sample-info.interface.js +0 -1
  258. package/lib/esm/events/adapters/importers/suunto/importer.suunto.activity.ids.js +0 -85
  259. package/lib/esm/events/adapters/importers/suunto/importer.suunto.device.names.js +0 -26
  260. package/lib/esm/events/adapters/importers/suunto/importer.suunto.integration.spec.js +0 -44
  261. package/lib/esm/events/adapters/importers/suunto/importer.suunto.json.js +0 -717
  262. package/lib/esm/events/adapters/importers/suunto/importer.suunto.sml.js +0 -125
  263. package/lib/esm/events/adapters/importers/tcx/importer.tcx.integration.spec.js +0 -46
  264. package/lib/esm/events/adapters/importers/tcx/importer.tcx.js +0 -442
  265. package/lib/esm/events/adapters/importers/tcx/importer.tcx.mapper.js +0 -91
  266. package/lib/esm/events/adapters/importers/tcx/utils.tcx.js +0 -36
  267. package/lib/esm/events/event.interface.js +0 -1
  268. package/lib/esm/events/event.js +0 -123
  269. package/lib/esm/events/event.json.interface.js +0 -1
  270. package/lib/esm/events/event.spec.js +0 -51
  271. package/lib/esm/events/utilities/activity.utilities.js +0 -1841
  272. package/lib/esm/events/utilities/activity.utilities.spec.js +0 -373
  273. package/lib/esm/events/utilities/event.utilities.js +0 -57
  274. package/lib/esm/events/utilities/grade-calculator/grade-calculator.js +0 -121
  275. package/lib/esm/events/utilities/grade-calculator/grade-calculator.spec.js +0 -93
  276. package/lib/esm/events/utilities/grade-calculator/low-pass-filter.js +0 -86
  277. package/lib/esm/events/utilities/helpers.js +0 -162
  278. package/lib/esm/geodesy/adapters/adapter.interface.js +0 -1
  279. package/lib/esm/geodesy/adapters/geolib.adapter.js +0 -28
  280. package/lib/esm/id/id.abstract.class.js +0 -9
  281. package/lib/esm/id/id.class.interface.js +0 -1
  282. package/lib/esm/id/id.class.spec.js +0 -13
  283. package/lib/esm/intensity-zones/intensity-zones.interface.js +0 -1
  284. package/lib/esm/intensity-zones/intensity-zones.js +0 -29
  285. package/lib/esm/intensity-zones/intensity-zones.json.interface.js +0 -1
  286. package/lib/esm/intensity-zones/intensity-zones.spec.js +0 -30
  287. package/lib/esm/laps/lap.interface.js +0 -1
  288. package/lib/esm/laps/lap.js +0 -29
  289. package/lib/esm/laps/lap.json.interface.js +0 -1
  290. package/lib/esm/laps/lap.types.js +0 -52
  291. package/lib/esm/meta-data/event-meta-data.interface.js +0 -6
  292. package/lib/esm/meta-data/meta-data.js +0 -57
  293. package/lib/esm/meta-data/meta-data.json.interface.js +0 -1
  294. package/lib/esm/privacy/privacy.class.interface.js +0 -5
  295. package/lib/esm/serializable/serializable.class.interface.js +0 -1
  296. package/lib/esm/service-tokens/oauth1-service-token.interface.js +0 -1
  297. package/lib/esm/service-tokens/oauth2-service-token.interface.js +0 -1
  298. package/lib/esm/specs/activities-parsing.integration.spec.js +0 -1847
  299. package/lib/esm/specs/activity-duration-stream.integration.spec.js +0 -57
  300. package/lib/esm/specs/fixtures/streams/strava/rides/3171472783.json +0 -52534
  301. package/lib/esm/specs/fixtures/streams/strava/rides/3171487458.json +0 -78818
  302. package/lib/esm/specs/fixtures/streams/strava/rides/343080886.json +0 -105090
  303. package/lib/esm/specs/fixtures/streams/strava/rides/5910143591.json +0 -110711
  304. package/lib/esm/specs/fixtures/streams/strava/runs/2451375851.json +0 -74846
  305. package/lib/esm/specs/fixtures/streams/strava/runs/2709634581.json +0 -66817
  306. package/lib/esm/specs/fixtures/streams/strava/runs/3156040843.json +0 -17594
  307. package/lib/esm/specs/fixtures/streams/strava/runs/3182900697.json +0 -17322
  308. package/lib/esm/specs/fixtures/streams/strava/runs/3183465494.json +0 -20463
  309. package/lib/esm/specs/fixtures/streams/strava/runs/3183490558.json +0 -58202
  310. package/lib/esm/specs/spec-utils.js +0 -159
  311. package/lib/esm/specs/strava-streams-compliance.spec.js +0 -951
  312. package/lib/esm/stats/stats.class.abstract.js +0 -32
  313. package/lib/esm/stats/stats.class.interface.js +0 -1
  314. package/lib/esm/stats/stats.json.interface.js +0 -1
  315. package/lib/esm/streams/compressed.stream.interface.js +0 -12
  316. package/lib/esm/streams/ibi-stream.js +0 -43
  317. package/lib/esm/streams/low-pass.stream.filter.js +0 -9
  318. package/lib/esm/streams/stream.filter.interface.js +0 -1
  319. package/lib/esm/streams/stream.interface.js +0 -1
  320. package/lib/esm/streams/stream.js +0 -72
  321. package/lib/esm/streams/stream.spec.js +0 -168
  322. package/lib/esm/tiles/tile.settings.interface.js +0 -41
  323. package/lib/esm/users/settings/dashboard/user.dashboard.settings.interface.js +0 -13
  324. package/lib/esm/users/settings/user.app.settings.interface.js +0 -5
  325. package/lib/esm/users/settings/user.chart.settings.interface.js +0 -23
  326. package/lib/esm/users/settings/user.map.settings.interface.js +0 -22
  327. package/lib/esm/users/settings/user.my-tracks.settings.interface.js +0 -1
  328. package/lib/esm/users/settings/user.settings.interface.js +0 -1
  329. package/lib/esm/users/settings/user.stats-settings.interface.js +0 -1
  330. package/lib/esm/users/settings/user.summaries.settings.interface.js +0 -1
  331. package/lib/esm/users/settings/user.unit.settings.interface.js +0 -73
  332. package/lib/esm/users/user.account.privileges.interface.js +0 -1
  333. package/lib/esm/users/user.export-to-csv.settings.interface.js +0 -1
  334. package/lib/esm/users/user.interface.js +0 -1
  335. package/lib/esm/users/user.js +0 -38
  336. package/lib/esm/users/user.service.meta.interface.js +0 -1
@@ -1,1847 +0,0 @@
1
- import * as fs from 'fs';
2
- import { SportsLib } from '../index';
3
- import { DataHeartRate } from '../data/data.heart-rate';
4
- import { DataLongitudeDegrees } from '../data/data.longitude-degrees';
5
- import { DataLatitudeDegrees } from '../data/data.latitude-degrees';
6
- import { DataDistance } from '../data/data.distance';
7
- import { DataSpeed } from '../data/data.speed';
8
- import { DataCadence } from '../data/data.cadence';
9
- import { DataPower } from '../data/data.power';
10
- import { DataAltitude } from '../data/data.altitude';
11
- import { ActivityTypes } from '../activities/activity.types';
12
- import { DataAscent } from '../data/data.ascent';
13
- import { SpecUtils } from './spec-utils';
14
- import { DataTimerTime } from '../data/data.timer-time';
15
- import { DataPause } from '../data/data.pause';
16
- import { DataEnergy } from '../data/data.energy';
17
- import { DataHeartRateAvg } from '../data/data.heart-rate-avg';
18
- import { DataCadenceMax } from '../data/data.cadence-max';
19
- import { DataPowerAvg } from '../data/data.power-avg';
20
- import { DataCadenceAvg } from '../data/data.cadence-avg';
21
- import { DataSpeedAvg } from '../data/data.speed-avg';
22
- import { DataPowerMax } from '../data/data.power-max';
23
- import { DataDescent } from '../data/data.descent';
24
- import { DataHeartRateMax } from '../data/data.heart-rate-max';
25
- import { DataPoolLength } from '../data/data.pool-length';
26
- import { DataTotalCycles } from '../data/data-total-cycles';
27
- import { DataActiveLengths } from '../data/data-active-lengths';
28
- import { DataPaceAvg } from '../data/data.pace-avg';
29
- import { DataTemperatureAvg } from '../data/data.temperature-avg';
30
- import { DataMovingTime } from '../data/data.moving-time';
31
- import xmldom from '@xmldom/xmldom';
32
- import { DataGradeAdjustedPaceAvg } from '../data/data.grade-adjusted-pace-avg';
33
- import { DataActiveLap } from '../data/data-active-lap';
34
- import { DataSWOLF25m } from '../data/data.swolf-25m';
35
- import { DataSWOLF50m } from '../data/data.swolf-50m';
36
- import { DataLeftBalance } from '../data/data.left-balance';
37
- import { DataRightBalance } from '../data/data.right-balance';
38
- import { DataPowerTorqueEffectivenessLeft } from '../data/data.power-torque-effectiveness-left';
39
- import { DataPowerTorqueEffectivenessRight } from '../data/data.power-torque-effectiveness-right';
40
- import { DataPowerPedalSmoothnessRight } from '../data/data.power-pedal-smoothness-right';
41
- import { DataPowerPedalSmoothnessLeft } from '../data/data.power-pedal-smoothness-left';
42
- import { DataPowerNormalized } from '../data/data.power-normalized';
43
- import { DataPowerIntensityFactor } from '../data/data.power-intensity-factor';
44
- import { DataPowerTrainingStressScore } from '../data/data.power-training-stress-score';
45
- import { DataPowerWork } from '../data/data.power-work';
46
- import { DataCyclingStandingTime } from '../data/data.cycling-standing-time';
47
- import { DataCyclingSeatedTime } from '../data/data.cycling-seated-time';
48
- import { DataVerticalOscillation } from '../data/data.vertical-oscillation';
49
- import { DataVerticalRatio } from '../data/data.vertical-ratio';
50
- import { DataStanceTime } from '../data/data.stance-time';
51
- import { DataStanceTimeBalanceRight } from '../data/data-stance-time-balance-right';
52
- import { DataStanceTimeBalanceLeft } from '../data/data-stance-time-balance-left';
53
- import { DataAvgStrideLength } from '../data/data.avg-stride-length';
54
- import { DataAerobicTrainingEffect } from '../data/data-aerobic-training-effect';
55
- import { DataAnaerobicTrainingEffect } from '../data/data-anaerobic-training-effect';
56
- import { DataAltitudeSmooth } from '../data/data.altitude-smooth';
57
- import { DataGrade } from '../data/data.grade';
58
- import { ActivityParsingOptions } from '../activities/activity-parsing-options';
59
- import { standardDeviation } from '../events/utilities/helpers';
60
- describe('FIT/TCX/GPX activity parsing compliance', () => {
61
- const domParser = new xmldom.DOMParser();
62
- /* it('Template: should parse FIT activity file', done => {
63
- // Given FIT Source: https://connect.garmin.com/modern/activity/xxxxxxxx OR https://www.strava.com/activities/xxxxxxx (should be "public")
64
- const path = '/path/to/your/file.fit';
65
- const buffer = fs.readFileSync(path);
66
-
67
- // When
68
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
69
-
70
- // Then
71
- eventInterfacePromise.then((event: EventInterface) => {
72
- const activity = event.getFirstActivity();
73
- done();
74
- });
75
- });*/
76
- /* it('Template: should parse TCX activity file', done => {
77
- // Given TCX Source: https://connect.garmin.com/modern/activity/xxxxxxxx OR https://www.strava.com/activities/xxxxxxx (should be "public")
78
- const path = '/path/to/your/file.tcx';
79
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
80
-
81
- // When
82
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
83
-
84
- // Then
85
- eventInterfacePromise.then((event: EventInterface) => {
86
- const activity = event.getFirstActivity();
87
- done();
88
- });
89
- });*/
90
- /* it('Template: should parse GPX activity file', done => {
91
- // Given GPX Source: https://connect.garmin.com/modern/activity/xxxxxxxx OR https://www.strava.com/activities/xxxxxxx (should be "public")
92
- const path = '/path/to/your/file.gpx';
93
- const gpxString = fs.readFileSync(path).toString();
94
-
95
- // When
96
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
97
-
98
- // Then
99
- eventInterfacePromise.then((event: EventInterface) => {
100
- const activity = event.getFirstActivity();
101
- done();
102
- });
103
- });*/
104
- describe('Swimming', () => {
105
- describe('FIT', () => {
106
- it('should parse swimming pool FIT file (1)', done => {
107
- // Given FIT Source: https://connect.garmin.com/modern/activity/6688025408 OR https://www.strava.com/activities/4232464474
108
- const path = __dirname + '/fixtures/swim/fit/6688025408.fit';
109
- const buffer = fs.readFileSync(path);
110
- // When
111
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
112
- // Then
113
- eventInterfacePromise.then((event) => {
114
- const activity = event.getFirstActivity();
115
- expect(activity.creator.name).toEqual('Garmin Forerunner 935');
116
- expect(activity.creator.productId).toEqual(2691);
117
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
118
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
119
- const pauseTime = activity.getStat(DataPause.type).getValue();
120
- const elapsedTime = activity.getDuration().getValue();
121
- expect(activity.type).toEqual(ActivityTypes.Swimming);
122
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(2300);
123
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(458);
124
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(20);
125
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(23);
126
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(126);
127
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(146);
128
- expect(activity.getStat(DataPoolLength.type).getValue()).toEqual(50);
129
- expect(activity.getStat(DataActiveLengths.type).getValue()).toEqual(46);
130
- expect(activity.getStat(DataSWOLF25m.type).getValue()).toEqual(36.7);
131
- expect(activity.getStat(DataSWOLF50m.type).getValue()).toEqual(73.4);
132
- expect(activity.getStat(DataTotalCycles.type).getValue()).toEqual(806);
133
- const laps = activity.getLaps();
134
- expect(laps.length).toEqual(36);
135
- expect(laps[0].getStat(DataActiveLap.type).getValue()).toBeTruthy();
136
- expect(laps[1].getStat(DataActiveLap.type).getValue()).toBeFalsy();
137
- expect(laps[1].lapId).toEqual(2);
138
- expect(activity.hasStreamData(DataSpeed.type)).toBeTruthy();
139
- expect(activity.hasStreamData(DataHeartRate.type)).toBeTruthy();
140
- expect(activity.hasStreamData(DataCadence.type)).toBeTruthy();
141
- expect(activity.hasStreamData(DataDistance.type)).toBeTruthy();
142
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(activity.getStat(DataSpeedAvg.type).getValue()), '01:50');
143
- SpecUtils.assertNearEqualTime(movingTime, '44:06');
144
- SpecUtils.assertNearEqualTime(timerTime, '01:06:03');
145
- SpecUtils.assertNearEqualTime(elapsedTime, '01:06:23');
146
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
147
- done();
148
- }).catch((e) => done(e));
149
- });
150
- it('should parse swimming pool FIT file (2)', done => {
151
- // Given FIT Source: https://connect.garmin.com/modern/activity/6021532030 OR https://www.strava.com/activities/5258304128
152
- const path = __dirname + '/fixtures/swim/fit/6021532030.fit';
153
- const buffer = fs.readFileSync(path);
154
- // When
155
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
156
- // Then
157
- eventInterfacePromise.then((event) => {
158
- const activity = event.getFirstActivity();
159
- expect(activity.type).toEqual(ActivityTypes.Swimming);
160
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(780);
161
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(235);
162
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(26);
163
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(28);
164
- expect(activity.getStat(DataPoolLength.type).getValue()).toEqual(20);
165
- expect(activity.getStat(DataActiveLengths.type).getValue()).toEqual(39);
166
- expect(activity.getStat(DataSWOLF25m.type).getValue()).toEqual(63.9);
167
- expect(activity.getStat(DataSWOLF50m.type).getValue()).toEqual(127.7);
168
- expect(activity.getStat(DataTotalCycles.type).getValue()).toEqual(596);
169
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(activity.getStat(DataSpeedAvg.type).getValue()), '02:58');
170
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
171
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
172
- const pauseTime = activity.getStat(DataPause.type).getValue();
173
- const elapsedTime = activity.getDuration().getValue();
174
- SpecUtils.assertNearEqualTime(movingTime, '23:09');
175
- SpecUtils.assertNearEqualTime(timerTime, '23:09');
176
- SpecUtils.assertNearEqualTime(elapsedTime, '23:31');
177
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
178
- done();
179
- }).catch((e) => done(e));
180
- });
181
- it('should parse swimming pool FIT file (3)', done => {
182
- // Given FIT Source: https://connect.garmin.com/modern/activity/6860712481 OR https://www.strava.com/activities/5376106733
183
- const path = __dirname + '/fixtures/swim/fit/6860712481.fit';
184
- const buffer = fs.readFileSync(path);
185
- // When
186
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
187
- // Then
188
- eventInterfacePromise.then((event) => {
189
- const activity = event.getFirstActivity();
190
- expect(activity.type).toEqual(ActivityTypes.Swimming);
191
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(2000);
192
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(401);
193
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(28);
194
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(131);
195
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(157);
196
- expect(activity.getStat(DataPoolLength.type).getValue()).toEqual(25);
197
- expect(activity.getStat(DataActiveLengths.type).getValue()).toEqual(80);
198
- expect(activity.getStat(DataSWOLF25m.type).getValue()).toEqual(46.1);
199
- expect(activity.getStat(DataSWOLF50m.type).getValue()).toEqual(92.2);
200
- expect(activity.getStat(DataTotalCycles.type).getValue()).toEqual(984);
201
- // TODO Check streams based on laps for swims performed in a pool
202
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(activity.getStat(DataSpeedAvg.type).getValue()), '02:06');
203
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
204
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
205
- const pauseTime = activity.getStat(DataPause.type).getValue();
206
- const elapsedTime = activity.getDuration().getValue();
207
- SpecUtils.assertNearEqualTime(movingTime, '41:25');
208
- SpecUtils.assertNearEqualTime(timerTime, '47:27');
209
- SpecUtils.assertNearEqualTime(elapsedTime, '49:43');
210
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
211
- done();
212
- }).catch((e) => done(e));
213
- });
214
- it('should parse swimming pool FIT file (4)', done => {
215
- // Given FIT Source: https://connect.garmin.com/modern/activity/7617306288 OR https://www.strava.com/activities/6076695527
216
- const path = __dirname + '/fixtures/swim/fit/7617306288.fit';
217
- const buffer = fs.readFileSync(path);
218
- // When
219
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
220
- // Then
221
- eventInterfacePromise.then((event) => {
222
- const activity = event.getFirstActivity();
223
- expect(activity.type).toEqual(ActivityTypes.Swimming);
224
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(150);
225
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(activity.getStat(DataSpeedAvg.type).getValue()), '01:54');
226
- expect(activity.getLaps().length).toEqual(6);
227
- done();
228
- }).catch((e) => done(e));
229
- });
230
- it('should parse swimming open water FIT file (1)', done => {
231
- // Given https://connect.garmin.com/modern/activity/6788312639/1 OR https://www.strava.com/activities/5305763421
232
- const path = __dirname + '/fixtures/swim/fit/6788312639-1.fit';
233
- const buffer = fs.readFileSync(path);
234
- // When
235
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
236
- // Then
237
- eventInterfacePromise.then((event) => {
238
- const activity = event.getFirstActivity();
239
- expect(activity.type).toEqual(ActivityTypes.OpenWaterSwimming);
240
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(1505.03);
241
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(403);
242
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(32);
243
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(48);
244
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(158);
245
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(170);
246
- expect(activity.getStat(DataTotalCycles.type).getValue()).toEqual(993);
247
- expect(activity.getStat(DataSWOLF25m.type).getValue()).toEqual(47.5);
248
- expect(activity.getStat(DataSWOLF50m.type).getValue()).toEqual(95);
249
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(activity.getStat(DataSpeedAvg.type).getValue()), '02:04');
250
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
251
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
252
- const pauseTime = activity.getStat(DataPause.type).getValue();
253
- const elapsedTime = activity.getDuration().getValue();
254
- SpecUtils.assertNearEqualTime(movingTime, '24:28');
255
- SpecUtils.assertNearEqualTime(timerTime, '31:06');
256
- SpecUtils.assertNearEqualTime(elapsedTime, '31:06');
257
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
258
- done();
259
- }).catch((e) => done(e));
260
- });
261
- });
262
- describe('TCX', () => {
263
- it('should parse swimming pool TCX file (1)', done => {
264
- // Given TCX Source: https://connect.garmin.com/modern/activity/6832570127 OR https://www.strava.com/activities/5347012220
265
- // Given FIT Source: https://connect.garmin.com/modern/activity/6688025408 OR https://www.strava.com/activities/4232464474
266
- const path = __dirname + '/fixtures/swim/tcx/6688025408.tcx';
267
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
268
- // When
269
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
270
- // Then
271
- eventInterfacePromise.then((event) => {
272
- const activity = event.getFirstActivity();
273
- // expect(activity.type).toEqual(ActivityTypes.Swimming); // TODO To be auto-detected by sports-data-science library (work in progress)
274
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(2300);
275
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(458);
276
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(119);
277
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(146);
278
- const laps = activity.getLaps();
279
- expect(laps.length).toEqual(36);
280
- expect(laps[0].getStat(DataActiveLap.type).getValue()).toBeTruthy();
281
- expect(laps[1].getStat(DataActiveLap.type).getValue()).toBeFalsy();
282
- expect(laps[1].lapId).toEqual(2);
283
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(activity.getStat(DataSpeedAvg.type).getValue()), '01:50');
284
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
285
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
286
- const pauseTime = activity.getStat(DataPause.type).getValue();
287
- const elapsedTime = activity.getDuration().getValue();
288
- SpecUtils.assertNearEqualTime(movingTime, '44:06');
289
- SpecUtils.assertNearEqualTime(timerTime, '01:06:03');
290
- SpecUtils.assertNearEqualTime(elapsedTime, '01:06:23');
291
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime);
292
- done();
293
- }).catch((e) => done(e));
294
- });
295
- it('should parse swimming pool TCX file (2)', done => {
296
- // Given TCX Source: https://connect.garmin.com/modern/activity/6861441616 or https://www.strava.com/activities/5378130384
297
- // Given FIT Source: https://connect.garmin.com/modern/activity/6860712481 OR https://www.strava.com/activities/5376106733
298
- const path = __dirname + '/fixtures/swim/tcx/6860712481.tcx';
299
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
300
- // When
301
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
302
- // Then
303
- eventInterfacePromise.then((event) => {
304
- const activity = event.getFirstActivity();
305
- // expect(activity.type).toEqual(ActivityTypes.Swimming); // TODO To be auto-detected by sports-data-science library (work in progress)
306
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(2000);
307
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(401);
308
- expect(activity.getStat(DataTotalCycles.type).getValue()).toEqual(984);
309
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(128);
310
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(156);
311
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(activity.getStat(DataSpeedAvg.type).getValue()), '02:05');
312
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
313
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
314
- const pauseTime = activity.getStat(DataPause.type).getValue();
315
- const elapsedTime = activity.getDuration().getValue();
316
- SpecUtils.assertNearEqualTime(movingTime, '41:25');
317
- SpecUtils.assertNearEqualTime(timerTime, '47:27');
318
- SpecUtils.assertNearEqualTime(elapsedTime, '47:27');
319
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
320
- done();
321
- }).catch((e) => done(e));
322
- });
323
- });
324
- describe('GPX', () => {
325
- it('should parse swimming open water GPX file (1)', done => {
326
- // Given GPX Source: https://connect.garmin.com/modern/activity/6867388194 OR https://www.strava.com/activities/5382390985
327
- // Given FIT Source: https://connect.garmin.com/modern/activity/4623204522/1 OR https://www.strava.com/activities/5352030147
328
- const path = __dirname + '/fixtures/swim/gpx/4623204522-1.gpx';
329
- const gpxString = fs.readFileSync(path).toString();
330
- // When
331
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
332
- // Then
333
- eventInterfacePromise.then((event) => {
334
- // Swim
335
- const swimActivity = event.getFirstActivity();
336
- // expect(swimActivity.type).toEqual(ActivityTypes.OpenWaterSwimming); // TODO To be auto-detected by sports-data-science library (work in progress)
337
- expect(swimActivity.getStreamData(DataSpeed.type).length).toEqual(3689);
338
- expect(swimActivity.startDate.toISOString()).toEqual('2018-10-13T17:05:01.000Z');
339
- expect(swimActivity.endDate.toISOString()).toEqual('2018-10-13T18:06:29.000Z');
340
- expect(swimActivity.getStat(DataDistance.type).getValue()).toBeCloseTo(3869, 0);
341
- expect(swimActivity.getStat(DataCadenceAvg.type).getValue()).toEqual(36);
342
- expect(swimActivity.getStat(DataCadenceMax.type).getValue()).toEqual(39);
343
- expect(swimActivity.getStat(DataHeartRateAvg.type).getValue()).toEqual(74);
344
- expect(swimActivity.getStat(DataHeartRateMax.type).getValue()).toEqual(115);
345
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(swimActivity.getStat(DataSpeedAvg.type).getValue()), '01:31', 2);
346
- // Verifying time data
347
- const movingTime = swimActivity.getStat(DataMovingTime.type).getValue();
348
- const timerTime = swimActivity.getStat(DataTimerTime.type).getValue();
349
- const pauseTime = swimActivity.getStat(DataPause.type).getValue();
350
- const elapsedTime = swimActivity.getDuration().getValue();
351
- SpecUtils.assertNearEqualTime(movingTime, '01:00:35', 1);
352
- SpecUtils.assertNearEqualTime(timerTime, '01:01:29');
353
- SpecUtils.assertNearEqualTime(elapsedTime, '01:01:29');
354
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
355
- done();
356
- }).catch((e) => done(e));
357
- });
358
- it('should parse swimming open water GPX file (2)', done => {
359
- // Given GPX Source: https://connect.garmin.com/modern/activity/6867446668 OR https://www.strava.com/activities/5382426315
360
- // Given FIT Source: https://connect.garmin.com/modern/activity/6090674952 OR https://www.strava.com/activities/5366783958
361
- const path = __dirname + '/fixtures/swim/gpx/6090674952.gpx';
362
- const gpxString = fs.readFileSync(path).toString();
363
- // When
364
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
365
- // Then
366
- eventInterfacePromise.then((event) => {
367
- const swimActivity = event.getFirstActivity();
368
- // expect(swimActivity.type).toEqual(ActivityTypes.OpenWaterSwimming); // TODO To be auto-detected by sports-data-science library (work in progress)
369
- expect(swimActivity.startDate.toISOString()).toEqual('2021-01-04T16:22:18.000Z');
370
- expect(swimActivity.endDate.toISOString()).toEqual('2021-01-04T17:37:05.000Z');
371
- expect(swimActivity.getStat(DataDistance.type).getValue()).toBeCloseTo(2537, 0);
372
- expect(swimActivity.getStat(DataHeartRateAvg.type).getValue()).toEqual(145);
373
- expect(swimActivity.getStat(DataHeartRateMax.type).getValue()).toEqual(184);
374
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(swimActivity.getStat(DataSpeedAvg.type).getValue()), '02:29');
375
- // Verifying time data
376
- const movingTime = swimActivity.getStat(DataMovingTime.type).getValue();
377
- const timerTime = swimActivity.getStat(DataTimerTime.type).getValue();
378
- const pauseTime = swimActivity.getStat(DataPause.type).getValue();
379
- const elapsedTime = swimActivity.getDuration().getValue();
380
- SpecUtils.assertNearEqualTime(movingTime, '55:43', 1);
381
- SpecUtils.assertNearEqualTime(timerTime, '01:14:47');
382
- SpecUtils.assertNearEqualTime(elapsedTime, '01:14:47');
383
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
384
- done();
385
- }).catch((e) => done(e));
386
- });
387
- });
388
- });
389
- describe('Running', () => {
390
- describe('FIT', () => {
391
- it('should parse running FIT file (1)', done => {
392
- // Given FIT Source: https://connect.garmin.com/modern/activity/2067489619 OR https://www.strava.com/activities/1221143311
393
- const path = __dirname + '/fixtures/runs/fit/2067489619.fit';
394
- const buffer = fs.readFileSync(path);
395
- // When
396
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
397
- // Then
398
- eventInterfacePromise.then((event) => {
399
- const activity = event.getFirstActivity();
400
- expect(activity.creator.name).toEqual('Garmin VivoActive HR');
401
- expect(activity.creator.manufacturer).toEqual('garmin');
402
- expect(activity.type).toEqual(ActivityTypes.Running);
403
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(4489.39);
404
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(58);
405
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(88);
406
- expect(activity.getStat(DataTotalCycles.type).getValue()).toEqual(2782);
407
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(130);
408
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(179);
409
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
410
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '10:28', 1);
411
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '09:11', 1);
412
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
413
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
414
- const pauseTime = activity.getStat(DataPause.type).getValue();
415
- const elapsedTime = activity.getDuration().getValue();
416
- SpecUtils.assertNearEqualTime(movingTime, '45:42');
417
- SpecUtils.assertNearEqualTime(timerTime, '47:00');
418
- SpecUtils.assertNearEqualTime(elapsedTime, '47:04');
419
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
420
- done();
421
- }).catch((e) => done(e));
422
- });
423
- it('should parse running FIT file (2)', done => {
424
- // Given FIT Source: https://connect.garmin.com/modern/activity/6782987395 OR https://www.strava.com/activities/2451375851
425
- const path = __dirname + '/fixtures/runs/fit/6782987395.fit';
426
- const buffer = fs.readFileSync(path);
427
- // When
428
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
429
- // Then
430
- eventInterfacePromise.then((event) => {
431
- const activity = event.getFirstActivity();
432
- expect(activity.type).toEqual(ActivityTypes.Running);
433
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(14004.85);
434
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(79);
435
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(111);
436
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(137);
437
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(167);
438
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
439
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '05:56', 1);
440
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '05:19', 1);
441
- const laps = activity.getLaps();
442
- expect(laps.length).toEqual(2);
443
- expect(laps[0].getStat(DataActiveLap.type).getValue()).toBeTruthy();
444
- expect(laps[1].getStat(DataActiveLap.type).getValue()).toBeTruthy();
445
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
446
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
447
- const pauseTime = activity.getStat(DataPause.type).getValue();
448
- const elapsedTime = activity.getDuration().getValue();
449
- SpecUtils.assertNearEqualTime(movingTime, '01:19:37');
450
- SpecUtils.assertNearEqualTime(timerTime, '01:23:09');
451
- SpecUtils.assertNearEqualTime(elapsedTime, '01:23:09');
452
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
453
- done();
454
- }).catch((e) => done(e));
455
- });
456
- it('should parse running FIT file (Suunto export) (3)', done => {
457
- // Given FIT Source (Suunto export): https://connect.garmin.com/modern/activity/6909950168 OR https://www.strava.com/activities/5423646653
458
- const path = __dirname + '/fixtures/runs/fit/6909950168.fit';
459
- const buffer = fs.readFileSync(path);
460
- // When
461
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
462
- // Then
463
- eventInterfacePromise.then((event) => {
464
- const activity = event.getFirstActivity();
465
- expect(activity.type).toEqual(ActivityTypes.TrailRunning);
466
- expect(activity.creator.name).toEqual('Suunto 9');
467
- expect(activity.creator.productId).toEqual(34);
468
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(6458);
469
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(487);
470
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(90);
471
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(94);
472
- expect(activity.getStat(DataPowerAvg.type).getValue()).toEqual(227);
473
- expect(activity.getStat(DataPowerMax.type).getValue()).toEqual(294);
474
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(148);
475
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(161);
476
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
477
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '05:35', 1);
478
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '05:34', 1);
479
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
480
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
481
- const pauseTime = activity.getStat(DataPause.type).getValue();
482
- const elapsedTime = activity.getDuration().getValue();
483
- SpecUtils.assertNearEqualTime(movingTime, '35:42');
484
- SpecUtils.assertNearEqualTime(timerTime, '36:01');
485
- SpecUtils.assertNearEqualTime(elapsedTime, '36:36');
486
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
487
- done();
488
- }).catch((e) => done(e));
489
- });
490
- it('should parse running FIT file (Suunto export) (4)', done => {
491
- // Given FIT Source (Suunto export): https://connect.garmin.com/modern/activity/6910052863 OR https://www.strava.com/activities/5423660493
492
- const path = __dirname + '/fixtures/runs/fit/6910052863.fit';
493
- const buffer = fs.readFileSync(path);
494
- // When
495
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
496
- // Then
497
- eventInterfacePromise.then((event) => {
498
- const activity = event.getFirstActivity();
499
- expect(activity.type).toEqual(ActivityTypes.TrailRunning);
500
- expect(activity.creator.name).toEqual('Suunto 9');
501
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(8225);
502
- expect(activity.getStat(DataAscent.type).getValue()).toEqual(1817);
503
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(2540);
504
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(44);
505
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(96);
506
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(164);
507
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(174);
508
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
509
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '19:20', 1);
510
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '07:32', 1);
511
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
512
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
513
- const pauseTime = activity.getStat(DataPause.type).getValue();
514
- const elapsedTime = activity.getDuration().getValue();
515
- SpecUtils.assertNearEqualTime(movingTime, '02:35:40');
516
- SpecUtils.assertNearEqualTime(timerTime, '02:39:03');
517
- SpecUtils.assertNearEqualTime(elapsedTime, '02:40:02');
518
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
519
- done();
520
- }).catch((e) => done(e));
521
- });
522
- it('should parse running FIT file (Suunto export) (5)', done => {
523
- // Given FIT Source (Suunto export): https://connect.garmin.com/modern/activity/6914448270 OR https://www.strava.com/activities/5427988571
524
- const path = __dirname + '/fixtures/runs/fit/6914448270.fit';
525
- const buffer = fs.readFileSync(path);
526
- // When
527
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
528
- // Then
529
- eventInterfacePromise.then((event) => {
530
- const activity = event.getFirstActivity();
531
- expect(activity.type).toEqual(ActivityTypes.Running);
532
- expect(activity.creator.name).toEqual('Suunto 9 Baroless');
533
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(49897);
534
- expect(activity.getStat(DataAscent.type).getValue()).toEqual(1063);
535
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(4445);
536
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(74);
537
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(119);
538
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
539
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '06:49', 1);
540
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '06:20', 1);
541
- const movingTime = activity.getStat(DataMovingTime.type).getValue(); // TODO If moving time unknown or INVALID loop on all records in activity utils
542
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
543
- const pauseTime = activity.getStat(DataPause.type).getValue();
544
- const elapsedTime = activity.getDuration().getValue();
545
- SpecUtils.assertNearEqualTime(movingTime, '05:28:14');
546
- SpecUtils.assertNearEqualTime(timerTime, '05:40:19');
547
- SpecUtils.assertNearEqualTime(elapsedTime, '05:40:19');
548
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
549
- done();
550
- }).catch((e) => done(e));
551
- });
552
- it('should parse running FIT file (Suunto export) (6)', done => {
553
- // Given FIT Source (Suunto export): https://connect.garmin.com/modern/activity/6914538454 OR https://www.strava.com/activities/5428064152
554
- const path = __dirname + '/fixtures/runs/fit/6914538454.fit';
555
- const buffer = fs.readFileSync(path);
556
- // When
557
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
558
- // Then
559
- eventInterfacePromise.then((event) => {
560
- const activity = event.getFirstActivity();
561
- expect(activity.type).toEqual(ActivityTypes.Running);
562
- expect(activity.creator.name).toEqual('Suunto 9 Baroless');
563
- expect(activity.creator.manufacturer).toEqual('suunto');
564
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(4330);
565
- expect(activity.getStat(DataAscent.type).getValue()).toEqual(0);
566
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(354);
567
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(87);
568
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(109);
569
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
570
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '04:52', 1);
571
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
572
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
573
- const pauseTime = activity.getStat(DataPause.type).getValue();
574
- const elapsedTime = activity.getDuration().getValue();
575
- SpecUtils.assertNearEqualTime(movingTime, '18:51');
576
- SpecUtils.assertNearEqualTime(timerTime, '21:04');
577
- SpecUtils.assertNearEqualTime(elapsedTime, '21:04');
578
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
579
- done();
580
- }).catch((e) => done(e));
581
- });
582
- it('should parse running FIT file (Coros export) (7)', done => {
583
- // Given FIT Source (Coros export): https://connect.garmin.com/modern/activity/6916663933 OR https://www.strava.com/activities/5429996380
584
- const path = __dirname + '/fixtures/runs/fit/6916663933.fit';
585
- const buffer = fs.readFileSync(path);
586
- // When
587
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
588
- // Then
589
- eventInterfacePromise.then((event) => {
590
- const activity = event.getFirstActivity();
591
- expect(activity.type).toEqual(ActivityTypes.Running);
592
- expect(activity.creator.name).toEqual('Coros APEX Pro');
593
- expect(activity.creator.productId).toEqual(841);
594
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(10743.64);
595
- expect(activity.getStat(DataAscent.type).getValue()).toEqual(142);
596
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(685);
597
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(92);
598
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(106);
599
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(160);
600
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(173);
601
- expect(activity.getStat(DataPowerAvg.type).getValue()).toEqual(332);
602
- expect(activity.getStat(DataPowerMax.type).getValue()).toEqual(518);
603
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
604
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '04:31', 1);
605
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '04:24', 1);
606
- expect(activity.getStat(DataStanceTimeBalanceLeft.type).getValue()).toEqual(49.14);
607
- expect(activity.getStat(DataStanceTimeBalanceRight.type).getValue()).toEqual(50.86);
608
- expect(activity.getStat(DataStanceTime.type).getValue()).toEqual(206);
609
- expect(activity.getStat(DataVerticalOscillation.type).getValue()).toEqual(94);
610
- expect(activity.getStat(DataVerticalRatio.type).getValue()).toEqual(7.9);
611
- expect(activity.getStat(DataAvgStrideLength.type).getValue()).toEqual(1.2);
612
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
613
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
614
- const pauseTime = activity.getStat(DataPause.type).getValue();
615
- const elapsedTime = activity.getDuration().getValue();
616
- SpecUtils.assertNearEqualTime(movingTime, '48:35');
617
- SpecUtils.assertNearEqualTime(timerTime, '48:42');
618
- SpecUtils.assertNearEqualTime(elapsedTime, '48:42');
619
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
620
- done();
621
- }).catch((e) => done(e));
622
- });
623
- it('should parse running FIT file (Coros export) (8)', done => {
624
- // Given FIT Source (Coros export): https://connect.garmin.com/modern/activity/6916728382 OR https://www.strava.com/activities/5430055225
625
- const path = __dirname + '/fixtures/runs/fit/6916728382.fit';
626
- const buffer = fs.readFileSync(path);
627
- // When
628
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
629
- // Then
630
- eventInterfacePromise.then((event) => {
631
- const activity = event.getFirstActivity();
632
- expect(activity.type).toEqual(ActivityTypes.Running);
633
- expect(activity.creator.name).toEqual('Coros APEX Pro');
634
- expect(activity.creator.manufacturer).toEqual('coros');
635
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(21524.3);
636
- expect(activity.getStat(DataAscent.type).getValue()).toEqual(539);
637
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(1661);
638
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(71);
639
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(88);
640
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(131);
641
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(164);
642
- expect(activity.getStat(DataTemperatureAvg.type).getValue()).toEqual(22);
643
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
644
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '07:31', 1);
645
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
646
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
647
- const pauseTime = activity.getStat(DataPause.type).getValue();
648
- const elapsedTime = activity.getDuration().getValue();
649
- SpecUtils.assertNearEqualTime(movingTime, '02:39:59');
650
- SpecUtils.assertNearEqualTime(timerTime, '02:41:39');
651
- SpecUtils.assertNearEqualTime(elapsedTime, '02:41:39');
652
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
653
- done();
654
- }).catch((e) => done(e));
655
- });
656
- it('should parse running treadmill FIT file (1)', done => {
657
- // Given FIT Source: https://connect.garmin.com/modern/activity/6860622783 or https://www.strava.com/activities/5375834427
658
- const path = __dirname + '/fixtures/runs/fit/6860622783.fit';
659
- const buffer = fs.readFileSync(path);
660
- // When
661
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
662
- // Then
663
- eventInterfacePromise.then((event) => {
664
- const activity = event.getFirstActivity();
665
- expect(activity.type).toEqual(ActivityTypes.Treadmill);
666
- expect(activity.hasPowerMeter()).toBeTruthy();
667
- expect(activity.isTrainer()).toBeTruthy();
668
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(10630.37);
669
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(82);
670
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(128);
671
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(145);
672
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(177);
673
- expect(activity.getStat(DataStanceTimeBalanceLeft.type).getValue()).toEqual(49.91);
674
- expect(activity.getStat(DataStanceTimeBalanceRight.type).getValue()).toEqual(50.09);
675
- expect(activity.getStat(DataStanceTime.type).getValue()).toEqual(271.3);
676
- expect(activity.getStat(DataVerticalOscillation.type).getValue()).toEqual(97.2);
677
- expect(activity.getStat(DataVerticalRatio.type).getValue()).toEqual(9.57);
678
- expect(activity.getStat(DataAvgStrideLength.type).getValue()).toEqual(1.04);
679
- expect(activity.getStat(DataTotalCycles.type).getValue()).toEqual(4242);
680
- expect(activity.getStat(DataAerobicTrainingEffect.type).getValue()).toEqual(2.2);
681
- expect(activity.getStat(DataAnaerobicTrainingEffect.type).getValue()).toEqual(1.8);
682
- expect(activity.getStat(DataPowerWork.type).getValue()).toEqual(692);
683
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '04:51', 1);
684
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
685
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
686
- const pauseTime = activity.getStat(DataPause.type).getValue();
687
- const elapsedTime = activity.getDuration().getValue();
688
- SpecUtils.assertNearEqualTime(movingTime, '48:43');
689
- SpecUtils.assertNearEqualTime(timerTime, '51:38');
690
- SpecUtils.assertNearEqualTime(elapsedTime, '01:02:44');
691
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
692
- done();
693
- }).catch((e) => done(e));
694
- });
695
- });
696
- describe('TCX', () => {
697
- it('should parse running TCX file (1)', done => {
698
- // Given Recorded with "Strava Android App" => https://connect.garmin.com/modern/activity/1604524853 OR https://www.strava.com/activities/708752345
699
- const path = __dirname + '/fixtures/runs/tcx/1604524853.tcx';
700
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
701
- // When
702
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
703
- // Then
704
- eventInterfacePromise.then((event) => {
705
- const activity = event.getFirstActivity();
706
- expect(activity.type).toEqual(ActivityTypes.run);
707
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '09:15', 1);
708
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '07:07', 1);
709
- SpecUtils.assertEqual(event.getFirstActivity().getStat(DataAscent.type).getValue(), 432);
710
- SpecUtils.assertEqual(event.getFirstActivity().getStat(DataDescent.type).getValue(), 440);
711
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(6106.6);
712
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(69);
713
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(99);
714
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(158);
715
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(191);
716
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
717
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
718
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
719
- const pauseTime = activity.getStat(DataPause.type).getValue();
720
- const elapsedTime = activity.getDuration().getValue();
721
- SpecUtils.assertNearEqualTime(movingTime, '58:59', 3);
722
- SpecUtils.assertNearEqualTime(timerTime, '01:07:47');
723
- SpecUtils.assertNearEqualTime(elapsedTime, '01:07:47');
724
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
725
- done();
726
- }).catch((e) => done(e));
727
- });
728
- it('should parse running TCX file (2)', done => {
729
- // Given TCX Source: https://connect.garmin.com/modern/activity/6851149716 OR https://www.strava.com/activities/5366592367
730
- // Given FIT Source: https://connect.garmin.com/modern/activity/6782987395 OR https://www.strava.com/activities/2451375851
731
- const path = __dirname + '/fixtures/runs/tcx/6782987395.tcx';
732
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
733
- // When
734
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
735
- // Then
736
- eventInterfacePromise.then((event) => {
737
- const activity = event.getFirstActivity();
738
- expect(activity.type).toEqual(ActivityTypes.run);
739
- expect(activity.creator.name).toEqual('Forerunner 945');
740
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '05:41');
741
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '05:19', 1);
742
- SpecUtils.assertEqual(activity.getStat(DataAscent.type).getValue(), 363);
743
- SpecUtils.assertEqual(activity.getStat(DataDescent.type).getValue(), 386);
744
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(14004.85);
745
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(982);
746
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(80);
747
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(111);
748
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(137);
749
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(167);
750
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
751
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
752
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
753
- const pauseTime = activity.getStat(DataPause.type).getValue();
754
- const elapsedTime = activity.getDuration().getValue();
755
- SpecUtils.assertNearEqualTime(movingTime, '01:19:38');
756
- SpecUtils.assertNearEqualTime(timerTime, '01:23:09');
757
- SpecUtils.assertNearEqualTime(elapsedTime, '01:23:09');
758
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
759
- done();
760
- }).catch((e) => done(e));
761
- });
762
- it('should parse running TCX file (3)', done => {
763
- // Given TCX Source: https://connect.garmin.com/modern/activity/6860622916 or https://www.strava.com/activities/5375754773
764
- const path = __dirname + '/fixtures/runs/tcx/6860622916.tcx';
765
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
766
- // When
767
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
768
- // Then
769
- eventInterfacePromise.then((event) => {
770
- const activity = event.getFirstActivity();
771
- expect(activity.type).toEqual(ActivityTypes.run);
772
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '04:25');
773
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '04:24');
774
- SpecUtils.assertEqual(activity.getStat(DataAscent.type).getValue(), 85);
775
- SpecUtils.assertEqual(activity.getStat(DataDescent.type).getValue(), 74);
776
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(13973.09);
777
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(739);
778
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(89);
779
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(98);
780
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(143);
781
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(168);
782
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
783
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
784
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
785
- const pauseTime = activity.getStat(DataPause.type).getValue();
786
- const elapsedTime = activity.getDuration().getValue();
787
- SpecUtils.assertNearEqualTime(movingTime, '01:02:17');
788
- SpecUtils.assertNearEqualTime(timerTime, '01:02:17');
789
- SpecUtils.assertNearEqualTime(elapsedTime, '01:02:17');
790
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
791
- done();
792
- }).catch((e) => done(e));
793
- });
794
- it('should parse running TCX file (4)', done => {
795
- // Given TCX Source: (garmin connect upload impossible) or https://www.strava.com/activities/6281425038
796
- const path = __dirname + '/fixtures/runs/tcx/6281425038.tcx';
797
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
798
- // When
799
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
800
- // Then
801
- eventInterfacePromise.then((event) => {
802
- const activity = event.getFirstActivity();
803
- expect(activity.type).toEqual(ActivityTypes.run);
804
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '06:19');
805
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '05:58');
806
- const laps = activity.getLaps();
807
- expect(laps.length).toEqual(5);
808
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
809
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
810
- const pauseTime = activity.getStat(DataPause.type).getValue();
811
- const elapsedTime = activity.getDuration().getValue();
812
- SpecUtils.assertNearEqualTime(movingTime, '25:45');
813
- SpecUtils.assertNearEqualTime(timerTime, '25:45');
814
- SpecUtils.assertNearEqualTime(elapsedTime, '36:02');
815
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
816
- done();
817
- }).catch((e) => done(e));
818
- });
819
- it('should parse running treadmill TCX file (3)', done => {
820
- // Given FIT Source: https://connect.garmin.com/modern/activity/6860622783 or https://www.strava.com/activities/5375834427
821
- const path = __dirname + '/fixtures/runs/tcx/6860622783.tcx';
822
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
823
- // When
824
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
825
- // Then
826
- eventInterfacePromise.then((event) => {
827
- const activity = event.getFirstActivity();
828
- expect(activity.type).toEqual(ActivityTypes.IndoorRunning);
829
- expect(activity.isTrainer()).toBeTruthy();
830
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(10630.37);
831
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(82);
832
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(128);
833
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(145);
834
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(177);
835
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '04:51', 1);
836
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
837
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
838
- const pauseTime = activity.getStat(DataPause.type).getValue();
839
- const elapsedTime = activity.getDuration().getValue();
840
- SpecUtils.assertNearEqualTime(movingTime, '48:43');
841
- SpecUtils.assertNearEqualTime(timerTime, '51:38');
842
- SpecUtils.assertNearEqualTime(elapsedTime, '01:02:44');
843
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
844
- done();
845
- }).catch((e) => done(e));
846
- });
847
- });
848
- describe('GPX', () => {
849
- it('should parse running GPX file (1)', done => {
850
- // Given GPX Source: https://connect.garmin.com/modern/activity/6870534840 OR https://www.strava.com/activities/5385528846
851
- // Given FIT Source: https://connect.garmin.com/modern/activity/2067489619 OR https://www.strava.com/activities/1221143311
852
- const path = __dirname + '/fixtures/runs/gpx/2067489619.gpx';
853
- const gpxString = fs.readFileSync(path).toString();
854
- // When
855
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
856
- // Then
857
- eventInterfacePromise.then((event) => {
858
- // Swim
859
- const activity = event.getFirstActivity();
860
- expect(activity.type).toEqual(ActivityTypes.Running);
861
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '09:18', 1);
862
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '09:18', 1);
863
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(4400, 0);
864
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(35, 0);
865
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(67);
866
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(88);
867
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(134);
868
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(178);
869
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
870
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
871
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
872
- const pauseTime = activity.getStat(DataPause.type).getValue();
873
- const elapsedTime = activity.getDuration().getValue();
874
- SpecUtils.assertNearEqualTime(movingTime, '44:48');
875
- SpecUtils.assertNearEqualTime(timerTime, '47:00');
876
- SpecUtils.assertNearEqualTime(elapsedTime, '47:04');
877
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
878
- done();
879
- }).catch((e) => done(e));
880
- });
881
- it('should parse running GPX file (2)', done => {
882
- // Given GPX Source: https://connect.garmin.com/modern/activity/6870566668 OR https://www.strava.com/activities/5385561485
883
- // Given FIT Source: https://connect.garmin.com/modern/activity/6782987395 OR https://www.strava.com/activities/2451375851
884
- const path = __dirname + '/fixtures/runs/gpx/6782987395.gpx';
885
- const gpxString = fs.readFileSync(path).toString();
886
- // When
887
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
888
- // Then
889
- eventInterfacePromise.then((event) => {
890
- const activity = event.getFirstActivity();
891
- expect(activity.type).toEqual(ActivityTypes.Running);
892
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '05:53', 1);
893
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '05:18', 1);
894
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(14170.5, 0);
895
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(363, 0);
896
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(82);
897
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(111);
898
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(137);
899
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(167);
900
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
901
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
902
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
903
- const pauseTime = activity.getStat(DataPause.type).getValue();
904
- const elapsedTime = activity.getDuration().getValue();
905
- SpecUtils.assertNearEqualTime(movingTime, '01:17:11');
906
- SpecUtils.assertNearEqualTime(timerTime, '01:23:09');
907
- SpecUtils.assertNearEqualTime(elapsedTime, '01:23:09');
908
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
909
- done();
910
- }).catch((e) => done(e));
911
- });
912
- it('should parse running GPX file (3)', done => {
913
- // Given Recorded with "Strava Android App" => https://connect.garmin.com/modern/activity/1681613317 OR https://www.strava.com/activities/906581465
914
- const path = __dirname + '/fixtures/runs/gpx/1681613317.gpx';
915
- const gpxString = fs.readFileSync(path).toString();
916
- // When
917
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
918
- // Then
919
- eventInterfacePromise.then((event) => {
920
- const activity = event.getFirstActivity();
921
- expect(activity.type).toEqual(ActivityTypes.run);
922
- expect(activity.hasPowerMeter()).toBeFalsy();
923
- expect(activity.isTrainer()).toBeFalsy();
924
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '06:27', 1);
925
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '06:23', 1);
926
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(4593, 0);
927
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(39, 0);
928
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(79);
929
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(96);
930
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(146);
931
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(176);
932
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
933
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
934
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
935
- const pauseTime = activity.getStat(DataPause.type).getValue();
936
- const elapsedTime = activity.getDuration().getValue();
937
- SpecUtils.assertNearEqualTime(movingTime, '32:09');
938
- SpecUtils.assertNearEqualTime(timerTime, '32:38');
939
- SpecUtils.assertNearEqualTime(elapsedTime, '32:38');
940
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
941
- done();
942
- }).catch((e) => done(e));
943
- });
944
- it('should parse running GPX file (4)', done => {
945
- // Given Recorded with "MyTracks" => https://connect.garmin.com/modern/activity/6909258631 OR https://www.strava.com/activities/5422847134
946
- const path = __dirname + '/fixtures/runs/gpx/6909258631.gpx';
947
- const gpxString = fs.readFileSync(path).toString();
948
- // When
949
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
950
- // Then
951
- eventInterfacePromise.then((event) => {
952
- const activity = event.getFirstActivity();
953
- // expect(activity.type).toEqual(ActivityTypes.run); // TODO To be auto-detected by sports-data-science library (work in progress)
954
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(40878.5, 1);
955
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(2780, 0);
956
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(2780, 0);
957
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '07:22', 1);
958
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
959
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
960
- const pauseTime = activity.getStat(DataPause.type).getValue();
961
- const elapsedTime = activity.getDuration().getValue();
962
- SpecUtils.assertNearEqualTime(movingTime, '04:51:49');
963
- SpecUtils.assertNearEqualTime(timerTime, '06:30:22');
964
- SpecUtils.assertNearEqualTime(elapsedTime, '06:30:22');
965
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
966
- done();
967
- }).catch((e) => done(e));
968
- });
969
- it('should parse running GPX file (5)', done => {
970
- // Given https://connect.garmin.com/modern/activity/6048438275 OR https://www.strava.com/activities/3497177564
971
- const path = __dirname + '/fixtures/runs/gpx/6048438275.gpx';
972
- const gpxString = fs.readFileSync(path).toString();
973
- // When
974
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
975
- // Then
976
- eventInterfacePromise.then((event) => {
977
- const activity = event.getFirstActivity();
978
- expect(activity.type).toEqual(ActivityTypes.run);
979
- expect(activity.hasPowerMeter()).toBeFalsy();
980
- expect(activity.isTrainer()).toBeFalsy();
981
- SpecUtils.assertNearEqual(activity.getStat(DataDistance.type).getValue(), 16771.3, 1, 1);
982
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(579, 0);
983
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(86);
984
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(123);
985
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '04:48', 1);
986
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '04:17', 1);
987
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
988
- expect(activity.getSquashedStreamData('Distance').length).toEqual(activity.getSquashedStreamData('Speed').length);
989
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
990
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
991
- const pauseTime = activity.getStat(DataPause.type).getValue();
992
- const elapsedTime = activity.getDuration().getValue();
993
- SpecUtils.assertNearEqualTime(movingTime, '01:04:19');
994
- SpecUtils.assertNearEqualTime(timerTime, '01:22:50');
995
- SpecUtils.assertNearEqualTime(elapsedTime, '01:22:50');
996
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
997
- done();
998
- }).catch((e) => done(e));
999
- });
1000
- it('should parse running GPX file (6)', done => {
1001
- // Given https://www.strava.com/activities/3632493456 or https://connect.garmin.com/modern/activity/6037744996
1002
- const path = __dirname + '/fixtures/runs/gpx/6037744996.gpx';
1003
- const gpxString = fs.readFileSync(path).toString();
1004
- // When
1005
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
1006
- // Then
1007
- eventInterfacePromise.then((event) => {
1008
- const activity = event.getFirstActivity();
1009
- expect(activity.type).toEqual(ActivityTypes.run);
1010
- expect(activity.hasPowerMeter()).toBeFalsy();
1011
- expect(activity.isTrainer()).toBeFalsy();
1012
- SpecUtils.assertNearEqual(activity.getStat(DataDistance.type).getValue(), 5115.1, 1, 1);
1013
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(516, 0);
1014
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(68);
1015
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(124);
1016
- expect(activity.getStat(DataPaceAvg.type).getValue()).toBeGreaterThanOrEqual(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue());
1017
- SpecUtils.assertNearEqualTime(activity.getStat(DataPaceAvg.type).getValue(), '13:10', 1);
1018
- SpecUtils.assertNearEqualTime(activity.getStat(DataGradeAdjustedPaceAvg.type).getValue(), '09:07', 1);
1019
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1020
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1021
- const pauseTime = activity.getStat(DataPause.type).getValue();
1022
- const elapsedTime = activity.getDuration().getValue();
1023
- SpecUtils.assertNearEqualTime(movingTime, '28:35');
1024
- SpecUtils.assertNearEqualTime(timerTime, '01:07:19');
1025
- SpecUtils.assertNearEqualTime(elapsedTime, '01:07:19');
1026
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1027
- done();
1028
- }).catch((e) => done(e));
1029
- });
1030
- });
1031
- });
1032
- describe('Cycling', () => {
1033
- describe('FIT', () => {
1034
- it('should parse cycling FIT file (1)', done => {
1035
- // Given FIT Source: https://connect.garmin.com/modern/activity/3939576645 OR https://www.strava.com/activities/2610176355
1036
- const path = __dirname + '/fixtures/rides/fit/3939576645.fit';
1037
- const buffer = fs.readFileSync(path);
1038
- const expectedSamplesLength = 2547;
1039
- // When
1040
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1041
- // Then
1042
- eventInterfacePromise.then((event) => {
1043
- // Verify streams consistency
1044
- const activity = event.getFirstActivity();
1045
- expect(activity.creator.name).toEqual('Garmin Edge 1000');
1046
- expect(activity.generateTimeStream([DataDistance.type]).getData(true).length).toEqual(expectedSamplesLength);
1047
- expect(activity.hasPowerMeter()).toBeFalsy();
1048
- expect(activity.isTrainer()).toBeFalsy();
1049
- expect(activity.getSquashedStreamData(DataLongitudeDegrees.type).length).toEqual(expectedSamplesLength);
1050
- expect(activity.getSquashedStreamData(DataLatitudeDegrees.type).length).toEqual(expectedSamplesLength);
1051
- expect(activity.getSquashedStreamData(DataDistance.type).length).toEqual(expectedSamplesLength);
1052
- expect(activity.getSquashedStreamData(DataAltitude.type).length).toEqual(expectedSamplesLength);
1053
- expect(activity.getSquashedStreamData(DataAltitudeSmooth.type).length).toEqual(expectedSamplesLength);
1054
- expect(activity.getSquashedStreamData(DataSpeed.type).length).toEqual(expectedSamplesLength);
1055
- expect(activity.getSquashedStreamData(DataCadence.type).length).toEqual(expectedSamplesLength);
1056
- expect(activity.getSquashedStreamData(DataHeartRate.type).length).toEqual(expectedSamplesLength);
1057
- expect(activity.getSquashedStreamData(DataGrade.type).length).toEqual(expectedSamplesLength);
1058
- const missingStreamCall = () => {
1059
- activity.getSquashedStreamData(DataPower.type);
1060
- };
1061
- expect(missingStreamCall).toThrow();
1062
- // Verify global activity stats
1063
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1064
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(42220.87);
1065
- expect(activity.getStat(DataAscent.type).getValue()).toEqual(668);
1066
- expect(activity.getStat(DataDescent.type).getValue()).toEqual(664);
1067
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(1497);
1068
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(68);
1069
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(109);
1070
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(155);
1071
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(186);
1072
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toEqual(5.812); // Or 20.9 kph
1073
- expect(activity.getStat(DataTotalCycles.type).getValue()).toEqual(6550);
1074
- // Verifying time data
1075
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1076
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1077
- const pauseTime = activity.getStat(DataPause.type).getValue();
1078
- const elapsedTime = activity.getDuration().getValue();
1079
- SpecUtils.assertNearEqualTime(movingTime, '02:00:42', 1);
1080
- SpecUtils.assertNearEqualTime(timerTime, '02:01:04');
1081
- SpecUtils.assertNearEqualTime(elapsedTime, '02:04:36');
1082
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1083
- done();
1084
- }).catch((e) => done(e));
1085
- });
1086
- it('should parse cycling FIT file (2)', done => {
1087
- // Given FIT Source: https://connect.garmin.com/modern/activity/828989227 OR https://www.strava.com/activities/343080886
1088
- const path = __dirname + '/fixtures/rides/fit/828989227.fit';
1089
- const buffer = fs.readFileSync(path);
1090
- // When
1091
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1092
- // Then
1093
- eventInterfacePromise.then((event) => {
1094
- const activity = event.getFirstActivity();
1095
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1096
- expect(activity.creator.name).toEqual('Garmin Edge 810');
1097
- expect(activity.hasPowerMeter()).toBeFalsy();
1098
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(141944.2);
1099
- expect(activity.getStat(DataAscent.type).getValue()).toEqual(2052);
1100
- expect(activity.getStat(DataDescent.type).getValue()).toEqual(2028);
1101
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(2629);
1102
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(79);
1103
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(118);
1104
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(148);
1105
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(174);
1106
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toEqual(7.219); // Or 26 kph
1107
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1108
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1109
- const pauseTime = activity.getStat(DataPause.type).getValue();
1110
- const elapsedTime = activity.getDuration().getValue();
1111
- SpecUtils.assertNearEqualTime(movingTime, '05:26:49');
1112
- SpecUtils.assertNearEqualTime(timerTime, '05:27:44');
1113
- SpecUtils.assertNearEqualTime(elapsedTime, '06:07:08');
1114
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1115
- done();
1116
- }).catch((e) => done(e));
1117
- });
1118
- it('should parse cycling FIT file (3)', done => {
1119
- // Given FIT Source: https://connect.garmin.com/modern/activity/614953343 OR https://www.strava.com/activities/208748758
1120
- const path = __dirname + '/fixtures/rides/fit/614953343.fit';
1121
- const buffer = fs.readFileSync(path);
1122
- // When
1123
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1124
- // Then
1125
- eventInterfacePromise.then((event) => {
1126
- const activity = event.getFirstActivity();
1127
- expect(activity.creator.name).toEqual('Garmin Edge 800');
1128
- expect(activity.hasPowerMeter()).toBeFalsy();
1129
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1130
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1131
- const pauseTime = activity.getStat(DataPause.type).getValue();
1132
- const elapsedTime = activity.getDuration().getValue();
1133
- SpecUtils.assertNearEqualTime(movingTime, '05:52:28', 1);
1134
- SpecUtils.assertNearEqualTime(timerTime, '05:54:34');
1135
- SpecUtils.assertNearEqualTime(elapsedTime, '07:04:31');
1136
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1137
- done();
1138
- }).catch((e) => done(e));
1139
- });
1140
- it('should parse cycling FIT file (4)', done => {
1141
- // Given FIT Source: https://connect.garmin.com/modern/activity/6783622686 OR https://www.strava.com/activities/5300988022
1142
- const path = __dirname + '/fixtures/rides/fit/6783622686.fit';
1143
- const buffer = fs.readFileSync(path);
1144
- // When
1145
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1146
- // Then
1147
- eventInterfacePromise.then((event) => {
1148
- const activity = event.getFirstActivity();
1149
- expect(activity.creator.name).toEqual('Garmin Edge 1030');
1150
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1151
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1152
- const pauseTime = activity.getStat(DataPause.type).getValue();
1153
- const elapsedTime = activity.getDuration().getValue();
1154
- SpecUtils.assertNearEqualTime(movingTime, '05:07:53');
1155
- SpecUtils.assertNearEqualTime(timerTime, '05:08:22');
1156
- SpecUtils.assertNearEqualTime(elapsedTime, '07:26:55');
1157
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1158
- done();
1159
- }).catch((e) => done(e));
1160
- });
1161
- it('should parse cycling FIT file (5)', done => {
1162
- // Given FIT Source: https://connect.garmin.com/modern/activity/7386755164 OR https://www.strava.com/activities/5952147686
1163
- const path = __dirname + '/fixtures/rides/fit/7386755164.fit';
1164
- const buffer = fs.readFileSync(path);
1165
- // When
1166
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1167
- // Then
1168
- eventInterfacePromise.then((event) => {
1169
- const activity = event.getFirstActivity();
1170
- expect(activity.creator.name).toEqual('Garmin Edge 1030');
1171
- // Power extended stats
1172
- expect(activity.getStat(DataLeftBalance.type).getValue()).toEqual(51.45);
1173
- expect(activity.getStat(DataRightBalance.type).getValue()).toEqual(48.55);
1174
- expect(activity.getStat(DataPowerTorqueEffectivenessLeft.type).getValue()).toEqual(80);
1175
- expect(activity.getStat(DataPowerTorqueEffectivenessRight.type).getValue()).toEqual(76.5);
1176
- expect(activity.getStat(DataPowerPedalSmoothnessLeft.type).getValue()).toEqual(22);
1177
- expect(activity.getStat(DataPowerPedalSmoothnessRight.type).getValue()).toEqual(20.5);
1178
- expect(activity.getStat(DataPowerNormalized.type).getValue()).toEqual(179);
1179
- expect(activity.getStat(DataPowerIntensityFactor.type).getValue()).toEqual(0.786);
1180
- expect(activity.getStat(DataPowerTrainingStressScore.type).getValue()).toEqual(105.4);
1181
- expect(activity.getStat(DataPowerWork.type).getValue()).toEqual(832);
1182
- // Cycling dynamics: Power "position" stats
1183
- SpecUtils.assertNearEqualTime(activity.getStat(DataCyclingStandingTime.type).getValue(), '17:53', 0);
1184
- SpecUtils.assertNearEqualTime(activity.getStat(DataCyclingSeatedTime.type).getValue(), '01:25:02', 0);
1185
- done();
1186
- }).catch((e) => done(e));
1187
- });
1188
- it('should parse cycling FIT file (6)', done => {
1189
- // Given FIT Source: https://connect.garmin.com/modern/activity/7445393868 OR https://www.strava.com/activities/5921768617
1190
- const path = __dirname + '/fixtures/rides/fit/7445393868.fit';
1191
- const buffer = fs.readFileSync(path);
1192
- // When
1193
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1194
- // Then
1195
- eventInterfacePromise.then((event) => {
1196
- const activity = event.getFirstActivity();
1197
- expect(activity.creator.name).toEqual('Garmin Edge 1000');
1198
- expect(activity.hasPowerMeter()).toBeTruthy();
1199
- expect(activity.getStat(DataLeftBalance.type).getValue()).toEqual(45.91);
1200
- expect(activity.getStat(DataRightBalance.type).getValue()).toEqual(54.09);
1201
- expect(activity.getStat(DataPowerTorqueEffectivenessLeft.type).getValue()).toEqual(71);
1202
- expect(activity.getStat(DataPowerTorqueEffectivenessRight.type).getValue()).toEqual(73);
1203
- expect(activity.getStat(DataPowerPedalSmoothnessLeft.type).getValue()).toEqual(20);
1204
- expect(activity.getStat(DataPowerPedalSmoothnessRight.type).getValue()).toEqual(21.5);
1205
- expect(activity.getStat(DataPowerNormalized.type).getValue()).toEqual(147);
1206
- expect(activity.getStat(DataPowerIntensityFactor.type).getValue()).toEqual(0.733);
1207
- expect(activity.getStat(DataPowerTrainingStressScore.type).getValue()).toEqual(48.3);
1208
- expect(activity.getStat(DataPowerWork.type).getValue()).toEqual(417);
1209
- done();
1210
- }).catch((e) => done(e));
1211
- });
1212
- it('should parse cycling FIT file (7)', done => {
1213
- // Given FIT Source: https://connect.garmin.com/modern/activity/7432332116 OR https://www.strava.com/activities/5910143591
1214
- const path = __dirname + '/fixtures/rides/fit/7432332116.fit';
1215
- const buffer = fs.readFileSync(path);
1216
- const expectedSamplesLength = 10063;
1217
- // When
1218
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1219
- // Then
1220
- eventInterfacePromise.then((event) => {
1221
- const activity = event.getFirstActivity();
1222
- expect(activity.creator.name).toEqual('Garmin Edge 1000');
1223
- expect(activity.hasPowerMeter()).toBeTruthy();
1224
- expect(activity.getStat(DataPowerAvg.type).getValue()).toEqual(152);
1225
- expect(activity.getStat(DataPowerNormalized.type).getValue()).toEqual(172);
1226
- expect(activity.getStat(DataPowerMax.type).getValue()).toEqual(564);
1227
- expect(activity.getSquashedStreamData(DataLongitudeDegrees.type).length).toEqual(expectedSamplesLength);
1228
- expect(activity.getSquashedStreamData(DataLatitudeDegrees.type).length).toEqual(expectedSamplesLength);
1229
- expect(activity.getSquashedStreamData(DataDistance.type).length).toEqual(expectedSamplesLength);
1230
- expect(activity.getSquashedStreamData(DataAltitude.type).length).toEqual(expectedSamplesLength);
1231
- expect(activity.getSquashedStreamData(DataSpeed.type).length).toEqual(expectedSamplesLength);
1232
- expect(activity.getSquashedStreamData(DataCadence.type).length).toEqual(expectedSamplesLength);
1233
- expect(activity.getSquashedStreamData(DataHeartRate.type).length).toEqual(expectedSamplesLength);
1234
- expect(activity.getSquashedStreamData(DataPower.type).length).toEqual(expectedSamplesLength);
1235
- done();
1236
- }).catch((e) => done(e));
1237
- });
1238
- it('should parse cycling FIT file (8)', done => {
1239
- // Given FIT Source: https://connect.garmin.com/modern/activity/7739869618 OR https://www.strava.com/activities/2380240532
1240
- const path = __dirname + '/fixtures/rides/fit/7739869618.fit';
1241
- const buffer = fs.readFileSync(path);
1242
- // When
1243
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1244
- // Then
1245
- eventInterfacePromise.then((event) => {
1246
- const activity = event.getFirstActivity();
1247
- expect(activity.creator.name).toEqual('Wahoo ELEMNT BOLT');
1248
- expect(activity.creator.manufacturer).toEqual('wahoo_fitness');
1249
- expect(activity.creator.isRecognized).toBeTruthy();
1250
- done();
1251
- }).catch((e) => done(e));
1252
- });
1253
- it('should parse cycling FIT file (9)', done => {
1254
- // Given FIT Source: https://connect.garmin.com/modern/activity/5319808632 OR https://www.strava.com/activities/3849490840
1255
- const path = __dirname + '/fixtures/rides/fit/5319808632.fit';
1256
- const buffer = fs.readFileSync(path);
1257
- // When
1258
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1259
- // Then
1260
- eventInterfacePromise.then((event) => {
1261
- const activity = event.getFirstActivity();
1262
- expect(activity.startDate.toISOString()).toEqual('2020-07-26T15:28:41.000Z');
1263
- expect(activity.endDate.toISOString()).toEqual('2020-07-26T16:31:26.063Z');
1264
- done();
1265
- }).catch((e) => done(e));
1266
- });
1267
- it('should parse virtual cycling FIT file (1)', done => {
1268
- // Given FIT Source: https://connect.garmin.com/modern/activity/971150603 OR https://www.strava.com/activities/442080924
1269
- const path = __dirname + '/fixtures/rides/fit/971150603.fit';
1270
- const buffer = fs.readFileSync(path);
1271
- const expectedSamplesLength = 3806;
1272
- // When
1273
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1274
- // Then
1275
- eventInterfacePromise.then((event) => {
1276
- // Verify streams consistency
1277
- const activity = event.getFirstActivity();
1278
- expect(activity.creator.name).toEqual('Zwift');
1279
- expect(activity.creator.productId).toEqual(15706);
1280
- expect(activity.creator.isRecognized).toBeTruthy();
1281
- expect(activity.generateTimeStream([DataDistance.type]).getData(true).length).toEqual(expectedSamplesLength);
1282
- expect(activity.hasPowerMeter()).toBeTruthy();
1283
- expect(activity.isTrainer()).toBeFalsy();
1284
- expect(activity.getSquashedStreamData(DataLongitudeDegrees.type).length).toEqual(expectedSamplesLength);
1285
- expect(activity.getSquashedStreamData(DataLatitudeDegrees.type).length).toEqual(expectedSamplesLength);
1286
- expect(activity.getSquashedStreamData(DataDistance.type).length).toEqual(expectedSamplesLength);
1287
- expect(activity.getSquashedStreamData(DataAltitude.type).length).toEqual(expectedSamplesLength);
1288
- expect(activity.getSquashedStreamData(DataSpeed.type).length).toEqual(expectedSamplesLength);
1289
- expect(activity.getSquashedStreamData(DataCadence.type).length).toEqual(expectedSamplesLength);
1290
- expect(activity.getSquashedStreamData(DataHeartRate.type).length).toEqual(expectedSamplesLength);
1291
- expect(activity.getSquashedStreamData(DataPower.type).length).toEqual(expectedSamplesLength);
1292
- // Verify global activity stats
1293
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1294
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(32227.5);
1295
- SpecUtils.assertEqual(activity.getStat(DataAscent.type).getValue(), 242, 0);
1296
- expect(activity.getStat(DataEnergy.type)).toBeUndefined(); // Zwift didn't give the calories
1297
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(76);
1298
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(114);
1299
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(148);
1300
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(180);
1301
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toEqual(8.476); // Or 30.5 kph
1302
- expect(activity.getStat(DataPowerAvg.type).getValue()).toEqual(143);
1303
- expect(activity.getStat(DataPowerMax.type).getValue()).toEqual(381);
1304
- // Verifying time data
1305
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1306
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1307
- const pauseTime = activity.getStat(DataPause.type).getValue();
1308
- const elapsedTime = activity.getDuration().getValue();
1309
- SpecUtils.assertNearEqualTime(movingTime, '01:02:53', 1);
1310
- SpecUtils.assertNearEqualTime(timerTime, '01:03:35');
1311
- SpecUtils.assertNearEqualTime(elapsedTime, '01:03:42');
1312
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1313
- done();
1314
- }).catch((e) => done(e));
1315
- });
1316
- });
1317
- describe('TCX', () => {
1318
- it('should parse cycling TCX file (1)', done => {
1319
- // Given TCX Source: https://connect.garmin.com/modern/activity/6791039036 OR https://www.strava.com/activities/5308417342
1320
- // Given FIT Source: https://connect.garmin.com/modern/activity/3939576645 OR https://www.strava.com/activities/2610176355
1321
- const path = __dirname + '/fixtures/rides/tcx/6791039036.tcx';
1322
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
1323
- // When
1324
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
1325
- // Then
1326
- eventInterfacePromise.then((event) => {
1327
- // Verify global activity stats
1328
- const activity = event.getFirstActivity();
1329
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1330
- expect(activity.creator.name).toEqual('Garmin Edge 1000');
1331
- SpecUtils.assertEqual(activity.getStat(DataAscent.type).getValue(), 672, 0);
1332
- SpecUtils.assertEqual(activity.getStat(DataDescent.type).getValue(), 664);
1333
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(42220.87);
1334
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(1497);
1335
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(69);
1336
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(108);
1337
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(153);
1338
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(186);
1339
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toBeCloseTo(6.536); // Or 23.5 kph
1340
- // Verifying time data
1341
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1342
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1343
- const pauseTime = activity.getStat(DataPause.type).getValue();
1344
- const elapsedTime = activity.getDuration().getValue();
1345
- SpecUtils.assertNearEqualTime(movingTime, '02:01:59', 1);
1346
- SpecUtils.assertNearEqualTime(timerTime, '02:01:04');
1347
- SpecUtils.assertNearEqualTime(elapsedTime, '02:04:36');
1348
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1349
- done();
1350
- }).catch((e) => done(e));
1351
- });
1352
- it('should parse cycling TCX file (2)', done => {
1353
- // Given TCX Source: https://connect.garmin.com/modern/activity/6838497277 or https://www.strava.com/activities/5354278524
1354
- // Given FIT Source: https://connect.garmin.com/modern/activity/3953195468 or https://www.strava.com/activities/2621275265
1355
- const path = __dirname + '/fixtures/rides/tcx/6838497277.tcx';
1356
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
1357
- // When
1358
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
1359
- // Then
1360
- eventInterfacePromise.then((event) => {
1361
- const activity = event.getFirstActivity();
1362
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1363
- expect(activity.hasPowerMeter()).toBeFalsy();
1364
- expect(activity.isTrainer()).toBeFalsy();
1365
- SpecUtils.assertEqual(activity.getStat(DataAscent.type).getValue(), 685, 0);
1366
- SpecUtils.assertEqual(activity.getStat(DataDescent.type).getValue(), 670);
1367
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(59853.31);
1368
- expect(activity.getStat(DataEnergy.type).getValue()).toEqual(2206);
1369
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(68);
1370
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(109);
1371
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(160);
1372
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(192);
1373
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toBeCloseTo(6.278); // 22.6 kph
1374
- // Verifying time data
1375
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1376
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1377
- const pauseTime = activity.getStat(DataPause.type).getValue();
1378
- const elapsedTime = activity.getDuration().getValue();
1379
- SpecUtils.assertNearEqualTime(movingTime, '02:52:10', 1.5);
1380
- SpecUtils.assertNearEqualTime(timerTime, '02:55:15');
1381
- SpecUtils.assertNearEqualTime(elapsedTime, '02:55:15');
1382
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1383
- done();
1384
- }).catch((e) => done(e));
1385
- });
1386
- it('should parse cycling TCX file (3)', done => {
1387
- // Given TCX Source: https://connect.garmin.com/modern/activity/7555170032 or https://www.strava.com/activities/6020442882
1388
- // Given FIT Source: https://connect.garmin.com/modern/activity/7432332116 OR https://www.strava.com/activities/5910143591
1389
- const path = __dirname + '/fixtures/rides/tcx/7555170032.tcx';
1390
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
1391
- const expectedSamplesLength = 10063;
1392
- // When
1393
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
1394
- // Then
1395
- eventInterfacePromise.then((event) => {
1396
- const activity = event.getFirstActivity();
1397
- expect(activity.creator.name).toEqual('Garmin Edge 1000');
1398
- expect(activity.hasPowerMeter()).toBeTruthy();
1399
- expect(activity.getStat(DataPowerAvg.type).getValue()).toBeCloseTo(152, 0);
1400
- expect(activity.getStat(DataPowerNormalized.type).getValue()).toBeCloseTo(171, 0);
1401
- expect(activity.getStat(DataPowerMax.type).getValue()).toEqual(564);
1402
- expect(activity.getSquashedStreamData(DataLongitudeDegrees.type).length).toEqual(expectedSamplesLength);
1403
- expect(activity.getSquashedStreamData(DataLatitudeDegrees.type).length).toEqual(expectedSamplesLength);
1404
- expect(activity.getSquashedStreamData(DataDistance.type).length).toEqual(expectedSamplesLength);
1405
- expect(activity.getSquashedStreamData(DataAltitude.type).length).toEqual(expectedSamplesLength);
1406
- expect(activity.getSquashedStreamData(DataSpeed.type).length).toEqual(expectedSamplesLength);
1407
- expect(activity.getSquashedStreamData(DataCadence.type).length).toEqual(expectedSamplesLength);
1408
- expect(activity.getSquashedStreamData(DataHeartRate.type).length).toEqual(expectedSamplesLength);
1409
- expect(activity.getSquashedStreamData(DataPower.type).length).toEqual(expectedSamplesLength);
1410
- done();
1411
- }).catch((e) => done(e));
1412
- });
1413
- it('should parse virtual cycling TCX file (1)', done => {
1414
- // Given https://connect.garmin.com/modern/activity/6823905801 OR https://www.strava.com/activities/5340305665
1415
- const path = __dirname + '/fixtures/rides/tcx/6823905801.tcx';
1416
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
1417
- // When
1418
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
1419
- // Then
1420
- eventInterfacePromise.then((event) => {
1421
- const activity = event.getFirstActivity();
1422
- expect(activity.hasPowerMeter()).toBeTruthy();
1423
- expect(activity.isTrainer()).toBeFalsy();
1424
- // Verify global activity stats
1425
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1426
- expect(activity.getStat(DataDistance.type).getValue()).toEqual(32227.5);
1427
- SpecUtils.assertEqual(activity.getStat(DataAscent.type).getValue(), 242);
1428
- expect(activity.getStat(DataEnergy.type)).toBeUndefined(); // Zwift didn't give the calories
1429
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(76);
1430
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(114);
1431
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(148);
1432
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(180);
1433
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toBeCloseTo(8.47, 3); // Or 30.5 kph
1434
- SpecUtils.assertEqual(activity.getStat(DataPowerAvg.type).getValue(), 143);
1435
- expect(activity.getStat(DataPowerMax.type).getValue()).toEqual(381);
1436
- // Verifying time data
1437
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1438
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1439
- const pauseTime = activity.getStat(DataPause.type).getValue();
1440
- const elapsedTime = activity.getDuration().getValue();
1441
- SpecUtils.assertNearEqualTime(movingTime, '01:03:10', 1);
1442
- SpecUtils.assertNearEqualTime(timerTime, '01:03:35');
1443
- SpecUtils.assertNearEqualTime(elapsedTime, '01:03:42');
1444
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1445
- done();
1446
- }).catch((e) => done(e));
1447
- });
1448
- });
1449
- describe('GPX', () => {
1450
- it('should parse cycling GPX file (1)', done => {
1451
- // Given GPX Source: https://connect.garmin.com/modern/activity/6870609105 OR https://www.strava.com/activities/5385601807
1452
- // Given FIT Source: https://connect.garmin.com/modern/activity/3939576645 OR https://www.strava.com/activities/2610176355
1453
- const path = __dirname + '/fixtures/rides/gpx/3939576645.gpx';
1454
- const gpxString = fs.readFileSync(path).toString();
1455
- // When
1456
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
1457
- // Then
1458
- eventInterfacePromise.then((event) => {
1459
- const activity = event.getFirstActivity();
1460
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1461
- expect(activity.hasPowerMeter()).toBeFalsy();
1462
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(41829, 0);
1463
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(672, 0);
1464
- expect(activity.getStat(DataDescent.type).getValue()).toBeCloseTo(664, 0);
1465
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(69);
1466
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(108);
1467
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(153);
1468
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(186);
1469
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toBeCloseTo(6.479); // Or 23.32 kph
1470
- // Verifying time data
1471
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1472
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1473
- const pauseTime = activity.getStat(DataPause.type).getValue();
1474
- const elapsedTime = activity.getDuration().getValue();
1475
- SpecUtils.assertNearEqualTime(movingTime, '02:00:42', 1.5);
1476
- SpecUtils.assertNearEqualTime(timerTime, '02:04:35');
1477
- SpecUtils.assertNearEqualTime(elapsedTime, '02:04:36');
1478
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1479
- done();
1480
- }).catch((e) => done(e));
1481
- });
1482
- it('should parse cycling GPX file (2)', done => {
1483
- // Given GPX Source: https://connect.garmin.com/modern/activity/6870692308 OR https://www.strava.com/activities/5385683390
1484
- // Given FIT Source: https://connect.garmin.com/modern/activity/828989227 OR https://www.strava.com/activities/343080886
1485
- const path = __dirname + '/fixtures/rides/gpx/828989227.gpx';
1486
- const gpxString = fs.readFileSync(path).toString();
1487
- // When
1488
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
1489
- // Then
1490
- eventInterfacePromise.then((event) => {
1491
- const activity = event.getFirstActivity();
1492
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1493
- expect(activity.hasPowerMeter()).toBeFalsy();
1494
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(141975, 0);
1495
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(2052, 0);
1496
- expect(activity.getStat(DataDescent.type).getValue()).toBeCloseTo(2034, 0);
1497
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(79);
1498
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(118);
1499
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(148);
1500
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(174);
1501
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toBeCloseTo(7.329); // Or 26.3 kph
1502
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1503
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1504
- const pauseTime = activity.getStat(DataPause.type).getValue();
1505
- const elapsedTime = activity.getDuration().getValue();
1506
- SpecUtils.assertNearEqualTime(movingTime, '05:26:49', 2);
1507
- SpecUtils.assertNearEqualTime(timerTime, '06:07:13');
1508
- SpecUtils.assertNearEqualTime(elapsedTime, '06:07:13');
1509
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1510
- done();
1511
- }).catch((e) => done(e));
1512
- });
1513
- it('should parse cycling GPX file (3)', done => {
1514
- // Given GPX Source: https://connect.garmin.com/modern/activity/6905455978 OR https://www.strava.com/activities/5419099678
1515
- // Given FIT Source: https://connect.garmin.com/modern/activity/4108490848 OR https://www.strava.com/activities/2749884297
1516
- const path = __dirname + '/fixtures/rides/gpx/4108490848.gpx';
1517
- const gpxString = fs.readFileSync(path).toString();
1518
- // When
1519
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
1520
- // Then
1521
- eventInterfacePromise.then((event) => {
1522
- const activity = event.getFirstActivity();
1523
- expect(activity.name).toEqual('Meylan Road Cycling');
1524
- expect(activity.type).toEqual(ActivityTypes.Cycling);
1525
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(49909, 0);
1526
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(292, 0);
1527
- expect(activity.getStat(DataDescent.type).getValue()).toBeCloseTo(283, 0);
1528
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(76);
1529
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(117);
1530
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(165);
1531
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(186);
1532
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toBeCloseTo(7.903); // Or 28.4 kph
1533
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1534
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1535
- const pauseTime = activity.getStat(DataPause.type).getValue();
1536
- const elapsedTime = activity.getDuration().getValue();
1537
- SpecUtils.assertNearEqualTime(movingTime, '01:47:13', 1);
1538
- SpecUtils.assertNearEqualTime(timerTime, '01:49:20');
1539
- SpecUtils.assertNearEqualTime(elapsedTime, '01:49:20');
1540
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1541
- done();
1542
- }).catch((e) => done(e));
1543
- });
1544
- it('should parse cycling GPX file (4)', done => {
1545
- // Given GPX Source: https://connect.garmin.com/modern/activity/7555261629 or https://www.strava.com/activities/6020530554
1546
- // Given FIT Source: https://connect.garmin.com/modern/activity/7432332116 OR https://www.strava.com/activities/5910143591
1547
- const path = __dirname + '/fixtures/rides/gpx/7555261629.gpx';
1548
- const gpxString = fs.readFileSync(path).toString();
1549
- const expectedSamplesLength = 10063;
1550
- // When
1551
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
1552
- // Then
1553
- eventInterfacePromise.then((event) => {
1554
- const activity = event.getFirstActivity();
1555
- expect(activity.hasPowerMeter()).toBeTruthy();
1556
- expect(activity.getStat(DataPowerAvg.type).getValue()).toBeCloseTo(152, 0);
1557
- expect(activity.getStat(DataPowerNormalized.type).getValue()).toBeCloseTo(171, 0);
1558
- expect(activity.getStat(DataPowerMax.type).getValue()).toEqual(564);
1559
- expect(activity.getSquashedStreamData(DataLongitudeDegrees.type).length).toEqual(expectedSamplesLength);
1560
- expect(activity.getSquashedStreamData(DataLatitudeDegrees.type).length).toEqual(expectedSamplesLength);
1561
- expect(activity.getSquashedStreamData(DataDistance.type).length).toEqual(expectedSamplesLength);
1562
- expect(activity.getSquashedStreamData(DataAltitude.type).length).toEqual(expectedSamplesLength);
1563
- expect(activity.getSquashedStreamData(DataSpeed.type).length).toEqual(expectedSamplesLength);
1564
- expect(activity.getSquashedStreamData(DataCadence.type).length).toEqual(expectedSamplesLength);
1565
- expect(activity.getSquashedStreamData(DataHeartRate.type).length).toEqual(expectedSamplesLength);
1566
- expect(activity.getSquashedStreamData(DataPower.type).length).toEqual(expectedSamplesLength);
1567
- done();
1568
- }).catch((e) => done(e));
1569
- });
1570
- it('should parse virtual cycling GPX file (1)', done => {
1571
- // Given GPX Source: https://connect.garmin.com/modern/activity/6909869014 OR https://www.strava.com/activities/5423473093
1572
- // Given FIT Source: https://connect.garmin.com/modern/activity/1137672073 OR https://www.strava.com/activities/553573871
1573
- const path = __dirname + '/fixtures/rides/gpx/6909869014.gpx';
1574
- const gpxString = fs.readFileSync(path).toString();
1575
- // When
1576
- const eventInterfacePromise = SportsLib.importFromGPX(gpxString, xmldom.DOMParser);
1577
- // Then
1578
- eventInterfacePromise.then((event) => {
1579
- const activity = event.getFirstActivity();
1580
- expect(activity.type).toEqual(ActivityTypes.VirtualCycling);
1581
- expect(activity.hasPowerMeter()).toBeTruthy();
1582
- expect(activity.isTrainer()).toBeTruthy();
1583
- expect(activity.getStat(DataDistance.type).getValue()).toBeCloseTo(28620, 0);
1584
- expect(activity.getStat(DataAscent.type).getValue()).toBeCloseTo(271, 0);
1585
- expect(activity.getStat(DataDescent.type).getValue()).toBeCloseTo(257, 0);
1586
- expect(activity.getStat(DataCadenceAvg.type).getValue()).toEqual(75);
1587
- expect(activity.getStat(DataCadenceMax.type).getValue()).toEqual(120);
1588
- expect(activity.getStat(DataHeartRateAvg.type).getValue()).toEqual(161);
1589
- expect(activity.getStat(DataHeartRateMax.type).getValue()).toEqual(184);
1590
- expect(activity.getStat(DataPowerAvg.type).getValue()).toBeCloseTo(142, 0);
1591
- expect(activity.getStat(DataPowerMax.type).getValue()).toBeCloseTo(330);
1592
- expect(activity.getStat(DataSpeedAvg.type).getValue()).toBeCloseTo(7.55); // Or 27.2 kph
1593
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1594
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1595
- const pauseTime = activity.getStat(DataPause.type).getValue();
1596
- const elapsedTime = activity.getDuration().getValue();
1597
- SpecUtils.assertNearEqualTime(movingTime, '01:02:58', 1);
1598
- SpecUtils.assertNearEqualTime(timerTime, '01:03:09');
1599
- SpecUtils.assertNearEqualTime(elapsedTime, '01:03:09');
1600
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1601
- done();
1602
- }).catch((e) => done(e));
1603
- });
1604
- });
1605
- });
1606
- describe('Triathlon', () => {
1607
- describe('FIT', () => {
1608
- it('should parse a .FIT Triathlon IronMan w/ 3 activities (swim + ride + run) ', done => {
1609
- // Given https://connect.garmin.com/modern/activity/4623204522 ; https://www.strava.com/activities/5352030147 + https://www.strava.com/activities/5352030778 + https://www.strava.com/activities/5352030764
1610
- const path = __dirname + '/fixtures/triathlons/fit/4623204522.fit';
1611
- const buffer = fs.readFileSync(path);
1612
- const activitiesCount = 5;
1613
- // When
1614
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1615
- // Then
1616
- eventInterfacePromise.then((event) => {
1617
- expect(event.getActivities().length).toEqual(activitiesCount);
1618
- // Swim
1619
- const swimActivity = event.getFirstActivity();
1620
- expect(swimActivity.type).toEqual(ActivityTypes.OpenWaterSwimming);
1621
- expect(swimActivity.getStreamData(DataSpeed.type).length).toEqual(3689);
1622
- expect(swimActivity.startDate.toISOString()).toEqual('2018-10-13T17:05:01.000Z');
1623
- expect(swimActivity.endDate.toISOString()).toEqual('2018-10-13T18:06:29.000Z');
1624
- expect(swimActivity.getStat(DataDistance.type).getValue()).toEqual(3933.3);
1625
- expect(swimActivity.getStat(DataEnergy.type).getValue()).toEqual(869);
1626
- expect(swimActivity.getStat(DataCadenceAvg.type).getValue()).toEqual(37);
1627
- expect(swimActivity.getStat(DataCadenceMax.type).getValue()).toEqual(48);
1628
- expect(swimActivity.getStat(DataHeartRateAvg.type).getValue()).toEqual(93);
1629
- expect(swimActivity.getStat(DataHeartRateMax.type).getValue()).toEqual(112);
1630
- expect(swimActivity.getStat(DataTotalCycles.type).getValue()).toEqual(2294);
1631
- SpecUtils.assertNearEqualTime(SpecUtils.speedToSwimPace(swimActivity.getStat(DataSpeedAvg.type).getValue()), '01:34');
1632
- // Verifying time data
1633
- let movingTime = swimActivity.getStat(DataMovingTime.type).getValue();
1634
- let timerTime = swimActivity.getStat(DataTimerTime.type).getValue();
1635
- let pauseTime = swimActivity.getStat(DataPause.type).getValue();
1636
- let elapsedTime = swimActivity.getDuration().getValue();
1637
- SpecUtils.assertNearEqualTime(movingTime, '01:01:16', 1);
1638
- SpecUtils.assertNearEqualTime(timerTime, '01:01:29');
1639
- SpecUtils.assertNearEqualTime(elapsedTime, '01:01:29');
1640
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1641
- // Transition
1642
- let transition = event.getActivities()[1];
1643
- expect(transition.type).toEqual(ActivityTypes.Transition);
1644
- // Cycling
1645
- const cyclingActivity = event.getActivities()[2];
1646
- expect(cyclingActivity.type).toEqual(ActivityTypes.Cycling);
1647
- expect(cyclingActivity.getStreamData(DataSpeed.type).length).toEqual(17250);
1648
- expect(cyclingActivity.startDate.toISOString()).toEqual('2018-10-13T18:10:15.000Z');
1649
- expect(cyclingActivity.endDate.toISOString()).toEqual('2018-10-13T22:57:44.000Z');
1650
- expect(cyclingActivity.getStat(DataDistance.type).getValue()).toEqual(180301.58);
1651
- expect(cyclingActivity.getStat(DataEnergy.type).getValue()).toEqual(3804);
1652
- expect(cyclingActivity.getStat(DataCadenceAvg.type).getValue()).toEqual(89);
1653
- expect(cyclingActivity.getStat(DataCadenceMax.type).getValue()).toEqual(117);
1654
- expect(cyclingActivity.getStat(DataHeartRateAvg.type).getValue()).toEqual(140);
1655
- expect(cyclingActivity.getStat(DataHeartRateMax.type).getValue()).toEqual(153);
1656
- expect(cyclingActivity.getStat(DataTotalCycles.type).getValue()).toEqual(24373);
1657
- expect(cyclingActivity.getStat(DataSpeedAvg.type).getValue()).toBeCloseTo(10.453, 2); // Or 37.6 kph
1658
- // Verifying time data
1659
- movingTime = cyclingActivity.getStat(DataMovingTime.type).getValue();
1660
- timerTime = cyclingActivity.getStat(DataTimerTime.type).getValue();
1661
- pauseTime = cyclingActivity.getStat(DataPause.type).getValue();
1662
- elapsedTime = cyclingActivity.getDuration().getValue();
1663
- SpecUtils.assertNearEqualTime(movingTime, '04:42:28', 1);
1664
- SpecUtils.assertNearEqualTime(timerTime, '04:47:29');
1665
- SpecUtils.assertNearEqualTime(elapsedTime, '04:47:29');
1666
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime);
1667
- transition = event.getActivities()[3];
1668
- expect(transition.type).toEqual(ActivityTypes.Transition);
1669
- const runningActivity = event.getActivities()[4];
1670
- expect(runningActivity.type).toEqual(ActivityTypes.Running);
1671
- expect(runningActivity.startDate.toISOString()).toEqual('2018-10-13T22:57:45.000Z');
1672
- expect(runningActivity.endDate.toISOString()).toEqual('2018-10-14T02:42:23.000Z');
1673
- expect(runningActivity.getStat(DataDistance.type).getValue()).toEqual(42563.91);
1674
- expect(runningActivity.getStat(DataEnergy.type).getValue()).toEqual(2056);
1675
- expect(runningActivity.getStat(DataCadenceAvg.type).getValue()).toEqual(84);
1676
- expect(runningActivity.getStat(DataCadenceMax.type).getValue()).toEqual(116);
1677
- expect(runningActivity.getStat(DataHeartRateAvg.type).getValue()).toEqual(142);
1678
- expect(runningActivity.getStat(DataHeartRateMax.type).getValue()).toEqual(151);
1679
- SpecUtils.assertNearEqualTime(runningActivity.getStat(DataPaceAvg.type).getValue(), '05:08', 1);
1680
- // Verifying time data
1681
- movingTime = runningActivity.getStat(DataMovingTime.type).getValue();
1682
- timerTime = runningActivity.getStat(DataTimerTime.type).getValue();
1683
- pauseTime = runningActivity.getStat(DataPause.type).getValue();
1684
- elapsedTime = runningActivity.getDuration().getValue();
1685
- SpecUtils.assertNearEqualTime(movingTime, '03:36:57', 1);
1686
- SpecUtils.assertNearEqualTime(timerTime, '03:38:13');
1687
- SpecUtils.assertNearEqualTime(elapsedTime, '03:39:01');
1688
- SpecUtils.assertEqual(pauseTime, elapsedTime - movingTime, 1);
1689
- done();
1690
- }).catch((e) => done(e));
1691
- });
1692
- });
1693
- });
1694
- describe('Others', () => {
1695
- it('should reject parsing of broken fit file (empty activities)', done => {
1696
- // Given
1697
- const path = __dirname + '/fixtures/others/empty-activities.fit';
1698
- const buffer = fs.readFileSync(path);
1699
- const expectedErrorMessage = 'No activities found';
1700
- const expectedErrorClassName = 'EmptyEventLibError';
1701
- const expectedCode = 'EVENT_EMPTY_ERROR';
1702
- // When
1703
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1704
- // Then
1705
- eventInterfacePromise.then(() => {
1706
- throw new Error('Should not be resolved...');
1707
- }, (err) => {
1708
- expect(err.constructor.name).toEqual(expectedErrorClassName);
1709
- expect(err.message).toEqual(expectedErrorMessage);
1710
- expect(err.code).toEqual(expectedCode);
1711
- expect(err.event).toBeNull();
1712
- done();
1713
- });
1714
- });
1715
- it('should reject parsing of broken fit file (empty sessions)', done => {
1716
- // Given
1717
- const path = __dirname + '/fixtures/others/empty-sessions.fit';
1718
- const buffer = fs.readFileSync(path);
1719
- const expectedErrorMessage = 'No activities found';
1720
- const expectedErrorClassName = 'EmptyEventLibError';
1721
- const expectedCode = 'EVENT_EMPTY_ERROR';
1722
- // When
1723
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1724
- // Then
1725
- eventInterfacePromise.then(() => {
1726
- throw new Error('Should not be resolved...');
1727
- }, (err) => {
1728
- expect(err.constructor.name).toEqual(expectedErrorClassName);
1729
- expect(err.message).toEqual(expectedErrorMessage);
1730
- expect(err.code).toEqual(expectedCode);
1731
- expect(err.event).toBeNull();
1732
- done();
1733
- });
1734
- });
1735
- it('should parse fit file with broken sessionObject.start_time date', done => {
1736
- // Given
1737
- const path = __dirname + '/fixtures/others/broken-dates.fit';
1738
- const buffer = fs.readFileSync(path);
1739
- // When
1740
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1741
- // Then
1742
- eventInterfacePromise.then(event => {
1743
- expect(event.startDate.toISOString()).toEqual('2017-03-20T19:09:28.000Z');
1744
- expect(event.endDate.toISOString()).toEqual('2017-03-20T19:20:26.083Z');
1745
- done();
1746
- });
1747
- });
1748
- it('should handle activity with broken start lat/lng', done => {
1749
- // Given FIT Source: https://connect.garmin.com/modern/activity/7606651718 OR https://www.strava.com/activities/6066984530
1750
- const path = __dirname + '/fixtures/others/broken-start-latlng.fit';
1751
- const buffer = fs.readFileSync(path);
1752
- // When
1753
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1754
- // Then
1755
- eventInterfacePromise.then((event) => {
1756
- const activity = event.getFirstActivity();
1757
- const longStream = activity.getSquashedStreamData(DataLongitudeDegrees.type);
1758
- const latStream = activity.getSquashedStreamData(DataLatitudeDegrees.type);
1759
- expect(longStream[0]).not.toEqual(0);
1760
- expect(latStream[0]).not.toEqual(0);
1761
- done();
1762
- });
1763
- });
1764
- it('should reject parsing of a too long activity (31 days)', done => {
1765
- // Given
1766
- const path = __dirname + '/fixtures/others/31-days-activity.fit';
1767
- const buffer = fs.readFileSync(path);
1768
- const expectedErrorMessage = 'Activity duration exceeds 14 days. That is not supported';
1769
- const expectedErrorClassName = 'DurationExceededEventLibError';
1770
- const expectedCode = 'DURATION_EXCEEDED_EVENT_ERROR';
1771
- // When
1772
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1773
- // Then
1774
- eventInterfacePromise.then(() => {
1775
- throw new Error('Should not be resolved...');
1776
- }, (err) => {
1777
- expect(err.constructor.name).toEqual(expectedErrorClassName);
1778
- expect(err.message).toEqual(expectedErrorMessage);
1779
- expect(err.code).toEqual(expectedCode);
1780
- expect(err.event).toBeNull();
1781
- done();
1782
- });
1783
- });
1784
- it('should handle inverted elapsed and timer time', done => {
1785
- // Given FIT Source: https://connect.garmin.com/modern/activity/7852903753 OR https://www.strava.com/activities/6288405028
1786
- const path = __dirname + '/fixtures/others/inverted-times.fit';
1787
- const buffer = fs.readFileSync(path);
1788
- // When
1789
- const eventInterfacePromise = SportsLib.importFromFit(buffer);
1790
- // Then
1791
- eventInterfacePromise.then((event) => {
1792
- const activity = event.getFirstActivity();
1793
- // Verifying time data
1794
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1795
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1796
- const elapsedTime = activity.getDuration().getValue();
1797
- SpecUtils.assertNearEqualTime(movingTime, '47:20', 1);
1798
- SpecUtils.assertNearEqualTime(timerTime, '47:20');
1799
- SpecUtils.assertNearEqualTime(elapsedTime, '06:01:20');
1800
- done();
1801
- });
1802
- });
1803
- it('should handle calculation on a ultra long activity (27 days) with acceptable human time', done => {
1804
- // Given FIT Source: https://connect.garmin.com/modern/activity/7769719668 OR https://www.strava.com/activities/6197356353
1805
- const path = __dirname + '/fixtures/others/27-days-activity.fit';
1806
- const buffer = fs.readFileSync(path);
1807
- const options = ActivityParsingOptions.DEFAULT;
1808
- options.maxActivityDurationDays = 30;
1809
- const expectedSamplesLength = 3699;
1810
- // When
1811
- const eventInterfacePromise = SportsLib.importFromFit(buffer, options);
1812
- // Then
1813
- eventInterfacePromise.then((event) => {
1814
- const activity = event.getFirstActivity();
1815
- expect(activity.getSquashedStreamData(DataDistance.type).length).toEqual(expectedSamplesLength);
1816
- expect(activity.getSquashedStreamData(DataSpeed.type).length).toEqual(expectedSamplesLength);
1817
- expect(activity.getSquashedStreamData(DataCadence.type).length).toEqual(expectedSamplesLength);
1818
- expect(activity.getSquashedStreamData(DataHeartRate.type).length).toEqual(expectedSamplesLength);
1819
- expect(activity.getSquashedStreamData(DataGrade.type).length).toEqual(expectedSamplesLength);
1820
- done();
1821
- });
1822
- });
1823
- it('should handle and detect an activity with broken speed data', done => {
1824
- // Given TCX Source: (unable to upload on garmin connect) OR https://www.strava.com/activities/3197023890
1825
- const path = __dirname + '/fixtures/others/broken-speed-activity.tcx';
1826
- const doc = domParser.parseFromString(fs.readFileSync(path).toString(), 'application/xml');
1827
- const options = ActivityParsingOptions.DEFAULT;
1828
- options.streams.fixAbnormal.speed = true;
1829
- // When
1830
- const eventInterfacePromise = SportsLib.importFromTCX(doc);
1831
- // Then
1832
- eventInterfacePromise.then((event) => {
1833
- const activity = event.getFirstActivity();
1834
- const speedStdDev = standardDeviation(activity.getSquashedStreamData(DataSpeed.type));
1835
- expect(speedStdDev).toBeCloseTo(0.55, 2);
1836
- // Verifying time data
1837
- const movingTime = activity.getStat(DataMovingTime.type).getValue();
1838
- const timerTime = activity.getStat(DataTimerTime.type).getValue();
1839
- const elapsedTime = activity.getDuration().getValue();
1840
- SpecUtils.assertNearEqualTime(movingTime, '05:04:20');
1841
- SpecUtils.assertNearEqualTime(timerTime, '5:07:54');
1842
- SpecUtils.assertNearEqualTime(elapsedTime, '5:07:54');
1843
- done();
1844
- });
1845
- });
1846
- });
1847
- });