gooby 1.1.0 → 1.2.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 (78) hide show
  1. data/README +200 -35
  2. data/bin/code_scan.rb +1 -3
  3. data/bin/gooby_been_there.rb +12 -14
  4. data/bin/gooby_config.rb +11 -3
  5. data/bin/gooby_csv_validation.rb +50 -0
  6. data/bin/gooby_first_trackpoints_as_poi.rb +31 -0
  7. data/bin/gooby_gen_gmap.rb +7 -3
  8. data/bin/gooby_parser.rb +7 -5
  9. data/bin/gooby_splitter.rb +7 -4
  10. data/bin/gooby_version.rb +7 -3
  11. data/bin/run_all.sh +12 -2
  12. data/bin/run_been_there.sh +4 -1
  13. data/bin/run_config.sh +12 -0
  14. data/bin/run_csv_validation.sh +15 -0
  15. data/bin/run_db_gen.sh +1 -1
  16. data/bin/run_db_load.sh +1 -1
  17. data/bin/run_first_trackpoints_as_poi.sh +16 -0
  18. data/bin/run_gen_gmaps.sh +7 -6
  19. data/bin/run_parse_full.sh +45 -0
  20. data/bin/run_parse_samples.sh +21 -0
  21. data/bin/run_split.sh +5 -4
  22. data/bin/run_version.sh +12 -0
  23. data/config/gooby_config.yaml +130 -131
  24. data/data/20050305_corporate_cup_hm.csv +251 -251
  25. data/data/20050430_nashville_marathon_km.csv +1208 -0
  26. data/data/20060115_phoenix_marathon.csv +1280 -1280
  27. data/data/20070101_davidson_11m.csv +251 -0
  28. data/data/{davidson_11m_20070101.xml → 20070101_davidson_11m.xml} +0 -0
  29. data/data/{davidson_5K_20070505.xml → 20070505_davidson_5k.xml} +0 -0
  30. data/data/20070505_davidson_5k_km.csv +286 -0
  31. data/data/hrm1.csv +5 -0
  32. data/lib/gooby.rb +27 -3144
  33. data/lib/gooby_code_scanner.rb +288 -0
  34. data/lib/gooby_command.rb +210 -0
  35. data/lib/gooby_configuration.rb +123 -0
  36. data/lib/gooby_counter_hash.rb +95 -0
  37. data/lib/gooby_course.rb +117 -0
  38. data/lib/gooby_csv_point.rb +71 -0
  39. data/lib/gooby_csv_reader.rb +71 -0
  40. data/lib/gooby_csv_run.rb +28 -0
  41. data/lib/gooby_delim_line.rb +42 -0
  42. data/lib/gooby_dttm.rb +87 -0
  43. data/lib/gooby_duration.rb +86 -0
  44. data/lib/gooby_forerunner_xml_parser.rb +191 -0
  45. data/lib/gooby_forerunner_xml_splitter.rb +115 -0
  46. data/lib/gooby_google_map_generator.rb +385 -0
  47. data/lib/gooby_history.rb +41 -0
  48. data/lib/gooby_kernel.rb +163 -0
  49. data/lib/gooby_lap.rb +30 -0
  50. data/lib/gooby_line.rb +80 -0
  51. data/lib/gooby_object.rb +22 -0
  52. data/lib/gooby_point.rb +172 -0
  53. data/lib/gooby_run.rb +213 -0
  54. data/lib/gooby_simple_xml_parser.rb +50 -0
  55. data/lib/gooby_test_helper.rb +23 -0
  56. data/lib/gooby_track.rb +47 -0
  57. data/lib/gooby_track_point.rb +229 -0
  58. data/lib/gooby_training_center_xml_parser.rb +224 -0
  59. data/lib/gooby_training_center_xml_splitter.rb +116 -0
  60. data/lib/split_code.sh +29 -0
  61. data/samples/20050305_corporate_cup_hm.html +269 -269
  62. data/samples/20050430_nashville_marathon.html +1410 -1266
  63. data/samples/20060115_phoenix_marathon.html +1311 -1311
  64. data/samples/{davidson_11m_20070101.html → 20070101_davidson_11m.html} +267 -267
  65. data/samples/20070505_davidson_5k.html +413 -0
  66. data/samples/been_there.txt +52 -704
  67. data/samples/hrm1.html +87 -0
  68. data/sql/gooby.ddl +20 -16
  69. data/sql/gooby_load.dml +36 -9
  70. metadata +48 -14
  71. data/bin/example_usage.txt +0 -55
  72. data/bin/run_parse.sh +0 -43
  73. data/bin/run_parse_named.sh +0 -19
  74. data/data/20050430_nashville_marathon.csv +0 -1208
  75. data/data/davidson_11m_20070101.csv +0 -251
  76. data/data/davidson_5K_20070505.csv +0 -286
  77. data/data/test1.txt +0 -4
  78. data/samples/davidson_5K_20070505.html +0 -395
