joule 1.0.0 → 1.0.1

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.
@@ -1,2 +1,8 @@
1
1
  require 'joule/tcx/parser'
2
- require 'joule/tcx/properties'
2
+ require 'joule/tcx/properties'
3
+
4
+ module Joule
5
+ module TCX
6
+ FILE_EXTENSION = "tcx"
7
+ end
8
+ end
@@ -1,49 +1,33 @@
1
1
  require 'nokogiri'
2
+ require 'time'
2
3
 
3
4
  module Joule
4
5
  module TCX
5
- class Parser
6
- include Joule::Calculator::MarkerCalculator
7
- include Joule::Calculator::PeakPowerCalculator
8
-
9
- attr_reader :data_points, :markers, :properties, :peak_powers
10
-
11
- def initialize(string_or_io)
12
- @string_or_io = string_or_io
13
- @data_points = Array.new
14
- @properties = Joule::TCX::Properties.new
15
- @markers = Array.new
16
- @peak_powers = Array.new
17
- @has_native_speed = false
18
- end
6
+ class Parser < Joule::Base::Parser
19
7
 
20
- def parse(options = {})
21
- @properties.record_interval = 1
8
+ def parse_workout()
22
9
  @total_record_count = 0
23
10
  parse_activity("Biking")
24
11
  create_workout_marker()
25
-
26
- if(options[:calculate_marker_values])
27
- calculate_marker_values()
28
- end
29
-
30
- if(options[:calculate_peak_power_values])
31
- calculate_peak_power_values(:durations => options[:durations], :total_duration => @markers.first.duration_seconds)
32
- end
33
-
12
+ end
13
+
14
+ def parse_properties
15
+ @workout.properties = Joule::TCX::Properties.new
16
+ @workout.properties.record_interval = 1
34
17
  end
35
18
 
36
19
  private
37
20
  def create_workout_marker
38
- if(@markers.size > 1)
39
- @markers << Marker.new(:start => 0, :end => @data_points.size - 1)
21
+ if(@workout.markers.size > 1)
22
+ @workout.markers << Marker.new(:start => 0, :end => @workout.data_points.size - 1)
40
23
  end
41
24
  end
25
+
42
26
 
43
27
  def parse_activity(sport)
44
- document = Nokogiri::XML::Document.parse(@string_or_io)
28
+ document = Nokogiri::XML::Document.parse(@data)
45
29
  document.xpath("//xmlns:Activity[@Sport='#{sport}']").each do |activity|
46
- @properties.id = activity.at("./xmlns:Id").content
30
+ @workout.properties.date_time = Time.parse(activity.at("./xmlns:Id").content)
47
31
 
48
32
  activity.children.each do |child|
49
33
  parse_lap(child) if child.name == "Lap"
@@ -57,30 +41,19 @@ module Joule
57
41
  def parse_lap(lap_node)
58
42
 
59
43
  marker = Marker.new
60
- marker.start_time = DateTime.parse(lap_node.attribute("StartTime").content)
61
-
62
- if(@markers.size == 0)
63
- @properties.start_date_time = marker.start_time
64
- end
65
-
66
- if @data_points.size > 0
67
- marker.start = @data_points.last.time + 1
44
+
45
+ if @workout.data_points.size > 0
46
+ marker.start = @workout.data_points.last.time + 1
68
47
  else
69
48
  marker.start= 0
70
49
  end
71
50
 
72
51
  lap_node.children.each do |child|
73
52
  marker.duration_seconds = child.content.to_i if child.name == "TotalTimeSeconds"
74
- # puts "Distance in meters: #{child.content}" if child.name == "DistanceMeters"
75
- # puts "Maximum Speed: #{child.content}" if child.name == "MaximumSpeed"
76
- # puts "Calories: #{child.content}" if child.name == "Calories"
77
- # puts "Intensity: #{child.content}" if child.name == "Intensity"
78
- # puts "Cadence: #{child.content}" if child.name == "Cadence"
79
- # puts "Trigger Method: #{child.content}" if child.name == "TriggerMethod"
80
53
  parse_track(child) if(child.name == "Track")
81
54
  end
82
- marker.end = @data_points.last.time
83
- @markers << marker
55
+ marker.end = @workout.data_points.last.time
56
+ @workout.markers << marker
84
57
  end
85
58
 
86
59
  def parse_track(track)
@@ -104,21 +77,21 @@ module Joule
104
77
  parse_extensions(data, data_point) if data.name == "Extensions"
105
78
  parse_position(data, data_point) if data.name == "Position"
106
79
  end
107
- @data_points << data_point
80
+ @workout.data_points << data_point
108
81
  @trackpoint_count = @trackpoint_count + 1
109
82
  @total_record_count = @total_record_count + 1
110
83
  end
111
84
 
112
85
  def parse_times(data, data_point)
