joule 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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