@sports-alliance/sports-lib 7.0.8 → 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 (326) hide show
  1. package/lib/esm/index.js +12034 -152
  2. package/package.json +2 -2
  3. package/lib/esm/activities/activity-parsing-options.js +0 -19
  4. package/lib/esm/activities/activity.interface.js +0 -1
  5. package/lib/esm/activities/activity.js +0 -281
  6. package/lib/esm/activities/activity.json.interface.js +0 -1
  7. package/lib/esm/activities/activity.spec.js +0 -348
  8. package/lib/esm/activities/activity.types.js +0 -1046
  9. package/lib/esm/activities/activityt-types.spec.js +0 -16
  10. package/lib/esm/activities/devices/device.interface.js +0 -1
  11. package/lib/esm/activities/devices/device.js +0 -26
  12. package/lib/esm/activities/devices/device.json.interface.js +0 -1
  13. package/lib/esm/constants/constants.js +0 -8
  14. package/lib/esm/creators/creator.interface.js +0 -1
  15. package/lib/esm/creators/creator.js +0 -37
  16. package/lib/esm/creators/creator.json.interface.js +0 -1
  17. package/lib/esm/creators/creator.spec.js +0 -25
  18. package/lib/esm/data/data-active-lap.js +0 -4
  19. package/lib/esm/data/data-active-lengths.js +0 -4
  20. package/lib/esm/data/data-aerobic-training-effect.js +0 -8
  21. package/lib/esm/data/data-anaerobic-training-effect.js +0 -8
  22. package/lib/esm/data/data-stance-time-balance-left.js +0 -4
  23. package/lib/esm/data/data-stance-time-balance-right.js +0 -4
  24. package/lib/esm/data/data-stance-time-balance.js +0 -3
  25. package/lib/esm/data/data-store.spec.js +0 -78
  26. package/lib/esm/data/data-total-cycles.js +0 -4
  27. package/lib/esm/data/data.absolute-pressure.js +0 -5
  28. package/lib/esm/data/data.accumulated-power.js +0 -8
  29. package/lib/esm/data/data.activity-types.js +0 -7
  30. package/lib/esm/data/data.air-power-avg.js +0 -4
  31. package/lib/esm/data/data.air-power-max.js +0 -4
  32. package/lib/esm/data/data.air-power-min.js +0 -4
  33. package/lib/esm/data/data.air-power.js +0 -8
  34. package/lib/esm/data/data.alti-baro-profile.js +0 -4
  35. package/lib/esm/data/data.altitude-avg.js +0 -4
  36. package/lib/esm/data/data.altitude-gps.js +0 -5
  37. package/lib/esm/data/data.altitude-max.js +0 -4
  38. package/lib/esm/data/data.altitude-min.js +0 -4
  39. package/lib/esm/data/data.altitude-smooth.js +0 -4
  40. package/lib/esm/data/data.altitude.js +0 -8
  41. package/lib/esm/data/data.array.js +0 -13
  42. package/lib/esm/data/data.ascent-time.js +0 -4
  43. package/lib/esm/data/data.ascent.js +0 -4
  44. package/lib/esm/data/data.auto-lap-distance.js +0 -5
  45. package/lib/esm/data/data.auto-lap-duration.js +0 -4
  46. package/lib/esm/data/data.auto-lap-used.js +0 -7
  47. package/lib/esm/data/data.auto-pause-used.js +0 -7
  48. package/lib/esm/data/data.avg-stride-length.js +0 -4
  49. package/lib/esm/data/data.balance.js +0 -6
  50. package/lib/esm/data/data.bare.js +0 -4
  51. package/lib/esm/data/data.battery-charge.js +0 -8
  52. package/lib/esm/data/data.battery-consumption.js +0 -8
  53. package/lib/esm/data/data.battery-current.js +0 -8
  54. package/lib/esm/data/data.battery-life-estimation.js +0 -4
  55. package/lib/esm/data/data.battery-voltage.js +0 -8
  56. package/lib/esm/data/data.bike-pod-used.js +0 -7
  57. package/lib/esm/data/data.boolean.js +0 -9
  58. package/lib/esm/data/data.cadence-avg.js +0 -4
  59. package/lib/esm/data/data.cadence-max.js +0 -4
  60. package/lib/esm/data/data.cadence-min.js +0 -4
  61. package/lib/esm/data/data.cadence.js +0 -8
  62. package/lib/esm/data/data.cycling-dynamics.js +0 -3
  63. package/lib/esm/data/data.cycling-position.js +0 -37
  64. package/lib/esm/data/data.cycling-seated-time.js +0 -5
  65. package/lib/esm/data/data.cycling-standing-time.js +0 -5
  66. package/lib/esm/data/data.descent-time.js +0 -4
  67. package/lib/esm/data/data.descent.js +0 -4
  68. package/lib/esm/data/data.description.js +0 -4
  69. package/lib/esm/data/data.device-location.js +0 -4
  70. package/lib/esm/data/data.device-names.js +0 -7
  71. package/lib/esm/data/data.distance.js +0 -15
  72. package/lib/esm/data/data.duration.js +0 -56
  73. package/lib/esm/data/data.ehpe.js +0 -5
  74. package/lib/esm/data/data.enabled-navigation-systems.js +0 -4
  75. package/lib/esm/data/data.end-altitude.js +0 -4
  76. package/lib/esm/data/data.end-position.js +0 -4
  77. package/lib/esm/data/data.energy.js +0 -8
  78. package/lib/esm/data/data.epoc.js +0 -5
  79. package/lib/esm/data/data.event.js +0 -3
  80. package/lib/esm/data/data.evpe.js +0 -4
  81. package/lib/esm/data/data.feeling.js +0 -15
  82. package/lib/esm/data/data.foot-pod-used.js +0 -7
  83. package/lib/esm/data/data.form-power.js +0 -4
  84. package/lib/esm/data/data.fused-altitude.js +0 -7
  85. package/lib/esm/data/data.fused-location.js +0 -7
  86. package/lib/esm/data/data.gnss-distance.js +0 -4
  87. package/lib/esm/data/data.grade-adjusted-pace-avg.js +0 -15
  88. package/lib/esm/data/data.grade-adjusted-pace-max.js +0 -15
  89. package/lib/esm/data/data.grade-adjusted-pace-min.js +0 -15
  90. package/lib/esm/data/data.grade-adjusted-pace.js +0 -25
  91. package/lib/esm/data/data.grade-adjusted-speed-avg.js +0 -46
  92. package/lib/esm/data/data.grade-adjusted-speed-max.js +0 -46
  93. package/lib/esm/data/data.grade-adjusted-speed-min.js +0 -46
  94. package/lib/esm/data/data.grade-adjusted-speed.js +0 -78
  95. package/lib/esm/data/data.grade-smooth.js +0 -7
  96. package/lib/esm/data/data.grade.js +0 -7
  97. package/lib/esm/data/data.ground-time.js +0 -8
  98. package/lib/esm/data/data.heart-rate-avg.js +0 -4
  99. package/lib/esm/data/data.heart-rate-max.js +0 -4
  100. package/lib/esm/data/data.heart-rate-min.js +0 -4
  101. package/lib/esm/data/data.heart-rate-used.js +0 -7
  102. package/lib/esm/data/data.heart-rate-zone-five-duration.js +0 -4
  103. package/lib/esm/data/data.heart-rate-zone-four-duration.js +0 -4
  104. package/lib/esm/data/data.heart-rate-zone-one-duration.js +0 -4
  105. package/lib/esm/data/data.heart-rate-zone-three-duration.js +0 -4
  106. package/lib/esm/data/data.heart-rate-zone-two-duration.js +0 -4
  107. package/lib/esm/data/data.heart-rate.js +0 -8
  108. package/lib/esm/data/data.ibi.js +0 -8
  109. package/lib/esm/data/data.interface.js +0 -5
  110. package/lib/esm/data/data.js +0 -62
  111. package/lib/esm/data/data.json.interface.js +0 -1
  112. package/lib/esm/data/data.latitude-degrees.js +0 -5
  113. package/lib/esm/data/data.left-balance.js +0 -4
  114. package/lib/esm/data/data.leg-stiffness.js +0 -16
  115. package/lib/esm/data/data.longitude-degrees.js +0 -5
  116. package/lib/esm/data/data.moving-time.js +0 -4
  117. package/lib/esm/data/data.number-of-satellites.js +0 -7
  118. package/lib/esm/data/data.number-of.samples.js +0 -4
  119. package/lib/esm/data/data.number.js +0 -13
  120. package/lib/esm/data/data.pace-avg.js +0 -8
  121. package/lib/esm/data/data.pace-max.js +0 -8
  122. package/lib/esm/data/data.pace-min.js +0 -8
  123. package/lib/esm/data/data.pace.js +0 -46
  124. package/lib/esm/data/data.pause.js +0 -4
  125. package/lib/esm/data/data.peak-epoc.js +0 -7
  126. package/lib/esm/data/data.peak-training-effect.js +0 -4
  127. package/lib/esm/data/data.percent.js +0 -4
  128. package/lib/esm/data/data.pool-length.js +0 -5
  129. package/lib/esm/data/data.position.interface.js +0 -1
  130. package/lib/esm/data/data.position.js +0 -18
  131. package/lib/esm/data/data.power-avg.js +0 -4
  132. package/lib/esm/data/data.power-down.js +0 -4
  133. package/lib/esm/data/data.power-intensity-factor.js +0 -5
  134. package/lib/esm/data/data.power-left.js +0 -4
  135. package/lib/esm/data/data.power-max.js +0 -4
  136. package/lib/esm/data/data.power-min.js +0 -4
  137. package/lib/esm/data/data.power-normalized.js +0 -4
  138. package/lib/esm/data/data.power-pedal-smoothness-left.js +0 -4
  139. package/lib/esm/data/data.power-pedal-smoothness-right.js +0 -4
  140. package/lib/esm/data/data.power-pod-used.js +0 -7
  141. package/lib/esm/data/data.power-right.js +0 -4
  142. package/lib/esm/data/data.power-torque-effectiveness-left.js +0 -4
  143. package/lib/esm/data/data.power-torque-effectiveness-right.js +0 -4
  144. package/lib/esm/data/data.power-training-stress-score.js +0 -5
  145. package/lib/esm/data/data.power-up.js +0 -4
  146. package/lib/esm/data/data.power-work.js +0 -5
  147. package/lib/esm/data/data.power-zone-five-duration.js +0 -4
  148. package/lib/esm/data/data.power-zone-four-duration.js +0 -4
  149. package/lib/esm/data/data.power-zone-one-duration.js +0 -4
  150. package/lib/esm/data/data.power-zone-three-duration.js +0 -4
  151. package/lib/esm/data/data.power-zone-two-duration.js +0 -4
  152. package/lib/esm/data/data.power.js +0 -8
  153. package/lib/esm/data/data.recovery-time.js +0 -7
  154. package/lib/esm/data/data.rider-position-change-event.js +0 -8
  155. package/lib/esm/data/data.right-balance.js +0 -4
  156. package/lib/esm/data/data.rpe.js +0 -23
  157. package/lib/esm/data/data.satellite-5-best-snr.js +0 -4
  158. package/lib/esm/data/data.sea-level-pressure.js +0 -5
  159. package/lib/esm/data/data.spec.js +0 -25
  160. package/lib/esm/data/data.speed-avg.js +0 -46
  161. package/lib/esm/data/data.speed-max.js +0 -46
  162. package/lib/esm/data/data.speed-min.js +0 -46
  163. package/lib/esm/data/data.speed-zone-five-duration.js +0 -4
  164. package/lib/esm/data/data.speed-zone-four-duration.js +0 -4
  165. package/lib/esm/data/data.speed-zone-one-duration.js +0 -4
  166. package/lib/esm/data/data.speed-zone-three-duration.js +0 -4
  167. package/lib/esm/data/data.speed-zone-two-duration.js +0 -4
  168. package/lib/esm/data/data.speed.js +0 -88
  169. package/lib/esm/data/data.sport-profile-name.js +0 -4
  170. package/lib/esm/data/data.stance-time.js +0 -5
  171. package/lib/esm/data/data.start-altitude.js +0 -4
  172. package/lib/esm/data/data.start-event.js +0 -4
  173. package/lib/esm/data/data.start-position.js +0 -4
  174. package/lib/esm/data/data.step-length.js +0 -4
  175. package/lib/esm/data/data.steps-old.js +0 -4
  176. package/lib/esm/data/data.steps.js +0 -4
  177. package/lib/esm/data/data.stop-all-event.js +0 -4
  178. package/lib/esm/data/data.stop-event.js +0 -4
  179. package/lib/esm/data/data.store.export.spec.js +0 -66
  180. package/lib/esm/data/data.store.js +0 -1213
  181. package/lib/esm/data/data.string.js +0 -13
  182. package/lib/esm/data/data.stryd-altitude.js +0 -4
  183. package/lib/esm/data/data.stryd-distance.js +0 -4
  184. package/lib/esm/data/data.stryd-speed.js +0 -4
  185. package/lib/esm/data/data.swim-pace-avg.js +0 -8
  186. package/lib/esm/data/data.swim-pace-max.js +0 -8
  187. package/lib/esm/data/data.swim-pace-min.js +0 -8
  188. package/lib/esm/data/data.swim-pace.js +0 -19
  189. package/lib/esm/data/data.swolf-25m.js +0 -4
  190. package/lib/esm/data/data.swolf-50m.js +0 -4
  191. package/lib/esm/data/data.target-distance.js +0 -4
  192. package/lib/esm/data/data.target-heart-rate-zone.js +0 -4
  193. package/lib/esm/data/data.target-power-zone.js +0 -4
  194. package/lib/esm/data/data.target-speed-zone.js +0 -4
  195. package/lib/esm/data/data.target-time.js +0 -4
  196. package/lib/esm/data/data.temperature-avg.js +0 -4
  197. package/lib/esm/data/data.temperature-max.js +0 -4
  198. package/lib/esm/data/data.temperature-min.js +0 -4
  199. package/lib/esm/data/data.temperature.js +0 -8
  200. package/lib/esm/data/data.time.js +0 -6
  201. package/lib/esm/data/data.timer-time.js +0 -4
  202. package/lib/esm/data/data.vertical-oscillation.js +0 -5
  203. package/lib/esm/data/data.vertical-ratio.js +0 -5
  204. package/lib/esm/data/data.vertical-speed-avg.js +0 -53
  205. package/lib/esm/data/data.vertical-speed-max.js +0 -53
  206. package/lib/esm/data/data.vertical-speed-min.js +0 -53
  207. package/lib/esm/data/data.vertical-speed.js +0 -103
  208. package/lib/esm/data/data.vo2-max.js +0 -7
  209. package/lib/esm/data/ibi/data.ibi.filters.js +0 -52
  210. package/lib/esm/data/ibi/data.ibi.js +0 -98
  211. package/lib/esm/data/ibi/data.ibi.spec.js +0 -66
  212. package/lib/esm/duration/duration.class.abstract.js +0 -36
  213. package/lib/esm/duration/duration.class.interface.js +0 -1
  214. package/lib/esm/errors/duration-exceeded-event-lib.error.js +0 -9
  215. package/lib/esm/errors/empty-event-sports-libs.error.js +0 -9
  216. package/lib/esm/errors/event-lib.error.js +0 -8
  217. package/lib/esm/errors/lib.error.js +0 -6
  218. package/lib/esm/errors/parsing-event-lib.error.js +0 -9
  219. package/lib/esm/events/adapters/exporters/exporter.gpx.js +0 -75
  220. package/lib/esm/events/adapters/exporters/exporter.interface.js +0 -1
  221. package/lib/esm/events/adapters/exporters/exporter.json.js +0 -20
  222. package/lib/esm/events/adapters/file-type.enum.js +0 -7
  223. package/lib/esm/events/adapters/importers/fit/importer.fit.ant-plus.device.names.js +0 -25
  224. package/lib/esm/events/adapters/importers/fit/importer.fit.coros.device.names.js +0 -5
  225. package/lib/esm/events/adapters/importers/fit/importer.fit.development.device.names.js +0 -4
  226. package/lib/esm/events/adapters/importers/fit/importer.fit.garmin.device.names.js +0 -462
  227. package/lib/esm/events/adapters/importers/fit/importer.fit.garmin.profile.data.js +0 -877
  228. package/lib/esm/events/adapters/importers/fit/importer.fit.garmin.profile.mapper.js +0 -106
  229. package/lib/esm/events/adapters/importers/fit/importer.fit.garmin.profile.mapper.spec.js +0 -32
  230. package/lib/esm/events/adapters/importers/fit/importer.fit.hammerhead.device.names.js +0 -4
  231. package/lib/esm/events/adapters/importers/fit/importer.fit.integration.spec.js +0 -44
  232. package/lib/esm/events/adapters/importers/fit/importer.fit.js +0 -978
  233. package/lib/esm/events/adapters/importers/fit/importer.fit.lezyne.device.names.js +0 -3
  234. package/lib/esm/events/adapters/importers/fit/importer.fit.magellan.device.names.js +0 -5
  235. package/lib/esm/events/adapters/importers/fit/importer.fit.mapper.js +0 -231
  236. package/lib/esm/events/adapters/importers/fit/importer.fit.saris.device.names.js +0 -3
  237. package/lib/esm/events/adapters/importers/fit/importer.fit.spec.js +0 -326
  238. package/lib/esm/events/adapters/importers/fit/importer.fit.srm.device.names.js +0 -7
  239. package/lib/esm/events/adapters/importers/fit/importer.fit.suunto.device.names.js +0 -16
  240. package/lib/esm/events/adapters/importers/fit/importer.fit.wahoo.device.names.js +0 -10
  241. package/lib/esm/events/adapters/importers/gpx/gx-parser.js +0 -36
  242. package/lib/esm/events/adapters/importers/gpx/importer.gpx.integration.spec.js +0 -44
  243. package/lib/esm/events/adapters/importers/gpx/importer.gpx.js +0 -102
  244. package/lib/esm/events/adapters/importers/gpx/importer.gpx.mapper.js +0 -142
  245. package/lib/esm/events/adapters/importers/gpx/importer.gpx.spec.js +0 -71
  246. package/lib/esm/events/adapters/importers/json/importer.json.js +0 -160
  247. package/lib/esm/events/adapters/importers/sample-info.interface.js +0 -1
  248. package/lib/esm/events/adapters/importers/suunto/importer.suunto.activity.ids.js +0 -85
  249. package/lib/esm/events/adapters/importers/suunto/importer.suunto.device.names.js +0 -26
  250. package/lib/esm/events/adapters/importers/suunto/importer.suunto.integration.spec.js +0 -44
  251. package/lib/esm/events/adapters/importers/suunto/importer.suunto.json.js +0 -717
  252. package/lib/esm/events/adapters/importers/suunto/importer.suunto.sml.js +0 -125
  253. package/lib/esm/events/adapters/importers/tcx/importer.tcx.integration.spec.js +0 -46
  254. package/lib/esm/events/adapters/importers/tcx/importer.tcx.js +0 -442
  255. package/lib/esm/events/adapters/importers/tcx/importer.tcx.mapper.js +0 -91
  256. package/lib/esm/events/adapters/importers/tcx/utils.tcx.js +0 -36
  257. package/lib/esm/events/event.interface.js +0 -1
  258. package/lib/esm/events/event.js +0 -123
  259. package/lib/esm/events/event.json.interface.js +0 -1
  260. package/lib/esm/events/event.spec.js +0 -51
  261. package/lib/esm/events/utilities/activity.utilities.js +0 -1841
  262. package/lib/esm/events/utilities/activity.utilities.spec.js +0 -373
  263. package/lib/esm/events/utilities/event.utilities.js +0 -57
  264. package/lib/esm/events/utilities/grade-calculator/grade-calculator.js +0 -121
  265. package/lib/esm/events/utilities/grade-calculator/grade-calculator.spec.js +0 -93
  266. package/lib/esm/events/utilities/grade-calculator/low-pass-filter.js +0 -86
  267. package/lib/esm/events/utilities/helpers.js +0 -162
  268. package/lib/esm/geodesy/adapters/adapter.interface.js +0 -1
  269. package/lib/esm/geodesy/adapters/geolib.adapter.js +0 -28
  270. package/lib/esm/id/id.abstract.class.js +0 -9
  271. package/lib/esm/id/id.class.interface.js +0 -1
  272. package/lib/esm/id/id.class.spec.js +0 -13
  273. package/lib/esm/intensity-zones/intensity-zones.interface.js +0 -1
  274. package/lib/esm/intensity-zones/intensity-zones.js +0 -29
  275. package/lib/esm/intensity-zones/intensity-zones.json.interface.js +0 -1
  276. package/lib/esm/intensity-zones/intensity-zones.spec.js +0 -30
  277. package/lib/esm/laps/lap.interface.js +0 -1
  278. package/lib/esm/laps/lap.js +0 -29
  279. package/lib/esm/laps/lap.json.interface.js +0 -1
  280. package/lib/esm/laps/lap.types.js +0 -52
  281. package/lib/esm/meta-data/event-meta-data.interface.js +0 -6
  282. package/lib/esm/meta-data/meta-data.js +0 -57
  283. package/lib/esm/meta-data/meta-data.json.interface.js +0 -1
  284. package/lib/esm/privacy/privacy.class.interface.js +0 -5
  285. package/lib/esm/serializable/serializable.class.interface.js +0 -1
  286. package/lib/esm/service-tokens/oauth1-service-token.interface.js +0 -1
  287. package/lib/esm/service-tokens/oauth2-service-token.interface.js +0 -1
  288. package/lib/esm/specs/activities-parsing.integration.spec.js +0 -1847
  289. package/lib/esm/specs/activity-duration-stream.integration.spec.js +0 -57
  290. package/lib/esm/specs/fixtures/streams/strava/rides/3171472783.json +0 -52534
  291. package/lib/esm/specs/fixtures/streams/strava/rides/3171487458.json +0 -78818
  292. package/lib/esm/specs/fixtures/streams/strava/rides/343080886.json +0 -105090
  293. package/lib/esm/specs/fixtures/streams/strava/rides/5910143591.json +0 -110711
  294. package/lib/esm/specs/fixtures/streams/strava/runs/2451375851.json +0 -74846
  295. package/lib/esm/specs/fixtures/streams/strava/runs/2709634581.json +0 -66817
  296. package/lib/esm/specs/fixtures/streams/strava/runs/3156040843.json +0 -17594
  297. package/lib/esm/specs/fixtures/streams/strava/runs/3182900697.json +0 -17322
  298. package/lib/esm/specs/fixtures/streams/strava/runs/3183465494.json +0 -20463
  299. package/lib/esm/specs/fixtures/streams/strava/runs/3183490558.json +0 -58202
  300. package/lib/esm/specs/spec-utils.js +0 -159
  301. package/lib/esm/specs/strava-streams-compliance.spec.js +0 -951
  302. package/lib/esm/stats/stats.class.abstract.js +0 -32
  303. package/lib/esm/stats/stats.class.interface.js +0 -1
  304. package/lib/esm/stats/stats.json.interface.js +0 -1
  305. package/lib/esm/streams/compressed.stream.interface.js +0 -12
  306. package/lib/esm/streams/ibi-stream.js +0 -43
  307. package/lib/esm/streams/low-pass.stream.filter.js +0 -9
  308. package/lib/esm/streams/stream.filter.interface.js +0 -1
  309. package/lib/esm/streams/stream.interface.js +0 -1
  310. package/lib/esm/streams/stream.js +0 -72
  311. package/lib/esm/streams/stream.spec.js +0 -168
  312. package/lib/esm/tiles/tile.settings.interface.js +0 -41
  313. package/lib/esm/users/settings/dashboard/user.dashboard.settings.interface.js +0 -13
  314. package/lib/esm/users/settings/user.app.settings.interface.js +0 -5
  315. package/lib/esm/users/settings/user.chart.settings.interface.js +0 -23
  316. package/lib/esm/users/settings/user.map.settings.interface.js +0 -22
  317. package/lib/esm/users/settings/user.my-tracks.settings.interface.js +0 -1
  318. package/lib/esm/users/settings/user.settings.interface.js +0 -1
  319. package/lib/esm/users/settings/user.stats-settings.interface.js +0 -1
  320. package/lib/esm/users/settings/user.summaries.settings.interface.js +0 -1
  321. package/lib/esm/users/settings/user.unit.settings.interface.js +0 -73
  322. package/lib/esm/users/user.account.privileges.interface.js +0 -1
  323. package/lib/esm/users/user.export-to-csv.settings.interface.js +0 -1
  324. package/lib/esm/users/user.interface.js +0 -1
  325. package/lib/esm/users/user.js +0 -38
  326. package/lib/esm/users/user.service.meta.interface.js +0 -1