113
- time_of_day = DateTime.parse(data.content)
86
+ time_of_day = Time.parse(data.content)
114
87
  data_point.time_of_day = (time_of_day.hour * 3600) + (time_of_day.min * 60) + time_of_day.sec
115
- data_point.time = @total_record_count * @properties.record_interval
88
+ data_point.time = @total_record_count * @workout.properties.record_interval
116
89
 
117
90
  if(@trackpoint_count == 0)
118
91
  track_start_time = data_point.time_of_day
119
- @track_offset_in_seconds = track_start_time - @properties.start_time_in_seconds
92
+ @track_offset_in_seconds = track_start_time - @workout.properties.start_time_in_seconds
120
93
  end
121
- data_point.time_with_pauses = (@trackpoint_count * @properties.record_interval) + @track_offset_in_seconds
94
+ data_point.time_with_pauses = (@trackpoint_count * @workout.properties.record_interval) + @track_offset_in_seconds
122
95
  end
123
96
 
124
97
  def parse_heartrate(heartrate, data_point)
@@ -143,32 +116,14 @@ module Joule
143
116
  end
144
117
  end
145
118
 
146
- def calculate_marker_values
147
- @markers.each_with_index { |marker, i|
148
- calculate_marker_averages marker
149
- calculate_marker_maximums marker
150
- calculate_marker_training_metrics marker
151
-
152
- if i.eql?(0)
153
- marker.distance = @data_points.last.distance
154
- else
155
- marker.distance = @data_points[marker.end + 1].distance - @data_points[marker.start].distance
156
- end
157
-
158
- marker.duration_seconds = (marker.end - marker.start + 1) * @properties.record_interval
159
- marker.energy = (marker.average_power.round * marker.duration_seconds)/1000
160
-
161
- }
162
- end
163
-
164
119
  def calculate_speed
