geoptima 0.0.2 → 0.0.4
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/show_geoptima +49 -5
- data/examples/show_geoptima.rb +30 -3
- data/geoptima.gemspec +3 -1
- data/lib/geoptima/data.rb +32 -0
- data/lib/geoptima/version.rb +27 -1
- metadata +4 -4
data/bin/show_geoptima
CHANGED
@@ -7,6 +7,8 @@ $: << '../lib'
|
|
7
7
|
require 'date'
|
8
8
|
require 'geoptima'
|
9
9
|
|
10
|
+
Geoptima::assert_version("0.0.3")
|
11
|
+
|
10
12
|
$debug=false
|
11
13
|
|
12
14
|
$event_names=[]
|
@@ -17,7 +19,7 @@ def cw(val)
|
|
17
19
|
val.nil? ? '' : "(#{val})"
|
18
20
|
end
|
19
21
|
|
20
|
-
while arg=ARGV.shift
|
22
|
+
while arg=ARGV.shift do
|
21
23
|
if arg =~ /^\-(\w+)/
|
22
24
|
$1.split(//).each do |aa|
|
23
25
|
case aa
|
@@ -33,6 +35,10 @@ while arg=ARGV.shift:
|
|
33
35
|
$export=true
|
34
36
|
when 's'
|
35
37
|
$seperate=true
|
38
|
+
when 'o'
|
39
|
+
$export_stats=true
|
40
|
+
when 'm'
|
41
|
+
$map_headers=true
|
36
42
|
when 'E'
|
37
43
|
$event_names += ARGV.shift.split(/[\,\;\:\.]+/)
|
38
44
|
when 'T'
|
@@ -63,6 +69,8 @@ Usage: ./showGeoptimaEvents.rb <-dvxEh> <-L limit> <-E types> <-T min,max> file
|
|
63
69
|
-p print mode (print out final results to console) #{cw $print}
|
64
70
|
-v verbose mode (output extra information to console) #{cw $verbose}
|
65
71
|
-x export IMEI specific CSV files for further processing #{cw $export}
|
72
|
+
-o export field statistis #{cw $export_stats}
|
73
|
+
-m map headers to classic NetView compatible version #{cw $map_headers}
|
66
74
|
-s seperate the export files by event type #{cw $seperate}
|
67
75
|
-h show this help
|
68
76
|
-L limit verbose output to specific number of lines #{cw $print_limit}
|
@@ -76,8 +84,9 @@ $verbose = $verbose || $debug
|
|
76
84
|
$datasets = Geoptima::Dataset.make_datasets($files, :locate => true, :time_range => $time_range)
|
77
85
|
|
78
86
|
class Export
|
79
|
-
attr_reader :files, :names, :headers
|
87
|
+
attr_reader :files, :imei, :names, :headers
|
80
88
|
def initialize(imei,names,dataset)
|
89
|
+
@imei = imei
|
81
90
|
@names = names
|
82
91
|
if $export
|
83
92
|
if $seperate
|
@@ -91,12 +100,13 @@ class Export
|
|
91
100
|
end
|
92
101
|
@headers = names.inject({}) do |a,name|
|
93
102
|
a[name] = dataset.header([name]).reject{|h| h === 'timeoffset'}
|
103
|
+
a[name] = a[name].map{|h| "#{name}.#{h}"} unless($separate)
|
94
104
|
puts "Created header for name #{name}: #{a[name].join(',')}" if($debug)
|
95
105
|
a
|
96
106
|
end
|
97
107
|
@headers[nil] = @headers.values.flatten
|
98
108
|
files && files.each do |key,file|
|
99
|
-
file.puts
|
109
|
+
file.puts map_headers(['Time','Event','Latitude','Longitude','IMSI','IMEI']+header(key)).join("\t")
|
100
110
|
end
|
101
111
|
if $debug || $verbose
|
102
112
|
@headers.each do |name,head|
|
@@ -104,6 +114,38 @@ class Export
|
|
104
114
|
end
|
105
115
|
end
|
106
116
|
end
|
117
|
+
def cap(array,sep="")
|
118
|
+
array.map do |v|
|
119
|
+
"#{v[0..0].upcase}#{v[1..-1]}"
|
120
|
+
end.join(sep)
|
121
|
+
end
|
122
|
+
def map_headers(hnames)
|
123
|
+
$map_headers && hnames.map do |h|
|
124
|
+
case h
|
125
|
+
when 'Time'
|
126
|
+
'time'
|
127
|
+
when /gps\./
|
128
|
+
cap(h.split(/[\._]/),'_').gsub(/gps/i,'GPS')
|
129
|
+
when /^(call|signal|data|sms|mms|browser|neighbor)/i
|
130
|
+
cap(h.split(/[\._]/),'_').gsub(/Neighbor/,'Neighbour').gsub(/mms/i,'MMS').gsub(/sms/,'SMS')
|
131
|
+
when /\./
|
132
|
+
cap(h.split(/[\._]/))
|
133
|
+
else
|
134
|
+
h
|
135
|
+
end
|
136
|
+
end || hnames
|
137
|
+
end
|
138
|
+
def export_stats(stats)
|
139
|
+
File.open("#{imei}_stats.csv",'w') do |out|
|
140
|
+
stats.keys.sort.each do |header|
|
141
|
+
out.puts header
|
142
|
+
values = stats[header].keys.sort
|
143
|
+
out.puts values.join("\t")
|
144
|
+
out.puts values.map{|v| stats[header][v]}.join("\t")
|
145
|
+
out.puts
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
107
149
|
def header(name=nil)
|
108
150
|
@headers[name]
|
109
151
|
end
|
@@ -139,6 +181,7 @@ end
|
|
139
181
|
puts "Found #{$datasets.length} IMEIs"
|
140
182
|
$datasets.keys.sort.each do |imei|
|
141
183
|
dataset = $datasets[imei]
|
184
|
+
imsi = dataset.imsi
|
142
185
|
events = dataset.sorted
|
143
186
|
puts if($print)
|
144
187
|
puts "Found #{dataset}"
|
@@ -146,12 +189,13 @@ $datasets.keys.sort.each do |imei|
|
|
146
189
|
names = $event_names
|
147
190
|
names = dataset.events_names if(names.length<1)
|
148
191
|
export = Export.new(imei,names,dataset)
|
192
|
+
export.export_stats(dataset.stats) if($export_stats)
|
149
193
|
events.each do |event|
|
150
194
|
names.each do |name|
|
151
195
|
if event.name === name
|
152
196
|
fields = export.header($seperate ? name : nil).map{|h| event[h]}
|
153
|
-
export.puts_to "#{event.time_key}\t#{event.name}\t#{event.latitude}\t#{event.longitude}\t#{fields.join("\t")}", name
|
154
|
-
if_le{puts "#{event.time_key}\t#{event.name}\t#{event.latitude}\t#{event.longitude}\t#{event.fields.inspect}"}
|
197
|
+
export.puts_to "#{event.time_key}\t#{event.name}\t#{event.latitude}\t#{event.longitude}\t#{imsi}\t#{imei}\t#{fields.join("\t")}", name
|
198
|
+
if_le{puts "#{event.time_key}\t#{event.name}\t#{event.latitude}\t#{event.longitude}\t#{imsi}\t#{imei}\t#{event.fields.inspect}"}
|
155
199
|
end
|
156
200
|
end
|
157
201
|
end
|
data/examples/show_geoptima.rb
CHANGED
@@ -7,6 +7,8 @@ $: << '../lib'
|
|
7
7
|
require 'date'
|
8
8
|
require 'geoptima'
|
9
9
|
|
10
|
+
Geoptima::assert_version("0.0.4")
|
11
|
+
|
10
12
|
$debug=false
|
11
13
|
|
12
14
|
$event_names=[]
|
@@ -35,6 +37,8 @@ while arg=ARGV.shift do
|
|
35
37
|
$seperate=true
|
36
38
|
when 'o'
|
37
39
|
$export_stats=true
|
40
|
+
when 'm'
|
41
|
+
$map_headers=true
|
38
42
|
when 'E'
|
39
43
|
$event_names += ARGV.shift.split(/[\,\;\:\.]+/)
|
40
44
|
when 'T'
|
@@ -66,6 +70,7 @@ Usage: ./showGeoptimaEvents.rb <-dvxEh> <-L limit> <-E types> <-T min,max> file
|
|
66
70
|
-v verbose mode (output extra information to console) #{cw $verbose}
|
67
71
|
-x export IMEI specific CSV files for further processing #{cw $export}
|
68
72
|
-o export field statistis #{cw $export_stats}
|
73
|
+
-m map headers to classic NetView compatible version #{cw $map_headers}
|
69
74
|
-s seperate the export files by event type #{cw $seperate}
|
70
75
|
-h show this help
|
71
76
|
-L limit verbose output to specific number of lines #{cw $print_limit}
|
@@ -101,7 +106,7 @@ class Export
|
|
101
106
|
end
|
102
107
|
@headers[nil] = @headers.values.flatten
|
103
108
|
files && files.each do |key,file|
|
104
|
-
file.puts
|
109
|
+
file.puts map_headers(['Time','Event','Latitude','Longitude','IMSI','IMEI']+header(key)).join("\t")
|
105
110
|
end
|
106
111
|
if $debug || $verbose
|
107
112
|
@headers.each do |name,head|
|
@@ -109,6 +114,27 @@ class Export
|
|
109
114
|
end
|
110
115
|
end
|
111
116
|
end
|
117
|
+
def cap(array,sep="")
|
118
|
+
array.map do |v|
|
119
|
+
"#{v[0..0].upcase}#{v[1..-1]}"
|
120
|
+
end.join(sep)
|
121
|
+
end
|
122
|
+
def map_headers(hnames)
|
123
|
+
$map_headers && hnames.map do |h|
|
124
|
+
case h
|
125
|
+
when 'Time'
|
126
|
+
'time'
|
127
|
+
when /gps\./
|
128
|
+
cap(h.split(/[\._]/),'_').gsub(/gps/i,'GPS')
|
129
|
+
when /^(call|signal|data|sms|mms|browser|neighbor)/i
|
130
|
+
cap(h.split(/[\._]/),'_').gsub(/Neighbor/,'Neighbour').gsub(/mms/i,'MMS').gsub(/sms/,'SMS')
|
131
|
+
when /\./
|
132
|
+
cap(h.split(/[\._]/))
|
133
|
+
else
|
134
|
+
h
|
135
|
+
end
|
136
|
+
end || hnames
|
137
|
+
end
|
112
138
|
def export_stats(stats)
|
113
139
|
File.open("#{imei}_stats.csv",'w') do |out|
|
114
140
|
stats.keys.sort.each do |header|
|
@@ -155,6 +181,7 @@ end
|
|
155
181
|
puts "Found #{$datasets.length} IMEIs"
|
156
182
|
$datasets.keys.sort.each do |imei|
|
157
183
|
dataset = $datasets[imei]
|
184
|
+
imsi = dataset.imsi
|
158
185
|
events = dataset.sorted
|
159
186
|
puts if($print)
|
160
187
|
puts "Found #{dataset}"
|
@@ -167,8 +194,8 @@ $datasets.keys.sort.each do |imei|
|
|
167
194
|
names.each do |name|
|
168
195
|
if event.name === name
|
169
196
|
fields = export.header($seperate ? name : nil).map{|h| event[h]}
|
170
|
-
export.puts_to "#{event.time_key}\t#{event.name}\t#{event.latitude}\t#{event.longitude}\t#{fields.join("\t")}", name
|
171
|
-
if_le{puts "#{event.time_key}\t#{event.name}\t#{event.latitude}\t#{event.longitude}\t#{event.fields.inspect}"}
|
197
|
+
export.puts_to "#{event.time_key}\t#{event.name}\t#{event.latitude}\t#{event.longitude}\t#{imsi}\t#{imei}\t#{fields.join("\t")}", name
|
198
|
+
if_le{puts "#{event.time_key}\t#{event.name}\t#{event.latitude}\t#{event.longitude}\t#{imsi}\t#{imei}\t#{event.fields.inspect}"}
|
172
199
|
end
|
173
200
|
end
|
174
201
|
end
|
data/geoptima.gemspec
CHANGED
@@ -22,7 +22,9 @@ then rather consider the NetView and Customer IQ applications from AmanziTel at
|
|
22
22
|
EOF
|
23
23
|
|
24
24
|
s.require_path = 'lib'
|
25
|
-
s.files = Dir.glob("{bin,lib,
|
25
|
+
s.files = Dir.glob("{bin,lib,rdoc}/**/*").reject{|x| x=~/(tmp|target|test-data)/ || x=~/~$/} +
|
26
|
+
Dir.glob("examples/*rb") + Dir.glob("examples/sample*json") +
|
27
|
+
%w(README.rdoc CHANGELOG CONTRIBUTORS Gemfile geoptima.gemspec)
|
26
28
|
s.executables = ['show_geoptima']
|
27
29
|
s.has_rdoc = true
|
28
30
|
s.extra_rdoc_files = %w( README.rdoc )
|
data/lib/geoptima/data.rb
CHANGED
@@ -31,6 +31,21 @@ module Geoptima
|
|
31
31
|
|
32
32
|
# The Geoptima::Event class represents and individual record or event
|
33
33
|
class Event
|
34
|
+
KNOWN_HEADERS={
|
35
|
+
"gps" => ["timeoffset","latitude","longitude","altitude","accuracy","direction","speed"],
|
36
|
+
"service" => ["timeoffset","plmn","cell_id","lac","mnc","mcc"],
|
37
|
+
"call" => ["timeoffset","status","number"],
|
38
|
+
"runningApps" => ["timeoffset","appName","state"],
|
39
|
+
"batteryState" => ["timeoffset","state"],
|
40
|
+
"trafficSpeed" => ["timeoffset","interface","direction","delay","speed"],
|
41
|
+
"storageStatus" => ["timeoffset","path","totalSize","freeSize"],
|
42
|
+
"signal" => ["timeoffset","strength","rxqual","ecio"],
|
43
|
+
"roundtrip" => ["timeoffset","interface","address","type","roundtripTime"],
|
44
|
+
"httpRequest" => ["timeoffset","interface","address","delay","speed"],
|
45
|
+
"dnsLookup" => ["timeoffset","interface","address","lookupTime","ip"],
|
46
|
+
"ftpSpeed" => ["timeoffset","interface","direction","delay","peak","speed"],
|
47
|
+
"browserDedicatedTest" => ["timeoffset","url","pageRenders","pageRendered","pageSize","success"]
|
48
|
+
}
|
34
49
|
attr_reader :header, :name, :data, :fields, :time, :latitude, :longitude
|
35
50
|
def initialize(start,name,header,data)
|
36
51
|
@name = name
|
@@ -152,6 +167,23 @@ module Geoptima
|
|
152
167
|
events = data['values']
|
153
168
|
event_type = data.keys.reject{|k| k=~/values/}[0]
|
154
169
|
header = @events_metadata[event_type]
|
170
|
+
unless header
|
171
|
+
puts "No header found for '#{event_type}', trying known Geoptima headers"
|
172
|
+
header = Event::KNOWN_HEADERS[event_type]
|
173
|
+
if header
|
174
|
+
puts "Found known header '#{event_type}' => #{header.inspect}"
|
175
|
+
if data = events_data[event_type]
|
176
|
+
mismatch = data.length % header.length
|
177
|
+
if mismatch != 0
|
178
|
+
puts "Known header length #{header.length} incompatible with data length #{events_data[event_type].length}"
|
179
|
+
header = nil
|
180
|
+
end
|
181
|
+
else
|
182
|
+
puts "No data found for event type '#{event_type}'"
|
183
|
+
header = nil
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
155
187
|
if header
|
156
188
|
events_data[event_type] = (0...data[event_type].to_i).inject([]) do |a,block|
|
157
189
|
index = header.length * block
|
data/lib/geoptima/version.rb
CHANGED
@@ -1,3 +1,29 @@
|
|
1
1
|
module Geoptima
|
2
|
-
|
2
|
+
|
3
|
+
VERSION = "0.0.4"
|
4
|
+
|
5
|
+
def self.version_as_int(ver)
|
6
|
+
base = 1
|
7
|
+
ver.split(/\./).reverse.inject(0) do |acc,v|
|
8
|
+
acc += base * v.to_i
|
9
|
+
base *= 100
|
10
|
+
acc
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.compare_version(expected_ver)
|
15
|
+
version_as_int(expected_ver) - version_as_int(VERSION)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.assert_version(expected_ver)
|
19
|
+
if expected_ver.to_s != VERSION
|
20
|
+
diff = compare_version(expected_ver)
|
21
|
+
if(diff != 0)
|
22
|
+
msg = diff > 0 ? "against and older library" : "an older script"
|
23
|
+
puts "Geoptima library version mismatch. Expected #{expected_ver}, found #{VERSION}. Are you running #{msg}?"
|
24
|
+
exit -1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
3
29
|
end
|
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: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Craig Taverner
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-03-
|
18
|
+
date: 2012-03-09 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: json
|