gooby 0.9.3

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