@@ -0,0 +1,28 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ class CsvRun < GoobyObject
12
+
13
+ attr_reader :id, :points
14
+
15
+ def initialize(id)
16
+ @id = "#{id}"
17
+ @points = Array.new
18
+ end
19
+
20
+ def add_point(point)
21
+ if point
22
+ @points << point
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end # end of module
@@ -0,0 +1,42 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ =begin rdoc
12
+ Instances of this class represent a delimited line of text, such as csv.
13
+ =end
14
+
15
+ class DelimLine < GoobyObject
16
+
17
+ attr_reader :line, :trim, :delim, :tokens
18
+
19
+ def initialize(line, trim=true, delim=default_delimiter)
20
+ @line = line
21
+ @trim = trim
22
+ @delim = delim
23
+ @tokens = @line.split(@delim)
24
+ if trim
25
+ @tokens.each { | token | token.strip! }
26
+ end
27
+ end
28
+
29
+ def as_trackpoint(num_idx, lat_idx, lng_idx, alt_idx, dttm_idx)
30
+ Trackpoint.new(@tokens[num_idx], @tokens[lat_idx], @tokens[lng_idx], @tokens[alt_idx], @tokens[dttm_idx])
31
+ end
32
+
33
+ def is_comment?
34
+ @line.strip.match('^#') ? true : false
35
+ end
36
+
37
+ def to_s
38
+ "DelimLine: length: #{@line.size} trim: #{@trim} delim: #{@delim} tokens: #{@tokens.size}"
39
+ end
40
+ end
41
+
42
+ end # end of module
data/lib/gooby_dttm.rb ADDED
@@ -0,0 +1,87 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ =begin rdoc
12
+ Instances of this class represent a Date and Time as parsed from a value
13
+ such as '2006-01-15T13:41:40Z' in an XML file produced by a GPS device.
14
+ It wrappers both a DateTime and Time object.
15
+ =end
16
+
17
+ class DtTm < GoobyObject
18
+
19
+ attr_accessor :rawdata, :dateTime, :time, :valid
20
+
21
+ # Constructor; arg is a String like '2006-01-15T13:41:40Z'.
22
+ def initialize(raw)
23
+ if raw
24
+ @rawdata = raw.strip
25
+ if @rawdata.size > 18
26
+ @date_time = DateTime.parse(@rawdata[0..18])
27
+ @time = Time.parse(@date_time.to_s)
28
+ @valid = true
29
+ else
30
+ @valid = false
31
+ end
32
+ else
33
+ @rawdata = ''
34
+ @valid = false
35
+ end
36
+ end
37
+
38
+ public
39
+
40
+ # Return @time.to_i
41
+ def to_i()
42
+ (@time) ? @time.to_i : invalid_time
43
+ end
44
+
45
+ # Calculates and returns diff between another instance.
46
+ def seconds_diff(anotherDtTm)
47
+ if anotherDtTm
48
+ to_i - anotherDtTm.to_i
49
+ else
50
+ invalid_time
51
+ end
52
+ end
53
+
54
+ def yyyy_mm_dd
55
+ @time.strftime("%Y-%m-%d")
56
+ end
57
+
58
+ def yyyy_mm_dd_hh_mm_ss(delim=' ')
59
+ @time.strftime("%Y-%m-%d#{delim}%H:%M:%S")
60
+ end
61
+
62
+ def hh_mm_ss
63
+ @time.strftime("%H:%M:%S")
64
+ end
65
+
66
+ # Calculate and return time diff in 'hh:mm:ss' format.
67
+ def hhmmss_diff(anotherDtTm)
68
+ if anotherDtTm
69
+ t = @time - (anotherDtTm.to_i)
70
+ t.strftime("%H:%M:%S")
71
+ else
72
+ '00:00:00'
73
+ end
74
+ end
75
+
76
+ def to_s
77
+ "#{@rawdata}"
78
+ end
79
+
80
+ # Return a String with state values for debugging.
81
+ def print_string
82
+ "DtTm: #{yyyy_mm_dd_hh_mm_ss} #{to_i} #{@rawdata}"
83
+ end
84
+
85
+ end
86
+
87
+ end # end of module
@@ -0,0 +1,86 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ =begin rdoc
12
+ Instances of this class represent the contents of a Forerunner extract
13
+ <Duration> tag, such as:
14
+ <Duration>PT507.870S</Duration>
15
+ =end
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 # end of module
@@ -0,0 +1,191 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ =begin rdoc
12
+ Instances of this class are used to parse a Forerunner XML file in a SAX-like
13
+ manner. Instances of the model classes - History, Run, Track, Trackpoint,
14
+ etc. are created in this parsing process.
15
+
16
+ See http://www.garmin.com/xmlschemas/ForerunnerLogbookv1.xsd for the XML Schema
17
+ Definition for the Garmin Forerunner XML. The Gooby object model mirrors this XSD.
18
+ =end
19
+
20
+ class ForerunnerXmlParser
21
+
22
+ DETAIL_TAGS = %w( Notes StartTime Duration Length Latitude Longitude Altitude Time BeginPosition EndPosition )
23
+
24
+ include REXML::StreamListener
25
+
26
+ attr_reader :uom, :history, :cvHash, :tagCount
27
+
28
+ def initialize(uom)
29
+ @uom = uom
30
+ @cv_hash = Hash.new("")
31
+ @tag_count = 0
32
+ @run_count = 0
33
+ @lap_count = 0
34
+ @track_count = 0
35
+ @trackpoint_count = 0
36
+ @curr_text = "";
37
+ @history = History.new
38
+ @curr_run = nil
39
+ @curr_lap = nil
40
+ @curr_track = nil
41
+ @curr_begin_position = nil
42
+ @@curr_end_position = nil
43
+ end
44
+
45
+ public
46
+
47
+ # SAX API method; handles 'Run', 'Lap', 'Track'.
48
+ def tag_start(tagname, attrs)
49
+ @tag_count += 1
50
+ @currTag = tagname
51
+ @cv_hash[tagname] = ''
52
+
53
+ if detail_tag?(tagname)
54
+ @inDetail = true
55
+ end
56
+
57
+ if is_tag?('Run', tagname)
58
+ @run_count = @run_count + 1
59
+ @lap_count = 0
60
+ @track_count = 0
61
+ @trackpoint_count = 0
62
+ @curr_run = Run.new(@run_count)
63
+ @history.add_run(@curr_run)
64
+ @cv_hash['Notes'] = ''
65
+ return
66
+ end
67
+
68
+ if is_tag?('Lap', tagname)
69
+ @lap_count = @lap_count + 1
70
+ @curr_lap = Lap.new(@lap_count)
71
+ return
72
+ end
73
+
74
+ if is_tag?('Track', tagname)
75
+ @track_count = @track_count + 1
76
+ @curr_track = Track.new(@track_count)
77
+ return
78
+ end
79
+ end
80
+
81
+ # SAX API method; handles 'Position', 'Trackpoint', 'Track', 'Lap', 'Run'.
82
+ def tag_end(tagname)
83
+ if @inDetail
84
+ @cv_hash[tagname] = @curr_text
85
+ else
86
+ if is_tag?('Position', tagname)
87
+ lat = @cv_hash['Latitude']
88
+ long = @cv_hash['Longitude']
89
+ @curr_begin_position = Point.new(lat.strip, long.strip)
90
+ @@curr_end_position = Point.new(lat.strip, long.strip)
91
+ end
92
+
93
+ if is_tag?('BeginPosition', tagname)
94
+ lat = @cv_hash['Latitude']
95
+ long = @cv_hash['Longitude']
96
+ @curr_begin_position = Point.new(lat.strip, long.strip)
97
+ end
98
+
99
+ if is_tag?('EndPosition', tagname)
100
+ lat = @cv_hash['Latitude']
101
+ long = @cv_hash['Longitude']
102
+ @@curr_end_position = Point.new(lat.strip, long.strip)
103
+ end
104
+
105
+ if is_tag?('Trackpoint', tagname)
106
+ @trackpoint_count = @trackpoint_count + 1
107
+ lat = @cv_hash['Latitude']
108
+ long = @cv_hash['Longitude']
109
+ alt = @cv_hash['Altitude']
110
+ hb = @cv_hash['HeartRateBpm']
111
+ time = @cv_hash['Time']
112
+ tp = Trackpoint.new(@trackpoint_count, lat, long, alt, hb, time, @uom)
113
+ @curr_track.add_trackpoint(tp)
114
+
115
+ @cv_hash['Latitude'] = ''
116
+ @cv_hash['Longitude'] = ''
117
+ @cv_hash['Altitude'] = ''
118
+ @cv_hash['HeartRateBpm'] = ''
119
+ @cv_hash['Time'] = ''
120
+ end
121
+
122
+ if is_tag?('Track', tagname)
123
+ if @curr_run != nil
124
+ @curr_run.add_track(@curr_track)
125
+ end
126
+ end
127
+
128
+ if is_tag?('Lap', tagname)
129
+ @curr_lap.startTime = @cv_hash['StartTime']
130
+ @curr_lap.duration = Duration.new(@cv_hash['Duration'])
131
+ @curr_lap.length = @cv_hash['Length']
132
+ @curr_lap.begin_position = @curr_begin_position
133
+ @curr_lap.end_position = @@curr_end_position
134
+ @curr_run.add_lap(@curr_lap)
135
+ end
136
+
137
+ if is_tag?('Run', tagname)
138
+ @curr_run.notes = @cv_hash['Notes']
139
+ end
140
+ end
141
+
142
+ @inDetail = false
143
+ @curr_text = ""
144
+ @currTag = ""
145
+ end
146
+
147
+ # SAX API method.
148
+ def text(txt)
149
+ if @inDetail
150
+ @curr_text = @curr_text + txt
151
+ end
152
+ end
153
+
154
+ # Iterate all parsed Run objects and print each with to_s.
155
+ def gdump()
156
+ @history.runs().each { |run| puts run.to_s }
157
+ end
158
+
159
+ # Iterate all parsed Run objects and print each with to_s.
160
+ def dump()
161
+ @history.runs().each { |run| puts run.to_s }
162
+ end
163
+
164
+ # Iterate all parsed Run objects and print each with put_csv.
165
+ def put_run_csv()
166
+ @history.runs().each { |run| run.put_csv() }
167
+ end
168
+
169
+ # Iterate all parsed Run objects and print each with put_tkpt_csv.
170
+ def put_all_run_tkpt_csv()
171
+ @history.runs.each { |run| run.put_tkpt_csv() }
172
+ end
173
+
174
+ private
175
+
176
+ def is_tag?(tagname, value)
177
+ tagname == value
178
+ end
179
+
180
+ def detail_tag?(tagname)
181
+ DETAIL_TAGS.each { |typ|
182
+ if typ == tagname
183
+ return true
184
+ end
185
+ }
186
+ return false
187
+ end
188
+
189
+ end
190
+
191
+ end # end of module
@@ -0,0 +1,115 @@
1
+ =begin
2
+
3
+ Gooby = Google APIs + Ruby
4
+ Gooby - Copyright 2007 by Chris Joakim.
5
+ Gooby is available under GNU General Public License (GPL) license.
6
+
7
+ =end
8
+
9
+ module Gooby
10
+
11
+ =begin rdoc
12
+ Instances of this class are used to split a large ForerunnerLogbook
13
+ XML file into individual 'run_' files.
14
+ =end
15
+
16
+ class ForerunnerXmlSplitter < GoobyObject
17
+
18
+ attr_reader :out_dir, :forerunner_files, :out_files_hash
19
+
20
+ def initialize(xml_file, out_dir)
21
+ @out_dir = out_dir
22
+ @forerunner_files = Array.new
23
+ @forerunner_files << xml_file
24
+ @out_files_hash = Hash.new
25
+ end
26
+
27
+ def split
28
+ @forerunner_files.each { |f| process_file(f) }
29
+ write_files
30
+ end
31
+
32
+ private
33
+
34
+ def process_file(forerunnerXmlFile)
35
+ @file_name = forerunnerXmlFile
36
+ @xml_lines = read_lines(@file_name, false)
37
+ @line_num = 0
38
+ @run_num = 0
39
+ @curr_run_lines = Array.new
40
+ @curr_run_tkpts = 0
41
+ @start_line_num = 0
42
+ @end_line_num = 0
43
+ @first_start_time = nil
44
+
45
+ @xml_lines.each { |line|
46
+ @line_num = @line_num + 1
47
+ if (line.match(/<Run>/))
48
+ @run_num = @run_num + 1
49
+ @start_line_num = @line_num
50
+ @curr_run_lines = Array.new
51
+ @curr_run_lines << line
52
+ elsif (line.match(/<StartTime>/)) # <StartTime>2007-01-13T15:37:06Z</StartTime>
53
+ @curr_run_lines << line
54
+ if @first_start_time == nil
55
+ clone = String.new(line)
56
+ clone.gsub!(/[<>]/, ' ')
57
+ clone.gsub!(/[-:T]/, '_')
58
+ clone.gsub!(/[Z]/, '')
59
+ tokens = clone.split
60
+ @first_start_time = tokens[1]
61
+ end
62
+ elsif (line.match(/<Trackpoint>/))
63
+ @curr_run_tkpts = @curr_run_tkpts + 1
64
+ @curr_run_lines << line
65
+ elsif (line.match(/<\/Run>/))
66
+ @end_line_num = @line_num
67
+ @curr_run_lines << line
68
+ end_run
69
+ elsif (@curr_run_lines.size > 0)
70
+ @curr_run_lines << line
71
+ end
72
+ }
73
+ end
74
+
75
+ def end_run
76
+ out_file = "#{@out_dir}/run_#{@first_start_time}.xml"
77
+ comment = "<!-- file: #{out_file} lines: #{@curr_run_lines.size} (#{@start_line_num} to #{@end_line_num}) tkpts: #{@curr_run_tkpts} --> \n"
78
+ @curr_run_lines.insert(0, comment)
79
+
80
+ prev_entry = @out_files_hash[out_file]
81
+ if prev_entry
82
+ if (@curr_run_lines.size >= prev_entry.size)
83
+ puts "previous entry overlaid for #{out_file}. curr=#{@curr_run_lines.size} prev=#{prev_entry.size}"
84
+ @out_files_hash[out_file] = @curr_run_lines
85
+ else
86
+ puts "previous entry retained for #{out_file}. curr=#{@curr_run_lines.size} prev=#{prev_entry.size}"
87
+ end
88
+ else
89
+ puts "new entry for #{out_file}. curr=#{@curr_run_lines.size}"
90
+ @out_files_hash[out_file] = @curr_run_lines
91
+ end
92
+
93
+ @curr_run_lines = Array.new
94
+ @curr_run_tkpts = 0
95
+ @start_line_num = 0
96
+ @end_line_num = 0
97
+ @first_start_time = nil
98
+ end
99
+
100
+ def write_files
101
+ out_names = @out_files_hash.keys.sort
102
+ puts "Writing #{out_names.size} extract files..."
103
+ out_names.each { |out_name|
104
+ lines = @out_files_hash[out_name]
105
+ out = File.new out_name, "w+"
106
+ lines.each { |line| out.write line }
107
+ out.flush
108
+ out.close
109
+ puts "File written: #{out_name}"
110
+ }
111
+ puts "output files written."
112
+ end
113
+ end
114
+
115
+ end # end of module