Gooby 0.9.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.
- data/README +218 -0
- data/bin/forerunner_xml_parser.rb +28 -0
- data/bin/forerunner_xml_parser.sh +16 -0
- data/bin/forerunner_xml_splitter.rb +60 -0
- data/bin/gen_gmap.rb +30 -0
- data/bin/gen_gmap.sh +19 -0
- data/bin/tests_gen.rb +13 -0
- data/data/20041113_richmond_marathon.csv +1036 -0
- data/data/20041113_richmond_marathon.xml +8663 -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/forerunner_2005.xml +259620 -0
- data/data/forerunner_2006.xml +190853 -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/lib/cls_counter_hash.rb +83 -0
- data/lib/cls_delim_line.rb +40 -0
- data/lib/cls_dttm.rb +84 -0
- data/lib/cls_duration.rb +87 -0
- data/lib/cls_forerunner_xml_parser.rb +183 -0
- data/lib/cls_forerunner_xml_splitter.rb +113 -0
- data/lib/cls_geo_data.rb +186 -0
- data/lib/cls_gooby_object.rb +23 -0
- data/lib/cls_google_map_generator.rb +368 -0
- data/lib/cls_history.rb +38 -0
- data/lib/cls_lap.rb +27 -0
- data/lib/cls_line.rb +78 -0
- data/lib/cls_options.rb +74 -0
- data/lib/cls_position.rb +49 -0
- data/lib/cls_run.rb +199 -0
- data/lib/cls_simple_xml_parser.rb +46 -0
- data/lib/cls_test_regen.rb +187 -0
- data/lib/cls_track.rb +52 -0
- data/lib/cls_trackpoint.rb +205 -0
- data/lib/mod_introspect.rb +33 -0
- data/lib/mod_io.rb +65 -0
- data/lib/mod_project_info.rb +81 -0
- data/lib/mod_string.rb +26 -0
- data/lib/mod_test_helper.rb +22 -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 +146 -0
- data/samples/run_2007_02_24_15_01_35.html +298 -0
- data/tests/tst_cls_counter_hash.rb +105 -0
- data/tests/tst_cls_delim_line.rb +72 -0
- data/tests/tst_cls_dttm.rb +129 -0
- data/tests/tst_cls_duration.rb +49 -0
- data/tests/tst_cls_forerunner_xml_parser.rb +68 -0
- data/tests/tst_cls_geo_data.rb +69 -0
- data/tests/tst_cls_gooby_object.rb +24 -0
- data/tests/tst_cls_google_map_generator.rb +107 -0
- data/tests/tst_cls_history.rb +44 -0
- data/tests/tst_cls_lap.rb +36 -0
- data/tests/tst_cls_line.rb +108 -0
- data/tests/tst_cls_options.rb +77 -0
- data/tests/tst_cls_position.rb +64 -0
- data/tests/tst_cls_run.rb +140 -0
- data/tests/tst_cls_simple_xml_parser.rb +48 -0
- data/tests/tst_cls_track.rb +68 -0
- data/tests/tst_cls_trackpoint.rb +143 -0
- data/tests/tst_gooby.rb +28 -0
- data/tests/tst_mod_introspect.rb +30 -0
- data/tests/tst_mod_io.rb +51 -0
- data/tests/tst_mod_project_info.rb +77 -0
- data/tests/tst_mod_string.rb +56 -0
- metadata +142 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
=begin rdoc
|
|
2
|
+
|
|
3
|
+
Gooby - Copyright 2007 by Chris Joakim.
|
|
4
|
+
Gooby is available under GNU General Public License (GPL) license.
|
|
5
|
+
|
|
6
|
+
=end
|
|
7
|
+
|
|
8
|
+
require 'gooby'
|
|
9
|
+
|
|
10
|
+
module Gooby
|
|
11
|
+
|
|
12
|
+
class ForerunnerXmlSplitter < GoobyObject
|
|
13
|
+
|
|
14
|
+
attr_reader :out_dir, :forerunner_files, :out_files_hash
|
|
15
|
+
|
|
16
|
+
def initialize(out_dir, xml_file)
|
|
17
|
+
@out_dir = out_dir
|
|
18
|
+
@forerunner_files = Array.new
|
|
19
|
+
@forerunner_files << xml_file
|
|
20
|
+
@out_files_hash = Hash.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def split
|
|
24
|
+
@forerunner_files.each { |f| process_file(f) }
|
|
25
|
+
write_files
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def process_file(forerunnerXmlFile)
|
|
31
|
+
@file_name = forerunnerXmlFile
|
|
32
|
+
@xml_lines = read_lines(@file_name, false)
|
|
33
|
+
@line_num = 0
|
|
34
|
+
@run_num = 0
|
|
35
|
+
@curr_run_lines = Array.new
|
|
36
|
+
@curr_run_tkpts = 0
|
|
37
|
+
@start_line_num = 0
|
|
38
|
+
@end_line_num = 0
|
|
39
|
+
@first_start_time = nil
|
|
40
|
+
|
|
41
|
+
@xml_lines.each { |line|
|
|
42
|
+
@line_num = @line_num + 1
|
|
43
|
+
if (line.match(/<Run>/))
|
|
44
|
+
@run_num = @run_num + 1
|
|
45
|
+
@start_line_num = @line_num
|
|
46
|
+
@curr_run_lines = Array.new
|
|
47
|
+
@curr_run_lines << line
|
|
48
|
+
elsif (line.match(/<StartTime>/)) # <StartTime>2007-01-13T15:37:06Z</StartTime>
|
|
49
|
+
@curr_run_lines << line
|
|
50
|
+
if @first_start_time == nil
|
|
51
|
+
clone = String.new(line)
|
|
52
|
+
clone.gsub!(/[<>]/, ' ')
|
|
53
|
+
clone.gsub!(/[-:T]/, '_')
|
|
54
|
+
clone.gsub!(/[Z]/, '')
|
|
55
|
+
tokens = clone.split
|
|
56
|
+
@first_start_time = tokens[1]
|
|
57
|
+
end
|
|
58
|
+
elsif (line.match(/<Trackpoint>/))
|
|
59
|
+
@curr_run_tkpts = @curr_run_tkpts + 1
|
|
60
|
+
@curr_run_lines << line
|
|
61
|
+
elsif (line.match(/<\/Run>/))
|
|
62
|
+
@end_line_num = @line_num
|
|
63
|
+
@curr_run_lines << line
|
|
64
|
+
end_run
|
|
65
|
+
elsif (@curr_run_lines.size > 0)
|
|
66
|
+
@curr_run_lines << line
|
|
67
|
+
end
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def end_run
|
|
72
|
+
out_file = "#{@out_dir}/run_#{@first_start_time}.xml"
|
|
73
|
+
comment = "<!-- file: #{out_file} lines: #{@curr_run_lines.size} (#{@start_line_num} to #{@end_line_num}) tkpts: #{@curr_run_tkpts} --> \n"
|
|
74
|
+
@curr_run_lines.insert(0, comment)
|
|
75
|
+
|
|
76
|
+
prev_entry = @out_files_hash[out_file]
|
|
77
|
+
if prev_entry
|
|
78
|
+
if (@curr_run_lines.size >= prev_entry.size)
|
|
79
|
+
puts "previous entry overlaid for #{out_file}. curr=#{@curr_run_lines.size} prev=#{prev_entry.size}"
|
|
80
|
+
@out_files_hash[out_file] = @curr_run_lines
|
|
81
|
+
else
|
|
82
|
+
puts "previous entry retained for #{out_file}. curr=#{@curr_run_lines.size} prev=#{prev_entry.size}"
|
|
83
|
+
end
|
|
84
|
+
else
|
|
85
|
+
puts "new entry for #{out_file}. curr=#{@curr_run_lines.size}"
|
|
86
|
+
@out_files_hash[out_file] = @curr_run_lines
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
@curr_run_lines = Array.new
|
|
90
|
+
@curr_run_tkpts = 0
|
|
91
|
+
@start_line_num = 0
|
|
92
|
+
@end_line_num = 0
|
|
93
|
+
@first_start_time = nil
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def write_files
|
|
97
|
+
out_names = @out_files_hash.keys.sort
|
|
98
|
+
puts "Writing #{out_names.size} extract files..."
|
|
99
|
+
out_names.each { |out_name|
|
|
100
|
+
lines = @out_files_hash[out_name]
|
|
101
|
+
out = File.new out_name, "w+"
|
|
102
|
+
lines.each { |line| out.write line }
|
|
103
|
+
out.flush
|
|
104
|
+
out.close
|
|
105
|
+
puts "File written: #{out_name}"
|
|
106
|
+
}
|
|
107
|
+
puts "output files written."
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
|
data/lib/cls_geo_data.rb
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
=begin rdoc
|
|
2
|
+
|
|
3
|
+
Instances of this class represent a the set of Geographic data defined in file geo.txt
|
|
4
|
+
|
|
5
|
+
Gooby - Copyright 2007 by Chris Joakim.
|
|
6
|
+
Gooby is available under GNU General Public License (GPL) license.
|
|
7
|
+
|
|
8
|
+
=end
|
|
9
|
+
|
|
10
|
+
module Gooby
|
|
11
|
+
|
|
12
|
+
class GeoData < GoobyObject
|
|
13
|
+
|
|
14
|
+
attr_reader :filename, :lines, :poi_hash, :poi_array, :track_hash, :track_array, :route_hash, :route_array
|
|
15
|
+
|
|
16
|
+
def initialize(filename)
|
|
17
|
+
@filename = filename
|
|
18
|
+
@filename = 'data/geo_data.txt' if @filename == nil
|
|
19
|
+
@lines = read_lines(@filename, true)
|
|
20
|
+
@poi_hash = Hash.new
|
|
21
|
+
@poi_array = Array.new
|
|
22
|
+
@track_hash = Hash.new
|
|
23
|
+
@track_array = Array.new
|
|
24
|
+
@route_hash = Hash.new
|
|
25
|
+
@route_array = Array.new
|
|
26
|
+
parse_poi
|
|
27
|
+
parse_tracks
|
|
28
|
+
parse_routes
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def parse_poi
|
|
34
|
+
in_poi, poi_number = false, 0
|
|
35
|
+
@lines.each { |line|
|
|
36
|
+
line_obj = Line.new(line, nil, true)
|
|
37
|
+
tok_count = line_obj.token_count
|
|
38
|
+
is_point = line_obj.token_idx_equals(0, '.')
|
|
39
|
+
|
|
40
|
+
if line_obj.is_populated_non_comment
|
|
41
|
+
if line_obj.match('points_of_interest_start')
|
|
42
|
+
in_poi = true
|
|
43
|
+
elsif line_obj.match('points_of_interest_end')
|
|
44
|
+
in_poi = false
|
|
45
|
+
elsif in_poi && tok_count > 2 && is_point
|
|
46
|
+
poi_number = poi_number + 1
|
|
47
|
+
tkpt = Trackpoint.new(
|
|
48
|
+
poi_number, line_obj.tokens[1], line_obj.tokens[2],
|
|
49
|
+
'0', '', line_obj.concatinate_tokens(3))
|
|
50
|
+
add_poi(tkpt)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def parse_tracks
|
|
57
|
+
in_track, trk_number, tkpt_number = false, 0, 0
|
|
58
|
+
curr_trk, curr_run = nil, nil
|
|
59
|
+
@lines.each { |line|
|
|
60
|
+
line_obj = Line.new(line, nil, true)
|
|
61
|
+
tok_count = line_obj.token_count
|
|
62
|
+
is_point = line_obj.token_idx_equals(0, '.')
|
|
63
|
+
|
|
64
|
+
if line_obj.is_populated_non_comment
|
|
65
|
+
if line_obj.match('track_start')
|
|
66
|
+
in_track = true
|
|
67
|
+
trk_number = trk_number + 1
|
|
68
|
+
tkpt_number = 0
|
|
69
|
+
curr_trk = Track.new(0, line_obj.concatinate_tokens(1))
|
|
70
|
+
curr_run = Run.new(trk_number, line_obj.concatinate_tokens(1))
|
|
71
|
+
curr_run.add_track(curr_trk)
|
|
72
|
+
elsif line_obj.match('track_end')
|
|
73
|
+
in_track = false
|
|
74
|
+
curr_run.finish
|
|
75
|
+
add_track(curr_trk)
|
|
76
|
+
add_route(curr_run)
|
|
77
|
+
elsif in_track && tok_count > 2 && is_point
|
|
78
|
+
tkpt_number = tkpt_number + 1
|
|
79
|
+
tkpt = Trackpoint.new(
|
|
80
|
+
tkpt_number, line_obj.tokens[1], line_obj.tokens[2],
|
|
81
|
+
'0', '', line_obj.concatinate_tokens(3))
|
|
82
|
+
curr_trk.add_trackpoint(tkpt)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def parse_routes
|
|
89
|
+
in_route, route_number, trk_number, tkpt_number = false, 0, 0, 0
|
|
90
|
+
curr_trk, curr_run = nil, nil
|
|
91
|
+
@lines.each { |line|
|
|
92
|
+
line_obj = Line.new(line, nil, true)
|
|
93
|
+
tok_count = line_obj.token_count
|
|
94
|
+
is_point = line_obj.token_idx_equals(0, '.')
|
|
95
|
+
|
|
96
|
+
if line_obj.is_populated_non_comment
|
|
97
|
+
if line_obj.match('route_start')
|
|
98
|
+
in_route = true
|
|
99
|
+
trk_number = trk_number + 1
|
|
100
|
+
tkpt_number = 0
|
|
101
|
+
curr_trk = Track.new(0, line_obj.concatinate_tokens(1))
|
|
102
|
+
curr_run = Run.new(trk_number, line_obj.concatinate_tokens(1))
|
|
103
|
+
curr_run.add_track(curr_trk)
|
|
104
|
+
elsif line_obj.match('route_end')
|
|
105
|
+
in_route = false
|
|
106
|
+
curr_run.finish
|
|
107
|
+
add_route(curr_run)
|
|
108
|
+
elsif in_route && tok_count > 2 && is_point
|
|
109
|
+
tkpt_number = tkpt_number + 1
|
|
110
|
+
tkpt = Trackpoint.new(
|
|
111
|
+
tkpt_number, line_obj.tokens[1], line_obj.tokens[2],
|
|
112
|
+
'0', '', line_obj.concatinate_tokens(3))
|
|
113
|
+
curr_trk.add_trackpoint(tkpt)
|
|
114
|
+
elsif in_route && line_obj.token_idx_equals(0, 'track') && tok_count > 1
|
|
115
|
+
trk_desc = line_obj.concatinate_tokens(1)
|
|
116
|
+
trk = @track_hash[trk_desc]
|
|
117
|
+
if trk
|
|
118
|
+
trk.trackpoints.each { |tkpt| curr_trk.add_trackpoint(tkpt) }
|
|
119
|
+
end
|
|
120
|
+
elsif in_route && line_obj.token_idx_equals(0, 'track_rev') && tok_count > 1
|
|
121
|
+
trk_desc = line_obj.concatinate_tokens(1)
|
|
122
|
+
trk = @track_hash[trk_desc]
|
|
123
|
+
if trk
|
|
124
|
+
array = trk.trackpoints
|
|
125
|
+
trk.trackpoints.each { |tkpt| curr_trk.add_trackpoint(tkpt) }
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def add_poi(tkpt)
|
|
133
|
+
if tkpt
|
|
134
|
+
descr = tkpt.descr
|
|
135
|
+
if @poi_hash.has_key? descr
|
|
136
|
+
puts "Duplicate POI key ignored - '#{descr}'"
|
|
137
|
+
else
|
|
138
|
+
#puts "Adding POI: #{tkpt.to_poi_csv}"
|
|
139
|
+
@poi_hash[descr] = tkpt
|
|
140
|
+
@poi_array << tkpt
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def add_track(trk)
|
|
146
|
+
if trk
|
|
147
|
+
descr = trk.descr
|
|
148
|
+
if @track_hash.has_key? descr
|
|
149
|
+
puts "Duplicate Track key ignored - '#{descr}'"
|
|
150
|
+
else
|
|
151
|
+
@track_hash[descr] = trk
|
|
152
|
+
@track_array << trk
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def add_route(run)
|
|
158
|
+
if run
|
|
159
|
+
descr = run.descr
|
|
160
|
+
if @route_hash.has_key? descr
|
|
161
|
+
puts "Duplicate Route key ignored - '#{descr}'"
|
|
162
|
+
else
|
|
163
|
+
@route_hash[descr] = run
|
|
164
|
+
@route_array << run
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
public
|
|
170
|
+
|
|
171
|
+
def to_s
|
|
172
|
+
return "GeoData lines: #{lines.size} poi: #{@poi_hash.size} tracks: #{@track_hash.size} routes: #{@route_hash.size} "
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def dump
|
|
176
|
+
puts "#{self.class} dump:"
|
|
177
|
+
@poi_array.each { |tkpt| puts "POI: #{tkpt.to_geo_s}" }
|
|
178
|
+
@track_array.each { |trk| trk.dump }
|
|
179
|
+
@route_hash.keys.sort.each { |key|
|
|
180
|
+
puts "Route: '#{key}'"
|
|
181
|
+
}
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
=begin rdoc
|
|
2
|
+
|
|
3
|
+
This is the abstract superclass of several Gooby classes.
|
|
4
|
+
Includes modules GoobyIO, Introspect, and GoobyProjectInfo.
|
|
5
|
+
|
|
6
|
+
Gooby - Copyright 2007 by Chris Joakim.
|
|
7
|
+
Gooby is available under GNU General Public License (GPL) license.
|
|
8
|
+
|
|
9
|
+
=end
|
|
10
|
+
|
|
11
|
+
module Gooby
|
|
12
|
+
|
|
13
|
+
class GoobyObject
|
|
14
|
+
|
|
15
|
+
include Gooby::GoobyIO
|
|
16
|
+
include Gooby::GoobyString
|
|
17
|
+
include Gooby::Introspect
|
|
18
|
+
include Gooby::GoobyProjectInfo
|
|
19
|
+
include Gooby::Constants
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
=begin rdoc
|
|
2
|
+
|
|
3
|
+
Instances of this class represent a <Run> aggregate object from a
|
|
4
|
+
Forerunner XML file.
|
|
5
|
+
|
|
6
|
+
Additionally, there is distance, pace, and Google Map generation logic
|
|
7
|
+
in this class.
|
|
8
|
+
|
|
9
|
+
Gooby - Copyright 2007 by Chris Joakim.
|
|
10
|
+
Gooby is available under GNU General Public License (GPL) license.
|
|
11
|
+
|
|
12
|
+
=end
|
|
13
|
+
|
|
14
|
+
module Gooby
|
|
15
|
+
|
|
16
|
+
class GoogleMapGenerator < GoobyObject
|
|
17
|
+
|
|
18
|
+
attr_reader :csv_file, :csv_lines, :dttm_idx, :num_idx, :lat_idx, :lng_idx, :alt_idx, :cdist_idx
|
|
19
|
+
attr_reader :run, :tkpts, :content_hash, :center_longitude, :center_latitude, :gpoint_array, :overlay_points, :notes
|
|
20
|
+
attr_reader :center_longitude, :center_latitude
|
|
21
|
+
|
|
22
|
+
# The default csv input file format is as follows:
|
|
23
|
+
# 1 | 2006-01-15T18:31:10Z | 1279 | 33.42601 | -111.92927 | 347.654 | 26.3514930151813
|
|
24
|
+
# 1 | 2004-11-13T13:05:20Z | 2 | 37.54318 | -77.43636 | -58.022 | 0.00297286231747969
|
|
25
|
+
|
|
26
|
+
def initialize(csv_file, dttm_idx=1, num_idx=2, lat_idx=3, lng_idx=4, alt_idx=5, cdist_idx=6)
|
|
27
|
+
@csv_file = csv_file
|
|
28
|
+
@dttm_idx = dttm_idx
|
|
29
|
+
@num_idx = num_idx
|
|
30
|
+
@lat_idx = lat_idx
|
|
31
|
+
@lng_idx = lng_idx
|
|
32
|
+
@alt_idx = alt_idx
|
|
33
|
+
@cdist_idx = cdist_idx
|
|
34
|
+
@options = Gooby::Options.new(nil)
|
|
35
|
+
@content_hash = Hash.new('')
|
|
36
|
+
@run = Gooby::Run.new(1)
|
|
37
|
+
@track = Gooby::Track.new(1)
|
|
38
|
+
@run.add_track(@track)
|
|
39
|
+
@tkpts = Array.new
|
|
40
|
+
|
|
41
|
+
@csv_lines = read_as_ascii_lines(@csv_file, 10, true)
|
|
42
|
+
@csv_lines.each { | line |
|
|
43
|
+
dline = Gooby::DelimLine.new(line)
|
|
44
|
+
if (!dline.is_comment?)
|
|
45
|
+
tkpt = dline.as_trackpoint(@num_idx, @lat_idx, @lng_idx, @alt_idx, @dttm_idx)
|
|
46
|
+
if tkpt
|
|
47
|
+
@track.add_trackpoint(tkpt)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
}
|
|
51
|
+
@run.finish
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
=begin
|
|
55
|
+
Returns a Hash with specific generated content at the following keys:
|
|
56
|
+
=end
|
|
57
|
+
def generate(options)
|
|
58
|
+
if (options == nil)
|
|
59
|
+
@options = Gooby::Options.new(nil)
|
|
60
|
+
else
|
|
61
|
+
@options = options
|
|
62
|
+
end
|
|
63
|
+
@content_hash['when_generated'] = Time.now
|
|
64
|
+
@content_hash['title'] = @options.get('gmap_title')
|
|
65
|
+
filter_trackpoints
|
|
66
|
+
compute_center_point
|
|
67
|
+
generate_key_js
|
|
68
|
+
generate_map_div
|
|
69
|
+
generate_messages_div
|
|
70
|
+
generate_main_js_start
|
|
71
|
+
generate_main_js_route_overlay
|
|
72
|
+
generate_main_js_checkpoint_overlays
|
|
73
|
+
generate_main_js_map_clicked_listeners
|
|
74
|
+
generate_main_js_end
|
|
75
|
+
@content_hash
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def filter_trackpoints
|
|
79
|
+
count, @tkpts = 0, Array.new
|
|
80
|
+
firstTkpt = @options.get('gmap_first_tkpt_number')
|
|
81
|
+
lastTkpt = @options.get('gmap_last_tkpt_number')
|
|
82
|
+
@run.tracks.each { |trk|
|
|
83
|
+
trk.trackpoints.each { |tkpt|
|
|
84
|
+
count = count + 1
|
|
85
|
+
if ((count >= firstTkpt) && (count <= lastTkpt))
|
|
86
|
+
@tkpts.push(tkpt)
|
|
87
|
+
end
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
=begin
|
|
93
|
+
Returns a Hash with specific generated content at the following keys:
|
|
94
|
+
=end
|
|
95
|
+
def generate_page(options)
|
|
96
|
+
|
|
97
|
+
# puts "generate_page #{@csv_file} #{@csv_lines.size}"
|
|
98
|
+
content_hash = generate(nil)
|
|
99
|
+
s = String.new(@csv_file)
|
|
100
|
+
s.gsub("/", " ")
|
|
101
|
+
tokens = tokenize(s, nil)
|
|
102
|
+
out_file = "#{tokens[-2]}.html"
|
|
103
|
+
#content_hash.keys.sort.each { | key | puts key }
|
|
104
|
+
|
|
105
|
+
s = <<HERE
|
|
106
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
107
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
108
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
109
|
+
<head>
|
|
110
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
|
111
|
+
<title> Google Map by Gooby </title>
|
|
112
|
+
#{content_hash['key_js']}
|
|
113
|
+
#{content_hash['main_js_start']}
|
|
114
|
+
#{content_hash['main_js_route_overlay']}
|
|
115
|
+
#{content_hash['main_js_checkpoint_overlays']}
|
|
116
|
+
#{content_hash['main_js_map_clicked_listeners']}
|
|
117
|
+
#{content_hash['main_js_end']}
|
|
118
|
+
</head>
|
|
119
|
+
<body onload="load()" onunload="GUnload()">
|
|
120
|
+
<center>
|
|
121
|
+
<h3> #{content_hash['title']} </h3>
|
|
122
|
+
<h5> Generated by Gooby #{content_hash['when_generated']} <br> Gooby = Google APIs + Ruby </h5>
|
|
123
|
+
#{content_hash['map_div']}
|
|
124
|
+
#{content_hash['messages_div']}
|
|
125
|
+
</center>
|
|
126
|
+
</body>
|
|
127
|
+
</html>
|
|
128
|
+
HERE
|
|
129
|
+
|
|
130
|
+
# html_file = File.new(out_file, "w+")
|
|
131
|
+
# html_file.write(s)
|
|
132
|
+
# html_file.flush
|
|
133
|
+
# html_file.close
|
|
134
|
+
puts s # Output is redirected by shell.
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def compute_center_point
|
|
140
|
+
highLat = -999.0
|
|
141
|
+
highLong = -999.0
|
|
142
|
+
lowLat = 999.0
|
|
143
|
+
lowLong = 999.0
|
|
144
|
+
@tkpts.each { |tkpt|
|
|
145
|
+
highLat = tkpt.latitude_as_float if tkpt.latitude_as_float > highLat
|
|
146
|
+
lowLat = tkpt.latitude_as_float if tkpt.latitude_as_float < lowLat
|
|
147
|
+
highLong = tkpt.longitude_as_float if tkpt.longitude_as_float > highLong
|
|
148
|
+
lowLong = tkpt.longitude_as_float if tkpt.longitude_as_float < lowLong
|
|
149
|
+
}
|
|
150
|
+
@center_longitude = (highLong + lowLong) / 2
|
|
151
|
+
@center_latitude = (highLat + lowLat) / 2
|
|
152
|
+
@content_hash['center_longitude'] = @center_longitude
|
|
153
|
+
@content_hash['center_latitude'] = @center_latitude
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def generate_key_js
|
|
157
|
+
key = @options.get('gmap_key')
|
|
158
|
+
key.strip!
|
|
159
|
+
s = '<script src="http://maps.google.com/maps?file=api&v=2&key='
|
|
160
|
+
s << key
|
|
161
|
+
s << '" type="text/javascript"></script>'
|
|
162
|
+
@content_hash['key_js'] = s
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def generate_map_div
|
|
166
|
+
width = @options.get('gmap_width')
|
|
167
|
+
height = @options.get('gmap_height')
|
|
168
|
+
id = @options.get('gmap_map_element_id')
|
|
169
|
+
s = '<div id="'
|
|
170
|
+
s << id
|
|
171
|
+
s << '" style="width: '
|
|
172
|
+
s << width
|
|
173
|
+
s << '; height: '
|
|
174
|
+
s << height
|
|
175
|
+
s << '"></div>'
|
|
176
|
+
@content_hash['map_width'] = width
|
|
177
|
+
@content_hash['map_height'] = height
|
|
178
|
+
@content_hash['map_div'] = s
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def generate_messages_div
|
|
182
|
+
s = "<div id=\"messages\"></div>"
|
|
183
|
+
@content_hash['messages_div'] = s
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def generate_main_js_start
|
|
187
|
+
id = @options.get('gmap_map_element_id')
|
|
188
|
+
size = @options.get('gmap_size_control')
|
|
189
|
+
type = @options.get('gmap_type')
|
|
190
|
+
zoom = @options.get('gmap_zoom_level')
|
|
191
|
+
title = @options.get('gmap_title')
|
|
192
|
+
if size
|
|
193
|
+
if size == 'smallmap'
|
|
194
|
+
size = 'GSmallMapControl'
|
|
195
|
+
elsif size == 'smallzoom'
|
|
196
|
+
size = 'GSmallMapControl'
|
|
197
|
+
else
|
|
198
|
+
size = 'GLargeMapControl'
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
if type
|
|
203
|
+
if type == 'satellite'
|
|
204
|
+
type = 'G_SATELLITE_MAP'
|
|
205
|
+
elsif type == 'hybrid'
|
|
206
|
+
type = 'G_HYBRID_MAP'
|
|
207
|
+
else
|
|
208
|
+
type = 'G_NORMAL_MAP'
|
|
209
|
+
end
|
|
210
|
+
else
|
|
211
|
+
type = 'G_NORMAL_MAP'
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
s = '<script type="text/javascript">'
|
|
215
|
+
s << "\n"
|
|
216
|
+
s << "//<![CDATA[ \n"
|
|
217
|
+
s << " function load() { \n"
|
|
218
|
+
s << " if (GBrowserIsCompatible()) { \n"
|
|
219
|
+
s << ' var map = new GMap2(document.getElementById("'
|
|
220
|
+
s << id
|
|
221
|
+
s << '")); '
|
|
222
|
+
s << "\n"
|
|
223
|
+
|
|
224
|
+
if size
|
|
225
|
+
s << ' map.addControl(new '
|
|
226
|
+
s << size
|
|
227
|
+
s << '());'
|
|
228
|
+
s << "\n"
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
if type
|
|
232
|
+
s << ' map.addControl(new GMapTypeControl());'
|
|
233
|
+
s << "\n"
|
|
234
|
+
# s << ' map.setMapType('
|
|
235
|
+
# s << type
|
|
236
|
+
# s << ');'
|
|
237
|
+
s << "\n"
|
|
238
|
+
end
|
|
239
|
+
s << " var centerPoint = new GLatLng(#{@center_latitude}, #{@center_longitude}); \n"
|
|
240
|
+
s << " map.setCenter(centerPoint, #{zoom}); \n"
|
|
241
|
+
s << "\n"
|
|
242
|
+
@content_hash['main_js_start'] = s
|
|
243
|
+
@content_hash['title'] = title
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def generate_main_js_route_overlay
|
|
247
|
+
tkpt_count = @tkpts.size.to_f
|
|
248
|
+
app_max = @options.get('gmap_approx_max_points').to_f
|
|
249
|
+
comments = @options.get('gmap_gen_comments')
|
|
250
|
+
ratio = tkpt_count / app_max
|
|
251
|
+
@start_dttm = nil
|
|
252
|
+
if ratio > 1.0
|
|
253
|
+
increment = (tkpt_count / app_max).to_i
|
|
254
|
+
else
|
|
255
|
+
increment = 1
|
|
256
|
+
end
|
|
257
|
+
curr_idx, next_idx, gpoint_count, last_idx = -1, 0, 0, @tkpts.size - 1
|
|
258
|
+
s = " var points = new Array(); "
|
|
259
|
+
@tkpts.each { |tkpt|
|
|
260
|
+
curr_idx = curr_idx + 1
|
|
261
|
+
if curr_idx == 0
|
|
262
|
+
@start_dttm = tkpt.dttm
|
|
263
|
+
@start_pos = tkpt.position
|
|
264
|
+
time = Time.parse(@start_dttm.dateTime().to_s)
|
|
265
|
+
end
|
|
266
|
+
if ((curr_idx == next_idx) || (curr_idx == last_idx) || (tkpt.is_split()))
|
|
267
|
+
gpoint_count = gpoint_count + 1
|
|
268
|
+
s << tkpt.as_glatlng(comments, tkpt_count, curr_idx, gpoint_count, @start_dttm)
|
|
269
|
+
next_idx = curr_idx + increment
|
|
270
|
+
end
|
|
271
|
+
}
|
|
272
|
+
s << "\n"
|
|
273
|
+
s << "\n var routePolyline = new GPolyline(points); "
|
|
274
|
+
s << "\n map.addOverlay(routePolyline); "
|
|
275
|
+
@content_hash['main_js_route_overlay'] = s
|
|
276
|
+
@content_hash['main_js_route_overlay_increment'] = increment
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def generate_main_js_checkpoint_overlays
|
|
280
|
+
s = "\n // Create a base icon for all of our markers that specifies the "
|
|
281
|
+
s << "\n // shadow, icon dimensions, etc."
|
|
282
|
+
s << "\n var baseIcon = new GIcon();"
|
|
283
|
+
s << "\n baseIcon.shadow = \"http://www.joakim-systems.com/gicons/shadow50.png\";"
|
|
284
|
+
s << "\n baseIcon.iconSize = new GSize(20, 34);"
|
|
285
|
+
s << "\n baseIcon.shadowSize = new GSize(37, 34);"
|
|
286
|
+
s << "\n baseIcon.iconAnchor = new GPoint(9, 34);"
|
|
287
|
+
s << "\n baseIcon.infoWindowAnchor = new GPoint(9, 2);"
|
|
288
|
+
s << "\n baseIcon.infoShadowAnchor = new GPoint(18, 25);"
|
|
289
|
+
s << "\n"
|
|
290
|
+
|
|
291
|
+
curr_idx = -1
|
|
292
|
+
last_idx = @tkpts.size - 1
|
|
293
|
+
next_checkpoint = 0.0
|
|
294
|
+
@start_dttm = nil
|
|
295
|
+
@tkpts.each { | tkpt |
|
|
296
|
+
curr_idx = curr_idx + 1
|
|
297
|
+
if curr_idx == 0
|
|
298
|
+
@start_dttm = tkpt.dttm
|
|
299
|
+
info_window_html = tkpt.as_info_window_html('Start', @start_dttm)
|
|
300
|
+
s << "\n var iconStart = new GIcon(baseIcon); "
|
|
301
|
+
s << "\n iconStart.image = \"http://www.joakim-systems.com/gicons/dd-start.png\";"
|
|
302
|
+
s << "\n var pStart = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
|
|
303
|
+
s << "\n var mStart = new GMarker(pStart, iconStart);"
|
|
304
|
+
s << "\n GEvent.addListener(mStart, \"click\", function() { "
|
|
305
|
+
s << "\n mStart.openInfoWindowHtml(#{info_window_html});"
|
|
306
|
+
s << "\n }); "
|
|
307
|
+
s << "\n map.addOverlay(mStart);"
|
|
308
|
+
s << "\n "
|
|
309
|
+
next_checkpoint = 1.0
|
|
310
|
+
elsif curr_idx == last_idx
|
|
311
|
+
info_window_html = tkpt.as_info_window_html('Finish', @start_dttm)
|
|
312
|
+
s << "\n var iconFinish = new GIcon(baseIcon); "
|
|
313
|
+
s << "\n iconFinish.image = \"http://www.joakim-systems.com/gicons/dd-end.png\";"
|
|
314
|
+
s << "\n var pFinish = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
|
|
315
|
+
s << "\n var mFinish = new GMarker(pFinish, iconFinish);"
|
|
316
|
+
s << "\n GEvent.addListener(mFinish, \"click\", function() { "
|
|
317
|
+
s << "\n mFinish.openInfoWindowHtml(#{info_window_html});"
|
|
318
|
+
s << "\n }); "
|
|
319
|
+
s << "\n map.addOverlay(mFinish);"
|
|
320
|
+
s << "\n "
|
|
321
|
+
next_checkpoint = 999999
|
|
322
|
+
else
|
|
323
|
+
if (tkpt.cumulativeDistance >= next_checkpoint)
|
|
324
|
+
integer = next_checkpoint.to_i
|
|
325
|
+
info_window_html = tkpt.as_info_window_html("#{integer}", @start_dttm)
|
|
326
|
+
s << "\n var icon#{integer} = new GIcon(baseIcon); "
|
|
327
|
+
s << "\n icon#{integer}.image = \"http://www.joakim-systems.com/gicons/marker#{integer}.png\";"
|
|
328
|
+
s << "\n var p#{integer} = new GPoint(#{tkpt.longitude_as_float}, #{tkpt.latitude_as_float});"
|
|
329
|
+
s << "\n var m#{integer} = new GMarker(p#{integer}, icon#{integer});"
|
|
330
|
+
s << "\n GEvent.addListener(m#{integer}, \"click\", function() { "
|
|
331
|
+
s << "\n m#{integer}.openInfoWindowHtml(#{info_window_html});"
|
|
332
|
+
s << "\n }); "
|
|
333
|
+
s << "\n map.addOverlay(m#{integer});"
|
|
334
|
+
s << "\n "
|
|
335
|
+
next_checkpoint = next_checkpoint + 1.0
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
}
|
|
339
|
+
s << "\n"
|
|
340
|
+
@content_hash['main_js_checkpoint_overlays'] = s
|
|
341
|
+
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def generate_main_js_map_clicked_listeners
|
|
345
|
+
s = "\n"
|
|
346
|
+
s << "\n GEvent.addListener(map, \"click\", function() { "
|
|
347
|
+
s << "\n var center = map.getCenter(); \n"
|
|
348
|
+
s << "\n document.getElementById(\"messages\").innerHTML = 'click: ' + center.toString(); "
|
|
349
|
+
s << "\n });"
|
|
350
|
+
s << "\n GEvent.addListener(map, \"moveend\", function() { "
|
|
351
|
+
s << "\n var center = map.getCenter(); \n"
|
|
352
|
+
s << "\n document.getElementById(\"messages\").innerHTML = 'moveend: ' + center.toString(); "
|
|
353
|
+
s << "\n });"
|
|
354
|
+
@content_hash['main_js_map_clicked_listeners'] = s
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def generate_main_js_end
|
|
358
|
+
s = "\n } "
|
|
359
|
+
s << "\n } "
|
|
360
|
+
s << "\n//]]> \n"
|
|
361
|
+
s << "\n</script>"
|
|
362
|
+
|
|
363
|
+
@content_hash['main_js_end'] = s
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
end
|