geoptima 0.0.4 → 0.0.5
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/bin/geoptima_file_time +10 -0
- data/bin/show_geoptima +45 -4
- data/examples/geoptima_file_time.rb +10 -0
- data/examples/show_geoptima.rb +45 -4
- data/geoptima.gemspec +4 -3
- data/lib/geoptima/data.rb +46 -25
- data/lib/geoptima/version.rb +1 -1
- metadata +7 -6
data/bin/show_geoptima
CHANGED
@@ -7,7 +7,7 @@ $: << '../lib'
|
|
7
7
|
require 'date'
|
8
8
|
require 'geoptima'
|
9
9
|
|
10
|
-
Geoptima::assert_version("0.0.
|
10
|
+
Geoptima::assert_version("0.0.5")
|
11
11
|
|
12
12
|
$debug=false
|
13
13
|
|
@@ -39,6 +39,8 @@ while arg=ARGV.shift do
|
|
39
39
|
$export_stats=true
|
40
40
|
when 'm'
|
41
41
|
$map_headers=true
|
42
|
+
when 'l'
|
43
|
+
$more_headers=true
|
42
44
|
when 'E'
|
43
45
|
$event_names += ARGV.shift.split(/[\,\;\:\.]+/)
|
44
46
|
when 'T'
|
@@ -71,6 +73,7 @@ Usage: ./showGeoptimaEvents.rb <-dvxEh> <-L limit> <-E types> <-T min,max> file
|
|
71
73
|
-x export IMEI specific CSV files for further processing #{cw $export}
|
72
74
|
-o export field statistis #{cw $export_stats}
|
73
75
|
-m map headers to classic NetView compatible version #{cw $map_headers}
|
76
|
+
-l longer header list (phone and operator fields) #{cw $more_headers}
|
74
77
|
-s seperate the export files by event type #{cw $seperate}
|
75
78
|
-h show this help
|
76
79
|
-L limit verbose output to specific number of lines #{cw $print_limit}
|
@@ -86,6 +89,7 @@ $datasets = Geoptima::Dataset.make_datasets($files, :locate => true, :time_range
|
|
86
89
|
class Export
|
87
90
|
attr_reader :files, :imei, :names, :headers
|
88
91
|
def initialize(imei,names,dataset)
|
92
|
+
imei = dataset.imsi if(imei.to_s.length < 1)
|
89
93
|
@imei = imei
|
90
94
|
@names = names
|
91
95
|
if $export
|
@@ -106,7 +110,7 @@ class Export
|
|
106
110
|
end
|
107
111
|
@headers[nil] = @headers.values.flatten
|
108
112
|
files && files.each do |key,file|
|
109
|
-
file.puts map_headers(
|
113
|
+
file.puts map_headers(base_headers+more_headers+header(key)).join("\t")
|
110
114
|
end
|
111
115
|
if $debug || $verbose
|
112
116
|
@headers.each do |name,head|
|
@@ -114,6 +118,42 @@ class Export
|
|
114
118
|
end
|
115
119
|
end
|
116
120
|
end
|
121
|
+
def base_headers
|
122
|
+
['Time','Event','Latitude','Longitude']
|
123
|
+
end
|
124
|
+
def more_headers
|
125
|
+
$more_headers ? ['IMSI','IMEI','MSISDN','MCC','MNC','LAC','CI','RSSI','Platform','Model','OS','Operator'] : []
|
126
|
+
end
|
127
|
+
def base_fields(event)
|
128
|
+
[event.time_key,event.name,event.latitude,event.longitude]
|
129
|
+
end
|
130
|
+
def more_fields(event,dataset)
|
131
|
+
more_headers.map do |h|
|
132
|
+
case h
|
133
|
+
when 'RSSI'
|
134
|
+
dataset.recent(event,'signal.strength')
|
135
|
+
when 'LAC'
|
136
|
+
dataset.recent(event,'service.lac')
|
137
|
+
when 'CI'
|
138
|
+
dataset.recent(event,'service.cell_id')
|
139
|
+
when 'MCC'
|
140
|
+
dataset[h] || dataset.recent(event,'service.mcc')
|
141
|
+
when 'MNC'
|
142
|
+
dataset[h] || dataset.recent(event,'service.mnc')
|
143
|
+
when 'Operator'
|
144
|
+
dataset['carrierName']
|
145
|
+
when 'IMSI'
|
146
|
+
dataset.imsi
|
147
|
+
when 'IMEI'
|
148
|
+
dataset.imei
|
149
|
+
else
|
150
|
+
dataset[h]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
def get_field(event,name)
|
155
|
+
h=(base_headers+more_headers).grep(/#{name}/)
|
156
|
+
end
|
117
157
|
def cap(array,sep="")
|
118
158
|
array.map do |v|
|
119
159
|
"#{v[0..0].upcase}#{v[1..-1]}"
|
@@ -194,8 +234,9 @@ $datasets.keys.sort.each do |imei|
|
|
194
234
|
names.each do |name|
|
195
235
|
if event.name === name
|
196
236
|
fields = export.header($seperate ? name : nil).map{|h| event[h]}
|
197
|
-
export.
|
198
|
-
|
237
|
+
b_fields = export.base_fields(event) + export.more_fields(event,dataset)
|
238
|
+
export.puts_to "#{b_fields.join("\t")}\t#{fields.join("\t")}", name
|
239
|
+
if_le{puts "#{b_fields.join("\t")}\t#{event.fields.inspect}"}
|
199
240
|
end
|
200
241
|
end
|
201
242
|
end
|
data/examples/show_geoptima.rb
CHANGED
@@ -7,7 +7,7 @@ $: << '../lib'
|
|
7
7
|
require 'date'
|
8
8
|
require 'geoptima'
|
9
9
|
|
10
|
-
Geoptima::assert_version("0.0.
|
10
|
+
Geoptima::assert_version("0.0.5")
|
11
11
|
|
12
12
|
$debug=false
|
13
13
|
|
@@ -39,6 +39,8 @@ while arg=ARGV.shift do
|
|
39
39
|
$export_stats=true
|
40
40
|
when 'm'
|
41
41
|
$map_headers=true
|
42
|
+
when 'l'
|
43
|
+
$more_headers=true
|
42
44
|
when 'E'
|
43
45
|
$event_names += ARGV.shift.split(/[\,\;\:\.]+/)
|
44
46
|
when 'T'
|
@@ -71,6 +73,7 @@ Usage: ./showGeoptimaEvents.rb <-dvxEh> <-L limit> <-E types> <-T min,max> file
|
|
71
73
|
-x export IMEI specific CSV files for further processing #{cw $export}
|
72
74
|
-o export field statistis #{cw $export_stats}
|
73
75
|
-m map headers to classic NetView compatible version #{cw $map_headers}
|
76
|
+
-l longer header list (phone and operator fields) #{cw $more_headers}
|
74
77
|
-s seperate the export files by event type #{cw $seperate}
|
75
78
|
-h show this help
|
76
79
|
-L limit verbose output to specific number of lines #{cw $print_limit}
|
@@ -86,6 +89,7 @@ $datasets = Geoptima::Dataset.make_datasets($files, :locate => true, :time_range
|
|
86
89
|
class Export
|
87
90
|
attr_reader :files, :imei, :names, :headers
|
88
91
|
def initialize(imei,names,dataset)
|
92
|
+
imei = dataset.imsi if(imei.to_s.length < 1)
|
89
93
|
@imei = imei
|
90
94
|
@names = names
|
91
95
|
if $export
|
@@ -106,7 +110,7 @@ class Export
|
|
106
110
|
end
|
107
111
|
@headers[nil] = @headers.values.flatten
|
108
112
|
files && files.each do |key,file|
|
109
|
-
file.puts map_headers(
|
113
|
+
file.puts map_headers(base_headers+more_headers+header(key)).join("\t")
|
110
114
|
end
|
111
115
|
if $debug || $verbose
|
112
116
|
@headers.each do |name,head|
|
@@ -114,6 +118,42 @@ class Export
|
|
114
118
|
end
|
115
119
|
end
|
116
120
|
end
|
121
|
+
def base_headers
|
122
|
+
['Time','Event','Latitude','Longitude']
|
123
|
+
end
|
124
|
+
def more_headers
|
125
|
+
$more_headers ? ['IMSI','IMEI','MSISDN','MCC','MNC','LAC','CI','RSSI','Platform','Model','OS','Operator'] : []
|
126
|
+
end
|
127
|
+
def base_fields(event)
|
128
|
+
[event.time_key,event.name,event.latitude,event.longitude]
|
129
|
+
end
|
130
|
+
def more_fields(event,dataset)
|
131
|
+
more_headers.map do |h|
|
132
|
+
case h
|
133
|
+
when 'RSSI'
|
134
|
+
dataset.recent(event,'signal.strength')
|
135
|
+
when 'LAC'
|
136
|
+
dataset.recent(event,'service.lac')
|
137
|
+
when 'CI'
|
138
|
+
dataset.recent(event,'service.cell_id')
|
139
|
+
when 'MCC'
|
140
|
+
dataset[h] || dataset.recent(event,'service.mcc')
|
141
|
+
when 'MNC'
|
142
|
+
dataset[h] || dataset.recent(event,'service.mnc')
|
143
|
+
when 'Operator'
|
144
|
+
dataset['carrierName']
|
145
|
+
when 'IMSI'
|
146
|
+
dataset.imsi
|
147
|
+
when 'IMEI'
|
148
|
+
dataset.imei
|
149
|
+
else
|
150
|
+
dataset[h]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
def get_field(event,name)
|
155
|
+
h=(base_headers+more_headers).grep(/#{name}/)
|
156
|
+
end
|
117
157
|
def cap(array,sep="")
|
118
158
|
array.map do |v|
|
119
159
|
"#{v[0..0].upcase}#{v[1..-1]}"
|
@@ -194,8 +234,9 @@ $datasets.keys.sort.each do |imei|
|
|
194
234
|
names.each do |name|
|
195
235
|
if event.name === name
|
196
236
|
fields = export.header($seperate ? name : nil).map{|h| event[h]}
|
197
|
-
export.
|
198
|
-
|
237
|
+
b_fields = export.base_fields(event) + export.more_fields(event,dataset)
|
238
|
+
export.puts_to "#{b_fields.join("\t")}\t#{fields.join("\t")}", name
|
239
|
+
if_le{puts "#{b_fields.join("\t")}\t#{event.fields.inspect}"}
|
199
240
|
end
|
200
241
|
end
|
201
242
|
end
|
data/geoptima.gemspec
CHANGED
@@ -25,10 +25,11 @@ EOF
|
|
25
25
|
s.files = Dir.glob("{bin,lib,rdoc}/**/*").reject{|x| x=~/(tmp|target|test-data)/ || x=~/~$/} +
|
26
26
|
Dir.glob("examples/*rb") + Dir.glob("examples/sample*json") +
|
27
27
|
%w(README.rdoc CHANGELOG CONTRIBUTORS Gemfile geoptima.gemspec)
|
28
|
-
s.executables = ['show_geoptima']
|
29
|
-
|
28
|
+
s.executables = ['show_geoptima','geoptima_file_time']
|
29
|
+
|
30
30
|
s.extra_rdoc_files = %w( README.rdoc )
|
31
|
-
s.rdoc_options = ["--quiet", "--title", "
|
31
|
+
s.rdoc_options = ["--quiet", "--title", "Geoptima.rb", "--line-numbers", "--main", "README.rdoc", "--inline-source"]
|
32
|
+
|
32
33
|
s.add_dependency('json',">= 1.6.5")
|
33
34
|
s.required_ruby_version = ">= 1.8.6"
|
34
35
|
end
|
data/lib/geoptima/data.rb
CHANGED
@@ -71,6 +71,9 @@ module Geoptima
|
|
71
71
|
def [](key)
|
72
72
|
@fields[key] || @fields[key.gsub(/#{name}\./,'')]
|
73
73
|
end
|
74
|
+
def []=(key,value)
|
75
|
+
@fields[key] ||= value
|
76
|
+
end
|
74
77
|
def -(other)
|
75
78
|
(self.time - other.time) * SPERDAY
|
76
79
|
end
|
@@ -95,13 +98,14 @@ module Geoptima
|
|
95
98
|
def initialize(path)
|
96
99
|
@path = path
|
97
100
|
@json = JSON.parse(File.read(path))
|
101
|
+
@fields = {}
|
98
102
|
if $debug
|
99
103
|
puts "Read Geoptima: #{geoptima.to_json}"
|
100
104
|
puts "\tSubscriber: #{subscriber.to_json}"
|
101
|
-
puts "\tIMSI: #{imsi}"
|
102
|
-
puts "\tIMEI: #{imei}"
|
103
|
-
puts "\tMCC: #{
|
104
|
-
puts "\tMNC: #{
|
105
|
+
puts "\tIMSI: #{self['imsi']}"
|
106
|
+
puts "\tIMEI: #{self['imei']}"
|
107
|
+
puts "\tMCC: #{self['MCC']}"
|
108
|
+
puts "\tMNC: #{self['MNC']}"
|
105
109
|
puts "\tStart: #{start}"
|
106
110
|
end
|
107
111
|
end
|
@@ -114,20 +118,8 @@ module Geoptima
|
|
114
118
|
def subscriber
|
115
119
|
@subscriber ||= geoptima['subscriber']
|
116
120
|
end
|
117
|
-
def
|
118
|
-
@
|
119
|
-
end
|
120
|
-
def imei
|
121
|
-
@imei ||= subscriber['imei']
|
122
|
-
end
|
123
|
-
def platform
|
124
|
-
@platform ||= subscriber['Platform'] || subscriber['platform']
|
125
|
-
end
|
126
|
-
def model
|
127
|
-
@model ||= subscriber['Model'] || subscriber['model']
|
128
|
-
end
|
129
|
-
def os
|
130
|
-
@os ||= subscriber['OS']
|
121
|
+
def [](key)
|
122
|
+
@fields[key] ||= subscriber[key] || subscriber[key.downcase]
|
131
123
|
end
|
132
124
|
def start
|
133
125
|
@start ||= subscriber['start'] && DateTime.parse(subscriber['start'].gsub(/Asia\/Bangkok/,'GMT+7').gsub(/Mar 17 2044/,'Feb 14 2012'))
|
@@ -220,6 +212,7 @@ module Geoptima
|
|
220
212
|
@data = []
|
221
213
|
@options = options
|
222
214
|
@time_range = options[:time_range] || Range.new(Config[:min_datetime],Config[:max_datetime])
|
215
|
+
@fields = {}
|
223
216
|
end
|
224
217
|
|
225
218
|
def <<(data)
|
@@ -237,8 +230,8 @@ module Geoptima
|
|
237
230
|
|
238
231
|
def imsis
|
239
232
|
@imsis ||= @data.inject({}) do |a,d|
|
240
|
-
a[d
|
241
|
-
a[d
|
233
|
+
a[d['imsi']] ||= 0
|
234
|
+
a[d['imsi']] += d.count.to_i
|
242
235
|
a
|
243
236
|
end.to_a.sort do |a,b|
|
244
237
|
b[1]<=>a[1]
|
@@ -248,16 +241,44 @@ module Geoptima
|
|
248
241
|
end.compact.uniq
|
249
242
|
end
|
250
243
|
|
244
|
+
def recent(event,key)
|
245
|
+
unless event[key]
|
246
|
+
puts "Searching for recent values for '#{key}' starting at event #{event}" if($debug)
|
247
|
+
ev,prop=key.split(/\./)
|
248
|
+
ar=sorted
|
249
|
+
puts "\tSearching through #{ar && ar.length} events for event type #{ev} and property #{prop}" if($debug)
|
250
|
+
if i=ar.index(event)
|
251
|
+
afe = while(i>0)
|
252
|
+
fe = ar[i-=1]
|
253
|
+
puts "\t\tTesting event[#{i}]: #{fe}" if($debug)
|
254
|
+
break(fe) if(fe.nil? || fe.name == ev || (event.time - fe.time) * SPERDAY > 60)
|
255
|
+
end
|
256
|
+
if afe && afe.name == ev
|
257
|
+
puts "\t\tFound event[#{i}] with #{prop} => #{afe[prop]} and time gap of #{(event.time - fe.time) * SPERDAY} seconds" if($verbose)
|
258
|
+
event[key] = afe[prop]
|
259
|
+
end
|
260
|
+
else
|
261
|
+
puts "Event not found in search for recent '#{key}': #{event}"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
# @recent[key] ||= ''
|
265
|
+
event[key]
|
266
|
+
end
|
267
|
+
|
268
|
+
def [](key)
|
269
|
+
@fields[key.downcase] ||= @data.map{|d| d[key]}.compact.uniq[0]
|
270
|
+
end
|
271
|
+
|
251
272
|
def platform
|
252
|
-
|
273
|
+
self['Platform']
|
253
274
|
end
|
254
275
|
|
255
276
|
def model
|
256
|
-
|
277
|
+
self['Model']
|
257
278
|
end
|
258
279
|
|
259
280
|
def os
|
260
|
-
|
281
|
+
self['OS']
|
261
282
|
end
|
262
283
|
|
263
284
|
def first
|
@@ -360,8 +381,8 @@ module Geoptima
|
|
360
381
|
unless geoptima.valid?
|
361
382
|
puts "INVALID: #{geoptima.start}\t#{file}\n\n"
|
362
383
|
else
|
363
|
-
datasets[geoptima
|
364
|
-
datasets[geoptima
|
384
|
+
datasets[geoptima['imei']] ||= Geoptima::Dataset.new(geoptima['imei'], options)
|
385
|
+
datasets[geoptima['imei']] << geoptima
|
365
386
|
end
|
366
387
|
end
|
367
388
|
datasets
|
data/lib/geoptima/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geoptima
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Craig Taverner
|
@@ -45,12 +45,14 @@ description: |
|
|
45
45
|
email: craig@amanzi.com
|
46
46
|
executables:
|
47
47
|
- show_geoptima
|
48
|
+
- geoptima_file_time
|
48
49
|
extensions: []
|
49
50
|
|
50
51
|
extra_rdoc_files:
|
51
52
|
- README.rdoc
|
52
53
|
files:
|
53
54
|
- bin/show_geoptima
|
55
|
+
- bin/geoptima_file_time
|
54
56
|
- lib/geoptima/version.rb
|
55
57
|
- lib/geoptima/data.rb
|
56
58
|
- lib/geoptima.rb
|
@@ -58,6 +60,7 @@ files:
|
|
58
60
|
- examples/export_layer.rb
|
59
61
|
- examples/stats.rb
|
60
62
|
- examples/show_geoptima.rb
|
63
|
+
- examples/geoptima_file_time.rb
|
61
64
|
- examples/sample_geoptima.json
|
62
65
|
- README.rdoc
|
63
66
|
- CHANGELOG
|
@@ -71,9 +74,7 @@ post_install_message:
|
|
71
74
|
rdoc_options:
|
72
75
|
- --quiet
|
73
76
|
- --title
|
74
|
-
-
|
75
|
-
- --opname
|
76
|
-
- index.html
|
77
|
+
- Geoptima.rb
|
77
78
|
- --line-numbers
|
78
79
|
- --main
|
79
80
|
- README.rdoc
|