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