usps_intelligent_barcode 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +8 -0
  3. data/CHANGELOG.markdown +67 -0
  4. data/Gemfile +13 -0
  5. data/Gemfile.lock +90 -0
  6. data/LICENSE.md +11 -0
  7. data/README.markdown +64 -0
  8. data/Rakefile +40 -0
  9. data/VERSION +1 -0
  10. data/examples/example.rb +17 -0
  11. data/lib/USPS-intelligent-barcode.rb +17 -0
  12. data/lib/USPS-intelligent-barcode/bar_map.rb +52 -0
  13. data/lib/USPS-intelligent-barcode/bar_position.rb +40 -0
  14. data/lib/USPS-intelligent-barcode/bar_symbol.rb +49 -0
  15. data/lib/USPS-intelligent-barcode/bar_to_character_mapping.yml +66 -0
  16. data/lib/USPS-intelligent-barcode/barcode.rb +152 -0
  17. data/lib/USPS-intelligent-barcode/barcode_id.rb +98 -0
  18. data/lib/USPS-intelligent-barcode/character_position.rb +28 -0
  19. data/lib/USPS-intelligent-barcode/codeword_map.rb +38 -0
  20. data/lib/USPS-intelligent-barcode/codeword_to_character_mapping.yml +1366 -0
  21. data/lib/USPS-intelligent-barcode/crc.rb +52 -0
  22. data/lib/USPS-intelligent-barcode/mailer_id.rb +105 -0
  23. data/lib/USPS-intelligent-barcode/numeric_conversions.rb +22 -0
  24. data/lib/USPS-intelligent-barcode/routing_code.rb +134 -0
  25. data/lib/USPS-intelligent-barcode/serial_number.rb +88 -0
  26. data/lib/USPS-intelligent-barcode/service_type.rb +79 -0
  27. data/lib/usps_intelligent_barcode.rb +17 -0
  28. data/lib/usps_intelligent_barcode/bar_map.rb +52 -0
  29. data/lib/usps_intelligent_barcode/bar_position.rb +40 -0
  30. data/lib/usps_intelligent_barcode/bar_symbol.rb +49 -0
  31. data/lib/usps_intelligent_barcode/bar_to_character_mapping.yml +66 -0
  32. data/lib/usps_intelligent_barcode/barcode.rb +152 -0
  33. data/lib/usps_intelligent_barcode/barcode_id.rb +98 -0
  34. data/lib/usps_intelligent_barcode/character_position.rb +28 -0
  35. data/lib/usps_intelligent_barcode/codeword_map.rb +38 -0
  36. data/lib/usps_intelligent_barcode/codeword_to_character_mapping.yml +1366 -0
  37. data/lib/usps_intelligent_barcode/crc.rb +52 -0
  38. data/lib/usps_intelligent_barcode/mailer_id.rb +105 -0
  39. data/lib/usps_intelligent_barcode/numeric_conversions.rb +22 -0
  40. data/lib/usps_intelligent_barcode/routing_code.rb +134 -0
  41. data/lib/usps_intelligent_barcode/serial_number.rb +88 -0
  42. data/lib/usps_intelligent_barcode/service_type.rb +79 -0
  43. data/spec/bar_map_spec.rb +30 -0
  44. data/spec/bar_position_spec.rb +40 -0
  45. data/spec/bar_symbol_spec.rb +39 -0
  46. data/spec/barcode_id_spec.rb +106 -0
  47. data/spec/barcode_spec.rb +213 -0
  48. data/spec/character_position_spec.rb +25 -0
  49. data/spec/codeword_map_spec.rb +22 -0
  50. data/spec/crc_spec.rb +21 -0
  51. data/spec/mailer_id_spec.rb +124 -0
  52. data/spec/numeric_conversions_spec.rb +23 -0
  53. data/spec/routing_code_spec.rb +180 -0
  54. data/spec/serial_number_spec.rb +117 -0
  55. data/spec/service_type_spec.rb +93 -0
  56. data/spec/spec_helper.rb +8 -0
  57. data/usps_intelligent_barcode.gemspec +117 -0
  58. metadata +216 -0
