Gooby 0.9.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.
Files changed (98) hide show
  1. data/README +218 -0
  2. data/bin/forerunner_xml_parser.rb +28 -0
  3. data/bin/forerunner_xml_parser.sh +16 -0
  4. data/bin/forerunner_xml_splitter.rb +60 -0
  5. data/bin/gen_gmap.rb +30 -0
  6. data/bin/gen_gmap.sh +19 -0
  7. data/bin/tests_gen.rb +13 -0
  8. data/data/20041113_richmond_marathon.csv +1036 -0
  9. data/data/20041113_richmond_marathon.xml +8663 -0
  10. data/data/20050305_corporate_cup_hm.csv +251 -0
  11. data/data/20050305_corporate_cup_hm.xml +2208 -0
  12. data/data/20050430_nashville_marathon.csv +1208 -0
  13. data/data/20050430_nashville_marathon.xml +10043 -0
  14. data/data/20051119_dowd_ymca_hm.csv +251 -0
  15. data/data/20051119_dowd_ymca_hm.xml +2210 -0
  16. data/data/20051124_hyatt_turkey_trot_8K.csv +321 -0
  17. data/data/20051124_hyatt_turkey_trot_8K.xml +2651 -0
  18. data/data/forerunner_2005.xml +259620 -0
  19. data/data/forerunner_2006.xml +190853 -0
  20. data/data/forerunner_2007.xml +259014 -0
  21. data/data/geo_data.txt +171 -0
  22. data/data/phx.csv +1280 -0
  23. data/data/phx.xml +10620 -0
  24. data/data/run_2007_01_01_16_38_27.xml +2020 -0
  25. data/data/run_2007_01_06_15_27_31.xml +2020 -0
  26. data/data/run_2007_01_10_12_25_47.xml +820 -0
  27. data/data/run_2007_01_10_22_44_54.csv +112 -0
  28. data/data/run_2007_01_10_22_44_54.xml +908 -0
  29. data/data/run_2007_01_11_10_48_45.xml +1292 -0
  30. data/data/run_2007_01_13_15_37_06.xml +1964 -0
  31. data/data/run_2007_01_14_15_46_02.xml +1368 -0
  32. data/data/run_2007_01_15_14_01_48.xml +1868 -0
  33. data/data/run_2007_01_20_16_22_05.xml +1702 -0
  34. data/data/run_2007_01_27_17_32_13.xml +3626 -0
  35. data/data/run_2007_01_28_19_14_52.xml +2538 -0
  36. data/data/run_2007_02_03_14_30_20.xml +2016 -0
  37. data/data/run_2007_02_04_18_02_30.xml +1476 -0
  38. data/data/run_2007_02_17_16_29_35.xml +1236 -0
  39. data/data/run_2007_02_19_14_44_33.xml +1816 -0
  40. data/data/run_2007_02_23_15_53_55.xml +36 -0
  41. data/data/run_2007_02_23_15_55_20.xml +1296 -0
  42. data/data/run_2007_02_24_15_01_35.csv +484 -0
  43. data/data/run_2007_02_24_15_01_35.xml +3884 -0
  44. data/data/test1.txt +4 -0
  45. data/lib/cls_counter_hash.rb +83 -0
  46. data/lib/cls_delim_line.rb +40 -0
  47. data/lib/cls_dttm.rb +84 -0
  48. data/lib/cls_duration.rb +87 -0
  49. data/lib/cls_forerunner_xml_parser.rb +183 -0
  50. data/lib/cls_forerunner_xml_splitter.rb +113 -0
  51. data/lib/cls_geo_data.rb +186 -0
  52. data/lib/cls_gooby_object.rb +23 -0
  53. data/lib/cls_google_map_generator.rb +368 -0
  54. data/lib/cls_history.rb +38 -0
  55. data/lib/cls_lap.rb +27 -0
  56. data/lib/cls_line.rb +78 -0
  57. data/lib/cls_options.rb +74 -0
  58. data/lib/cls_position.rb +49 -0
  59. data/lib/cls_run.rb +199 -0
  60. data/lib/cls_simple_xml_parser.rb +46 -0
  61. data/lib/cls_test_regen.rb +187 -0
  62. data/lib/cls_track.rb +52 -0
  63. data/lib/cls_trackpoint.rb +205 -0
  64. data/lib/mod_introspect.rb +33 -0
  65. data/lib/mod_io.rb +65 -0
  66. data/lib/mod_project_info.rb +81 -0
  67. data/lib/mod_string.rb +26 -0
  68. data/lib/mod_test_helper.rb +22 -0
  69. data/samples/20041113_richmond_marathon.html +532 -0
  70. data/samples/20050305_corporate_cup_hm.html +448 -0
  71. data/samples/20050430_nashville_marathon.html +530 -0
  72. data/samples/gps_point_capture.html +54 -0
  73. data/samples/phoenix_marathon.html +542 -0
  74. data/samples/run_2007_01_10_22_44_54.html +146 -0
  75. data/samples/run_2007_02_24_15_01_35.html +298 -0
  76. data/tests/tst_cls_counter_hash.rb +105 -0
  77. data/tests/tst_cls_delim_line.rb +72 -0
  78. data/tests/tst_cls_dttm.rb +129 -0
  79. data/tests/tst_cls_duration.rb +49 -0
  80. data/tests/tst_cls_forerunner_xml_parser.rb +68 -0
  81. data/tests/tst_cls_geo_data.rb +69 -0
  82. data/tests/tst_cls_gooby_object.rb +24 -0
  83. data/tests/tst_cls_google_map_generator.rb +107 -0
  84. data/tests/tst_cls_history.rb +44 -0
  85. data/tests/tst_cls_lap.rb +36 -0
  86. data/tests/tst_cls_line.rb +108 -0
  87. data/tests/tst_cls_options.rb +77 -0
  88. data/tests/tst_cls_position.rb +64 -0
  89. data/tests/tst_cls_run.rb +140 -0
  90. data/tests/tst_cls_simple_xml_parser.rb +48 -0
  91. data/tests/tst_cls_track.rb +68 -0
  92. data/tests/tst_cls_trackpoint.rb +143 -0
  93. data/tests/tst_gooby.rb +28 -0
  94. data/tests/tst_mod_introspect.rb +30 -0
  95. data/tests/tst_mod_io.rb +51 -0
  96. data/tests/tst_mod_project_info.rb +77 -0
  97. data/tests/tst_mod_string.rb +56 -0
  98. metadata +142 -0