@@ -1,125 +0,0 @@
1
- import { EventImporterSuuntoJSON } from './importer.suunto.json';
2
- import { isNumber } from '../../../utilities/helpers';
3
- import { ActivityParsingOptions } from '../../../../activities/activity-parsing-options';
4
- import { XMLParser } from 'fast-xml-parser';
5
- export class EventImporterSuuntoSML {
6
- static getFromXML(contents, options = ActivityParsingOptions.DEFAULT, name = 'New Event') {
7
- const parser = new XMLParser();
8
- const json = parser.parse(contents).sml;
9
- // debugger;
10
- // A few mods here to convert it to compatible json suunto string
11
- json.DeviceLog.Samples = json.DeviceLog.Samples.Sample;
12
- const samplesWithUTC = json.DeviceLog.Samples.filter((sample) => !!sample.UTC);
13
- // Find the first UTC timestamped sample and use it later for start date
14
- const startDate = samplesWithUTC.length
15
- ? new Date(samplesWithUTC[0].UTC)
16
- : new Date(json.DeviceLog.Header.DateTime);
17
- // Determine the end date
18
- const endDate = samplesWithUTC.length > 1
19
- ? samplesWithUTC[samplesWithUTC.length - 1].UTC
20
- : new Date(startDate.getTime() + json.DeviceLog.Header.Duration * 1000);
21
- // Filter out the old activity type
22
- json.DeviceLog.Samples = json.DeviceLog.Samples.filter((sample) => {
23
- return !(sample.Events && sample.Events.Activity);
24
- });
25
- // Convert the events
26
- json.DeviceLog.Samples.filter((sample) => !!sample.Events).forEach((sample) => {
27
- sample.Events = [sample.Events];
28
- });
29
- // Inject start and end sample with event
30
- json.DeviceLog.Samples.unshift({
31
- Events: [
32
- {
33
- Activity: { ActivityType: json.DeviceLog.Header.ActivityType }
34
- }
35
- ],
36
- TimeISO8601: startDate.toISOString()
37
- });
38
- // Add the end time and adjust the start time
39
- json.DeviceLog.Header.TimeISO8601 = json.DeviceLog.Header.TimeISO8601 || endDate;
40
- // Add the time on the samples
41
- json.DeviceLog.Samples.forEach((sample) => {
42
- if (sample.TimeISO8601) {
43
- return;
44
- }
45
- if (sample.UTC) {
46
- sample.TimeISO8601 = new Date(sample.UTC).toISOString();
47
- return;
48
- }
49
- if (isNumber(sample.Time)) {
50
- sample.TimeISO8601 = new Date(startDate.getTime() + sample.Time * 1000).toISOString();
51
- return;
52
- }
53
- });
54
- // Convert the RR
55
- if (json.DeviceLog['R-R']) {
56
- json.DeviceLog['R-R'].Data = json.DeviceLog['R-R'].Data.split(' ').map((dataString) => Number(dataString));
57
- }
58
- json.DeviceLog.Header.Altitude = json.DeviceLog.Header.Altitude ? [json.DeviceLog.Header.Altitude] : null;
59
- json.DeviceLog.Header.HR = json.DeviceLog.Header.HR ? [json.DeviceLog.Header.HR] : null;
60
- json.DeviceLog.Header.Cadence = json.DeviceLog.Header.Cadence ? [json.DeviceLog.Header.Cadence] : null;
61
- json.DeviceLog.Header.Speed = json.DeviceLog.Header.Speed ? [json.DeviceLog.Header.Speed] : null;
62
- json.DeviceLog.Header.Power = json.DeviceLog.Header.Power ? [json.DeviceLog.Header.Power] : null;
63
- json.DeviceLog.Header.Temperature = json.DeviceLog.Header.Temperature ? [json.DeviceLog.Header.Temperature] : null;
64
- json.DeviceLog.Windows = [{ Window: Object.assign({ Type: 'Activity' }, json.DeviceLog.Header) }];
65
- // debugger;
66
- return EventImporterSuuntoJSON.getFromJSONString(JSON.stringify(json), options);
67
- }
68
- static getFromJSONString(jsonString, options = ActivityParsingOptions.DEFAULT) {
69
- const json = JSON.parse(jsonString);
70
- let samples;
71
- // Try to be a hero here
72
- try {
73
- samples = json.Samples.filter((sample) => !!JSON.parse(sample.Attributes)['suunto/sml'].Sample).map((sample) => {
74
- return Object.assign({ TimeISO8601: sample.TimeISO8601 }, JSON.parse(sample.Attributes)['suunto/sml'].Sample);
75
- });
76
- }
77
- catch (e) {
78
- samples = json.Samples.filter((sample) => !!sample.Attributes['suunto/sml'].Sample).map((sample) => {
79
- return Object.assign({ TimeISO8601: sample.TimeISO8601 }, sample.Attributes['suunto/sml'].Sample);
80
- });
81
- }
82
- let rr;
83
- try {
84
- rr = {
85
- Data: json.Samples.filter((sample) => !!JSON.parse(sample.Attributes)['suunto/sml']['R-R'])
86
- .map((sample) => {
87
- return JSON.parse(sample.Attributes)['suunto/sml']['R-R'];
88
- })
89
- .reduce((accu, rrSample) => {
90
- return accu.concat(rrSample.Data.split(',').map((dataString) => Number(dataString)));
91
- }, [])
92
- };
93
- }
94
- catch (e) {
95
- rr = {
96
- Data: json.Samples.filter((sample) => !!sample.Attributes['suunto/sml']['R-R'])
97
- .map((sample) => {
98
- return sample.Attributes['suunto/sml']['R-R'];
99
- })
100
- .reduce((accu, rrSample) => {
101
- return accu.concat(rrSample.IBI);
102
- }, [])
103
- };
104
- }
105
- // debugger;
106
- const suuntoJSON = {
107
- DeviceLog: {
108
- Header: {},
109
- Device: {
110
- Name: 'Suunto unknown',
111
- Info: {
112
- HW: 0,
113
- SW: 0,
114
- SerialNumber: 0
115
- }
116
- },
117
- Windows: [],
118
- Samples: samples,
119
- ['R-R']: rr
120
- }
121
- };
122
- // debugger;
123
- return EventImporterSuuntoJSON.getFromJSONString(JSON.stringify(suuntoJSON), options);
124
- }
125
- }
@@ -1,46 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import * as fs from 'fs';
11
- import * as path from 'path';
12
- import { DOMParser } from '@xmldom/xmldom';
13
- import { EventImporterTCX } from './importer.tcx';
14
- describe('EventImporterTCX Integration', () => {
15
- // Go up 5 levels from src/events/adapters/importers/tcx -> sports-lib root
16
- const samplesDir = path.resolve(__dirname, '../../../../../samples/tcx');
17
- it('should parse all sample tcx files', () => __awaiter(void 0, void 0, void 0, function* () {
18
- if (!fs.existsSync(samplesDir)) {
19
- console.warn(`Samples directory not found at ${samplesDir}. Skipping integration tests.`);
20
- return;
21
- }
22
- const files = fs.readdirSync(samplesDir).filter(f => f.endsWith('.tcx'));
23
- if (files.length === 0) {
24
- console.warn('No .tcx files found in samples directory.');
25
- return;
26
- }
27
- console.log(`Found ${files.length} .tcx files to test:`, files);
28
- const parser = new DOMParser();
29
- for (const file of files) {
30
- const filePath = path.join(samplesDir, file);
31
- const fileString = fs.readFileSync(filePath, 'utf-8');
32
- try {
33
- // Parse string to XML Document
34
- const xmlDoc = parser.parseFromString(fileString, 'text/xml');
35
- const event = yield EventImporterTCX.getFromXML(xmlDoc, undefined, file);
36
- expect(event).toBeDefined();
37
- expect(event.getActivities().length).toBeGreaterThan(0);
38
- console.log(`✅ Successfully parsed ${file}`);
39
- }
40
- catch (error) {
41
- console.error(`❌ Failed to parse ${file}:`, error);
42
- throw error;
43
- }
44
- }
45
- }));
46
- });
@@ -1,442 +0,0 @@
1
- import { Event } from '../../../event';
2
- import { Activity } from '../../../../activities/activity';
3
- import { Creator } from '../../../../creators/creator';
4
- import { Lap } from '../../../../laps/lap';
5
- import { DataEnergy } from '../../../../data/data.energy';
6
- import { DataDuration } from '../../../../data/data.duration';
7
- import { DataDistance } from '../../../../data/data.distance';
8
- import { DataPause } from '../../../../data/data.pause';
9
- import { DataSpeedMax } from '../../../../data/data.speed-max';
10
- import { DataHeartRateAvg } from '../../../../data/data.heart-rate-avg';
11
- import { DataHeartRateMax } from '../../../../data/data.heart-rate-max';
12
- import { ActivityTypes, ActivityTypesMoving } from '../../../../activities/activity.types';
13
- import { DataSpeedAvg } from '../../../../data/data.speed-avg';
14
- import { LapTypes } from '../../../../laps/lap.types';
15
- import { ImporterSuuntoDeviceNames } from '../suunto/importer.suunto.device.names';
16
- import { TCXSampleMapper } from './importer.tcx.mapper';
17
- import { EventUtilities } from '../../../utilities/event.utilities';
18
- import { convertSpeedToPace, isNumber } from '../../../utilities/helpers';
19
- import { DataMovingTime } from '../../../../data/data.moving-time';
20
- import { DataTimerTime } from '../../../../data/data.timer-time';
21
- import { findLapExtensionValue, findTrackPointExtensionValue } from './utils.tcx';
22
- import { DataTotalCycles } from '../../../../data/data-total-cycles';
23
- import { DataPaceAvg } from '../../../../data/data.pace-avg';
24
- import { ActivityUtilities } from '../../../utilities/activity.utilities';
25
- import { DataPowerAvg } from '../../../../data/data.power-avg';
26
- import { DataPowerMax } from '../../../../data/data.power-max';
27
- import { DataCadenceAvg } from '../../../../data/data.cadence-avg';
28
- import { DataActiveLap } from '../../../../data/data-active-lap';
29
- import { DataSWOLF25m } from '../../../../data/data.swolf-25m';
30
- import { DataSWOLF50m } from '../../../../data/data.swolf-50m';
31
- import { FileType } from '../../file-type.enum';
32
- import { DataCadence } from '../../../../data/data.cadence';
33
- import { ActivityParsingOptions } from '../../../../activities/activity-parsing-options';
34
- export class EventImporterTCX {
35
- /**
36
- * Returns active or rest state of a lap. This is pretty use-full on swim pool activities which are decomposed of many active or rest laps
37
- */
38
- static isActiveLap(lapElement) {
39
- const lapHasDistance = lapElement.getElementsByTagName('DistanceMeters').length > 0;
40
- const lapHasMaxSpeed = lapElement.getElementsByTagName('MaximumSpeed').length > 0;
41
- let lapDistance = 0;
42
- let lapMaxSpeed = 0;
43
- if (lapHasDistance) {
44
- lapDistance = Number(lapElement.getElementsByTagName('DistanceMeters')[0].textContent);
45
- }
46
- if (lapHasMaxSpeed) {
47
- lapMaxSpeed = Number(lapElement.getElementsByTagName('MaximumSpeed')[0].textContent);
48
- }
49
- return lapDistance > 0 || lapMaxSpeed > 0;
50
- }
51
- static getFromXML(xml, options = ActivityParsingOptions.DEFAULT, name = 'New Event') {
52
- return new Promise((resolve, reject) => {
53
- // Activities
54
- const activities = Array.from(xml.getElementsByTagName('TrainingCenterDatabase')[0].getElementsByTagName('Activity')).map(activityElement => {
55
- var _a;
56
- // Getting activity type
57
- const activityType = ActivityTypes[activityElement.getAttribute('Sport') || 'unknown'];
58
- // TCX begins with laps, get them
59
- const laps = this.getLaps(activityElement.getElementsByTagName('Lap'), activityType);
60
- // Create activity
61
- const startDate = new Date(activityElement.getElementsByTagName('Lap')[0].getAttribute('StartTime'));
62
- const endDate = laps[laps.length - 1].endDate;
63
- let activity = new Activity(startDate, endDate, activityType, this.getCreator(activityElement.getElementsByTagName('Creator')[0]), options);
64
- // Extract activity stats from laps retrieved
65
- activity = this.extractAndAssignActivityStatsFromLaps(laps, activity);
66
- // Extract activity stats provided by the root tcx file
67
- activity = this.extractAndAssignActivityStatsFromTcxRootDef(activityElement, activity);
68
- // Creates a array of track points elements
69
- let hasGpsData = false;
70
- const trackPointElements = Array.from(activityElement.getElementsByTagName('Lap')).reduce((trackPointElementArray, lapElement) => {
71
- Array.from(lapElement.getElementsByTagName('Trackpoint')).forEach(trackPointElement => {
72
- trackPointElementArray.push(trackPointElement);
73
- if (!hasGpsData) {
74
- hasGpsData = !!trackPointElement.getElementsByTagName('Position')[0];
75
- }
76
- });
77
- return trackPointElementArray;
78
- }, []);
79
- // Update activity type to indoor when no GPS data detected
80
- activity = this.updateActivityTypeCaseIndoor(hasGpsData, activity);
81
- if (!((_a = activity.getDistance()) === null || _a === void 0 ? void 0 : _a.getValue()) &&
82
- trackPointElements.length &&
83
- trackPointElements[trackPointElements.length - 1].getElementsByTagName('DistanceMeters')[0]) {
84
- // If the distance from laps is 0 and there is a last track-point with distance use that
85
- activity.setDistance(new DataDistance(Number(trackPointElements[trackPointElements.length - 1].getElementsByTagName('DistanceMeters')[0].textContent)));
86
- }
87
- // Setup sample info which could be use when getting sample values
88
- const hasPowerMeter = trackPointElements.findIndex(trackPointElement => Number.isFinite(findTrackPointExtensionValue(trackPointElement.childNodes, 'Watts'))) !== -1;
89
- const samplesInfo = { hasPowerMeter: hasPowerMeter };
90
- TCXSampleMapper.forEach(sampleMapping => {
91
- // Should check the children
92
- const subjectTrackPointElements = trackPointElements.filter((element) => {
93
- return isNumber(sampleMapping.getSampleValue(element, samplesInfo));
94
- });
95
- if (subjectTrackPointElements.length) {
96
- if (activity.hasStreamData(sampleMapping.dataType)) {
97
- return;
98
- }
99
- activity.addStream(activity.createStream(sampleMapping.dataType));
100
- subjectTrackPointElements.forEach((subjectTrackPointElement) => {
101
- activity.addDataToStream(sampleMapping.dataType, new Date(subjectTrackPointElement.getElementsByTagName('Time')[0].textContent), sampleMapping.getSampleValue(subjectTrackPointElement, samplesInfo));
102
- });
103
- }
104
- });
105
- return activity;
106
- });
107
- // Init the event
108
- const event = new Event(name, activities[0].startDate, activities[activities.length - 1].endDate, FileType.TCX);
109
- activities.forEach(activity => event.addActivity(activity));
110
- EventUtilities.generateStatsForAll(event);
111
- resolve(event);
112
- });
113
- }
114
- static updateActivityTypeCaseIndoor(hasGpsData, activity) {
115
- if (!hasGpsData) {
116
- switch (activity.type) {
117
- case ActivityTypes.Running:
118
- activity.type = ActivityTypes.IndoorRunning;
119
- break;
120
- case ActivityTypes.Cycling:
121
- activity.type = ActivityTypes.IndoorCycling;
122
- break;
123
- case ActivityTypes.Rowing:
124
- activity.type = ActivityTypes.IndoorRowing;
125
- break;
126
- }
127
- }
128
- return activity;
129
- }
130
- /**
131
- * Extract activity stats from laps retrieved
132
- */
133
- static extractAndAssignActivityStatsFromLaps(laps, activity) {
134
- // Go over the laps and start filling up the stats and creating the points
135
- laps.forEach((lap) => {
136
- var _a, _b, _c, _d, _e, _f;
137
- if (lap.getDuration().getValue() === 0) {
138
- return;
139
- }
140
- // Append duration to whole activity
141
- if (((_a = lap.getDuration()) === null || _a === void 0 ? void 0 : _a.getValue()) > 0) {
142
- if (!activity.getDuration()) {
143
- activity.setDuration(new DataDuration(0));
144
- }
145
- activity.getDuration().setValue(activity.getDuration().getValue() + lap.getDuration().getValue());
146
- }
147
- // Append timer time to whole activity
148
- if (((_b = lap.getTimer()) === null || _b === void 0 ? void 0 : _b.getValue()) > 0) {
149
- if (!activity.getTimer()) {
150
- activity.setTimer(new DataTimerTime(0));
151
- }
152
- activity.getTimer().setValue(activity.getTimer().getValue() + lap.getTimer().getValue());
153
- }
154
- // Append moving time to whole activity
155
- if (((_c = lap.getMovingTime()) === null || _c === void 0 ? void 0 : _c.getValue()) > 0) {
156
- if (!activity.getMovingTime()) {
157
- activity.setMovingTime(new DataMovingTime(0));
158
- }
159
- activity.getMovingTime().setValue(activity.getMovingTime().getValue() + lap.getMovingTime().getValue());
160
- }
161
- // Append pause time to whole activity
162
- if (((_d = lap.getPause()) === null || _d === void 0 ? void 0 : _d.getValue()) > 0) {
163
- if (!activity.getPause()) {
164
- activity.setPause(new DataPause(0));
165
- }
166
- activity.getPause().setValue(activity.getPause().getValue() + lap.getPause().getValue());
167
- }
168
- // Append distance to whole activity
169
- if (((_e = lap.getDistance()) === null || _e === void 0 ? void 0 : _e.getValue()) > 0) {
170
- if (!activity.getDistance()) {
171
- activity.setDistance(new DataDistance(0));
172
- }
173
- activity.getDistance().setValue(activity.getDistance().getValue() + lap.getDistance().getValue());
174
- }
175
- // Append energy to whole activity
176
- if (((_f = lap.getStat(DataEnergy.type)) === null || _f === void 0 ? void 0 : _f.getValue()) > 0) {
177
- if (!activity.getStat(DataEnergy.type)) {
178
- activity.addStat(new DataEnergy(0));
179
- }
180
- activity.addStat(new DataEnergy(activity.getStat(DataEnergy.type).getValue() +
181
- lap.getStat(DataEnergy.type).getValue()));
182
- }
183
- activity.addLap(lap);
184
- });
185
- // Looping on laps to assign stats to activity
186
- if (laps === null || laps === void 0 ? void 0 : laps.length) {
187
- // Getting avg speed/pace from laps:
188
- const lapAvgSpeeds = laps
189
- .filter(lap => { var _a; return ((_a = lap.getStat(DataSpeedAvg.type)) === null || _a === void 0 ? void 0 : _a.getValue()) >= 0; })
190
- .map(lap => { var _a; return (_a = lap.getStat(DataSpeedAvg.type)) === null || _a === void 0 ? void 0 : _a.getValue(); });
191
- if (lapAvgSpeeds.length) {
192
- const avgSpeed = ActivityUtilities.getAverage(lapAvgSpeeds);
193
- if (avgSpeed > 0) {
194
- activity.addStat(new DataSpeedAvg(avgSpeed));
195
- activity.addStat(new DataPaceAvg(convertSpeedToPace(avgSpeed)));
196
- }
197
- }
198
- // Cycles
199
- const lapTotalsCycles = laps
200
- .map(lap => { var _a; return ((_a = lap.getStat(DataTotalCycles.type)) === null || _a === void 0 ? void 0 : _a.getValue()) || 0; })
201
- .filter(count => count > 0);
202
- if (lapTotalsCycles.length) {
203
- const lapTotalCycles = ActivityUtilities.getSum(lapTotalsCycles);
204
- if (lapTotalCycles > 0) {
205
- activity.addStat(new DataTotalCycles(lapTotalCycles));
206
- }
207
- }
208
- // Avg cadence
209
- const lapDataCadenceAverages = laps
210
- .map(lap => { var _a; return ((_a = lap.getStat(DataCadenceAvg.type)) === null || _a === void 0 ? void 0 : _a.getValue()) || 0; })
211
- .filter(cad => cad > 0);
212
- if (lapDataCadenceAverages.length) {
213
- const dataCadenceAvg = ActivityUtilities.getAverage(lapDataCadenceAverages);
214
- if (dataCadenceAvg > 0) {
215
- activity.addStat(new DataCadenceAvg(Math.round(dataCadenceAvg)));
216
- }
217
- }
218
- }
219
- return activity;
220
- }
221
- /**
222
- * Extract activity stats provided by the root tcx file
223
- */
224
- static extractAndAssignActivityStatsFromTcxRootDef(activityElement, activity) {
225
- var _a, _b;
226
- if (!(((_a = activity.getStat(DataEnergy.type)) === null || _a === void 0 ? void 0 : _a.getValue()) > 0) &&
227
- activityElement.getElementsByTagName('Calories')[0]) {
228
- const calories = Number(activityElement.getElementsByTagName('Calories')[0].textContent);
229
- if (calories > 0) {
230
- activity.addStat(new DataEnergy(calories));
231
- }
232
- }
233
- if (!(((_b = activity.getStat(DataDistance.type)) === null || _b === void 0 ? void 0 : _b.getValue()) > 0) &&
234
- activityElement.getElementsByTagName('DistanceMeters')[0]) {
235
- activity.addStat(new DataDistance(Number(activityElement.getElementsByTagName('DistanceMeters')[0].textContent)));
236
- }
237
- if (activityElement.getElementsByTagName('MaximumSpeed')[0]) {
238
- activity.addStat(new DataSpeedMax(Number(activityElement.getElementsByTagName('MaximumSpeed')[0].textContent)));
239
- }
240
- return activity;
241
- }
242
- static getCreator(creatorElement) {
243
- const creator = new Creator('Unknown Device');
244
- if (!creatorElement) {
245
- return creator;
246
- }
247
- // Try to see if its a listed Suunto Device name
248
- if (creatorElement.getElementsByTagName('Name')[0]) {
249
- creator.name =
250
- ImporterSuuntoDeviceNames[creatorElement.getElementsByTagName('Name')[0].textContent] ||
251
- creatorElement.getElementsByTagName('Name')[0].textContent ||
252
- creator.name;
253
- }
254
- if (creatorElement.getElementsByTagName('Version')[0]) {
255
- creator.swInfo = creatorElement.getElementsByTagName('Version')[0].textContent;
256
- }
257
- return creator;
258
- }
259
- static getLaps(lapElements, activityType) {
260
- return Array.from(lapElements).reduce((lapArray, lapElement, lapIndex) => {
261
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
262
- // Calculating lap time data (moving time, timer time, elapsed time...)
263
- const speedThreshold = ActivityTypesMoving.getSpeedThreshold(activityType);
264
- let movingTime = 0;
265
- let elapsedTime = 0;
266
- const timerTime = lapElement.getElementsByTagName('TotalTimeSeconds').length
267
- ? Number(lapElement.getElementsByTagName('TotalTimeSeconds')[0].textContent)
268
- : 0;
269
- // Loop on track-points to detect moving speed
270
- const trackSpeeds = [];
271
- const trackElements = Array.from(lapElement.getElementsByTagName('Track'));
272
- trackElements.forEach(trackElement => {
273
- var _a;
274
- const trackPointsElements = Array.from(trackElement.getElementsByTagName('Trackpoint'));
275
- if (!(trackPointsElements === null || trackPointsElements === void 0 ? void 0 : trackPointsElements.length)) {
276
- return;
277
- }
278
- // Setting lap elapsed time from first and last track point
279
- const firstTrackPoint = trackPointsElements[0];
280
- const lastTrackPoint = trackPointsElements[trackPointsElements.length - 1];
281
- // Assign elapsed time if time available on first and last point
282
- if ((_a = lastTrackPoint === null || lastTrackPoint === void 0 ? void 0 : lastTrackPoint.getElementsByTagName('Time')) === null || _a === void 0 ? void 0 : _a.length) {
283
- elapsedTime =
284
- (new Date(lastTrackPoint.getElementsByTagName('Time')[0].textContent).getTime() -
285
- new Date(firstTrackPoint.getElementsByTagName('Time')[0].textContent).getTime()) /
286
- 1000;
287
- }
288
- // Parsing each track points to determine moving speed
289
- trackPointsElements.forEach((trackPointElement, index) => {
290
- // Skipping first record to be able to get delta with previous one
291
- if (index === 0) {
292
- return;
293
- }
294
- // Getting current time of track point
295
- const currentTime = new Date(trackPointElement.getElementsByTagName('Time')[0].textContent).getTime();
296
- const previousTime = new Date(trackPointsElements[index - 1].getElementsByTagName('Time')[0].textContent).getTime();
297
- const seconds = (currentTime - previousTime) / 1000;
298
- let speed = findTrackPointExtensionValue(trackPointElement.childNodes, 'Speed');
299
- // Try to get m/s using delta distance if speed extension is missing
300
- if (speed === null) {
301
- // If distance available on track point, then compute speed with it
302
- if (trackPointElement.getElementsByTagName('DistanceMeters').length &&
303
- trackPointsElements[index - 1].getElementsByTagName('DistanceMeters').length) {
304
- const currentDistance = Number(trackPointElement.getElementsByTagName('DistanceMeters')[0].textContent);
305
- const previousDistance = Number(trackPointsElements[index - 1].getElementsByTagName('DistanceMeters')[0].textContent);
306
- const meters = currentDistance - previousDistance;
307
- speed = meters / seconds;
308
- trackSpeeds.push(speed);
309
- }
310
- }
311
- else {
312
- trackSpeeds.push(speed);
313
- }
314
- // We track moving time only if speed available on track points and upper than threshold
315
- if (speed !== null && speed > speedThreshold) {
316
- movingTime += seconds;
317
- }
318
- });
319
- });
320
- // Active or rest lap?
321
- const isActiveLap = this.isActiveLap(lapElement);
322
- // If no moving time detected, try to detect from active laps
323
- if (movingTime === 0) {
324
- // Lap is considered as active. Track moving time..
325
- if (isActiveLap) {
326
- movingTime = timerTime;
327
- }
328
- }
329
- // If elapsed time not defined or lower than timer time then use timer time as elapsed time
330
- if (!elapsedTime || timerTime > elapsedTime) {
331
- elapsedTime = timerTime;
332
- }
333
- // Now creating the lap
334
- const startDate = new Date(lapElement.getAttribute('StartTime'));
335
- const endDate = new Date(startDate);
336
- endDate.setSeconds(endDate.getSeconds() + elapsedTime);
337
- const lap = new Lap(startDate, endDate, lapIndex + 1, LapTypes.AutoLap);
338
- // Add elapsed & timer stats to lap
339
- lap.addStat(new DataDuration(elapsedTime));
340
- lap.addStat(new DataTimerTime(Math.round(timerTime * 10) / 10));
341
- // Append moving stat only if moving time has been detected
342
- // We need that to compute total global moving time later
343
- if (movingTime > 0) {
344
- lap.addStat(new DataMovingTime(Math.round(movingTime * 10) / 10));
345
- }
346
- // Pause TIME on Object (activity, lap...)
347
- const pause = elapsedTime > movingTime ? Math.round((elapsedTime - movingTime) * 100) / 100 : 0;
348
- lap.setPause(new DataPause(pause));
349
- // Assign is active lap status
350
- lap.addStat(new DataActiveLap(isActiveLap));
351
- if (lapElement.getElementsByTagName('TriggerMethod')[0]) {
352
- lap.type = LapTypes[lapElement.getElementsByTagName('TriggerMethod')[0].textContent];
353
- }
354
- if (lapElement.getElementsByTagName('Calories')[0]) {
355
- lap.addStat(new DataEnergy(Number(lapElement.getElementsByTagName('Calories')[0].textContent)));
356
- }
357
- // Create a stats (required TCX fields)
358
- lap.addStat(new DataDistance(0));
359
- if (lapElement.getElementsByTagName('DistanceMeters')[0]) {
360
- lap.addStat(new DataDistance(Number(lapElement.getElementsByTagName('DistanceMeters')[0].textContent)));
361
- }
362
- // Optionals
363
- if (trackSpeeds.length) {
364
- const maxSpeed = ActivityUtilities.getMax(trackSpeeds);
365
- lap.addStat(new DataSpeedMax(maxSpeed));
366
- }
367
- else if (lapElement.getElementsByTagName('MaximumSpeed')[0]) {
368
- const maxSpeed = Number(lapElement.getElementsByTagName('MaximumSpeed')[0].textContent);
369
- lap.addStat(new DataSpeedMax(maxSpeed));
370
- }
371
- if (lapElement.getElementsByTagName('AverageHeartRateBpm')[0]) {
372
- const value = ((_b = (_a = lapElement.getElementsByTagName('AverageHeartRateBpm')[0]) === null || _a === void 0 ? void 0 : _a.getElementsByTagName('Value')[0]) === null || _b === void 0 ? void 0 : _b.textContent) ||
373
- ((_c = lapElement.getElementsByTagName('AverageHeartRateBpm')[0]) === null || _c === void 0 ? void 0 : _c.textContent);
374
- if (value) {
375
- lap.addStat(new DataHeartRateAvg(Number(value)));
376
- }
377
- }
378
- if (lapElement.getElementsByTagName('MaximumHeartRateBpm')[0]) {
379
- const value = ((_e = (_d = lapElement.getElementsByTagName('MaximumHeartRateBpm')[0]) === null || _d === void 0 ? void 0 : _d.getElementsByTagName('Value')[0]) === null || _e === void 0 ? void 0 : _e.textContent) ||
380
- ((_f = lapElement.getElementsByTagName('MaximumHeartRateBpm')[0]) === null || _f === void 0 ? void 0 : _f.textContent);
381
- if (value) {
382
- lap.addStat(new DataHeartRateMax(Number(value)));
383
- }
384
- }
385
- if (lapElement.getElementsByTagName('Cadence')[0]) {
386
- lap.addStat(new DataCadence(Number(lapElement.getElementsByTagName('Cadence')[0].textContent)));
387
- }
388
- // Fetching activity lap speed from records or from extensions if exists according https://www8.garmin.com/xmlschemas/ActivityExtensionv2.xsd schema
389
- const lapAvgSpeed = trackSpeeds.length
390
- ? ActivityUtilities.getAverage(trackSpeeds)
391
- : findLapExtensionValue(lapElement.childNodes, 'AvgSpeed');
392
- if (lapAvgSpeed !== null) {
393
- lap.addStat(new DataSpeedAvg(lapAvgSpeed));
394
- lap.addStat(new DataPaceAvg(convertSpeedToPace(lapAvgSpeed)));
395
- }
396
- // Cycles
397
- const lapTotalCycle = findLapExtensionValue(lapElement.childNodes, 'Steps');
398
- if (lapTotalCycle !== null) {
399
- lap.addStat(new DataTotalCycles(lapTotalCycle));
400
- }
401
- // Avg Watts
402
- const lapAvgWatts = findLapExtensionValue(lapElement.childNodes, 'AvgWatts');
403
- if (lapAvgWatts !== null) {
404
- lap.addStat(new DataPowerAvg(lapAvgWatts));
405
- }
406
- // Max Watts
407
- const lapMaxWatts = findLapExtensionValue(lapElement.childNodes, 'MaxWatts');
408
- if (lapMaxWatts !== null) {
409
- lap.addStat(new DataPowerMax(lapMaxWatts));
410
- }
411
- // AvgRunCadence
412
- const lapAvgRunCadence = findLapExtensionValue(lapElement.childNodes, 'AvgRunCadence');
413
- if (lapAvgRunCadence !== null) {
414
- lap.addStat(new DataCadenceAvg(lapAvgRunCadence));
415
- }
416
- // Try to set avg cadence from total cycle if not set on swimming activities only
417
- if (isActiveLap &&
418
- (activityType === ActivityTypes.Swimming || activityType === ActivityTypes.OpenWaterSwimming) &&
419
- !((_g = lap.getStat(DataCadenceAvg.type)) === null || _g === void 0 ? void 0 : _g.getValue()) &&
420
- timerTime &&
421
- lapTotalCycle) {
422
- const lapAvgCadence = Math.round((lapTotalCycle / timerTime) * 60);
423
- lap.addStat(new DataCadenceAvg(lapAvgCadence));
424
- }
425
- // Average SWOLF in 25m and 50m pool
426
- if (isActiveLap &&
427
- (activityType === ActivityTypes.Swimming || activityType === ActivityTypes.OpenWaterSwimming) &&
428
- ((_h = lap.getStat(DataCadenceAvg.type)) === null || _h === void 0 ? void 0 : _h.getValue()) > 0 &&
429
- ((_j = lap.getStat(DataSpeedAvg.type)) === null || _j === void 0 ? void 0 : _j.getValue()) > 0) {
430
- const avgCadence = lap.getStat(DataCadenceAvg.type).getValue();
431
- const avgSpeed = lap.getStat(DataSpeedAvg.type).getValue();
432
- const avgPace100m = 100 / avgSpeed;
433
- const swolf25m = ActivityUtilities.computeSwimSwolf(avgPace100m, avgCadence, 25);
434
- lap.addStat(new DataSWOLF25m(swolf25m));
435
- const swolf50m = ActivityUtilities.computeSwimSwolf(avgPace100m, avgCadence, 50);
436
- lap.addStat(new DataSWOLF50m(swolf50m));
437
- }
438
- lapArray.push(lap);
439
- return lapArray;
440
- }, []);
441
- }
442
- }