pippa 0.1.0 → 0.2.1
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.md +2 -0
- data/lib/pippa.rb +110 -66
- data/lib/pippa/maps/_zipcodes.dmp +0 -0
- data/lib/pippa/version.rb +2 -1
- data/pippa.gemspec +13 -6
- data/spec/data/zipcodes.png +0 -0
- data/spec/lib/map_spec.rb +1 -4
- data/spec/lib/pippa_spec.rb +5 -0
- metadata +33 -8
- checksums.yaml +0 -15
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Pippa
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/pippa)
|
4
|
+
|
3
5
|
Pippa - a Ruby gem for producing simple map graphics overlain with
|
4
6
|
geocoded dots of given area. Dot coordinates are in screen pixels,
|
5
7
|
latitude/longitude, or US zipcode.
|
data/lib/pippa.rb
CHANGED
@@ -9,6 +9,7 @@ require 'pippa/version'
|
|
9
9
|
require 'RMagick'
|
10
10
|
require 'csv'
|
11
11
|
|
12
|
+
# The Pippa API.
|
12
13
|
module Pippa
|
13
14
|
|
14
15
|
# Return a list of the valid map names.
|
@@ -16,6 +17,53 @@ module Pippa
|
|
16
17
|
Map.info[:map].keys
|
17
18
|
end
|
18
19
|
|
20
|
+
# Compress the zipcode CSV file to something that loads quicker.
|
21
|
+
#
|
22
|
+
# This gem is packaged with compressed zipcode table that only works
|
23
|
+
# if your ruby has compatible a +Marshal+ version. If loading fails,
|
24
|
+
# it will attempt to rewrite the table in a compatible format, but if
|
25
|
+
# you don't have write permission in the gem store, that will
|
26
|
+
# consistently fail. You can use this call with +sudo∂ irb+ to
|
27
|
+
# write a compatible table.
|
28
|
+
def self.compress_zipcodes
|
29
|
+
dump_zips.size
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return a hash mapping zip codes to CSV records of zip code data.
|
33
|
+
# NB: The file is big, so this takes a while to return the first time called.
|
34
|
+
#
|
35
|
+
# +CSV::Row+ struct format (see also http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Row.html):
|
36
|
+
#
|
37
|
+
# #<CSV::Row
|
38
|
+
# zipcode:"97475"
|
39
|
+
# zip_code_type:"PO BOX"
|
40
|
+
# city:"SPRINGFIELD"
|
41
|
+
# state:"OR"
|
42
|
+
# location_type:"PRIMARY"
|
43
|
+
# lat:44.05
|
44
|
+
# long:-123.02
|
45
|
+
# location:"NA-US-OR-SPRINGFIELD"
|
46
|
+
# decommisioned:"false"
|
47
|
+
# tax_returns_filed:nil
|
48
|
+
# estimated_population:nil
|
49
|
+
# total_wages:nil>
|
50
|
+
#
|
51
|
+
# See http://federalgovernmentzipcodes.us for more information on the zipcode data.
|
52
|
+
def self.zips
|
53
|
+
@@zips ||= zips_from_file
|
54
|
+
end
|
55
|
+
|
56
|
+
# Run the profiler and record results. (For development.)
|
57
|
+
def self.profile
|
58
|
+
require 'ruby-prof'
|
59
|
+
RubyProf.start
|
60
|
+
Map.write_zipcode_maps
|
61
|
+
result = RubyProf.stop
|
62
|
+
File.open('profile.htm', 'w') do |f|
|
63
|
+
RubyProf::GraphHtmlPrinter.new(result).print(f)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
19
67
|
# An image-based map class that can be overlain with dots
|
20
68
|
# of given area and location given by pixel coordinates, lat/lon,
|
21
69
|
# or zipcode (courtesy of http://federalgovernmentzipcodes.us).
|
@@ -160,6 +208,7 @@ module Pippa
|
|
160
208
|
def add_at_lat_lon(lat, lon, area = 0)
|
161
209
|
add_dot(*lat_lon_to_xy(lat, lon), area)
|
162
210
|
end
|
211
|
+
alias_method :add_dot_at_lat_lon, :add_at_lat_lon
|
163
212
|
|
164
213
|
# Add a dot on the map at given 5-digit zip code.
|
165
214
|
#
|
@@ -176,33 +225,10 @@ module Pippa
|
|
176
225
|
# map.add_at_zip('10996', 100)
|
177
226
|
# map.write_png('map.png')
|
178
227
|
def add_at_zip(zip, area = 0)
|
179
|
-
data =
|
180
|
-
add_at_lat_lon(data[:lat], data[:
|
181
|
-
end
|
182
|
-
|
183
|
-
# Return a hash mapping zip codes to CSV records of zip code data.
|
184
|
-
# NB: The file is big, so this takes a while to return the first time called.
|
185
|
-
#
|
186
|
-
# +CSV::Row+ struct format (see also http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Row.html):
|
187
|
-
#
|
188
|
-
# #<CSV::Row
|
189
|
-
# zipcode:"97475"
|
190
|
-
# zip_code_type:"PO BOX"
|
191
|
-
# city:"SPRINGFIELD"
|
192
|
-
# state:"OR"
|
193
|
-
# location_type:"PRIMARY"
|
194
|
-
# lat:44.05
|
195
|
-
# long:-123.02
|
196
|
-
# location:"NA-US-OR-SPRINGFIELD"
|
197
|
-
# decommisioned:"false"
|
198
|
-
# tax_returns_filed:nil
|
199
|
-
# estimated_population:nil
|
200
|
-
# total_wages:nil>
|
201
|
-
#
|
202
|
-
# See http://federalgovernmentzipcodes.us for more information on the zipcode data.
|
203
|
-
def self.zips
|
204
|
-
@@zips ||= zips_from_file
|
228
|
+
data = Pippa.zips[zip]
|
229
|
+
add_at_lat_lon(data[:lat], data[:lon], area) if data
|
205
230
|
end
|
231
|
+
alias_method :add_dot_at_zip, :add_at_zip
|
206
232
|
|
207
233
|
# Force rendering of all dots added so far onto the map.
|
208
234
|
# Then forget them so they're never rendered again.
|
@@ -299,7 +325,7 @@ module Pippa
|
|
299
325
|
def self.zipcode_map
|
300
326
|
generator = Random.new(42) # Force same on every run for testing.
|
301
327
|
m = Map.new('USA')
|
302
|
-
zips.each_key.each do |zip|
|
328
|
+
Pippa.zips.each_key.each do |zip|
|
303
329
|
m.add_at_zip(zip, generator.rand(4) ** 2)
|
304
330
|
end
|
305
331
|
m.fill = 'red'
|
@@ -316,17 +342,6 @@ module Pippa
|
|
316
342
|
m.write_jpg('spec/data/zipcodes.jpg')
|
317
343
|
end
|
318
344
|
|
319
|
-
# Run the profiler and record results.
|
320
|
-
def self.profile
|
321
|
-
require 'ruby-prof'
|
322
|
-
RubyProf.start
|
323
|
-
write_zipcode_maps
|
324
|
-
result = RubyProf.stop
|
325
|
-
File.open('profile.htm', 'w') do |f|
|
326
|
-
RubyProf::GraphHtmlPrinter.new(result).print(f)
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
345
|
private
|
331
346
|
|
332
347
|
#:nodoc:
|
@@ -411,36 +426,65 @@ module Pippa
|
|
411
426
|
data
|
412
427
|
end
|
413
428
|
end
|
429
|
+
end
|
414
430
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
end
|
435
|
-
end
|
436
|
-
zips = {}
|
437
|
-
CSV.foreach("#{File.dirname(__FILE__)}/pippa/maps/_zipcodes.csv",
|
438
|
-
:headers => :first_row,
|
439
|
-
:header_converters => :underscore_symbol,
|
440
|
-
:converters => :custom) do |row|
|
441
|
-
zips[row[:zipcode]] = row if row[:lat] && row[:long]
|
431
|
+
private
|
432
|
+
|
433
|
+
ZIPCODE_CSV_FILE_PATH = "#{File.dirname(__FILE__)}/pippa/maps/_zipcodes.csv" # :nodoc:
|
434
|
+
|
435
|
+
# Read zipcode data from unaltered CSV file.
|
436
|
+
def self.zips_from_csv
|
437
|
+
CSV::HeaderConverters[:underscore_symbol] = lambda do |s|
|
438
|
+
t = s.gsub(/::/, '/')
|
439
|
+
t.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
440
|
+
t.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
441
|
+
t.tr!("-", "_")
|
442
|
+
t.downcase!
|
443
|
+
t.to_sym
|
444
|
+
end
|
445
|
+
CSV::Converters[:custom] = lambda do |s, info|
|
446
|
+
begin
|
447
|
+
[:lat, :long].include?(info.header) ? Float(s) : s
|
448
|
+
rescue
|
449
|
+
s
|
442
450
|
end
|
443
|
-
zips
|
444
451
|
end
|
452
|
+
zips = {}
|
453
|
+
CSV.foreach(ZIPCODE_CSV_FILE_PATH,
|
454
|
+
:headers => :first_row,
|
455
|
+
:header_converters => :underscore_symbol,
|
456
|
+
:converters => :custom) do |row|
|
457
|
+
zips[row[:zipcode]] = row if row[:lat] && row[:long]
|
458
|
+
end
|
459
|
+
zips
|
460
|
+
end
|
461
|
+
|
462
|
+
ZIPCODE_DUMP_FILE_PATH = "#{File.dirname(__FILE__)}/pippa/maps/_zipcodes.dmp" # :nodoc:
|
463
|
+
|
464
|
+
# Use native Ruby facility to create a quick-loading, compatible version of CSV zipcode data.
|
465
|
+
def self.dump_zips
|
466
|
+
hash = {}
|
467
|
+
zips_from_csv.each do |zip, row|
|
468
|
+
hash[zip] = { :lat => row[:lat], :lon => row[:long] }
|
469
|
+
end
|
470
|
+
File.open(ZIPCODE_DUMP_FILE_PATH, 'wb') {|f| Marshal.dump(hash, f) }
|
471
|
+
hash
|
472
|
+
rescue
|
473
|
+
hash
|
474
|
+
end
|
475
|
+
|
476
|
+
# Read a previously created dump of the zipcode database.
|
477
|
+
def self.zips_from_dump
|
478
|
+
File.open(ZIPCODE_DUMP_FILE_PATH, 'rb') {|f| Marshal.load(f) }
|
479
|
+
end
|
480
|
+
|
481
|
+
# Read zipcode data. Tries compressed form first and then CSV.
|
482
|
+
# Format:
|
483
|
+
# "Zipcode","ZipCodeType","City","State","LocationType","Lat","Long",
|
484
|
+
# "Location","Decommisioned","TaxReturnsFiled","EstimatedPopulation","TotalWages"
|
485
|
+
def self.zips_from_file
|
486
|
+
zips_from_dump
|
487
|
+
rescue
|
488
|
+
dump_zips
|
445
489
|
end
|
446
490
|
end
|
Binary file
|
data/lib/pippa/version.rb
CHANGED
data/pippa.gemspec
CHANGED
@@ -8,14 +8,21 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Pippa::VERSION
|
9
9
|
spec.authors = ["Gene Ressler"]
|
10
10
|
spec.email = ["gene.ressler@gmail.com"]
|
11
|
-
|
12
|
-
spec.summary = %q{
|
11
|
+
|
12
|
+
spec.summary = %q{Reimplements some parts of the plot-latlon utility from CAIDA (http://www.caida.org).}
|
13
|
+
spec.description =
|
14
|
+
%q{Draw dots on maps by lat/lon or zip code. Includes a library of 30 map backgrounds,
|
15
|
+
and associated geocoding configuration data, and a table of US zip codes with their
|
16
|
+
approximate centroids as latitude and longitude. Exposes the ImageMagick image and
|
17
|
+
coordinate conversions so that overlaying labels, lines, and other features on dots
|
18
|
+
is possible. Renders as a blob suitable for e.g. Rails send_data as an img tag src
|
19
|
+
and writes files in any supported ImageMagick graphic format.}
|
20
|
+
|
13
21
|
spec.homepage = "https://github.com/gene-ressler/pippa/wiki"
|
14
|
-
spec.
|
22
|
+
spec.licenses = ["GPL-3.0", "RUC"]
|
15
23
|
|
16
|
-
spec.files = `git ls-files`.split($/)
|
17
|
-
spec.
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
24
|
+
spec.files = `git ls-files`.split($/)
|
25
|
+
spec.test_files = spec.files.grep(%r{^spec/})
|
19
26
|
spec.require_paths = ["lib"]
|
20
27
|
|
21
28
|
# Make work on earlier versions, but this is where testing has been performed.
|
data/spec/data/zipcodes.png
CHANGED
Binary file
|
data/spec/lib/map_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
# Test functions of the Pippa::Map API lightly. Much more possible here.
|
3
4
|
describe Pippa::Map do
|
4
5
|
|
5
6
|
let(:map) { Pippa::Map.zipcode_map }
|
@@ -19,10 +20,6 @@ describe Pippa::Map do
|
|
19
20
|
i[:projection].size.should == 4
|
20
21
|
end
|
21
22
|
|
22
|
-
it 'should have right number of zipcodes' do
|
23
|
-
Pippa::Map.zips.size.should == 41874
|
24
|
-
end
|
25
|
-
|
26
23
|
# Here I'm assuming timestamp metadata chunk always has same size.
|
27
24
|
# PNG docs are encouraging on this:
|
28
25
|
# http://www.libpng.org/pub/png/book/chapter11.html#png.ch11.div.2
|
data/spec/lib/pippa_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
# Test the Pippa API. Much more work possible here.
|
3
4
|
describe Pippa do
|
4
5
|
|
5
6
|
it 'should report version' do
|
@@ -10,4 +11,8 @@ describe Pippa do
|
|
10
11
|
Pippa.map_names.size.should be == 30
|
11
12
|
end
|
12
13
|
|
14
|
+
it 'should have right number of zipcodes' do
|
15
|
+
Pippa.zips.size.should == 41874
|
16
|
+
end
|
17
|
+
|
13
18
|
end
|
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pippa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Gene Ressler
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-30 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -27,6 +30,7 @@ dependencies:
|
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: rake
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ~>
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,6 +38,7 @@ dependencies:
|
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ~>
|
39
44
|
- !ruby/object:Gem::Version
|
@@ -41,6 +46,7 @@ dependencies:
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: rspec
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
51
|
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
@@ -48,6 +54,7 @@ dependencies:
|
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
@@ -55,6 +62,7 @@ dependencies:
|
|
55
62
|
- !ruby/object:Gem::Dependency
|
56
63
|
name: ruby-prof
|
57
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
58
66
|
requirements:
|
59
67
|
- - ~>
|
60
68
|
- !ruby/object:Gem::Version
|
@@ -62,6 +70,7 @@ dependencies:
|
|
62
70
|
type: :development
|
63
71
|
prerelease: false
|
64
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
65
74
|
requirements:
|
66
75
|
- - ~>
|
67
76
|
- !ruby/object:Gem::Version
|
@@ -69,6 +78,7 @@ dependencies:
|
|
69
78
|
- !ruby/object:Gem::Dependency
|
70
79
|
name: rmagick
|
71
80
|
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
72
82
|
requirements:
|
73
83
|
- - ~>
|
74
84
|
- !ruby/object:Gem::Version
|
@@ -76,11 +86,23 @@ dependencies:
|
|
76
86
|
type: :runtime
|
77
87
|
prerelease: false
|
78
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
79
90
|
requirements:
|
80
91
|
- - ~>
|
81
92
|
- !ruby/object:Gem::Version
|
82
93
|
version: '2.13'
|
83
|
-
description: Draw dots on maps by lat/lon or zip code.
|
94
|
+
description: ! 'Draw dots on maps by lat/lon or zip code. Includes a library of 30
|
95
|
+
map backgrounds,
|
96
|
+
|
97
|
+
and associated geocoding configuration data, and a table of US zip codes with their
|
98
|
+
|
99
|
+
approximate centroids as latitude and longitude. Exposes the ImageMagick image and
|
100
|
+
|
101
|
+
coordinate conversions so that overlaying labels, lines, and other features on dots
|
102
|
+
|
103
|
+
is possible. Renders as a blob suitable for e.g. Rails send_data as an img tag src
|
104
|
+
|
105
|
+
and writes files in any supported ImageMagick graphic format.'
|
84
106
|
email:
|
85
107
|
- gene.ressler@gmail.com
|
86
108
|
executables: []
|
@@ -123,6 +145,7 @@ files:
|
|
123
145
|
- lib/pippa/maps/World50-new.png
|
124
146
|
- lib/pippa/maps/_info
|
125
147
|
- lib/pippa/maps/_zipcodes.csv
|
148
|
+
- lib/pippa/maps/_zipcodes.dmp
|
126
149
|
- lib/pippa/version.rb
|
127
150
|
- pippa.gemspec
|
128
151
|
- spec/data/zipcodes.jpg
|
@@ -132,28 +155,30 @@ files:
|
|
132
155
|
- spec/spec_helper.rb
|
133
156
|
homepage: https://github.com/gene-ressler/pippa/wiki
|
134
157
|
licenses:
|
135
|
-
-
|
136
|
-
|
158
|
+
- GPL-3.0
|
159
|
+
- RUC
|
137
160
|
post_install_message:
|
138
161
|
rdoc_options: []
|
139
162
|
require_paths:
|
140
163
|
- lib
|
141
164
|
required_ruby_version: !ruby/object:Gem::Requirement
|
165
|
+
none: false
|
142
166
|
requirements:
|
143
167
|
- - ! '>='
|
144
168
|
- !ruby/object:Gem::Version
|
145
169
|
version: '0'
|
146
170
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
|
+
none: false
|
147
172
|
requirements:
|
148
173
|
- - ! '>='
|
149
174
|
- !ruby/object:Gem::Version
|
150
175
|
version: '0'
|
151
176
|
requirements: []
|
152
177
|
rubyforge_project:
|
153
|
-
rubygems_version:
|
178
|
+
rubygems_version: 1.8.23
|
154
179
|
signing_key:
|
155
|
-
specification_version:
|
156
|
-
summary:
|
180
|
+
specification_version: 3
|
181
|
+
summary: Reimplements some parts of the plot-latlon utility from CAIDA (http://www.caida.org).
|
157
182
|
test_files:
|
158
183
|
- spec/data/zipcodes.jpg
|
159
184
|
- spec/data/zipcodes.png
|
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
ZDg5YjUzMzdjYjMwZTBhZjFhZTlmZDM5OWM5MzgxMzYxNmU0YTdkZA==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NDc1MzEzMTc3MmZkMjRjN2IzMmNlZjM1MzYwZmU4OTlmZDA4NzllYw==
|
7
|
-
!binary "U0hBNTEy":
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
MmY3YTFjMDRmNzMyZjUxNjIwMzU5NTIyY2I5ZjhjYWUyZWE5ZTJkZDg3Yjg5
|
10
|
-
ZDY5YThmZmYyNDAwY2JiZjMyZmJkZGE5MjQ1YzRkOGZiZjMxZTk0ZWI3NTBk
|
11
|
-
ZmY3ZTRhOGI4NTI5NTBjZWNlNDEzNDg4Y2E4MGU2NGMyNGJmZmQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
Y2ZhM2E3YjhmNTUxYmJlNDE2YWQxNTA5YWE3YjgzNzk3MzliYTUzMmI3ZGMw
|
14
|
-
ZTE0M2ZiOGQwOWJiZDJlNjBhN2VjZjRhYzBjZDk1Yzk1YWU1ODFkMTllZDJh
|
15
|
-
NDQxZTgwYWE0MDlmNzBkNDFhZDAyZWM2MDI3Y2U2ZWJjOTQ1NTE=
|