@@ -0,0 +1,30 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ module Imb
4
+
5
+ describe BarMap do
6
+
7
+ let(:characters) do
8
+ [
9
+ 0x1FE0, 0x001F, 0x001F, 0x001F, 0x0ADB,
10
+ 0x01A3, 0x1BC3, 0x1838, 0x012B, 0x0076,
11
+ ]
12
+ end
13
+ let(:codes) do
14
+ [
15
+ 2, 0, 0, 3, 2, 0, 0, 1, 0, 0, 2, 1, 0,
16
+ 2, 2, 0, 0, 1, 0, 1, 0, 2, 0, 0, 1, 2,
17
+ 3, 1, 1, 3, 2, 1, 3, 1, 3, 0, 3, 3, 3,
18
+ 3, 3, 0, 2, 0, 3, 2, 2, 2, 2, 0, 1, 3,
19
+ 3, 0, 1, 2, 2, 1, 3, 0, 3, 1, 0, 1, 0,
20
+ ]
21
+ end
22
+ let(:bar_map) {BarMap.new}
23
+
24
+ specify do
25
+ expect(bar_map.symbols(characters).map(&:code)).to eq(codes)
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ module Imb
4
+
5
+ describe BarPosition do
6
+
7
+ describe '#map' do
8
+
9
+ let(:ascender_bit) {double 'ascender bit'}
10
+ let(:descender_bit) {double 'descender bit'}
11
+ let(:characters) {double 'array of characters'}
12
+ let(:descender_character_position) {double CharacterPosition}
13
+ let(:ascender_character_position) {double CharacterPosition}
14
+ let(:bar_position) do
15
+ BarPosition.new(descender_character_position,
16
+ ascender_character_position)
17
+ end
18
+ let(:bar_symbol) {double BarSymbol}
19
+
20
+ before(:each) do
21
+ allow(descender_character_position).to receive(:extract_bit_from_characters)\
22
+ .with(characters)\
23
+ .and_return(descender_bit)
24
+ allow(ascender_character_position).to receive(:extract_bit_from_characters)\
25
+ .with(characters)\
26
+ .and_return(ascender_bit)
27
+ allow(BarSymbol).to receive(:make)\
28
+ .with(ascender_bit, descender_bit)\
29
+ .and_return(bar_symbol)
30
+ end
31
+
32
+ specify do
33
+ expect(bar_position.map(characters)).to eq(bar_symbol)
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ module Imb
4
+
5
+ describe BarSymbol do
6
+
7
+ subject {BarSymbol.make(ascender_bit, descender_bit)}
8
+
9
+ context 'tracker' do
10
+ let(:ascender_bit) {0}
11
+ let(:descender_bit) {0}
12
+ its(:code) {should eq 0}
13
+ its(:letter) {should eq 'T'}
14
+ end
15
+
16
+ context 'descender' do
17
+ let(:ascender_bit) {0}
18
+ let(:descender_bit) {1}
19
+ its(:code) {should eq 1}
20
+ its(:letter) {should eq 'D'}
21
+ end
22
+
23
+ context 'ascender' do
24
+ let(:ascender_bit) {1}
25
+ let(:descender_bit) {0}
26
+ its(:code) {should eq 2}
27
+ its(:letter) {should eq 'A'}
28
+ end
29
+
30
+ context 'full' do
31
+ let(:ascender_bit) {1}
32
+ let(:descender_bit) {1}
33
+ its(:code) {should eq 3}
34
+ its(:letter) {should eq 'F'}
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,106 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ module Imb
4
+
5
+ describe BarcodeId do
6
+
7
+ describe '::coerce' do
8
+
9
+ subject {BarcodeId.coerce(o)}
10
+
11
+ context 'BarcodeId' do
12
+ let(:o) {BarcodeId.new(12)}
13
+ its(:to_i) {should == 12}
14
+ end
15
+
16
+ context 'String' do
17
+ let(:o) {'12'}
18
+ its(:to_i) {should == 12}
19
+ end
20
+
21
+ context 'Integer' do
22
+ let(:o) {12}
23
+ its(:to_i) {should == 12}
24
+ end
25
+
26
+ context 'unknown' do
27
+ let(:o) {Object.new}
28
+ specify do
29
+ expect {
30
+ BarcodeId.coerce(o)
31
+ }.to raise_error ArgumentError, 'Cannot coerce to BarcodeId'
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ describe '#to_i' do
38
+ let(:value) {23}
39
+ subject {BarcodeId.new(value)}
40
+ its(:to_i) {should == value}
41
+ end
42
+
43
+ describe '#=' do
44
+ def o1 ; BarcodeId.new(1) ; end
45
+ def o2 ; 1 ; end
46
+ def o3 ; BarcodeId.new(2) ; end
47
+ def o4 ; Object.new ; end
48
+ specify {expect(o1).to eq(o1)}
49
+ specify {expect(o1).to eq(o2)}
50
+ specify {expect(o1).not_to eq(o3)}
51
+ specify {expect(o1).not_to eq(o4)}
52
+ end
53
+
54
+ describe '#validate' do
55
+
56
+ let(:long_mailer_id?) {double 'long_mailer_id?'}
57
+
58
+ def validate(value)
59
+ BarcodeId.new(value).validate(long_mailer_id?)
60
+ end
61
+
62
+ def self.is_valid(value)
63
+ context "#{value}" do
64
+ specify {validate(value)}
65
+ end
66
+ end
67
+
68
+ def self.is_out_of_range(value)
69
+ context "#{value}" do
70
+ specify do
71
+ expect {
72
+ validate(value)
73
+ }.to raise_error ArgumentError, 'Must be 0..94'
74
+ end
75
+ end
76
+ end
77
+
78
+ def self.has_bad_least_significant_digit(value)
79
+ context "#{value}" do
80
+ specify do
81
+ expect {
82
+ validate(value)
83
+ }.to raise_error(ArgumentError,
84
+ 'Least significant digit must be 0..4')
85
+ end
86
+ end
87
+ end
88
+
89
+ is_out_of_range -1
90
+ is_valid 0
91
+ is_valid 4
92
+ has_bad_least_significant_digit 5
93
+ is_valid 94
94
+ is_out_of_range 95
95
+
96
+ end
97
+
98
+ describe '#shift_and_add_to' do
99
+ let(:barcode_id) {BarcodeId.new(12)}
100
+ let(:long_mailer_id?) {double 'long mailer id'}
101
+ specify {expect(barcode_id.shift_and_add_to(1, long_mailer_id?)).to eq(57)}
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,213 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ module Imb
4
+
5
+ describe Barcode do
6
+
7
+ let(:barcode) do
8
+ Barcode.new(barcode_id,
9
+ service_type,
10
+ mailer_id,
11
+ serial_number,
12
+ routing_code)
13
+ end
14
+ subject {barcode}
15
+
16
+ describe 'Examples from USPS-B-3200 rev. G, Appendix B' do
17
+
18
+ describe '#1' do
19
+
20
+ let(:barcode_id) {'01'}
21
+ let(:service_type) {'234'}
22
+ let(:mailer_id) {'567094'}
23
+ let(:serial_number) {'987654321'}
24
+ let(:routing_code) {nil}
25
+
26
+ its(:binary_data) {should == 0x00000000001122103B5C2004B1}
27
+ its(:frame_check_sequence) {should == 0x051}
28
+ its(:codewords) do
29
+ should == [0, 0, 0, 0, 559, 202, 508, 451, 124, 17]
30
+ end
31
+ its(:codewords_with_orientation_in_character_j) do
32
+ should == [0, 0, 0, 0, 559, 202, 508, 451, 124, 34]
33
+ end
34
+ its(:codewords_with_fcs_bit_in_character_a) do
35
+ should == [0, 0, 0, 0, 559, 202, 508, 451, 124, 34]
36
+ end
37
+ its(:characters) do
38
+ should == [
39
+ 0x001F, 0x001F, 0x001F, 0x001F, 0x1524,
40
+ 0x01A3, 0x043C, 0x1838, 0x012B, 0x0076,
41
+ ]
42
+ end
43
+ its(:characters_with_fcs_bits_0_through_9) do
44
+ should == [
45
+ 0x1FE0, 0x001F, 0x001F, 0x001F, 0x0ADB,
46
+ 0x01A3, 0x1BC3, 0x1838, 0x012B, 0x0076,
47
+ ]
48
+ end
49
+ its(:barcode_letters) do
50
+ should == ('ATTFATTDTTADTAATTDTDTATTDAFDDFADF'\
51
+ 'DFTFFFFFTATFAAAATDFFTDAADFTFDTDT')
52
+ end
53
+
54
+ end
55
+
56
+ describe '#2' do
57
+
58
+ let(:barcode_id) {'01'}
59
+ let(:service_type) {'234'}
60
+ let(:mailer_id) {'567094'}
61
+ let(:serial_number) {'987654321'}
62
+ let(:routing_code) {'01234'}
63
+
64
+ its(:binary_data) {should == 0x0000000D138A87BAB5CF3804B1}
65
+ its(:frame_check_sequence) {should == 0x065}
66
+ its(:codewords) do
67
+ should == [0, 0, 15, 14, 290, 567, 385, 48, 388, 333]
68
+ end
69
+ its(:codewords_with_orientation_in_character_j) do
70
+ should == [0, 0, 15, 14, 290, 567, 385, 48, 388, 666]
71
+ end
72
+ its(:codewords_with_fcs_bit_in_character_a) do
73
+ should == [0, 0, 15, 14, 290, 567, 385, 48, 388, 666]
74
+ end
75
+ its(:characters) do
76
+ should == [
77
+ 0x001F, 0x001F, 0x1D40, 0x0057, 0x0255,
78
+ 0x0724, 0x04E8, 0x009D, 0x030B, 0x0583,
79
+ ]
80
+ end
81
+ its(:characters_with_fcs_bits_0_through_9) do
82
+ should == [
83
+ 0x1FE0, 0x001F, 0x02BF, 0x0057, 0x0255,
84
+ 0x18DB, 0x1B17, 0x009D, 0x030B, 0x0583,
85
+ ]
86
+ end
87
+ its(:barcode_letters) do
88
+ should == ('DTTAFADDTTFTDTFTFDTDDADADAFADFATD'\
89
+ 'DFTAAAFDTTADFAAATDFDTDFADDDTDFFT')
90
+ end
91
+
92
+ end
93
+
94
+ describe '#3' do
95
+
96
+ let(:barcode_id) {'01'}
97
+ let(:service_type) {'234'}
98
+ let(:mailer_id) {'567094'}
99
+ let(:serial_number) {'987654321'}
100
+ let(:routing_code) {'012345678'}
101
+
102
+ its(:binary_data) {should == 0x000202BDC097711204D21804B1}
103
+ its(:frame_check_sequence) {should == 0x606}
104
+ its(:codewords) do
105
+ should == [0, 110, 1113, 1363, 198, 413, 470, 468, 1333, 513]
106
+ end
107
+ its(:codewords_with_orientation_in_character_j) do
108
+ should == [0, 110, 1113, 1363, 198, 413, 470, 468, 1333, 1026]
109
+ end
110
+ its(:codewords_with_fcs_bit_in_character_a) do
111
+ should == [659, 110, 1113, 1363, 198, 413, 470, 468, 1333, 1026]
112
+ end
113
+ its(:characters) do
114
+ should == [
115
+ 0x1154, 0x00F8, 0x1E01, 0x0110, 0x019A,
116
+ 0x1298, 0x03A2, 0x03A1, 0x0084, 0x0B11,
117
+ ]
118
+ end
119
+ its(:characters_with_fcs_bits_0_through_9) do
120
+ should == [
121
+ 0x1154, 0x1F07, 0x01FE, 0x0110, 0x019A,
122
+ 0x1298, 0x03A2, 0x03A1, 0x0084, 0x14EE,
123
+ ]
124
+ end
125
+ its(:barcode_letters) do
126
+ should == ('ADFTTAFDTTTTFATTADTAAATFTFTATDAAA'\
127
+ 'FDDADATATDTDTTDFDTDATADADTDFFTFA')
128
+ end
129
+
130
+ end
131
+
132
+ describe '#4' do
133
+
134
+ let(:barcode_id) {'01'}
135
+ let(:service_type) {'234'}
136
+ let(:mailer_id) {'567094'}
137
+ let(:serial_number) {'987654321'}
138
+ let(:routing_code) {'01234567891'}
139
+
140
+ its(:binary_data) {should == 0x016907B2A24ABC16A2E5C004B1}
141
+ its(:frame_check_sequence) {should == 0x751}
142
+ its(:codewords) do
143
+ should == [14, 787, 607, 1022, 861, 19, 816, 1294, 35, 301]
144
+ end
145
+ its(:codewords_with_orientation_in_character_j) do
146
+ should == [14, 787, 607, 1022, 861, 19, 816, 1294, 35, 602]
147
+ end
148
+ its(:codewords_with_fcs_bit_in_character_a) do
149
+ should == [673, 787, 607, 1022, 861, 19, 816, 1294, 35, 602]
150
+ end
151
+ its(:characters) do
152
+ should == [
153
+ 0x1234, 0x085C, 0x08E4, 0x0B06, 0x1922,
154
+ 0x1740, 0x0839, 0x1200, 0x0DC0, 0x04D4,
155
+ ]
156
+ end
157
+ its(:characters_with_fcs_bits_0_through_9) do
158
+ should == [
159
+ 0x0DCB, 0x085C, 0x08E4, 0x0B06, 0x06DD,
160
+ 0x1740, 0x17C6, 0x1200, 0x123F, 0x1B2B,
161
+ ]
162
+ end
163
+ its(:barcode_letters) do
164
+ should == ('AADTFFDFTDADTAADAATFDTDDAAADDTDTT'\
165
+ 'DAFADADDDTFFFDDTTTADFAAADFTDAADA')
166
+ end
167
+
168
+ end
169
+
170
+ end
171
+
172
+ describe '#accessors' do
173
+
174
+ let(:barcode) do
175
+ Barcode.new(barcode_id,
176
+ service_type,
177
+ mailer_id,
178
+ serial_number,
179
+ routing_code)
180
+ end
181
+ subject {barcode}
182
+
183
+ context 'when constructed with strings' do
184
+ let(:barcode_id) {'01'}
185
+ let(:service_type) {'234'}
186
+ let(:mailer_id) {'567094'}
187
+ let(:serial_number) {'987654321'}
188
+ let(:routing_code) {'98765432109'}
189
+ its(:barcode_id) {should == 1}
190
+ its(:service_type) {should == 234}
191
+ its(:mailer_id) {should == 567094}
192
+ its(:serial_number) {should == 987654321}
193
+ its(:routing_code) {should == RoutingCode.new(98765, 4321, 9)}
194
+ end
195
+
196
+ context 'when constructed with integers' do
197
+ let(:barcode_id) {01}
198
+ let(:service_type) {234}
199
+ let(:mailer_id) {567094}
200
+ let(:serial_number) {987654321}
201
+ let(:routing_code) {[98765, 4321, 9]}
202
+ its(:barcode_id) {should == 1}
203
+ its(:service_type) {should == 234}
204
+ its(:mailer_id) {should == 567094}
205
+ its(:serial_number) {should == 987654321}
206
+ its(:routing_code) {should == RoutingCode.new(98765, 4321, 9)}
207
+ end
208
+
209
+ end
210
+
211
+ end
212
+
213
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ module Imb
4
+
5
+ describe CharacterPosition do
6
+
7
+ describe '#extract_bit_from_characters' do
8
+
9
+ let(:characters) {[1, 2]}
10
+
11
+ def extract(character_index, bit_number)
12
+ CharacterPosition.new(character_index, bit_number)\
13
+ .extract_bit_from_characters(characters)
14
+ end
15
+
16
+ specify {expect(extract(0, 0)).to eq(1)}
17
+ specify {expect(extract(0, 1)).to eq(0)}
18
+ specify {expect(extract(1, 0)).to eq(0)}
19
+ specify {expect(extract(1, 1)).to eq(1)}
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end