gooby 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +242 -0
- data/bin/example_usage.rb +38 -0
- data/bin/tests_gen.rb +16 -0
- data/data/20050305_corporate_cup_hm.csv +251 -0
- data/data/20050305_corporate_cup_hm.xml +2208 -0
- data/data/20050430_nashville_marathon.csv +1208 -0
- data/data/20050430_nashville_marathon.xml +10043 -0
- data/data/20051119_dowd_ymca_hm.csv +251 -0
- data/data/20051119_dowd_ymca_hm.xml +2210 -0
- data/data/20051124_hyatt_turkey_trot_8K.csv +321 -0
- data/data/20051124_hyatt_turkey_trot_8K.xml +2651 -0
- data/data/2007_03_03.tcx +6207 -0
- data/data/forerunner_2007.xml +259014 -0
- data/data/geo_data.txt +171 -0
- data/data/phx.csv +1280 -0
- data/data/phx.xml +10620 -0
- data/data/run_2007_01_01_16_38_27.xml +2020 -0
- data/data/run_2007_01_06_15_27_31.xml +2020 -0
- data/data/run_2007_01_10_12_25_47.xml +820 -0
- data/data/run_2007_01_10_22_44_54.csv +112 -0
- data/data/run_2007_01_10_22_44_54.xml +908 -0
- data/data/run_2007_01_11_10_48_45.xml +1292 -0
- data/data/run_2007_01_13_15_37_06.xml +1964 -0
- data/data/run_2007_01_14_15_46_02.xml +1368 -0
- data/data/run_2007_01_15_14_01_48.xml +1868 -0
- data/data/run_2007_01_20_16_22_05.xml +1702 -0
- data/data/run_2007_01_27_17_32_13.xml +3626 -0
- data/data/run_2007_01_28_19_14_52.xml +2538 -0
- data/data/run_2007_02_03_14_30_20.xml +2016 -0
- data/data/run_2007_02_04_18_02_30.xml +1476 -0
- data/data/run_2007_02_17_16_29_35.xml +1236 -0
- data/data/run_2007_02_19_14_44_33.xml +1816 -0
- data/data/run_2007_02_23_15_53_55.xml +36 -0
- data/data/run_2007_02_23_15_55_20.xml +1296 -0
- data/data/run_2007_02_24_15_01_35.csv +484 -0
- data/data/run_2007_02_24_15_01_35.xml +3884 -0
- data/data/test1.txt +4 -0
- data/img/gicons/blank.png +0 -0
- data/img/gicons/dd-end.png +0 -0
- data/img/gicons/dd-start.png +0 -0
- data/img/gicons/marker.png +0 -0
- data/img/gicons/marker0.png +0 -0
- data/img/gicons/marker00.png +0 -0
- data/img/gicons/marker01.png +0 -0
- data/img/gicons/marker02.png +0 -0
- data/img/gicons/marker03.png +0 -0
- data/img/gicons/marker04.png +0 -0
- data/img/gicons/marker05.png +0 -0
- data/img/gicons/marker06.png +0 -0
- data/img/gicons/marker07.png +0 -0
- data/img/gicons/marker08.png +0 -0
- data/img/gicons/marker09.png +0 -0
- data/img/gicons/marker1.png +0 -0
- data/img/gicons/marker10.png +0 -0
- data/img/gicons/marker11.png +0 -0
- data/img/gicons/marker12.png +0 -0
- data/img/gicons/marker13.png +0 -0
- data/img/gicons/marker14.png +0 -0
- data/img/gicons/marker15.png +0 -0
- data/img/gicons/marker16.png +0 -0
- data/img/gicons/marker17.png +0 -0
- data/img/gicons/marker18.png +0 -0
- data/img/gicons/marker19.png +0 -0
- data/img/gicons/marker2.png +0 -0
- data/img/gicons/marker20.png +0 -0
- data/img/gicons/marker21.png +0 -0
- data/img/gicons/marker22.png +0 -0
- data/img/gicons/marker23.png +0 -0
- data/img/gicons/marker24.png +0 -0
- data/img/gicons/marker25.png +0 -0
- data/img/gicons/marker26.png +0 -0
- data/img/gicons/marker27.png +0 -0
- data/img/gicons/marker28.png +0 -0
- data/img/gicons/marker29.png +0 -0
- data/img/gicons/marker3.png +0 -0
- data/img/gicons/marker30.png +0 -0
- data/img/gicons/marker31.png +0 -0
- data/img/gicons/marker32.png +0 -0
- data/img/gicons/marker33.png +0 -0
- data/img/gicons/marker34.png +0 -0
- data/img/gicons/marker35.png +0 -0
- data/img/gicons/marker36.png +0 -0
- data/img/gicons/marker37.png +0 -0
- data/img/gicons/marker38.png +0 -0
- data/img/gicons/marker39.png +0 -0
- data/img/gicons/marker4.png +0 -0
- data/img/gicons/marker40.png +0 -0
- data/img/gicons/marker41.png +0 -0
- data/img/gicons/marker42.png +0 -0
- data/img/gicons/marker43.png +0 -0
- data/img/gicons/marker44.png +0 -0
- data/img/gicons/marker45.png +0 -0
- data/img/gicons/marker46.png +0 -0
- data/img/gicons/marker47.png +0 -0
- data/img/gicons/marker48.png +0 -0
- data/img/gicons/marker49.png +0 -0
- data/img/gicons/marker5.png +0 -0
- data/img/gicons/marker50.png +0 -0
- data/img/gicons/marker51.png +0 -0
- data/img/gicons/marker52.png +0 -0
- data/img/gicons/marker53.png +0 -0
- data/img/gicons/marker54.png +0 -0
- data/img/gicons/marker55.png +0 -0
- data/img/gicons/marker56.png +0 -0
- data/img/gicons/marker57.png +0 -0
- data/img/gicons/marker58.png +0 -0
- data/img/gicons/marker59.png +0 -0
- data/img/gicons/marker6.png +0 -0
- data/img/gicons/marker60.png +0 -0
- data/img/gicons/marker61.png +0 -0
- data/img/gicons/marker62.png +0 -0
- data/img/gicons/marker63.png +0 -0
- data/img/gicons/marker64.png +0 -0
- data/img/gicons/marker65.png +0 -0
- data/img/gicons/marker66.png +0 -0
- data/img/gicons/marker67.png +0 -0
- data/img/gicons/marker68.png +0 -0
- data/img/gicons/marker69.png +0 -0
- data/img/gicons/marker7.png +0 -0
- data/img/gicons/marker70.png +0 -0
- data/img/gicons/marker71.png +0 -0
- data/img/gicons/marker72.png +0 -0
- data/img/gicons/marker73.png +0 -0
- data/img/gicons/marker74.png +0 -0
- data/img/gicons/marker75.png +0 -0
- data/img/gicons/marker76.png +0 -0
- data/img/gicons/marker77.png +0 -0
- data/img/gicons/marker78.png +0 -0
- data/img/gicons/marker79.png +0 -0
- data/img/gicons/marker8.png +0 -0
- data/img/gicons/marker80.png +0 -0
- data/img/gicons/marker81.png +0 -0
- data/img/gicons/marker82.png +0 -0
- data/img/gicons/marker83.png +0 -0
- data/img/gicons/marker84.png +0 -0
- data/img/gicons/marker85.png +0 -0
- data/img/gicons/marker86.png +0 -0
- data/img/gicons/marker87.png +0 -0
- data/img/gicons/marker88.png +0 -0
- data/img/gicons/marker89.png +0 -0
- data/img/gicons/marker9.png +0 -0
- data/img/gicons/marker90.png +0 -0
- data/img/gicons/marker91.png +0 -0
- data/img/gicons/marker92.png +0 -0
- data/img/gicons/marker93.png +0 -0
- data/img/gicons/marker94.png +0 -0
- data/img/gicons/marker95.png +0 -0
- data/img/gicons/marker96.png +0 -0
- data/img/gicons/marker97.png +0 -0
- data/img/gicons/marker98.png +0 -0
- data/img/gicons/marker99.png +0 -0
- data/img/gicons/markerA.png +0 -0
- data/img/gicons/markerB.png +0 -0
- data/img/gicons/markerC.png +0 -0
- data/img/gicons/markerD.png +0 -0
- data/img/gicons/markerE.png +0 -0
- data/img/gicons/markerF.png +0 -0
- data/img/gicons/markerG.png +0 -0
- data/img/gicons/markerH.png +0 -0
- data/img/gicons/markerI.png +0 -0
- data/img/gicons/markerJ.png +0 -0
- data/img/gicons/mm_20_red.png +0 -0
- data/img/gicons/mm_20_shadow.png +0 -0
- data/img/gicons/readme.txt +11 -0
- data/img/gicons/shadow50.png +0 -0
- data/lib/gooby/cls_counter_hash.rb +78 -0
- data/lib/gooby/cls_delim_line.rb +35 -0
- data/lib/gooby/cls_dttm.rb +79 -0
- data/lib/gooby/cls_duration.rb +79 -0
- data/lib/gooby/cls_forerunner_xml_parser.rb +178 -0
- data/lib/gooby/cls_forerunner_xml_splitter.rb +109 -0
- data/lib/gooby/cls_geo_data.rb +181 -0
- data/lib/gooby/cls_gooby_command.rb +35 -0
- data/lib/gooby/cls_gooby_object.rb +18 -0
- data/lib/gooby/cls_google_map_generator.rb +363 -0
- data/lib/gooby/cls_history.rb +33 -0
- data/lib/gooby/cls_lap.rb +22 -0
- data/lib/gooby/cls_line.rb +75 -0
- data/lib/gooby/cls_options.rb +67 -0
- data/lib/gooby/cls_position.rb +44 -0
- data/lib/gooby/cls_run.rb +194 -0
- data/lib/gooby/cls_simple_xml_parser.rb +41 -0
- data/lib/gooby/cls_test_regen.rb +182 -0
- data/lib/gooby/cls_track.rb +47 -0
- data/lib/gooby/cls_trackpoint.rb +200 -0
- data/lib/gooby/mod_introspect.rb +26 -0
- data/lib/gooby/mod_io.rb +58 -0
- data/lib/gooby/mod_project_info.rb +80 -0
- data/lib/gooby/mod_string.rb +19 -0
- data/lib/gooby/mod_test_helper.rb +15 -0
- data/lib/gooby.rb +2265 -0
- data/pkg/code_header.txt +21 -0
- data/pkg/pkg.rb +236 -0
- data/pkg/test_header.txt +19 -0
- data/samples/20041113_richmond_marathon.html +532 -0
- data/samples/20050305_corporate_cup_hm.html +448 -0
- data/samples/20050430_nashville_marathon.html +530 -0
- data/samples/gps_point_capture.html +54 -0
- data/samples/phoenix_marathon.html +542 -0
- data/samples/run_2007_01_10_22_44_54.html +201 -0
- data/samples/run_2007_02_24_15_01_35.html +298 -0
- data/tests/tc_cls_counter_hash.rb +107 -0
- data/tests/tc_cls_delim_line.rb +74 -0
- data/tests/tc_cls_dttm.rb +131 -0
- data/tests/tc_cls_duration.rb +51 -0
- data/tests/tc_cls_forerunner_xml_parser.rb +70 -0
- data/tests/tc_cls_geo_data.xxx +71 -0
- data/tests/tc_cls_gooby_object.rb +26 -0
- data/tests/tc_cls_google_map_generator.rb +109 -0
- data/tests/tc_cls_history.rb +46 -0
- data/tests/tc_cls_lap.rb +38 -0
- data/tests/tc_cls_line.rb +110 -0
- data/tests/tc_cls_options.rb +79 -0
- data/tests/tc_cls_position.rb +66 -0
- data/tests/tc_cls_run.rb +142 -0
- data/tests/tc_cls_simple_xml_parser.rb +50 -0
- data/tests/tc_cls_track.rb +70 -0
- data/tests/tc_cls_trackpoint.rb +145 -0
- data/tests/tc_mod_introspect.rb +32 -0
- data/tests/tc_mod_io.rb +53 -0
- data/tests/tc_mod_project_info.rb +79 -0
- data/tests/tc_mod_string.rb +58 -0
- data/tests/ts_gooby.rb +1237 -0
- 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
|