Gooby 0.9.0

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