data/data/test1.txt ADDED
@@ -0,0 +1,4 @@
1
+ This is just a file
2
+ containing some
3
+
4
+ test data.
@@ -0,0 +1,83 @@
1
+ =begin rdoc
2
+
3
+ This class wrappers a Hash object and provides increment/decrement functionality
4
+ for a given key. It is used to sum the number of things (i.e. - xml tags) in a
5
+ collection.
6
+
7
+ Gooby - Copyright 2007 by Chris Joakim.
8
+ Gooby is available under GNU General Public License (GPL) license.
9
+
10
+ =end
11
+
12
+ module Gooby
13
+
14
+ class CounterHash < GoobyObject
15
+
16
+ def initialize
17
+ @hash = Hash.new(0)
18
+ end
19
+
20
+ # Return the Integer count for the given key; zero default.
21
+ def value(key)
22
+ (@hash.has_key?(key)) ? @hash[key] : 0
23
+ end
24
+
25
+ # Increment the count for the given key.
26
+ def increment(key)
27
+ if key == nil
28
+ return
29
+ end
30
+ if (@hash.has_key?(key))
31
+ val = @hash[key]
32
+ @hash[key] = val + 1
33
+ else
34
+ @hash[key] = 1
35
+ end
36
+ end
37
+
38
+ # Decrement the count for the given key.
39
+ def decrement(key)
40
+ if key == nil
41
+ return
42
+ end
43
+ if (@hash.has_key?(key))
44
+ val = @hash[key]
45
+ @hash[key] = val - 1
46
+ else
47
+ @hash[key] = -1
48
+ end
49
+ end
50
+
51
+ # Return an Array of the sorted keys.
52
+ def sorted_keys
53
+ @hash.keys.sort
54
+ end
55
+
56
+ # Return a String containing all key=val pairs.
57
+ def to_s
58
+ s = "CHash:"
59
+ sorted_keys.each { |key|
60
+ val = @hash[key]
61
+ s << " key: [#{key}] val: [#{val}]"
62
+ }
63
+ s
64
+ end
65
+
66
+ # Return an XML String containing all key=val pairs, optionally aligned.
67
+ def to_xml(aligned=false)
68
+ s = "<CHash>"
69
+ sorted_keys.each { |key|
70
+ val = @hash[key]
71
+ (aligned) ? s << "\n " : s << ''
72
+ s << " <entry key='#{key}' value='#{val}'/>"
73
+ }
74
+ if aligned
75
+ s << "\n "
76
+ end
77
+ s << " </CHash>"
78
+ s
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,40 @@
1
+ =begin rdoc
2
+
3
+ Instances of this class represent a delimited line of text, such as csv.
4
+
5
+ Gooby - Copyright 2007 by Chris Joakim.
6
+ Gooby is available under GNU General Public License (GPL) license.
7
+
8
+ =end
9
+
10
+ module Gooby
11
+
12
+ class DelimLine < GoobyObject
13
+
14
+ attr_reader :line, :trim, :delim, :tokens
15
+
16
+ def initialize(line, trim=true, delim=default_delimiter)
17
+ @line = line
18
+ @trim = trim
19
+ @delim = delim
20
+ @tokens = @line.split(@delim)
21
+ if trim
22
+ @tokens.each { | token | token.strip! }
23
+ end
24
+ end
25
+
26
+ def as_trackpoint(num_idx, lat_idx, lng_idx, alt_idx, dttm_idx)
27
+ Trackpoint.new(@tokens[num_idx], @tokens[lat_idx], @tokens[lng_idx], @tokens[alt_idx], @tokens[dttm_idx])
28
+ end
29
+
30
+ def is_comment?
31
+ @line.strip.match('^#') ? true : false
32
+ end
33
+
34
+ def to_s
35
+ "DelimLine: length: #{@line.size} trim: #{@trim} delim: #{@delim} tokens: #{@tokens.size}"
36
+ end
37
+
38
+ end
39
+
40
+ end
data/lib/cls_dttm.rb ADDED
@@ -0,0 +1,84 @@
1
+ =begin rdoc
2
+
3
+ Instances of this class represent a Date and Time as parsed from a value
4
+ such as '2006-01-15T13:41:40Z' in an XML file produced by a GPS device.
5
+ It wrappers both a DateTime and Time object.
6
+
7
+ Gooby - Copyright 2007 by Chris Joakim.
8
+ Gooby is available under GNU General Public License (GPL) license.
9
+
10
+ =end
11
+
12
+ module Gooby
13
+
14
+ class DtTm < GoobyObject
15
+
16
+ attr_accessor :rawdata, :dateTime, :time, :valid
17
+
18
+ # Constructor; arg is a String like '2006-01-15T13:41:40Z'.
19
+ def initialize(raw)
20
+ if raw
21
+ @rawdata = raw.strip
22
+ if @rawdata.size > 18
23
+ @dateTime = DateTime.parse(@rawdata[0..18])
24
+ @time = Time.parse(@dateTime.to_s)
25
+ @valid = true
26
+ else
27
+ @valid = false
28
+ end
29
+ else
30
+ @rawdata = ''
31
+ @valid = false
32
+ end
33
+ end
34
+
35
+ public
36
+
37
+ # Return @time.to_i
38
+ def to_i()
39
+ (@time) ? @time.to_i : invalid_time
40
+ end
41
+
42
+ # Calculates and returns diff between another instance.
43
+ def seconds_diff(anotherDtTm)
44
+ if anotherDtTm
45
+ to_i - anotherDtTm.to_i
46
+ else
47
+ invalid_time
48
+ end
49
+ end
50
+
51
+ def yyyy_mm_dd
52
+ @time.strftime("%Y-%m-%d")
53
+ end
54
+
55
+ def yyyy_mm_dd_hh_mm_ss
56
+ @time.strftime("%Y-%m-%d %H:%M:%S")
57
+ end
58
+
59
+ def hh_mm_ss
60
+ @time.strftime("%H:%M:%S")
61
+ end
62
+
63
+ # Calculate and return time diff in 'hh:mm:ss' format.
64
+ def hhmmss_diff(anotherDtTm)
65
+ if anotherDtTm
66
+ t = @time - (anotherDtTm.to_i)
67
+ t.strftime("%H:%M:%S")
68
+ else
69
+ '??:??:??'
70
+ end
71
+ end
72
+
73
+ def to_s
74
+ "#{@rawdata}"
75
+ end
76
+
77
+ # Return a String with state values for debugging.
78
+ def print_string
79
+ "DtTm: #{yyyy_mm_dd_hh_mm_ss} #{to_i} #{@rawdata}"
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,87 @@
1
+ =begin rdoc
2
+
3
+ Instances of this class represent the contents of a Forerunner extract
4
+ <Duration> tag, such as:
5
+
6
+ <Duration>PT507.870S</Duration>
7
+
8
+ Gooby - Copyright 2007 by Chris Joakim.
9
+ Gooby is available under GNU General Public License (GPL) license.
10
+
11
+ =end
12
+
13
+ require 'gooby'
14
+
15
+ module Gooby
16
+
17
+ class Duration < GoobyObject
18
+
19
+ attr_accessor :rawdata, :seconds, :minutes, :mmss
20
+
21
+ # Constructor; arg is a String like 'PT507.870S'.
22
+ def initialize(raw)
23
+ if raw
24
+ @rawdata = scrub(raw)
25
+ @seconds = @rawdata.to_f
26
+ @minutes = @seconds / 60
27
+ @base_min = @minutes.floor
28
+ @frac_min = @minutes - @base_min
29
+ @frac_sec = @frac_min * 60
30
+
31
+ @mmss = ''
32
+ if (@base_min < 10)
33
+ @mmss << "0#{@base_min}:"
34
+ else
35
+ @mmss << "#{@base_min}:"
36
+ end
37
+ if (@frac_sec < 10)
38
+ @mmss << "0#{@frac_sec}"
39
+ else
40
+ @mmss << "#{@frac_sec}"
41
+ end
42
+ if (@mmss.size > 8)
43
+ @mmss = @mmss[0..8]
44
+ end
45
+ else
46
+ @rawdata = ''
47
+ @seconds = invalidDistance
48
+ @minutes = invalidMinutes
49
+ @mmss = '??:??.?'
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def scrub(raw)
56
+ if (raw)
57
+ raw.strip!
58
+ newStr = ''
59
+ raw.each_byte { | b |
60
+ if ((b >= 48) && (b <= 57))
61
+ newStr << b
62
+ end
63
+ if (b == 46)
64
+ newStr << b
65
+ end
66
+ }
67
+ return newStr
68
+ else
69
+ ''
70
+ end
71
+ end
72
+
73
+ public
74
+
75
+ def to_s
76
+ "#{@mmss}"
77
+ end
78
+
79
+ # Return a String with state values for debugging.
80
+ def print_string
81
+ "Duration: #{@rawdata} sec: #{@seconds} min: #{@minutes} mmss: #{@mmss} bm: #{@base_min} fm: #{@frac_min} fs: #{@frac_sec}"
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
@@ -0,0 +1,183 @@
1
+ =begin rdoc
2
+
3
+ Instances of this class are used to parse a Forerunner XML file in a SAX-like
4
+ manner. Instances of the model classes - History, Run, Track, Trackpoint,
5
+ etc. are created in this parsing process.
6
+
7
+ See http://www.garmin.com/xmlschemas/ForerunnerLogbookv1.xsd for the XML Schema
8
+ Definition for the Garmin Forerunner XML. The Gooby object model mirrors this XSD.
9
+
10
+ Gooby - Copyright 2007 by Chris Joakim.
11
+ Gooby is available under GNU General Public License (GPL) license.
12
+
13
+ =end
14
+
15
+ module Gooby
16
+
17
+ class ForerunnerXmlParser
18
+
19
+ DETAIL_TAGS = %w( Notes StartTime Duration Length Latitude Longitude Altitude Time BeginPosition EndPosition )
20
+
21
+ include REXML::StreamListener
22
+
23
+ attr_reader :history, :cvHash, :tagCount
24
+
25
+ def initialize
26
+ @cvHash = Hash.new("")
27
+ @tagCount = 0
28
+ @runCount = 0
29
+ @lapCount = 0
30
+ @trackCount = 0
31
+ @trackpoint_count = 0
32
+ @currText = "";
33
+ @history = History.new
34
+ @currRun = nil
35
+ @currLap = nil
36
+ @currTrack = nil
37
+ @currBeginPosition = nil
38
+ @currEndPosition = nil
39
+ end
40
+
41
+ public
42
+
43
+ # SAX API method; handles 'Run', 'Lap', 'Track'.
44
+ def tag_start(tagname, attrs)
45
+ @tagCount += 1
46
+ @currTag = tagname
47
+ @cvHash[tagname] = ''
48
+
49
+ if detail_tag?(tagname)
50
+ @inDetail = true
51
+ end
52
+
53
+ if is_tag?('Run', tagname)
54
+ @runCount = @runCount + 1
55
+ @lapCount = 0
56
+ @trackCount = 0
57
+ @currRun = Run.new(@runCount)
58
+ @history.add_run(@currRun)
59
+ @cvHash['Notes'] = ''
60
+ return
61
+ end
62
+
63
+ if is_tag?('Lap', tagname)
64
+ @lapCount = @lapCount + 1
65
+ @currLap = Lap.new(@lapCount)
66
+ return
67
+ end
68
+
69
+ if is_tag?('Track', tagname)
70
+ @trackCount = @trackCount + 1
71
+ @currTrack = Track.new(@trackCount)
72
+ @trackpoint_count = 0
73
+ return
74
+ end
75
+
76
+ end
77
+
78
+ # SAX API method; handles 'Position', 'Trackpoint', 'Track', 'Lap', 'Run'.
79
+ def tag_end(tagname)
80
+ if @inDetail
81
+ @cvHash[tagname] = @currText
82
+ else
83
+ if is_tag?('Position', tagname)
84
+ lat = @cvHash['Latitude']
85
+ long = @cvHash['Longitude']
86
+ @currBeginPosition = Position.new(lat.strip, long.strip, '')
87
+ @currEndPosition = Position.new(lat.strip, long.strip, '')
88
+ end
89
+
90
+ if is_tag?('BeginPosition', tagname)
91
+ lat = @cvHash['Latitude']
92
+ long = @cvHash['Longitude']
93
+ @currBeginPosition = Position.new(lat.strip, long.strip, '')
94
+ end
95
+
96
+ if is_tag?('EndPosition', tagname)
97
+ lat = @cvHash['Latitude']
98
+ long = @cvHash['Longitude']
99
+ @currEndPosition = Position.new(lat.strip, long.strip, '')
100
+ end
101
+
102
+ if is_tag?('Trackpoint', tagname)
103
+ @trackpoint_count = @trackpoint_count + 1
104
+ lat = @cvHash['Latitude']
105
+ long = @cvHash['Longitude']
106
+ alt = @cvHash['Altitude']
107
+ time = @cvHash['Time']
108
+ tp = Trackpoint.new(@trackpoint_count, lat, long, alt, time)
109
+ @currTrack.add_trackpoint(tp)
110
+ end
111
+
112
+ if is_tag?('Track', tagname)
113
+ if @currRun != nil
114
+ @currRun.add_track(@currTrack)
115
+ end
116
+ end
117
+
118
+ if is_tag?('Lap', tagname)
119
+ @currLap.startTime = @cvHash['StartTime']
120
+ @currLap.duration = Duration.new(@cvHash['Duration'])
121
+ @currLap.length = @cvHash['Length']
122
+ @currLap.beginPosition = @currBeginPosition
123
+ @currLap.endPosition = @currEndPosition
124
+ @currRun.add_lap(@currLap)
125
+ end
126
+
127
+ if is_tag?('Run', tagname)
128
+ @currRun.notes = @cvHash['Notes']
129
+ end
130
+ end
131
+
132
+ @inDetail = false
133
+ @currText = ""
134
+ @currTag = ""
135
+ end
136
+
137
+ # SAX API method.
138
+ def text(txt)
139
+ if @inDetail
140
+ @currText = @currText + txt
141
+ end
142
+ end
143
+
144
+ # Iterate all parsed Run objects and print each with to_s.
145
+ def gdump()
146
+ @history.runs().each { |run| puts run.to_s }
147
+ end
148
+
149
+ # Iterate all parsed Run objects and print each with to_s.
150
+ def dump()
151
+ @history.runs().each { |run| puts run.to_s }
152
+ end
153
+
154
+ # Iterate all parsed Run objects and print each with put_csv.
155
+ def put_run_csv()
156
+ @history.runs().each { |run| run.put_csv() }
157
+ end
158
+
159
+ # Iterate all parsed Run objects and print each with put_tkpt_csv.
160
+ def put_all_run_tkpt_csv(with_header_comment)
161
+ @history.runs.each { |run|
162
+ run.put_tkpt_csv(with_header_comment)
163
+ }
164
+ end
165
+
166
+ private
167
+
168
+ def is_tag?(tagname, value)
169
+ tagname == value
170
+ end
171
+
172
+ def detail_tag?(tagname)
173
+ DETAIL_TAGS.each { |typ|
174
+ if typ == tagname
175
+ return true
176
+ end
177
+ }
178
+ return false
179
+ end
180
+
181
+ end
182
+
183
+ end