165
- @data_points.each_with_index { |v, i|
120
+ @workout.data_points.each_with_index { |v, i|
166
121
  if(i == 0)
167
122
  delta = v.distance
168
123
  else
169
- delta = v.distance - @data_points[i-1].distance
124
+ delta = v.distance - @workout.data_points[i-1].distance
170
125
  end
171
- v.speed = delta / @properties.record_interval
126
+ v.speed = delta / @workout.properties.record_interval
172
127
  }
173
128
  end
174
129
  end
@@ -1,11 +1,13 @@
1
1
  module Joule
2
2
  module TCX
3
3
  class Properties
4
- attr_accessor :id, :record_interval, :start_date_time
4
+ attr_accessor :record_interval, :date_time
5
5
 
6
6
  def start_time_in_seconds
7
- (@start_date_time.hour * 3600) + (@start_date_time.min * 60) + @start_date_time.sec
7
+ (@date_time.hour * 3600) + (@date_time.min * 60) + @date_time.sec
8
8
  end
9
+
10
+
9
11
  end
10
12
  end
11
13
  end
@@ -2,7 +2,7 @@ module Joule
2
2
  module UnitsConversion
3
3
  def convert_speed(speed)
4
4
  #convert to mm/s
5
- if self.properties.speed_units_are_english?
5
+ if @workout.properties.speed_units_are_english?
6
6
  miles_per_hour_to_millimeters_per_second speed
7
7
  else
8
8
  kilometers_per_hour_to_millimeters_per_second speed
@@ -11,7 +11,7 @@ module Joule
11
11
 
12
12
  def convert_distance(distance)
13
13
  #convert distance to mm
14
- if self.properties.distance_units_are_english?
14
+ if @workout.properties.distance_units_are_english?
15
15
  miles_to_millimeters distance
16
16
  else
17
17
  kilometers_to_millimeters distance
@@ -0,0 +1,29 @@
1
+ module Joule
2
+ class Workout
3
+ # An Array of DataPoint objects. Contains all the data points.
4
+ attr_accessor :data_points
5
+
6
+ # An Array of Marker objects. The first marker always represents the entire
7
+ # set of data.
8
+ attr_accessor :markers
9
+
10
+ # An Array of Hash objects representing the peak powers for a give duration (5
11
+ # second, 5 minute, 20 minute, etc). This is also sometimes referred to the
12
+ # mean maximal power. Peak power calculations can add a significant amount
13
+ # of time to parsing, so you can perform these later on if you want to with
14
+ # the Joule::Calculator::PeakPowerCalculator.
15
+ attr_accessor :peak_powers
16
+
17
+ # The properties object represents device properties specific to the data
18
+ # being parsed.
19
+ attr_accessor :properties
20
+
21
+ def initialize()
22
+ @data_points = Array.new
23
+ @markers = Array.new
24
+ @peak_powers = Array.new
25
+ @properties = Object.new
26
+ end
27
+
28
+ end
29
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joule
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 1
10
+ version: 1.0.1
5
11
  platform: ruby
6
12
  authors:
7
13
  - Andrew Olson
@@ -9,30 +15,42 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-01-05 00:00:00 -05:00
18
+ date: 2010-09-15 00:00:00 -04:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: nokogiri
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 1
32
+ - 4
33
+ - 1
23
34
  version: 1.4.1
24
- version:
35
+ type: :runtime
36
+ version_requirements: *id001
25
37
  - !ruby/object:Gem::Dependency
26
38
  name: fastercsv
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
30
42
  requirements:
31
43
  - - ">="
32
44
  - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 1
48
+ - 4
49
+ - 0
33
50
  version: 1.4.0
34
- version:
35
- description: ""
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Joule parses and does some basic analyzing of powermeter data. Supported formats include SRM(.srm), Saris PowerTap(.csv), iBike(.csv), and Garmin(.tcx)
36
54
  email: anolson@gmail.com
37
55
  executables: []
38
56
 
@@ -41,41 +59,42 @@ extensions: []
41
59
  extra_rdoc_files:
42
60
  - README.rdoc
43
61
  files:
44
- - lib/joule
45
62
  - lib/joule/array.rb
46
- - lib/joule/calculator
63
+ - lib/joule/base/parser.rb
64
+ - lib/joule/base.rb
47
65
  - lib/joule/calculator/marker_calculator.rb
48
66
  - lib/joule/calculator/peak_power_calculator.rb
49
67
  - lib/joule/calculator/power_calculator.rb
50
68
  - lib/joule/calculator.rb
51
- - lib/joule/csv
52
69
  - lib/joule/csv/parser.rb
53
70
  - lib/joule/csv.rb
54
71
  - lib/joule/data_point.rb
55
- - lib/joule/float.rb
56
- - lib/joule/ibike
72
+ - lib/joule/exception/unsupported_file_type_exception.rb
73
+ - lib/joule/exception.rb
74
+ - lib/joule/hashable.rb
57
75
  - lib/joule/ibike/parser.rb
58
76
  - lib/joule/ibike/properties.rb
59
77
  - lib/joule/ibike.rb
60
78
  - lib/joule/marker.rb
61
- - lib/joule/powertap
79
+ - lib/joule/peak_power.rb
62
80
  - lib/joule/powertap/parser.rb
63
81
  - lib/joule/powertap/properties.rb
64
82
  - lib/joule/powertap.rb
65
- - lib/joule/srm
66
83
  - lib/joule/srm/parser.rb
67
84
  - lib/joule/srm/properties.rb
68
85
  - lib/joule/srm.rb
69
- - lib/joule/tcx
70
86
  - lib/joule/tcx/parser.rb
71
87
  - lib/joule/tcx/properties.rb
72
88
  - lib/joule/tcx.rb
73
89
  - lib/joule/units_conversion.rb
90
+ - lib/joule/workout.rb
74
91
  - lib/joule.rb
75
92
  - README.rdoc
76
93
  - Rakefile
77
94
  has_rdoc: true
78
95
  homepage: http://github.com/anolson/joule
96
+ licenses: []
97
+
79
98
  post_install_message:
80
99
  rdoc_options:
81
100
  - --line-numbers
@@ -87,23 +106,30 @@ rdoc_options:
87
106
  require_paths:
88
107
  - lib
89
108
  required_ruby_version: !ruby/object:Gem::Requirement
109
+ none: false
90
110
  requirements:
91
111
  - - ">="
92
112
  - !ruby/object:Gem::Version
113
+ hash: 3
114
+ segments:
115
+ - 0
93
116
  version: "0"
94
- version:
95
117
  required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
96
119
  requirements:
97
120
  - - ">="
98
121
  - !ruby/object:Gem::Version
122
+ hash: 11
123
+ segments:
124
+ - 1
125
+ - 2
99
126
  version: "1.2"
100
- version:
101
127
  requirements: []
102
128
 
103
129
  rubyforge_project:
104
- rubygems_version: 1.3.1
130
+ rubygems_version: 1.3.7
105
131
  signing_key:
106
- specification_version: 2
132
+ specification_version: 3
107
133
  summary: A Ruby library for parsing bicycle powermeter data.
108
134
  test_files: []
109
135
 
@@ -1,39 +0,0 @@
1
- # Copyright (c) 2004-2009 David Heinemeier Hansson
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining
4
- # a copy of this software and associated documentation files (the
5
- # "Software"), to deal in the Software without restriction, including
6
- # without limitation the rights to use, copy, modify, merge, publish,
7
- # distribute, sublicense, and/or sell copies of the Software, and to
8
- # permit persons to whom the Software is furnished to do so, subject to
9
- # the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be
12
- # included in all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
22
- class Float
23
- remove_method :round
24
-
25
- # Rounds the float with the specified precision.
26
- #
27
- # x = 1.337
28
- # x.round # => 1
29
- # x.round(1) # => 1.3
30
- # x.round(2) # => 1.34
31
- def round(precision = nil)
32
- if precision
33
- magnitude = 10.0 ** precision
34
- (self * magnitude).round / magnitude
35
- else
36
- super()
37
- end
38
- end
39
- end