australia_postcode 0.1.0

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.
@@ -0,0 +1,124 @@
1
+ # coding: utf-8
2
+ require "csv"
3
+ require "australia/postcode/version"
4
+
5
+ # A module for all things Australian
6
+ module Australia
7
+ # The Australia::Postcode class represents Australian postcodes and provides
8
+ # methods for manipulating them. Right now you can find the distance between
9
+ # two postcodes and that's about it.
10
+ class Postcode
11
+ attr_reader :postcode, :suburb, :state, :delivery_center, :type, :latitude, :longitude
12
+
13
+ def initialize(postcode, suburb, state, delivery_center, type, latitude, longitude)
14
+ @postcode = postcode.to_i
15
+ @suburb = suburb.strip
16
+ @state = state.strip
17
+ @delivery_center = delivery_center.strip
18
+ @type = type.strip
19
+ @latitude = latitude.to_f
20
+ @longitude = longitude.to_f
21
+ end
22
+
23
+ # Returns a [latitude, longitude] tuple
24
+ #
25
+ # @return [Array]
26
+ def coords
27
+ [latitude, longitude]
28
+ end
29
+
30
+ # Computes the distance from this postcode to another postcode using the
31
+ # Haversine formula
32
+ #
33
+ # @return [Float]
34
+ def distance(other)
35
+ earth_radius = 6371
36
+ Δlat = radians(other.latitude - latitude)
37
+ Δlong = radians(other.longitude - longitude)
38
+ a = sin(Δlat / 2) * sin(Δlat / 2) +
39
+ cos(radians(latitude)) * cos(radians(other.latitude)) *
40
+ sin(Δlong / 2) * sin(Δlong / 2)
41
+ c = 2 * atan2(√(a), √(1 - a))
42
+ earth_radius * c
43
+ end
44
+
45
+ alias_method :-, :distance
46
+
47
+ # Inspects the [Postcode]
48
+ def inspect
49
+ "#<#{self.class} postcode=#{postcode.inspect} suburb=#{suburb.inspect} latitude=#{latitude.inspect} longitude=#{longitude.inspect}>"
50
+ end
51
+
52
+ private
53
+
54
+ def sin(θ)
55
+ Math.sin θ
56
+ end
57
+
58
+ def cos(θ)
59
+ Math.sin θ
60
+ end
61
+
62
+ def atan2(y, x)
63
+ Math.atan2 y, x
64
+ end
65
+
66
+ def √(x)
67
+ Math.sqrt x
68
+ end
69
+
70
+ def radians(degrees)
71
+ degrees * π / 180
72
+ end
73
+
74
+ def π
75
+ Math::PI
76
+ end
77
+
78
+ class << self
79
+ # Finds all postcodes/suburbs for the given postcode.
80
+ #
81
+ # @return [Array[Postcode]]
82
+ def find(postcode)
83
+ indexed_on_postcode[postcode.to_i]
84
+ end
85
+
86
+ # Finds all the postcodes/suburbs for the given suburb name.
87
+ #
88
+ # @return [Array[Postcode]]
89
+ def find_by_suburb(suburb)
90
+ indexed_on_suburb[suburb.strip.upcase]
91
+ end
92
+
93
+ # Finds the closest postcode to the given coordinates
94
+ #
95
+ # @return [Postcode]
96
+ def find_by_coords(latitude, longitude)
97
+ data.min_by { |postcode|
98
+ (latitude - postcode.latitude) ** 2 + (longitude - postcode.longitude) ** 2
99
+ }
100
+ end
101
+
102
+ private
103
+ def indexed_on_postcode
104
+ @indexed_on_postcode ||= data.group_by(&:postcode)
105
+ end
106
+
107
+ def indexed_on_suburb
108
+ @indexed_on_suburb ||= data.group_by(&:suburb)
109
+ end
110
+
111
+ def data
112
+ @data ||= raw_data.map { |data| new(*data) }
113
+ end
114
+
115
+ def raw_data
116
+ CSV.parse(File.read(data_filename)).drop(1)
117
+ end
118
+
119
+ def data_filename
120
+ File.expand_path("../postcode/data.csv", __FILE__)
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1 @@
1
+ require "australia/postcode"
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: australia_postcode
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Charlie Somerville
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: yard
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Library for manipulating Australian postcodes
31
+ email: charlie@charliesomerville.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/australia_postcode.rb
37
+ - lib/australia/postcode.rb
38
+ - lib/australia/postcode/data.csv
39
+ homepage: https://github.com/charliesome/australia_postcode
40
+ licenses: []
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 1.8.24
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Manipulates Australian postcodes
63
+ test_files: []
64
+ has_rdoc: