columbus3 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +41 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +7 -0
  10. data/bower_components/leaflet/.bower.json +34 -0
  11. data/bower_components/leaflet/CHANGELOG.md +929 -0
  12. data/bower_components/leaflet/CONTRIBUTING.md +155 -0
  13. data/bower_components/leaflet/Jakefile.js +48 -0
  14. data/bower_components/leaflet/LICENSE +23 -0
  15. data/bower_components/leaflet/PLUGIN-GUIDE.md +127 -0
  16. data/bower_components/leaflet/README.md +34 -0
  17. data/bower_components/leaflet/bower.json +24 -0
  18. data/bower_components/leaflet/component.json +20 -0
  19. data/bower_components/leaflet/dist/images/layers-2x.png +0 -0
  20. data/bower_components/leaflet/dist/images/layers.png +0 -0
  21. data/bower_components/leaflet/dist/images/marker-icon-2x.png +0 -0
  22. data/bower_components/leaflet/dist/images/marker-icon.png +0 -0
  23. data/bower_components/leaflet/dist/images/marker-shadow.png +0 -0
  24. data/bower_components/leaflet/dist/leaflet-src.js +9180 -0
  25. data/bower_components/leaflet/dist/leaflet.css +478 -0
  26. data/bower_components/leaflet/dist/leaflet.js +9 -0
  27. data/bower_components/leaflet/package.json +33 -0
  28. data/bower_components/leaflet-providers/.bower.json +35 -0
  29. data/bower_components/leaflet-providers/CONTRIBUTING.md +10 -0
  30. data/bower_components/leaflet-providers/README.md +54 -0
  31. data/bower_components/leaflet-providers/bower.json +25 -0
  32. data/bower_components/leaflet-providers/css/gh-fork-ribbon.css +127 -0
  33. data/bower_components/leaflet-providers/css/gh-fork-ribbon.ie.css +68 -0
  34. data/bower_components/leaflet-providers/leaflet-providers.js +630 -0
  35. data/bower_components/leaflet-providers/license.md +9 -0
  36. data/bower_components/leaflet-providers/package.json +38 -0
  37. data/columbus3.gemspec +28 -0
  38. data/exe/columbus3 +144 -0
  39. data/lib/columbus3/metadata/query_parser.racc +160 -0
  40. data/lib/columbus3/metadata/query_parser.tab.rb +349 -0
  41. data/lib/columbus3/metadata/sidecar.rb +48 -0
  42. data/lib/columbus3/renderer/renderer.rb +73 -0
  43. data/lib/columbus3/v900track/v900track.rb +157 -0
  44. data/lib/columbus3/v900track/v900waypoint.rb +51 -0
  45. data/lib/columbus3/version.rb +3 -0
  46. data/lib/columbus3.rb +6 -0
  47. data/lib/html/show.html.erb +84 -0
  48. data/lib/html/track.js.erb +15 -0
  49. metadata +164 -0
@@ -0,0 +1,349 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.12
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require 'date'
10
+ class QueryParser < Racc::Parser
11
+
12
+ module_eval(<<'...end query_parser.racc/module_eval...', 'query_parser.racc', 86)
13
+ attr_accessor :result
14
+
15
+ def parse(str)
16
+ @tokens = make_tokens str
17
+ do_parse
18
+ end
19
+
20
+ def next_token
21
+ @tokens.shift
22
+ end
23
+
24
+ LOCATION_GEN = /location/
25
+ LOCATION = /(start|end)_location/
26
+ DATE_GEN = /date/
27
+ DATE_FIELD = /(start|end)_date/
28
+ YEAR = /year/
29
+ FIELD = /(duration|distance(_aerial)?|(min|max)_height|(min|max)_speed|points|bearing)/
30
+
31
+ def make_tokens str
32
+ require 'strscan'
33
+ result = []
34
+ scanner = StringScanner.new str
35
+ until scanner.empty?
36
+ case
37
+ when match = scanner.scan(/(or|OR)/)
38
+ result << [:OR, nil]
39
+ when match = scanner.scan(/(and|AND)/)
40
+ result << [:AND, nil]
41
+ when match = scanner.scan(/\(/)
42
+ result << ['(', nil]
43
+ when match = scanner.scan(/\)/)
44
+ result << [')', nil]
45
+ when match = scanner.scan(/[0-9]+-[0-9]+-[0-9]+/)
46
+ result << [:DATE, match]
47
+ when match = scanner.scan(/([0-9]+):([0-9]+):([0-9]+)/)
48
+ seconds = match[6..7].to_i + match[3..4].to_i * 60 + match[0..1].to_i * 3600
49
+ result << [:DURATION, seconds]
50
+ when match = scanner.scan(/[0-9]+(\.[0-9]+)?/)
51
+ result << [:NUMBER, match]
52
+ when match = scanner.scan(LOCATION_GEN)
53
+ result << [:LOCATION_GEN, nil]
54
+ when match = scanner.scan(LOCATION)
55
+ result << [:LOCATION, match]
56
+ when match = scanner.scan(DATE_GEN)
57
+ result << [:DATE_GEN, nil]
58
+ when match = scanner.scan(DATE_FIELD)
59
+ result << [:DATE_FIELD, match]
60
+ when match = scanner.scan(YEAR)
61
+ result << [:YEAR, nil]
62
+ when match = scanner.scan(FIELD)
63
+ result << [:FIELD, match]
64
+ when match = scanner.scan(/"[^"]+"/)
65
+ result << [:STRING, match ]
66
+ when match = scanner.scan(/~/)
67
+ result << [:MATCH, '~']
68
+ when match = scanner.scan(/==/)
69
+ result << [:EQUAL, '==']
70
+ when match = scanner.scan(/>=/)
71
+ result << [:OP, '>=']
72
+ when match = scanner.scan(/>/)
73
+ result << [:OP, '>']
74
+ when match = scanner.scan(/<=/)
75
+ result << [:OP, '<=']
76
+ when match = scanner.scan(/</)
77
+ result << [:OP, '<']
78
+ when scanner.scan(/\s+/)
79
+ # ignore whitespace
80
+ else
81
+ raise "The lexer can't recognize <#{scanner.peek(5)}>"
82
+ end
83
+ end
84
+ result << [false, false]
85
+ return result
86
+ end
87
+ ...end query_parser.racc/module_eval...
88
+ ##### State transition tables begin ###
89
+
90
+ racc_action_table = [
91
+ 6, 7, 8, 9, 10, 11, 6, 7, 8, 9,
92
+ 10, 11, 5, 13, 14, 4, 29, 30, 5, 16,
93
+ 17, 4, 6, 7, 8, 9, 10, 11, 6, 7,
94
+ 8, 9, 10, 11, 5, 22, 21, 4, 22, 21,
95
+ 5, 22, 21, 4, 22, 21, 39, 40, 13, 14,
96
+ 18, 19, 12, 31, 32, 33, 35, 35, 37, 26,
97
+ 13 ]
98
+
99
+ racc_action_check = [
100
+ 0, 0, 0, 0, 0, 0, 14, 14, 14, 14,
101
+ 14, 14, 0, 15, 15, 0, 15, 16, 14, 6,
102
+ 6, 14, 4, 4, 4, 4, 4, 4, 13, 13,
103
+ 13, 13, 13, 13, 4, 8, 8, 4, 9, 9,
104
+ 13, 10, 10, 13, 11, 11, 25, 25, 2, 2,
105
+ 7, 7, 1, 17, 18, 19, 20, 23, 24, 12,
106
+ 28 ]
107
+
108
+ racc_action_pointer = [
109
+ -2, 52, 33, nil, 20, nil, 11, 42, 26, 29,
110
+ 32, 35, 59, 26, 4, -2, 3, 39, 40, 41,
111
+ 45, nil, nil, 46, 46, 34, nil, nil, 45, nil,
112
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
113
+ nil ]
114
+
115
+ racc_action_default = [
116
+ -20, -20, -1, -2, -20, -6, -20, -20, -20, -20,
117
+ -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
118
+ -20, -16, -17, -20, -20, -20, 41, -3, -4, -5,
119
+ -7, -8, -9, -10, -11, -15, -12, -13, -14, -18,
120
+ -19 ]
121
+
122
+ racc_goto_table = [
123
+ 2, 1, 38, nil, 15, 20, 23, 24, 25, 34,
124
+ nil, nil, 36, 27, 28 ]
125
+
126
+ racc_goto_check = [
127
+ 2, 1, 6, nil, 2, 4, 4, 4, 4, 5,
128
+ nil, nil, 5, 2, 2 ]
129
+
130
+ racc_goto_pointer = [
131
+ nil, 1, 0, nil, -3, -11, -23 ]
132
+
133
+ racc_goto_default = [
134
+ nil, nil, nil, 3, nil, nil, nil ]
135
+
136
+ racc_reduce_table = [
137
+ 0, 0, :racc_error,
138
+ 1, 20, :_reduce_none,
139
+ 1, 21, :_reduce_2,
140
+ 3, 21, :_reduce_3,
141
+ 3, 21, :_reduce_4,
142
+ 3, 21, :_reduce_5,
143
+ 1, 22, :_reduce_6,
144
+ 3, 22, :_reduce_7,
145
+ 3, 22, :_reduce_8,
146
+ 3, 22, :_reduce_9,
147
+ 3, 22, :_reduce_10,
148
+ 3, 22, :_reduce_11,
149
+ 3, 22, :_reduce_12,
150
+ 3, 22, :_reduce_13,
151
+ 3, 22, :_reduce_14,
152
+ 1, 24, :_reduce_15,
153
+ 1, 23, :_reduce_none,
154
+ 1, 23, :_reduce_none,
155
+ 1, 25, :_reduce_none,
156
+ 1, 25, :_reduce_none ]
157
+
158
+ racc_reduce_n = 20
159
+
160
+ racc_shift_n = 41
161
+
162
+ racc_token_table = {
163
+ false => 0,
164
+ :error => 1,
165
+ :LOCATION_GEN => 2,
166
+ :LOCATION => 3,
167
+ :DATE_GEN => 4,
168
+ :DATE_FIELD => 5,
169
+ :YEAR_FIELD => 6,
170
+ :FIELD => 7,
171
+ :MATCH => 8,
172
+ :EQUAL => 9,
173
+ :OP => 10,
174
+ :DATE => 11,
175
+ :NUMBER => 12,
176
+ :DURATION => 13,
177
+ :STRING => 14,
178
+ :AND => 15,
179
+ :OR => 16,
180
+ "(" => 17,
181
+ ")" => 18 }
182
+
183
+ racc_nt_base = 19
184
+
185
+ racc_use_result_var = true
186
+
187
+ Racc_arg = [
188
+ racc_action_table,
189
+ racc_action_check,
190
+ racc_action_default,
191
+ racc_action_pointer,
192
+ racc_goto_table,
193
+ racc_goto_check,
194
+ racc_goto_default,
195
+ racc_goto_pointer,
196
+ racc_nt_base,
197
+ racc_reduce_table,
198
+ racc_token_table,
199
+ racc_shift_n,
200
+ racc_reduce_n,
201
+ racc_use_result_var ]
202
+
203
+ Racc_token_to_s_table = [
204
+ "$end",
205
+ "error",
206
+ "LOCATION_GEN",
207
+ "LOCATION",
208
+ "DATE_GEN",
209
+ "DATE_FIELD",
210
+ "YEAR_FIELD",
211
+ "FIELD",
212
+ "MATCH",
213
+ "EQUAL",
214
+ "OP",
215
+ "DATE",
216
+ "NUMBER",
217
+ "DURATION",
218
+ "STRING",
219
+ "AND",
220
+ "OR",
221
+ "\"(\"",
222
+ "\")\"",
223
+ "$start",
224
+ "start",
225
+ "exp",
226
+ "simple_exp",
227
+ "op_or_equal",
228
+ "date",
229
+ "value" ]
230
+
231
+ Racc_debug_parser = false
232
+
233
+ ##### State transition tables end #####
234
+
235
+ # reduce 0 omitted
236
+
237
+ # reduce 1 omitted
238
+
239
+ module_eval(<<'.,.,', 'query_parser.racc', 50)
240
+ def _reduce_2(val, _values, result)
241
+ result = "#{val[0]}"
242
+ result
243
+ end
244
+ .,.,
245
+
246
+ module_eval(<<'.,.,', 'query_parser.racc', 51)
247
+ def _reduce_3(val, _values, result)
248
+ result = "(#{val[0]} and #{val[2]})"
249
+ result
250
+ end
251
+ .,.,
252
+
253
+ module_eval(<<'.,.,', 'query_parser.racc', 52)
254
+ def _reduce_4(val, _values, result)
255
+ result = "(#{val[0]} or #{val[2]})"
256
+ result
257
+ end
258
+ .,.,
259
+
260
+ module_eval(<<'.,.,', 'query_parser.racc', 53)
261
+ def _reduce_5(val, _values, result)
262
+ result = "(#{val[1]})"
263
+ result
264
+ end
265
+ .,.,
266
+
267
+ module_eval(<<'.,.,', 'query_parser.racc', 55)
268
+ def _reduce_6(val, _values, result)
269
+ result = "x[:start_location].include?(#{val[0]}) or x[:end_location].include?(#{val[0]})"
270
+ result
271
+ end
272
+ .,.,
273
+
274
+ module_eval(<<'.,.,', 'query_parser.racc', 57)
275
+ def _reduce_7(val, _values, result)
276
+ result = "x[:start_location].include?(#{val[2]}) or x[:end_location].include?(#{val[2]})"
277
+ result
278
+ end
279
+ .,.,
280
+
281
+ module_eval(<<'.,.,', 'query_parser.racc', 59)
282
+ def _reduce_8(val, _values, result)
283
+ result = "x[:start_location] == #{val[2]} or x[:end_location] == #{val[2]}"
284
+ result
285
+ end
286
+ .,.,
287
+
288
+ module_eval(<<'.,.,', 'query_parser.racc', 61)
289
+ def _reduce_9(val, _values, result)
290
+ result = "x[:#{val[0]}].include?(#{val[2]})"
291
+ result
292
+ end
293
+ .,.,
294
+
295
+ module_eval(<<'.,.,', 'query_parser.racc', 63)
296
+ def _reduce_10(val, _values, result)
297
+ result = "x[:#{val[0]}] == #{val[2]}"
298
+ result
299
+ end
300
+ .,.,
301
+
302
+ module_eval(<<'.,.,', 'query_parser.racc', 65)
303
+ def _reduce_11(val, _values, result)
304
+ result = "x[:start_date] #{val[1]} #{val[2]} or x[:end_date] #{val[1]} #{val[2]}"
305
+ result
306
+ end
307
+ .,.,
308
+
309
+ module_eval(<<'.,.,', 'query_parser.racc', 67)
310
+ def _reduce_12(val, _values, result)
311
+ result = "#{val[0]} #{val[1]} #{val[2]}"
312
+ result
313
+ end
314
+ .,.,
315
+
316
+ module_eval(<<'.,.,', 'query_parser.racc', 69)
317
+ def _reduce_13(val, _values, result)
318
+ result = "x[:start_date].year #{val[1]} #{val[2]} or x[:end_date].year #{val[1]} #{val[2]}"
319
+ result
320
+ end
321
+ .,.,
322
+
323
+ module_eval(<<'.,.,', 'query_parser.racc', 71)
324
+ def _reduce_14(val, _values, result)
325
+ result = "x[:#{val[0]}] #{val[1]} #{val[2]}"
326
+ result
327
+ end
328
+ .,.,
329
+
330
+ module_eval(<<'.,.,', 'query_parser.racc', 73)
331
+ def _reduce_15(val, _values, result)
332
+ result = "Date.parse(\"#{val[0]}\")"
333
+ result
334
+ end
335
+ .,.,
336
+
337
+ # reduce 16 omitted
338
+
339
+ # reduce 17 omitted
340
+
341
+ # reduce 18 omitted
342
+
343
+ # reduce 19 omitted
344
+
345
+ def _reduce_none(val, _values, result)
346
+ val[0]
347
+ end
348
+
349
+ end # class QueryParser
@@ -0,0 +1,48 @@
1
+ require 'yaml'
2
+
3
+ module Columbus3
4
+ class Sidecar
5
+ def initialize filename
6
+ @metadata = Hash.new
7
+ @metadata[:filename] = filename
8
+ end
9
+
10
+ def metadata= metadata
11
+ filename = @metadata[:filename]
12
+ @metadata = metadata
13
+ @metadata[:filename] = filename
14
+ end
15
+
16
+ def metadata
17
+ @metadata
18
+ end
19
+
20
+ def keys
21
+ @metadata.keys
22
+ end
23
+
24
+ def load
25
+ YAML.load(File.read(@metadata[:filename] + ".yaml", "r"))
26
+ end
27
+
28
+ def save
29
+ File.open(@metadata[:filename] + ".yaml", "w") do |file|
30
+ file << @metadata.to_yaml
31
+ end
32
+ end
33
+ end
34
+
35
+ class SidecarSearch
36
+ def initialize
37
+ @metadata = Array.new
38
+ end
39
+
40
+ def load array
41
+ @metadata = array.each.map { |x| YAML.load(File.read(x)) }
42
+ end
43
+
44
+ def search term
45
+ @metadata.select { |x| eval(term) }
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,73 @@
1
+ require 'erb'
2
+ require 'yaml'
3
+
4
+ module Columbus3
5
+ # renderer controls the transformation of a V900 tracks into a displayable format,
6
+ # whatever this means
7
+ module LeafletRenderer
8
+ # apply the ERB in html/show.html.erb (which includes all the tracks to display)
9
+ # and save it in the current directory, under _show.html
10
+ def self.show files
11
+ template = File.join(File.dirname(__FILE__), "/../../html/show.html.erb")
12
+ renderer = ERB.new(File.read(template))
13
+
14
+ # context: location of css and js + list of files to show
15
+ bower_dir = File.join(File.dirname(__FILE__), "/../../../bower_components")
16
+ @leaflet_providers = File.join(bower_dir, 'leaflet-providers/leaflet-providers.js')
17
+ @leaflet_js = File.join(bower_dir, 'leaflet/dist/leaflet.js')
18
+ @leaflet_css = File.join(bower_dir, 'leaflet/dist/leaflet.css')
19
+ @files = files
20
+
21
+ # generate the output
22
+ html = renderer.result(binding)
23
+
24
+ # save it to file
25
+ File.open("_show.html", "w") do |file|
26
+ file << html
27
+ end
28
+ end
29
+
30
+ # make a v900 track into a leaflet layer cached to disk
31
+ def self.to_leaflet filename, force = false
32
+
33
+ target = to_leaflet_filename filename
34
+
35
+ if force or not File.exists? target
36
+ track = V900Track.new filename
37
+ File.open(target, "w") do |file|
38
+ id = sanitize filename
39
+
40
+ file.printf <<EOS
41
+ latlong_#{id} = #{track.range.each.map { |i| track[i].lat_lon }};\n
42
+ start_#{id} = L.marker(#{track.first.lat_lon}).bindPopup('Start');\n
43
+ end_#{id} = L.marker(#{track.last.lat_lon}).bindPopup('End');\n
44
+ poly_#{id} = L.polyline(latlong_#{id}, {color: 'red'});\n
45
+
46
+ max_speed_#{id} = L.marker(#{track[track.max_speed_idx].lat_lon}).bindPopup('Max speed #{track.max_speed}')\n;
47
+ max_height_#{id} = L.marker(#{track[track.max_height_idx].lat_lon}).bindPopup('Max height #{track.max_height}')\n;
48
+ min_height_#{id} = L.marker(#{track[track.min_height_idx].lat_lon}).bindPopup('Min height #{track.min_height}')\n;
49
+
50
+ #{to_leaflet_layername filename} = L.layerGroup([start_#{id}, end_#{id}, poly_#{id}, max_speed_#{id}, max_height_#{id}, min_height_#{id}]);\n
51
+ #{to_leaflet_layername filename}.addTo(map);\n
52
+ EOS
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ def self.to_leaflet_filename filename
59
+ filename + ".js"
60
+ end
61
+
62
+ def self.to_leaflet_layername filename
63
+ "layer_" + sanitize(filename)
64
+ end
65
+
66
+ private
67
+
68
+ def self.sanitize filename
69
+ filename.gsub(/[^0-9A-Za-z\-]/, "_")
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,157 @@
1
+ require 'csv'
2
+ require 'geocoder'
3
+
4
+ require 'columbus3/v900track/v900waypoint'
5
+
6
+ class V900Track
7
+ def initialize filename
8
+ read filename
9
+ end
10
+
11
+ def read filename
12
+ @data = CSV::read(filename, :headers => true).each.map { |item| V900Waypoint.new(item) }
13
+ end
14
+
15
+ def size
16
+ @data.size
17
+ end
18
+
19
+ # an alias for size
20
+ def points
21
+ @data.size
22
+ end
23
+
24
+ def range
25
+ (0..self.size - 1)
26
+ end
27
+
28
+ # to enumerate (till I can solve the each issue)
29
+ def to_a
30
+ @data
31
+ end
32
+
33
+ # it does not work
34
+ #def each
35
+ # @data.each
36
+ #end
37
+
38
+ def get i
39
+ self[i]
40
+ end
41
+
42
+ def [](i)
43
+ @data[i]
44
+ end
45
+
46
+ def first
47
+ @data[0]
48
+ end
49
+
50
+ def last
51
+ @data[size - 1]
52
+ end
53
+
54
+ # statistics
55
+
56
+ def start_date
57
+ first.time
58
+ end
59
+
60
+ def end_date
61
+ last.time
62
+ end
63
+
64
+ def duration
65
+ last.time - first.time
66
+ end
67
+
68
+ def min_speed
69
+ get :<, :speed
70
+ end
71
+
72
+ def max_speed
73
+ get :>, :speed
74
+ end
75
+
76
+ def min_height
77
+ get :<, :height
78
+ end
79
+
80
+ def max_height
81
+ get :>, :height
82
+ end
83
+
84
+ def min_speed_idx
85
+ get_idx :<, :speed
86
+ end
87
+
88
+ def max_speed_idx
89
+ get_idx :>, :speed
90
+ end
91
+
92
+ def min_height_idx
93
+ get_idx :<, :height
94
+ end
95
+
96
+ def max_height_idx
97
+ get_idx :>, :height
98
+ end
99
+
100
+ def start_location
101
+ Geocoder.address(first.lat_lon)
102
+ end
103
+
104
+ def end_location
105
+ Geocoder.address(last.lat_lon)
106
+ end
107
+
108
+ def bearing
109
+ Geocoder::Calculations.compass_point(Geocoder::Calculations.bearing_between(first.lat_lon, last.lat_lon))
110
+ end
111
+
112
+ def distance_aerial
113
+ Geocoder::Calculations.distance_between(first.lat_lon, last.lat_lon, :units => :km)
114
+ end
115
+
116
+ def distance
117
+ distance = 0
118
+ range.each do |i|
119
+ distance += Geocoder::Calculations.distance_between(self[i].lat_lon, self[i-1].lat_lon, :units => :km)
120
+ end
121
+ distance
122
+ end
123
+
124
+ # return a hash with all the metadata
125
+ # ... it could be a nice metamethod, creating a key for each public methods
126
+ def metadata
127
+ metadata = Hash.new
128
+
129
+ [:start_date, :end_date, :duration, :size, :start_location, :end_location, :min_speed, :max_speed, :min_height, :max_height, :bearing, :distance, :distance_aerial].map { |x| metadata[x] = self.send(x) }
130
+
131
+ metadata
132
+ end
133
+
134
+ private
135
+
136
+ def get comparison, method
137
+ current = self[0].send(method) # initialize max or min to the first value in the file
138
+ range.each do |i|
139
+ current = self[i].send(method) if self[i].send(method).send(comparison, current)
140
+ end
141
+ current
142
+ end
143
+
144
+ def get_idx comparison, method
145
+ current = self[0].send(method) # initialize max or min to the first value in the file
146
+ idx = 0
147
+ range.each do |i|
148
+ if self[i].send(method).send(comparison, current) then
149
+ current = self[i].send(method)
150
+ idx = i
151
+ end
152
+ end
153
+ idx
154
+ end
155
+
156
+ end
157
+
@@ -0,0 +1,51 @@
1
+ require 'time'
2
+
3
+ # a facade which presents a CSV::row as a v900 waypoint
4
+ class V900Waypoint
5
+ def initialize row
6
+ @row = row
7
+ end
8
+
9
+ def index
10
+ @row["INDEX"].to_i
11
+ end
12
+
13
+ def tag
14
+ @row["TAG"]
15
+ end
16
+
17
+ def time
18
+ date = @row["DATE"]
19
+ time = @row["TIME"]
20
+ # make sure it is understood as ZULU time (UTC) and pad time to six numbers 75858 -> 075858
21
+ Time.parse("#{date}T" + ("%06d" % time) + "Z")
22
+ end
23
+
24
+ def lon
25
+ value = @row["LONGITUDE E/W"]
26
+ value.match(/(N|E)/) ? value[0..-2].to_f : -1 * value[0..-2].to_f
27
+ end
28
+
29
+ def lat
30
+ value = @row["LATITUDE N/S"]
31
+ value.match(/(N|E)/) ? value[0..-2].to_f : -1 * value[0..-2].to_f
32
+ end
33
+
34
+ # return an array with lat and lon: [lat, lon]
35
+ def lat_lon
36
+ [lat, lon]
37
+ end
38
+
39
+ def height
40
+ @row["HEIGHT"].to_i
41
+ end
42
+
43
+ def speed
44
+ @row["SPEED"].to_i
45
+ end
46
+
47
+ def heading
48
+ @row["HEADING"].to_i
49
+ end
50
+
51
+ end
@@ -0,0 +1,3 @@
1
+ module Columbus3
2
+ VERSION = "0.1.0"
3
+ end
data/lib/columbus3.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "columbus3/version"
2
+ require "columbus3/metadata/query_parser.tab"
3
+ require "columbus3/metadata/sidecar"
4
+ require "columbus3/v900track/v900track"
5
+ require "columbus3/v900track/v900waypoint"
6
+ require "columbus3/renderer/renderer"