gooby 0.9.3

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 (224) hide show
  1. data/README +242 -0
  2. data/bin/example_usage.rb +38 -0
  3. data/bin/tests_gen.rb +16 -0
  4. data/data/20050305_corporate_cup_hm.csv +251 -0
  5. data/data/20050305_corporate_cup_hm.xml +2208 -0
  6. data/data/20050430_nashville_marathon.csv +1208 -0
  7. data/data/20050430_nashville_marathon.xml +10043 -0
  8. data/data/20051119_dowd_ymca_hm.csv +251 -0
  9. data/data/20051119_dowd_ymca_hm.xml +2210 -0
  10. data/data/20051124_hyatt_turkey_trot_8K.csv +321 -0
  11. data/data/20051124_hyatt_turkey_trot_8K.xml +2651 -0
  12. data/data/2007_03_03.tcx +6207 -0
  13. data/data/forerunner_2007.xml +259014 -0
  14. data/data/geo_data.txt +171 -0
  15. data/data/phx.csv +1280 -0
  16. data/data/phx.xml +10620 -0
  17. data/data/run_2007_01_01_16_38_27.xml +2020 -0
  18. data/data/run_2007_01_06_15_27_31.xml +2020 -0
  19. data/data/run_2007_01_10_12_25_47.xml +820 -0
  20. data/data/run_2007_01_10_22_44_54.csv +112 -0
  21. data/data/run_2007_01_10_22_44_54.xml +908 -0
  22. data/data/run_2007_01_11_10_48_45.xml +1292 -0
  23. data/data/run_2007_01_13_15_37_06.xml +1964 -0
  24. data/data/run_2007_01_14_15_46_02.xml +1368 -0
  25. data/data/run_2007_01_15_14_01_48.xml +1868 -0
  26. data/data/run_2007_01_20_16_22_05.xml +1702 -0
  27. data/data/run_2007_01_27_17_32_13.xml +3626 -0
  28. data/data/run_2007_01_28_19_14_52.xml +2538 -0
  29. data/data/run_2007_02_03_14_30_20.xml +2016 -0
  30. data/data/run_2007_02_04_18_02_30.xml +1476 -0
  31. data/data/run_2007_02_17_16_29_35.xml +1236 -0
  32. data/data/run_2007_02_19_14_44_33.xml +1816 -0
  33. data/data/run_2007_02_23_15_53_55.xml +36 -0
  34. data/data/run_2007_02_23_15_55_20.xml +1296 -0
  35. data/data/run_2007_02_24_15_01_35.csv +484 -0
  36. data/data/run_2007_02_24_15_01_35.xml +3884 -0
  37. data/data/test1.txt +4 -0
  38. data/img/gicons/blank.png +0 -0
  39. data/img/gicons/dd-end.png +0 -0
  40. data/img/gicons/dd-start.png +0 -0
  41. data/img/gicons/marker.png +0 -0
  42. data/img/gicons/marker0.png +0 -0
  43. data/img/gicons/marker00.png +0 -0
  44. data/img/gicons/marker01.png +0 -0
  45. data/img/gicons/marker02.png +0 -0
  46. data/img/gicons/marker03.png +0 -0
  47. data/img/gicons/marker04.png +0 -0
  48. data/img/gicons/marker05.png +0 -0
  49. data/img/gicons/marker06.png +0 -0
  50. data/img/gicons/marker07.png +0 -0
  51. data/img/gicons/marker08.png +0 -0
  52. data/img/gicons/marker09.png +0 -0
  53. data/img/gicons/marker1.png +0 -0
  54. data/img/gicons/marker10.png +0 -0
  55. data/img/gicons/marker11.png +0 -0
  56. data/img/gicons/marker12.png +0 -0
  57. data/img/gicons/marker13.png +0 -0
  58. data/img/gicons/marker14.png +0 -0
  59. data/img/gicons/marker15.png +0 -0
  60. data/img/gicons/marker16.png +0 -0
  61. data/img/gicons/marker17.png +0 -0
  62. data/img/gicons/marker18.png +0 -0
  63. data/img/gicons/marker19.png +0 -0
  64. data/img/gicons/marker2.png +0 -0
  65. data/img/gicons/marker20.png +0 -0
  66. data/img/gicons/marker21.png +0 -0
  67. data/img/gicons/marker22.png +0 -0
  68. data/img/gicons/marker23.png +0 -0
  69. data/img/gicons/marker24.png +0 -0
  70. data/img/gicons/marker25.png +0 -0
  71. data/img/gicons/marker26.png +0 -0
  72. data/img/gicons/marker27.png +0 -0
  73. data/img/gicons/marker28.png +0 -0
  74. data/img/gicons/marker29.png +0 -0
  75. data/img/gicons/marker3.png +0 -0
  76. data/img/gicons/marker30.png +0 -0
  77. data/img/gicons/marker31.png +0 -0
  78. data/img/gicons/marker32.png +0 -0
  79. data/img/gicons/marker33.png +0 -0
  80. data/img/gicons/marker34.png +0 -0
  81. data/img/gicons/marker35.png +0 -0
  82. data/img/gicons/marker36.png +0 -0
  83. data/img/gicons/marker37.png +0 -0
  84. data/img/gicons/marker38.png +0 -0
  85. data/img/gicons/marker39.png +0 -0
  86. data/img/gicons/marker4.png +0 -0
  87. data/img/gicons/marker40.png +0 -0
  88. data/img/gicons/marker41.png +0 -0
  89. data/img/gicons/marker42.png +0 -0
  90. data/img/gicons/marker43.png +0 -0
  91. data/img/gicons/marker44.png +0 -0
  92. data/img/gicons/marker45.png +0 -0
  93. data/img/gicons/marker46.png +0 -0
  94. data/img/gicons/marker47.png +0 -0
  95. data/img/gicons/marker48.png +0 -0
  96. data/img/gicons/marker49.png +0 -0
  97. data/img/gicons/marker5.png +0 -0
  98. data/img/gicons/marker50.png +0 -0
  99. data/img/gicons/marker51.png +0 -0
  100. data/img/gicons/marker52.png +0 -0
  101. data/img/gicons/marker53.png +0 -0
  102. data/img/gicons/marker54.png +0 -0
  103. data/img/gicons/marker55.png +0 -0
  104. data/img/gicons/marker56.png +0 -0
  105. data/img/gicons/marker57.png +0 -0
  106. data/img/gicons/marker58.png +0 -0
  107. data/img/gicons/marker59.png +0 -0
  108. data/img/gicons/marker6.png +0 -0
  109. data/img/gicons/marker60.png +0 -0
  110. data/img/gicons/marker61.png +0 -0
  111. data/img/gicons/marker62.png +0 -0
  112. data/img/gicons/marker63.png +0 -0
  113. data/img/gicons/marker64.png +0 -0
  114. data/img/gicons/marker65.png +0 -0
  115. data/img/gicons/marker66.png +0 -0
  116. data/img/gicons/marker67.png +0 -0
  117. data/img/gicons/marker68.png +0 -0
  118. data/img/gicons/marker69.png +0 -0
  119. data/img/gicons/marker7.png +0 -0
  120. data/img/gicons/marker70.png +0 -0
  121. data/img/gicons/marker71.png +0 -0
  122. data/img/gicons/marker72.png +0 -0
  123. data/img/gicons/marker73.png +0 -0
  124. data/img/gicons/marker74.png +0 -0
  125. data/img/gicons/marker75.png +0 -0
  126. data/img/gicons/marker76.png +0 -0
  127. data/img/gicons/marker77.png +0 -0
  128. data/img/gicons/marker78.png +0 -0
  129. data/img/gicons/marker79.png +0 -0
  130. data/img/gicons/marker8.png +0 -0
  131. data/img/gicons/marker80.png +0 -0
  132. data/img/gicons/marker81.png +0 -0
  133. data/img/gicons/marker82.png +0 -0
  134. data/img/gicons/marker83.png +0 -0
  135. data/img/gicons/marker84.png +0 -0
  136. data/img/gicons/marker85.png +0 -0
  137. data/img/gicons/marker86.png +0 -0
  138. data/img/gicons/marker87.png +0 -0
  139. data/img/gicons/marker88.png +0 -0
  140. data/img/gicons/marker89.png +0 -0
  141. data/img/gicons/marker9.png +0 -0
  142. data/img/gicons/marker90.png +0 -0
  143. data/img/gicons/marker91.png +0 -0
  144. data/img/gicons/marker92.png +0 -0
  145. data/img/gicons/marker93.png +0 -0
  146. data/img/gicons/marker94.png +0 -0
  147. data/img/gicons/marker95.png +0 -0
  148. data/img/gicons/marker96.png +0 -0
  149. data/img/gicons/marker97.png +0 -0
  150. data/img/gicons/marker98.png +0 -0
  151. data/img/gicons/marker99.png +0 -0
  152. data/img/gicons/markerA.png +0 -0
  153. data/img/gicons/markerB.png +0 -0
  154. data/img/gicons/markerC.png +0 -0
  155. data/img/gicons/markerD.png +0 -0
  156. data/img/gicons/markerE.png +0 -0
  157. data/img/gicons/markerF.png +0 -0
  158. data/img/gicons/markerG.png +0 -0
  159. data/img/gicons/markerH.png +0 -0
  160. data/img/gicons/markerI.png +0 -0
  161. data/img/gicons/markerJ.png +0 -0
  162. data/img/gicons/mm_20_red.png +0 -0
  163. data/img/gicons/mm_20_shadow.png +0 -0
  164. data/img/gicons/readme.txt +11 -0
  165. data/img/gicons/shadow50.png +0 -0
  166. data/lib/gooby/cls_counter_hash.rb +78 -0
  167. data/lib/gooby/cls_delim_line.rb +35 -0
  168. data/lib/gooby/cls_dttm.rb +79 -0
  169. data/lib/gooby/cls_duration.rb +79 -0
  170. data/lib/gooby/cls_forerunner_xml_parser.rb +178 -0
  171. data/lib/gooby/cls_forerunner_xml_splitter.rb +109 -0
  172. data/lib/gooby/cls_geo_data.rb +181 -0
  173. data/lib/gooby/cls_gooby_command.rb +35 -0
  174. data/lib/gooby/cls_gooby_object.rb +18 -0
  175. data/lib/gooby/cls_google_map_generator.rb +363 -0
  176. data/lib/gooby/cls_history.rb +33 -0
  177. data/lib/gooby/cls_lap.rb +22 -0
  178. data/lib/gooby/cls_line.rb +75 -0
  179. data/lib/gooby/cls_options.rb +67 -0
  180. data/lib/gooby/cls_position.rb +44 -0
  181. data/lib/gooby/cls_run.rb +194 -0
  182. data/lib/gooby/cls_simple_xml_parser.rb +41 -0
  183. data/lib/gooby/cls_test_regen.rb +182 -0
  184. data/lib/gooby/cls_track.rb +47 -0
  185. data/lib/gooby/cls_trackpoint.rb +200 -0
  186. data/lib/gooby/mod_introspect.rb +26 -0
  187. data/lib/gooby/mod_io.rb +58 -0
  188. data/lib/gooby/mod_project_info.rb +80 -0
  189. data/lib/gooby/mod_string.rb +19 -0
  190. data/lib/gooby/mod_test_helper.rb +15 -0
  191. data/lib/gooby.rb +2265 -0
  192. data/pkg/code_header.txt +21 -0
  193. data/pkg/pkg.rb +236 -0
  194. data/pkg/test_header.txt +19 -0
  195. data/samples/20041113_richmond_marathon.html +532 -0
  196. data/samples/20050305_corporate_cup_hm.html +448 -0
  197. data/samples/20050430_nashville_marathon.html +530 -0
  198. data/samples/gps_point_capture.html +54 -0
  199. data/samples/phoenix_marathon.html +542 -0
  200. data/samples/run_2007_01_10_22_44_54.html +201 -0
  201. data/samples/run_2007_02_24_15_01_35.html +298 -0
  202. data/tests/tc_cls_counter_hash.rb +107 -0
  203. data/tests/tc_cls_delim_line.rb +74 -0
  204. data/tests/tc_cls_dttm.rb +131 -0
  205. data/tests/tc_cls_duration.rb +51 -0
  206. data/tests/tc_cls_forerunner_xml_parser.rb +70 -0
  207. data/tests/tc_cls_geo_data.xxx +71 -0
  208. data/tests/tc_cls_gooby_object.rb +26 -0
  209. data/tests/tc_cls_google_map_generator.rb +109 -0
  210. data/tests/tc_cls_history.rb +46 -0
  211. data/tests/tc_cls_lap.rb +38 -0
  212. data/tests/tc_cls_line.rb +110 -0
  213. data/tests/tc_cls_options.rb +79 -0
  214. data/tests/tc_cls_position.rb +66 -0
  215. data/tests/tc_cls_run.rb +142 -0
  216. data/tests/tc_cls_simple_xml_parser.rb +50 -0
  217. data/tests/tc_cls_track.rb +70 -0
  218. data/tests/tc_cls_trackpoint.rb +145 -0
  219. data/tests/tc_mod_introspect.rb +32 -0
  220. data/tests/tc_mod_io.rb +53 -0
  221. data/tests/tc_mod_project_info.rb +79 -0
  222. data/tests/tc_mod_string.rb +58 -0
  223. data/tests/ts_gooby.rb +1237 -0
  224. metadata +270 -0
