tcx 0.1.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE.md +22 -0
- data/README.md +43 -0
- data/lib/tcx/models/abstract_source.rb +10 -0
- data/lib/tcx/models/activity.rb +11 -0
- data/lib/tcx/models/activity_list.rb +9 -0
- data/lib/tcx/models/base.rb +30 -0
- data/lib/tcx/models/cadence.rb +9 -0
- data/lib/tcx/models/course.rb +12 -0
- data/lib/tcx/models/course_folder.rb +9 -0
- data/lib/tcx/models/course_lap.rb +16 -0
- data/lib/tcx/models/course_list.rb +9 -0
- data/lib/tcx/models/course_point.rb +12 -0
- data/lib/tcx/models/course_point_type.rb +24 -0
- data/lib/tcx/models/courses.rb +7 -0
- data/lib/tcx/models/custom_heart_rate_zone.rb +8 -0
- data/lib/tcx/models/database.rb +11 -0
- data/lib/tcx/models/duration.rb +6 -0
- data/lib/tcx/models/extensions.rb +6 -0
- data/lib/tcx/models/folders.rb +7 -0
- data/lib/tcx/models/gender.rb +10 -0
- data/lib/tcx/models/heart_rate_as_percent_of_max.rb +9 -0
- data/lib/tcx/models/heart_rate_bpm.rb +9 -0
- data/lib/tcx/models/heart_rate_in_beats_per_minute.rb +9 -0
- data/lib/tcx/models/heart_rate_value.rb +10 -0
- data/lib/tcx/models/intensity.rb +10 -0
- data/lib/tcx/models/lap.rb +19 -0
- data/lib/tcx/models/name_key_reference.rb +8 -0
- data/lib/tcx/models/position.rb +8 -0
- data/lib/tcx/models/predefined_heart_rate_zone.rb +7 -0
- data/lib/tcx/models/sensor_state.rb +10 -0
- data/lib/tcx/models/sport.rb +11 -0
- data/lib/tcx/models/step.rb +11 -0
- data/lib/tcx/models/target.rb +10 -0
- data/lib/tcx/models/track.rb +7 -0
- data/lib/tcx/models/trackpoint.rb +15 -0
- data/lib/tcx/models/trigger_method.rb +13 -0
- data/lib/tcx/models/value.rb +9 -0
- data/lib/tcx/models/version.rb +10 -0
- data/lib/tcx/models/workout.rb +10 -0
- data/lib/tcx/models/workout_list.rb +9 -0
- data/lib/tcx/models.rb +40 -0
- data/lib/tcx/version.rb +5 -0
- data/lib/tcx.rb +17 -0
- metadata +129 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2d01c5e7b68db327c2799dedc1bae6129d7e15611fc6150f0e579370e6e88f03
|
|
4
|
+
data.tar.gz: 91be5cd3892f53f44624ee133e0a19fb9bab5d81199529dfacc33a2310d02c79
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5ce16d273b98f168852ae1544b913ee8ac92fc7fda6db73a34c181a1787d1056c8b4883aecb74ce3ebb78ccfeaa3ab518a8ec9fe0a8696368267046bb4bc8113
|
|
7
|
+
data.tar.gz: e1666d5a681fb5e95ccdb59f97a2fb34c64a4b561a68d7e2c47bf2273c718a99bca0bb18480f380dd31ff1396dec742091c75c4036c1161db6a5b76aed5713bd
|
data/CHANGELOG.md
ADDED
data/LICENSE.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Daniel Doubrovkine and Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# TCX
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/rb/tcx)
|
|
4
|
+
[](https://github.com/dblock/tcx/actions/workflows/test.yml)
|
|
5
|
+
|
|
6
|
+
A Garmin Training Center XML (TCX) reader (and future writer). Unlike prior art such as [tcx_rb](https://github.com/keithdoggett/tcx_rb) or [tcxread](https://github.com/firefly-cpp/tcxread), aims to provide a more coherent API by implementing the complete read/write [TCX schema](https://www8.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd) in a more structured way.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
Add to Gemfile.
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
gem 'tcx'
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Run `bundle install`.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
require 'tcx'
|
|
22
|
+
|
|
23
|
+
tcx = Tcx.load_file('examples/multiple_running_activities.tcx') # => Tcx::Database
|
|
24
|
+
|
|
25
|
+
tcx.activities # => [Tcx::Activity]
|
|
26
|
+
...
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
See [examples/multiple_running_activities.rb](examples/multiple_running_activities.rb) for a detailed example.
|
|
30
|
+
|
|
31
|
+
## Upgrading
|
|
32
|
+
|
|
33
|
+
See [UPGRADING](UPGRADING.md).
|
|
34
|
+
|
|
35
|
+
## Contributing
|
|
36
|
+
|
|
37
|
+
See [CONTRIBUTING](CONTRIBUTING.md).
|
|
38
|
+
|
|
39
|
+
## Copyright and License
|
|
40
|
+
|
|
41
|
+
Copyright (c) 2025, [Daniel Doubrovkine](https://twitter.com/dblockdotorg) and [Contributors](CHANGELOG.md).
|
|
42
|
+
|
|
43
|
+
This project is licensed under the [MIT License](LICENSE.md).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class AbstractSource < Base
|
|
5
|
+
property 'name', from: 'Name'
|
|
6
|
+
property 'unit_id', from: 'UnitId'
|
|
7
|
+
property 'product_id', from: 'ProductID'
|
|
8
|
+
property 'version', from: 'Version', transform_with: ->(v) { Version.parse(v) }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Activity < Base
|
|
5
|
+
property 'sport', from: 'Sport', transform_with: ->(v) { Sport.parse(v) }
|
|
6
|
+
property 'id', from: 'Id'
|
|
7
|
+
property 'laps', from: 'Lap', transform_with: ->(v) { to_array(v).map { |el| Lap.parse(el) } }
|
|
8
|
+
property 'notes', from: 'Notes'
|
|
9
|
+
property 'creator', from: 'Creator', transform_with: ->(v) { AbstractSource.parse(v) }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Base < Hashie::Trash
|
|
5
|
+
include Hashie::Extensions::IgnoreUndeclared
|
|
6
|
+
|
|
7
|
+
def self.parse(xml)
|
|
8
|
+
attributes = xml.attributes.to_h
|
|
9
|
+
|
|
10
|
+
xml.children.each do |child|
|
|
11
|
+
next unless child.is_a?(Nokogiri::XML::Element)
|
|
12
|
+
|
|
13
|
+
attributes[child.name] = if attributes.key?(child.name)
|
|
14
|
+
to_array(attributes[child.name]) + [child]
|
|
15
|
+
elsif child.children.one? && child.children.first.is_a?(Nokogiri::XML::Text)
|
|
16
|
+
child.text
|
|
17
|
+
else
|
|
18
|
+
child
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
new attributes
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Transform an XmlElement into [XmlElement], cannot be used with Array or causes a coercion error
|
|
26
|
+
def self.to_array(value)
|
|
27
|
+
value.is_a?(Array) ? value : [value]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Course < Base
|
|
5
|
+
property 'name', from: 'Name'
|
|
6
|
+
property 'laps', from: 'Lap', transform_with: ->(v) { to_array(v).map { |el| CourseLap.parse(el) } }
|
|
7
|
+
property 'tracks', from: 'Track', transform_with: ->(v) { to_array(v).map { |el| Track.parse(el) } }
|
|
8
|
+
property 'notes', from: 'Notes'
|
|
9
|
+
property 'course_points', from: 'CoursePoint', transform_with: ->(v) { to_array(v).map { |el| CoursePoint.parse(el) } }
|
|
10
|
+
property 'creator', from: 'Creator', transform_with: ->(v) { AbstractSource.parse(v) }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class CourseFolder < Base
|
|
5
|
+
property 'folders', from: 'Folder', transform_with: ->(v) { to_array(v).map { |el| CourseFolder.parse(el) } }
|
|
6
|
+
property 'course_references', from: 'CourseNameRef', transform_with: ->(v) { to_array(v).map { |el| NameKeyReference.parse(el) } }
|
|
7
|
+
property 'notes', from: 'Notes'
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class CourseLap < Base
|
|
5
|
+
property 'total_time_seconds', from: 'TotalTimeSeconds', transform_with: lambda(&:to_f)
|
|
6
|
+
property 'distance_meters', from: 'DistanceMeters', transform_with: lambda(&:to_f)
|
|
7
|
+
property 'begin_position', from: 'BeginPosition', transform_with: ->(v) { Position.parse(v) }
|
|
8
|
+
property 'begin_altitude_meters', from: 'BeginAltitudeMeters', transform_with: lambda(&:to_f)
|
|
9
|
+
property 'end_position', from: 'EndPosition', transform_with: ->(v) { Position.parse(v) }
|
|
10
|
+
property 'end_altitude_meters', from: 'EndAltitudeMeters', transform_with: lambda(&:to_f)
|
|
11
|
+
property 'average_heart_rate_bpm', from: 'AverageHeartRateBpm', transform_with: ->(v) { HeartRateInBeatsPerMinute.parse(v) }
|
|
12
|
+
property 'maximum_heart_rate_bpm', from: 'MaximumHeartRateBpm', transform_with: ->(v) { HeartRateInBeatsPerMinute.parse(v) }
|
|
13
|
+
property 'intensity', from: 'Intensity', transform_with: ->(v) { Intensity.parse(v) }
|
|
14
|
+
property 'cadence', from: 'Cadence', transform_with: ->(v) { Cadence.parse(v) }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class CoursePoint < Base
|
|
5
|
+
property 'name', from: 'Name'
|
|
6
|
+
property 'time', from: 'Time', transform_with: ->(v) { Time.parse(v) }
|
|
7
|
+
property 'position', from: 'Position', transform_with: ->(v) { Position.parse(v) }
|
|
8
|
+
property 'altitude_meters', from: 'AltitudeMeters', transform_with: lambda(&:to_f)
|
|
9
|
+
property 'point_type', from: 'PointType', transform_with: ->(v) { CoursePointType.parse(v) }
|
|
10
|
+
property 'notes', from: 'Notes'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class CoursePointType
|
|
5
|
+
include Ruby::Enum
|
|
6
|
+
|
|
7
|
+
define :generic, 'Generic'
|
|
8
|
+
define :summit, 'Summit'
|
|
9
|
+
define :valley, 'Valley'
|
|
10
|
+
define :water, 'Water'
|
|
11
|
+
define :food, 'Food'
|
|
12
|
+
define :danger, 'Danger'
|
|
13
|
+
define :left, 'Left'
|
|
14
|
+
define :right, 'Right'
|
|
15
|
+
define :straight, 'Straight'
|
|
16
|
+
define :first, 'First'
|
|
17
|
+
define :category_4th, '4th Category'
|
|
18
|
+
define :category_3rd, '3rd Category'
|
|
19
|
+
define :category_2nd, '2nd Category'
|
|
20
|
+
define :category_1st, '1st Category'
|
|
21
|
+
define :hors, 'Hors'
|
|
22
|
+
define :sprint, 'Sprint'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Database < Base
|
|
5
|
+
property 'folders', from: 'Folders', transform_with: ->(arr) { Folders.parse(arr) }
|
|
6
|
+
property 'activities', from: 'Activities', transform_with: ->(arr) { ActivityList.parse(arr) }
|
|
7
|
+
property 'workouts', from: 'Workouts', transform_with: ->(arr) { WorkoutList.parse(arr) }
|
|
8
|
+
property 'courses', from: 'Courses', transform_with: ->(arr) { CourseList.parse(arr) }
|
|
9
|
+
property 'author', from: 'Author', transform_with: ->(el) { AbstractSource.parse(el) }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class HeartRateValue < Base
|
|
5
|
+
property 'heart_rate_above', from: 'HeartRateAbove', transform_with: ->(v) { HeartRateInBeatsPerMinute.parse(v) }
|
|
6
|
+
property 'heart_rate_below', from: 'HeartRateBelow', transform_with: ->(v) { HeartRateInBeatsPerMinute.parse(v) }
|
|
7
|
+
property 'heart_rate_in_beats_per_minute', from: 'HeartRateInBeatsPerMinute', transform_with: ->(v) { HeartRateInBeatsPerMinute.parse(v) }
|
|
8
|
+
property 'heart_rate_as_percent_of_max', from: 'HeartRateAsPercentOfMax', transform_with: ->(v) { HeartRateAsPercentOfMax.parse(v) }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Lap < Base
|
|
5
|
+
property 'start_time', from: 'StartTime', transform_with: ->(v) { Time.parse(v) }
|
|
6
|
+
property 'total_time_seconds', from: 'TotalTimeSeconds', transform_with: lambda(&:to_f)
|
|
7
|
+
property 'distance_meters', from: 'DistanceMeters', transform_with: lambda(&:to_f)
|
|
8
|
+
property 'maximum_speed', from: 'MaximumSpeed', transform_with: lambda(&:to_f)
|
|
9
|
+
property 'calories', from: 'Calories', transform_with: lambda(&:to_i)
|
|
10
|
+
property 'average_heart_rate_bpm', from: 'AverageHeartRateBpm', transform_with: ->(v) { HeartRateInBeatsPerMinute.parse(v) }
|
|
11
|
+
property 'maximum_heart_rate_bpm', from: 'MaximumHeartRateBpm', transform_with: ->(v) { HeartRateInBeatsPerMinute.parse(v) }
|
|
12
|
+
property 'intensity', from: 'Intensity', transform_with: ->(v) { Intensity.parse(v) }
|
|
13
|
+
property 'cadence', from: 'Cadence', transform_with: ->(v) { Cadence.parse(v) }
|
|
14
|
+
property 'trigger_method', from: 'TriggerMethod', transform_with: ->(v) { TriggerMethod.parse(v) }
|
|
15
|
+
property 'tracks', from: 'Track', transform_with: ->(v) { to_array(v).map { |el| Track.parse(el) } }
|
|
16
|
+
property 'notes', from: 'Notes'
|
|
17
|
+
property 'extensions', from: 'Extensions', transform_with: ->(v) { Extensions.parse(v) }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Step < Base
|
|
5
|
+
property 'step_id', from: 'StepId'
|
|
6
|
+
property 'name', from: 'Name'
|
|
7
|
+
property 'duration', from: 'Duration', transform_with: ->(v) { Duration.parse(v) }
|
|
8
|
+
property 'intensity', from: 'Intensity', transform_with: ->(v) { Intensity.parse(v) }
|
|
9
|
+
property 'target', from: 'Target', transform_with: ->(v) { Target.parse(v) }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Target < Base
|
|
5
|
+
property 'heart_rate_zone', from: 'HeartRateZone', transform_with: ->(v) { HeartRateZone.parse(v) }
|
|
6
|
+
property 'speed_zone', from: 'SpeedZone', transform_with: ->(v) { SpeedZone.parse(v) }
|
|
7
|
+
property 'cadence', from: 'Cadence', transform_with: ->(v) { Cadence.parse(v) }
|
|
8
|
+
property 'power_zone', from: 'PowerZone', transform_with: ->(v) { PowerZone.parse(v) }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Trackpoint < Base
|
|
5
|
+
property 'time', from: 'Time', transform_with: ->(v) { Time.parse(v) }
|
|
6
|
+
property 'position', from: 'Position', transform_with: ->(v) { Position.parse(v) }
|
|
7
|
+
property 'altitude_meters', from: 'AltitudeMeters', transform_with: lambda(&:to_f)
|
|
8
|
+
property 'distance_meters', from: 'DistanceMeters', transform_with: lambda(&:to_f)
|
|
9
|
+
property 'heart_rate_bpm', from: 'HeartRateBpm', transform_with: ->(v) { HeartRateInBeatsPerMinute.parse(v) }
|
|
10
|
+
property 'cadence', from: 'Cadence', transform_with: ->(v) { Cadence.parse(v) }
|
|
11
|
+
property 'sensor_state', from: 'SensorState', transform_with: ->(v) { SensorState.parse(v) }
|
|
12
|
+
property 'extensions', from: 'Extensions', transform_with: ->(v) { Extensions.parse(v) }
|
|
13
|
+
# TODO: Extensions/TPX/Speed
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Version < Base
|
|
5
|
+
property 'version_major', from: 'VersionMajor', transform_with: lambda(&:to_i)
|
|
6
|
+
property 'version_minor', from: 'VersionMinor', transform_with: lambda(&:to_i)
|
|
7
|
+
property 'build_major', from: 'BuildMajor', transform_with: lambda(&:to_i)
|
|
8
|
+
property 'build_minor', from: 'BuildMinor', transform_with: lambda(&:to_i)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tcx
|
|
4
|
+
class Workout < Base
|
|
5
|
+
property 'name', from: 'Name'
|
|
6
|
+
property 'sport', from: 'Sport', transform_with: ->(v) { Sport.parse(v) }
|
|
7
|
+
property 'steps', from: 'Step', transform_with: ->(v) { to_array(v).map { |el| Step.parse(el) } }
|
|
8
|
+
property 'creator', from: 'Creator', transform_with: ->(v) { AbstractSource.parse(v) }
|
|
9
|
+
end
|
|
10
|
+
end
|
data/lib/tcx/models.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'models/base'
|
|
4
|
+
require_relative 'models/value'
|
|
5
|
+
require_relative 'models/abstract_source'
|
|
6
|
+
require_relative 'models/activity'
|
|
7
|
+
require_relative 'models/activity_list'
|
|
8
|
+
require_relative 'models/cadence'
|
|
9
|
+
require_relative 'models/course'
|
|
10
|
+
require_relative 'models/course_folder'
|
|
11
|
+
require_relative 'models/course_lap'
|
|
12
|
+
require_relative 'models/course_list'
|
|
13
|
+
require_relative 'models/course_point'
|
|
14
|
+
require_relative 'models/course_point_type'
|
|
15
|
+
require_relative 'models/courses'
|
|
16
|
+
require_relative 'models/custom_heart_rate_zone'
|
|
17
|
+
require_relative 'models/database'
|
|
18
|
+
require_relative 'models/duration'
|
|
19
|
+
require_relative 'models/extensions'
|
|
20
|
+
require_relative 'models/folders'
|
|
21
|
+
require_relative 'models/gender'
|
|
22
|
+
require_relative 'models/heart_rate_as_percent_of_max'
|
|
23
|
+
require_relative 'models/heart_rate_bpm'
|
|
24
|
+
require_relative 'models/heart_rate_in_beats_per_minute'
|
|
25
|
+
require_relative 'models/heart_rate_value'
|
|
26
|
+
require_relative 'models/intensity'
|
|
27
|
+
require_relative 'models/lap'
|
|
28
|
+
require_relative 'models/name_key_reference'
|
|
29
|
+
require_relative 'models/position'
|
|
30
|
+
require_relative 'models/predefined_heart_rate_zone'
|
|
31
|
+
require_relative 'models/sensor_state'
|
|
32
|
+
require_relative 'models/sport'
|
|
33
|
+
require_relative 'models/step'
|
|
34
|
+
require_relative 'models/target'
|
|
35
|
+
require_relative 'models/track'
|
|
36
|
+
require_relative 'models/trackpoint'
|
|
37
|
+
require_relative 'models/trigger_method'
|
|
38
|
+
require_relative 'models/version'
|
|
39
|
+
require_relative 'models/workout'
|
|
40
|
+
require_relative 'models/workout_list'
|
data/lib/tcx/version.rb
ADDED
data/lib/tcx.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'hashie'
|
|
4
|
+
require 'time'
|
|
5
|
+
require 'ruby-enum'
|
|
6
|
+
require 'nokogiri'
|
|
7
|
+
|
|
8
|
+
require_relative 'tcx/version'
|
|
9
|
+
require_relative 'tcx/models'
|
|
10
|
+
|
|
11
|
+
module Tcx
|
|
12
|
+
def self.load_file(path)
|
|
13
|
+
xml = Nokogiri::XML(File.open(path))
|
|
14
|
+
xml.root.add_namespace_definition('ns3', 'http://www.garmin.com/xmlschemas/ActivityExtension/v2')
|
|
15
|
+
Tcx::Database.parse(xml.root)
|
|
16
|
+
end
|
|
17
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: tcx
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Daniel Doubrovkine
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-10-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: hashie
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: nokogiri
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: ruby-enum
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
description:
|
|
56
|
+
email: dblock@dblock.org
|
|
57
|
+
executables: []
|
|
58
|
+
extensions: []
|
|
59
|
+
extra_rdoc_files: []
|
|
60
|
+
files:
|
|
61
|
+
- CHANGELOG.md
|
|
62
|
+
- LICENSE.md
|
|
63
|
+
- README.md
|
|
64
|
+
- lib/tcx.rb
|
|
65
|
+
- lib/tcx/models.rb
|
|
66
|
+
- lib/tcx/models/abstract_source.rb
|
|
67
|
+
- lib/tcx/models/activity.rb
|
|
68
|
+
- lib/tcx/models/activity_list.rb
|
|
69
|
+
- lib/tcx/models/base.rb
|
|
70
|
+
- lib/tcx/models/cadence.rb
|
|
71
|
+
- lib/tcx/models/course.rb
|
|
72
|
+
- lib/tcx/models/course_folder.rb
|
|
73
|
+
- lib/tcx/models/course_lap.rb
|
|
74
|
+
- lib/tcx/models/course_list.rb
|
|
75
|
+
- lib/tcx/models/course_point.rb
|
|
76
|
+
- lib/tcx/models/course_point_type.rb
|
|
77
|
+
- lib/tcx/models/courses.rb
|
|
78
|
+
- lib/tcx/models/custom_heart_rate_zone.rb
|
|
79
|
+
- lib/tcx/models/database.rb
|
|
80
|
+
- lib/tcx/models/duration.rb
|
|
81
|
+
- lib/tcx/models/extensions.rb
|
|
82
|
+
- lib/tcx/models/folders.rb
|
|
83
|
+
- lib/tcx/models/gender.rb
|
|
84
|
+
- lib/tcx/models/heart_rate_as_percent_of_max.rb
|
|
85
|
+
- lib/tcx/models/heart_rate_bpm.rb
|
|
86
|
+
- lib/tcx/models/heart_rate_in_beats_per_minute.rb
|
|
87
|
+
- lib/tcx/models/heart_rate_value.rb
|
|
88
|
+
- lib/tcx/models/intensity.rb
|
|
89
|
+
- lib/tcx/models/lap.rb
|
|
90
|
+
- lib/tcx/models/name_key_reference.rb
|
|
91
|
+
- lib/tcx/models/position.rb
|
|
92
|
+
- lib/tcx/models/predefined_heart_rate_zone.rb
|
|
93
|
+
- lib/tcx/models/sensor_state.rb
|
|
94
|
+
- lib/tcx/models/sport.rb
|
|
95
|
+
- lib/tcx/models/step.rb
|
|
96
|
+
- lib/tcx/models/target.rb
|
|
97
|
+
- lib/tcx/models/track.rb
|
|
98
|
+
- lib/tcx/models/trackpoint.rb
|
|
99
|
+
- lib/tcx/models/trigger_method.rb
|
|
100
|
+
- lib/tcx/models/value.rb
|
|
101
|
+
- lib/tcx/models/version.rb
|
|
102
|
+
- lib/tcx/models/workout.rb
|
|
103
|
+
- lib/tcx/models/workout_list.rb
|
|
104
|
+
- lib/tcx/version.rb
|
|
105
|
+
homepage: http://github.com/dblock/tcx
|
|
106
|
+
licenses:
|
|
107
|
+
- MIT
|
|
108
|
+
metadata:
|
|
109
|
+
rubygems_mfa_required: 'true'
|
|
110
|
+
post_install_message:
|
|
111
|
+
rdoc_options: []
|
|
112
|
+
require_paths:
|
|
113
|
+
- lib
|
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
115
|
+
requirements:
|
|
116
|
+
- - ">="
|
|
117
|
+
- !ruby/object:Gem::Version
|
|
118
|
+
version: '3.0'
|
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '2.5'
|
|
124
|
+
requirements: []
|
|
125
|
+
rubygems_version: 3.5.16
|
|
126
|
+
signing_key:
|
|
127
|
+
specification_version: 4
|
|
128
|
+
summary: A Garmin Training Center XML (TCX) reader/writer.
|
|
129
|
+
test_files: []
|