@@ -0,0 +1,194 @@
1
+ module Gooby
2
+
3
+ =begin rdoc
4
+ Instances of this class represent a <Run> aggregate object from a
5
+ Forerunner XML file.
6
+
7
+ Additionally, there is distance, pace, and Google Map generation logic
8
+ in this class.
9
+ =end
10
+
11
+ class Run < GoobyObject
12
+
13
+ attr_accessor :number, :descr, :notes, :tracks, :tkpts, :laps, :distance
14
+
15
+ def initialize(number=0, descr='')
16
+ @number = number
17
+ @descr = descr
18
+ @notes = ''
19
+ @tracks = Array.new
20
+ @tkpts = Array.new
21
+ @laps = Array.new
22
+ @distance = 0
23
+ @options = Hash.new
24
+ @logProgress = true
25
+ @finished = false
26
+ end
27
+
28
+ public
29
+
30
+ # This method is invoked at end-of-parsing.
31
+ def finish()
32
+ @logProgress = false
33
+ unless @finished
34
+ @tracks.each { |trk|
35
+ trk.trackpoints().each { |tkpt|
36
+ tkpt.runNumber = @number
37
+ @tkpts.push(tkpt)
38
+ }
39
+ }
40
+ compute_distance_and_pace
41
+ compute_splits
42
+ @finished = true
43
+ end
44
+ end
45
+
46
+ public
47
+
48
+ def add_track(trk)
49
+ if trk != nil
50
+ @tracks.push(trk)
51
+ end
52
+ end
53
+
54
+ def trackpoint_count()
55
+ @tkpts.size()
56
+ end
57
+
58
+ def add_lap(lap)
59
+ @laps.push(lap)
60
+ end
61
+
62
+ def lapCount()
63
+ @laps.size
64
+ end
65
+
66
+ def start_dttm()
67
+ count = 0
68
+ @tracks.each { |trk|
69
+ trk.trackpoints().each { |tkpt|
70
+ return tkpt.dttm()
71
+ }
72
+ }
73
+ return nil
74
+ end
75
+
76
+ def end_dttm()
77
+ lastOne = nil
78
+ @tracks.each { |trk|
79
+ trk.trackpoints().each { |tkpt|
80
+ lastOne = tkpt.dttm()
81
+ }
82
+ }
83
+ lastOne
84
+ end
85
+
86
+ def duration()
87
+ first = start_dttm()
88
+ last = end_dttm()
89
+ if first
90
+ if last
91
+ return last.hhmmss_diff(first)
92
+ end
93
+ end
94
+ return "??:??:??"
95
+ end
96
+
97
+ def start_yyyy_mm_dd
98
+ if start_dttm()
99
+ start_dttm().yyyy_mm_dd()
100
+ else
101
+ ""
102
+ end
103
+ end
104
+
105
+ def start_hh_mm_ss
106
+ if start_dttm()
107
+ start_dttm().hh_mm_ss()
108
+ else
109
+ ""
110
+ end
111
+ end
112
+
113
+ def end_hh_mm_ss
114
+ if end_dttm()
115
+ end_dttm().hh_mm_ss()
116
+ else
117
+ ""
118
+ end
119
+ end
120
+
121
+ def to_s
122
+ finish() unless @finished
123
+ s = "Run: #{@number} date: #{start_yyyy_mm_dd} distance: #{distance} duration: #{duration} "
124
+ s << " tracks: #{@tracks.size} tkpts: #{trackpoint_count} laps: #{lapCount} "
125
+ s << " notes: #{@notes} "
126
+ s
127
+ end
128
+
129
+ def print_string
130
+ finish() unless @finished
131
+ "Run number=#{@number} tracks=#{@tracks.size} tkpts=#{@tkpts.size} laps=#{@laps.size} distance=#{@distance} "
132
+ end
133
+
134
+ def put_csv()
135
+ finish() unless @finished
136
+ puts "#{@number}|#{}|#{start_yyyy_mm_dd()}|#{start_hh_mm_ss()}|#{end_hh_mm_ss}|#{duration()}|#{@distance}|#{@tracks.size}|#{trackpoint_count()}|#{lapCount}|#{@notes.strip}"
137
+ end
138
+
139
+ def put_tkpt_csv(with_header_comment=false)
140
+ finish() unless @finished
141
+ if with_header_comment
142
+ puts "# Run: #{@number} date: #{start_yyyy_mm_dd} dist: #{distance} dur: #{duration} trks: #{@tracks.size} tkpts: #{trackpoint_count} laps: #{lapCount} "
143
+ end
144
+ @tkpts.each { | tkpt | puts tkpt.to_csv }
145
+ end
146
+
147
+ def put_laps
148
+ @laps.each { | lap | puts lap.to_s }
149
+ end
150
+
151
+ private
152
+
153
+ def compute_distance_and_pace
154
+ cumulative_dist = 0.to_f;
155
+ curr_index = -1
156
+ prev_tkpt = nil
157
+ start_dttm = nil
158
+ @tkpts.each { | tkpt |
159
+ curr_index = curr_index + 1
160
+ if curr_index == 0
161
+ start_dttm = tkpt.dttm()
162
+ prev_tkpt = tkpt
163
+ else
164
+ cumulative_dist = tkpt.compute_distance_and_pace(curr_index, start_dttm, cumulative_dist, prev_tkpt, 'M')
165
+ prev_tkpt = tkpt
166
+ end
167
+ }
168
+ @distance = cumulative_dist
169
+ end
170
+
171
+ def compute_splits
172
+ nextSplitDist = 1.00
173
+ prevSplitTkpt = nil
174
+ loop1Count = 0;
175
+ @tkpts.each { |tkpt|
176
+ loop1Count = loop1Count + 1
177
+ if tkpt.cumulativeDistance() >= nextSplitDist
178
+ tkpt.set_split(0 + nextSplitDist, prevSplitTkpt)
179
+ nextSplitDist = nextSplitDist + 1.00
180
+ prevSplitTkpt = tkpt
181
+ end
182
+ }
183
+ # set first and last booleans
184
+ count = 0
185
+ @tkpts.each { |tkpt|
186
+ count = count + 1
187
+ tkpt.first = true if count == 1
188
+ tkpt.last = true if count == loop1Count
189
+ }
190
+ end
191
+
192
+ end
193
+
194
+ end # end of module
@@ -0,0 +1,41 @@
1
+ module Gooby
2
+
3
+ =begin rdoc
4
+ Sample implementation of a REXML::StreamListener SAX parser.
5
+ =end
6
+
7
+ class SimpleXmlParser
8
+
9
+ include REXML::StreamListener
10
+
11
+ attr_accessor :tag_count, :watched_tags
12
+
13
+ def initialize
14
+ @tag_count = 0
15
+ @counter_hash = CounterHash.new
16
+ end
17
+
18
+ public
19
+
20
+ # SAX API method. Increments the tagname in the counter hash.
21
+ def tag_start(tag_name, attrs)
22
+ @tag_count = @tag_count + 1
23
+ @counter_hash.increment(tag_name)
24
+ end
25
+
26
+ # SAX API method. No impl.
27
+ def tag_end(tagname)
28
+ end
29
+
30
+ # SAX API method. No impl.
31
+ def text(txt)
32
+ end
33
+
34
+ # Prints the state of this object (the counter hash).
35
+ def dump
36
+ puts @counter_hash.to_s
37
+ end
38
+
39
+ end
40
+
41
+ end # end of module
@@ -0,0 +1,182 @@
1
+ module Gooby
2
+
3
+ =begin rdoc
4
+ This class is used to generate, on an ongoing basis, the various Gooby test
5
+ classes. Regeneration retains the current test methods, and adds stubs for
6
+ new test methods. All methods, old and new, appear in the merged output in
7
+ propper sort sequence.
8
+ =end
9
+
10
+ class TestGenerator < GoobyObject
11
+
12
+ def initialize
13
+ tested_files.each { | base_rb_file |
14
+ test_file = "tc_#{base_rb_file}"
15
+ if true
16
+ @codeLines = read_lines("lib/#{base_rb_file}")
17
+ @testLines = read_lines("tests/#{test_file}")
18
+ @codeHash = Hash.new
19
+ @testHash = Hash.new
20
+ @mergedHash = Hash.new
21
+ @excludeClasses = %w( TestHelper TestGenerator )
22
+ puts "current codeLines = #{@codeLines.size}"
23
+ puts "current testLines = #{@testLines.size}"
24
+ parse_code_lines
25
+ parse_test_lines
26
+ merge_keys
27
+ regenerate(test_file)
28
+ end
29
+ }
30
+ end
31
+
32
+ private
33
+
34
+ # Produce a Hash with keys and values like the following:
35
+ # test|class|Trackpoint|deg2rad Trackpoint|deg2rad(degrees)
36
+
37
+ def parse_code_lines
38
+ type = ''
39
+ type_name = ''
40
+ meth_name = ''
41
+ @codeLines.each { | line |
42
+ line.strip!
43
+ if (line.match(/^module /))
44
+ type = 'module'
45
+ tokens = line.split
46
+ type_name = tokens[1]
47
+ elsif (line.match(/^class /))
48
+ type = 'class'
49
+ tokens = line.split
50
+ type_name = tokens[1]
51
+ elsif (line.match(/^def /))
52
+ signature = line[4...999]
53
+ short_method = parse_meth_name("#{signature}")
54
+ @codeHash["test_#{type}_#{type_name}"] = "#{type_name}"
55
+ @codeHash["test_#{type}_#{type_name}_#{short_method}"] = "#{type_name}|#{signature}"
56
+ end
57
+ }
58
+ end
59
+
60
+ def parse_meth_name(string)
61
+ string.gsub!('(', ' ')
62
+ string.gsub!(')', ' ')
63
+ tokens = string.split
64
+ tokens[0]
65
+ end
66
+
67
+ def parse_test_lines
68
+ in_method = true
69
+ method_name = 'a_start'
70
+ method_lines = Array.new
71
+ line_num = 0
72
+
73
+ @testLines.each { | line |
74
+ line_num = line_num + 1
75
+ line.chomp!
76
+ prefix = line[0...5] # ' def'
77
+ prefix21 = line[0...21] # ' ### Start of tests.'
78
+
79
+ if ((prefix == ' def') || (prefix == "\tdef"))
80
+ in_method = true
81
+ tokens = line.split
82
+ method_name = tokens[1]
83
+ method_lines = Array.new
84
+ end
85
+ if in_method
86
+ method_lines << "#{line}"
87
+ end
88
+ if prefix21 == ' ### Start of tests.'
89
+ in_method = false
90
+ @testHash["#{method_name}"] = method_lines
91
+ end
92
+ if ((prefix == ' end') || (prefix == "\tend"))
93
+ in_method = false
94
+ @testHash["#{method_name}"] = method_lines
95
+ end
96
+ }
97
+ end
98
+
99
+ def merge_keys
100
+ @codeHash.keys.sort.each { |key| @mergedHash["#{key}"] = "code" }
101
+ @testHash.keys.sort.each { |key| @mergedHash["#{key}"] = "test" }
102
+ end
103
+
104
+ def regenerate(test_file)
105
+ code = ''
106
+ @mergedHash.keys.sort.each { |key|
107
+
108
+ tokens = key.split('_')
109
+ type, name, meth = tokens[1], tokens[2], tokens[3]
110
+
111
+ processThisKey = true
112
+ @excludeClasses.each { |xc|
113
+ if xc == name
114
+ processThisKey = false
115
+ end
116
+ }
117
+
118
+ next if !processThisKey
119
+
120
+ if @testHash.has_key?(key)
121
+ # We already have a test method written in the test class,
122
+ # so keep this currently existing test code!
123
+
124
+ if @codeHash.has_key?(key)
125
+ comment = nil
126
+ else
127
+ if key != 'a_start'
128
+ comment = "# Warning: possible obsolete test method - #{key}"
129
+ end
130
+ end
131
+
132
+ code << "\n"
133
+ if comment != nil
134
+ code << "\n#{comment}"
135
+ code << "\n"
136
+ end
137
+ array = @testHash["#{key}"]
138
+ array.each { |line| code << "\n#{line}" }
139
+ else
140
+ # We don't have this test method in the current test class,
141
+ # so generate a test method stub.
142
+
143
+ code << "\n"
144
+ code << "\n def #{key}"
145
+ code << "\n"
146
+
147
+ if @gen_impl_stub
148
+ if type = 'class'
149
+ code << "\n #obj = #{type}.new"
150
+ code << "\n #result = obj.#{meth}"
151
+ code << "\n #expected = ''"
152
+ s = "\n"
153
+ s << ' #assert_equal(expected, actual, "'
154
+ s << "#{type}.#{meth} "
155
+ s << 'values are not as expected; #{result} vs #{expected}")'
156
+ code << s
157
+ else
158
+ code << "\n #result = #{type}.#{meth}"
159
+ code << "\n #expected = ''"
160
+ s = "\n"
161
+ s << ' #assert_equal(expected, actual, "'
162
+ s << "#{type}.#{meth} "
163
+ s << 'values are not as expected; #{result} vs #{expected}")'
164
+ code << s
165
+ end
166
+ end
167
+ code << "\n end"
168
+ end
169
+ }
170
+ code << "\nend" # end of class
171
+ code << "\n"
172
+ fn = "tests/#{test_file}"
173
+ out = File.new fn, "w+"
174
+ out.write code
175
+ out.flush
176
+ out.close
177
+ puts "file written: #{fn}"
178
+ end
179
+
180
+ end
181
+
182
+ end # end of module
@@ -0,0 +1,47 @@
1
+ module Gooby
2
+
3
+ =begin rdoc
4
+ Instances of this class represent a <Track> aggregate object from a Forerunner
5
+ XML file. Note that a <Run> may contain more than one <Track> aggregates.
6
+ =end
7
+
8
+ class Track < GoobyObject
9
+
10
+ attr_reader :number, :descr, :trackpoints
11
+
12
+ def initialize(num=0, descr='')
13
+ @number = num
14
+ @descr = descr
15
+ @trackpoints = Array.new
16
+ end
17
+
18
+ public
19
+
20
+ def add_trackpoint(tkpt)
21
+ @trackpoints.push(tkpt)
22
+ end
23
+
24
+ def size
25
+ @trackpoints.size
26
+ end
27
+
28
+ def first_tkpt
29
+ @trackpoints.size > 0 ? @trackpoints[0] : nil
30
+ end
31
+
32
+ def last_tkpt
33
+ @trackpoints.size > 0 ? @trackpoints[-1] : nil
34
+ end
35
+
36
+ def to_s
37
+ return "Trk: #{@descr} tkpts: #{size}"
38
+ end
39
+
40
+ def dump
41
+ puts "Track: '#{@descr}' tkpts: #{size}"
42
+ @trackpoints.each { |tkpt| puts tkpt.to_csv } # to_geo_s
43
+ end
44
+
45
+ end
46
+
47
+ end # end of module
@@ -0,0 +1,200 @@
1
+ module Gooby
2
+
3
+ =begin rdoc
4
+ Instances of this class represent a <Trackpoint> aggregate from a Forerunner
5
+ XML file. Additionally, there is distance, pace, and Google Map generation
6
+ logic in this class.
7
+
8
+ <Trackpoint>
9
+ <Position>
10
+ <Latitude>35.49577</Latitude>
11
+ <Longitude>-80.83281</Longitude>
12
+ <Altitude>232.296</Altitude>
13
+ </Position>
14
+ <Time>2007-01-06T15:27:51Z</Time>
15
+ </Trackpoint>
16
+ =end
17
+
18
+ class Trackpoint < Position
19
+
20
+ attr_reader :first, :last, :number, :runNumber, :dttm, :prevTkpt, :descr
21
+ attr_reader :cumulativeDistance, :cumulativePace, :incrementalDistance, :split, :prevSplit
22
+ attr_writer :first, :last, :runNumber
23
+
24
+ def initialize(num, lat, lng, alt, time_string, descr='')
25
+ @number = num
26
+ @runNumber = 0
27
+
28
+ # initialize superclass variables:
29
+ @latitude = lat.to_s
30
+ @longitude = lng.to_s
31
+ @altitude = alt.to_s
32
+ @note = note.to_s
33
+ @dttm = DtTm.new(time_string)
34
+ @first = false
35
+ @last = false
36
+ @prevTkpt = nil
37
+ @cumulativeDistance, @split = 0.0, 0.0
38
+ @cumulativePace = ""
39
+ @descr = descr
40
+ end
41
+
42
+ public
43
+
44
+ def position
45
+ Position.new(@latitude, @longitude, @altitude, @note)
46
+ end
47
+
48
+ def to_s
49
+ "Tkpt: #{@number} #{super.to_s} date: #{@dttm.to_s} cdist: #{@cumulativeDistance}"
50
+ end
51
+
52
+ def to_csv
53
+ ss = position.to_csv
54
+ "#{@runNumber} | #{@dttm.to_s} | #{@number} | #{ss} | #{@cumulativeDistance} "
55
+ end
56
+
57
+ def to_geo_s
58
+ ss = position.to_csv
59
+ "Tkpt: #{@number} | #{ss} | #{@descr}"
60
+ end
61
+
62
+ def compute_distance_and_pace(curr_index, start_dttm, prev_cumulative_dist, prev_trackpoint, units)
63
+ @prev_tkpt = prev_trackpoint
64
+ @cumulativeDistance = prev_cumulative_dist.to_f
65
+
66
+ if @prev_tkpt
67
+ arg1 = latitude().to_f
68
+ arg2 = @prev_tkpt.latitude().to_f
69
+ arg3 = latitude().to_f
70
+ arg4 = @prev_tkpt.latitude().to_f
71
+ theta = longitude().to_f - @prev_tkpt.longitude().to_f
72
+
73
+ res1 = Math.sin(deg2rad(arg1))
74
+ res2 = Math.sin(deg2rad(arg2))
75
+ res3 = Math.cos(deg2rad(arg3))
76
+ res4 = Math.cos(deg2rad(arg4))
77
+ res5 = Math.cos(deg2rad(theta.to_f))
78
+
79
+ incremental_distance = ((res1 * res2) + (res3 * res4 * res5)).to_f
80
+
81
+ if (!incremental_distance.nan?)
82
+ incremental_distance = Math.acos(incremental_distance.to_f)
83
+ if (!incremental_distance.nan?)
84
+ incremental_distance = rad2deg(incremental_distance)
85
+ if (!incremental_distance.nan?)
86
+ incremental_distance = incremental_distance * 60 * 1.1515;
87
+ if (!incremental_distance.nan?)
88
+ if units == "K"
89
+ incremental_distance = incremental_distance * 1.609344;
90
+ end
91
+ if units == "N"
92
+ incremental_distance = incremental_distance * 0.8684;
93
+ end
94
+ @cumulativeDistance = @cumulativeDistance + incremental_distance.to_f
95
+ end
96
+ end
97
+ end
98
+ end
99
+ compute_cumulative_pace(start_dttm)
100
+ @cumulativeDistance
101
+ else
102
+ 0
103
+ end
104
+ end
105
+
106
+ def compute_cumulative_pace(start_dttm)
107
+ if @cumulativeDistance > 0
108
+ secsDiff = @dttm.seconds_diff(start_dttm)
109
+ secsMile = ((secsDiff.to_f) / (@cumulativeDistance.to_f))
110
+ minsMile = (secsMile / 60)
111
+ wholeMins = minsMile.floor
112
+ secsBal = secsMile - (wholeMins * 60)
113
+ s1 = "#{secsDiff} #{secsMile} #{minsMile} #{wholeMins} #{secsBal} #{@cumulativeDistance} | "
114
+ s2 = sprintf("%d:%2.1f", minsMile, secsBal)
115
+ @cumulativePace = "#{s2}"
116
+ else
117
+ @cumulativePace = ""
118
+ end
119
+ end
120
+
121
+ def set_split(n, tkpt)
122
+ @split, @prevSplit = n, tkpt
123
+ end
124
+
125
+ def is_split()
126
+ (@split >= 1)
127
+ end
128
+
129
+ def is_first()
130
+ @first
131
+ end
132
+
133
+ def is_last()
134
+ @last
135
+ end
136
+
137
+ def split_info(dtTm)
138
+ if is_split
139
+ hhmmss = ''
140
+ if @prevSplit
141
+ return "#{@split} #{@dttm.hhmmss_diff(@prevSplit.dttm())}"
142
+ else
143
+ return "#{@split} #{@dttm.hhmmss_diff(dtTm)}"
144
+ end
145
+ else
146
+ ""
147
+ end
148
+ end
149
+
150
+ private
151
+
152
+ def deg2rad(degrees)
153
+ (((0 + degrees) * Math::PI) / 180)
154
+ end
155
+
156
+ def rad2deg(radians)
157
+ (((0 + radians) * 180) / Math::PI)
158
+ end
159
+
160
+ public
161
+
162
+ def as_glatlng(comments, tkpt_count, curr_idx, gpoint_count, start_dttm)
163
+ if comments
164
+ secs_diff = @dttm.seconds_diff(start_dttm)
165
+ fmt_time = @dttm.hhmmss_diff(start_dttm)
166
+ "\n points.push(new GLatLng(#{latitude_as_float},#{longitude_as_float})); " +
167
+ "// #{gpoint_count} (#{curr_idx + 1} of #{tkpt_count}) #{@dttm.to_s} #{secs_diff} #{fmt_time} #{@cumulativeDistance} #{split_info(start_dttm)} "
168
+ else
169
+ "\n points.push(new GLatLng(#{latitude_as_float},#{longitude_as_float})); "
170
+ end
171
+ end
172
+
173
+ def as_info_window_html(checkpoint, start_dttm)
174
+ s = "\"<table align='left'>"
175
+ if checkpoint
176
+ secs_diff = @dttm.seconds_diff(start_dttm)
177
+ fmt_time = @dttm.hhmmss_diff(start_dttm)
178
+
179
+ if checkpoint == 'Start'
180
+ s << "<tr><td colspan='2'><b>Start!</b></td></tr>"
181
+ elsif checkpoint == 'Finish'
182
+ s << "<tr><td colspan='2'><b>Finish!</b></td></tr>"
183
+ else
184
+ s << "<tr><td colspan='2'><b>Checkpoint #{checkpoint}</b></td></tr>"
185
+ end
186
+ s << "<tr><td>Distance: </td><td>#{@cumulativeDistance}</td></tr>"
187
+ s << "<tr><td>Time of Day: </td><td>#{@dttm.to_s} </td></tr>"
188
+ s << "<tr><td>Elapsed Time: </td><td>#{fmt_time} </td></tr>"
189
+ s << "<tr><td>Average Pace: </td><td>#{@cumulativePace} </td></tr>"
190
+ s << "<tr><td>Lat/Lng: </td><td>#{latitude_as_float} , #{longitude_as_float} </td></tr>"
191
+ s << "<tr><td>Altitude: </td><td>#{altitude_as_float}m </td></tr>"
192
+ s
193
+ end
194
+ s << "</table>\""
195
+ s
196
+ end
197
+
198
+ end
199
+
200
+ end # end of module
@@ -0,0 +1,26 @@
1
+ module Gooby
2
+
3
+ module Introspect
4
+
5
+ # Return a String w/instance variable and method info.
6
+ def introspect
7
+ c = self.class
8
+ s = "Class: #{c} "
9
+ iv = self.instance_variables.sort
10
+ s << " ivc=#{iv.size}"
11
+ iv.each { |v| s << " #{v}" }
12
+ meth = self.methods.sort
13
+ s << " mc=#{meth.size}"
14
+ meth.each { |m| s << " #{m}" }
15
+ s << ""
16
+ s
17
+ end
18
+
19
+ # Return 'self.instance_variables'.
20
+ def to_yaml_properties
21
+ self.instance_variables
22
+ end
23
+
24
+ end
25
+
26
+ end # end of module