USPS-intelligent-barcode 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.
Files changed (37) hide show
  1. data/Gemfile +9 -0
  2. data/Gemfile.lock +33 -0
  3. data/LICENSE.md +11 -0
  4. data/README.md +56 -0
  5. data/Rakefile +46 -0
  6. data/VERSION +1 -0
  7. data/examples/example.rb +17 -0
  8. data/lib/USPS-intelligent-barcode.rb +5 -0
  9. data/lib/USPS-intelligent-barcode/BarMap.rb +40 -0
  10. data/lib/USPS-intelligent-barcode/BarPosition.rb +26 -0
  11. data/lib/USPS-intelligent-barcode/Barcode.rb +110 -0
  12. data/lib/USPS-intelligent-barcode/BarcodeId.rb +66 -0
  13. data/lib/USPS-intelligent-barcode/CharacterPosition.rb +16 -0
  14. data/lib/USPS-intelligent-barcode/CodewordMap.rb +28 -0
  15. data/lib/USPS-intelligent-barcode/Crc.rb +42 -0
  16. data/lib/USPS-intelligent-barcode/MailerId.rb +70 -0
  17. data/lib/USPS-intelligent-barcode/NumericConversions.rb +13 -0
  18. data/lib/USPS-intelligent-barcode/RoutingCode.rb +77 -0
  19. data/lib/USPS-intelligent-barcode/SerialNumber.rb +61 -0
  20. data/lib/USPS-intelligent-barcode/ServiceType.rb +51 -0
  21. data/lib/USPS-intelligent-barcode/autoload.rb +61 -0
  22. data/lib/USPS-intelligent-barcode/bar_to_character_mapping.yml +66 -0
  23. data/lib/USPS-intelligent-barcode/codeword_to_character_mapping.yml +1366 -0
  24. data/spec/BarMap_spec.rb +30 -0
  25. data/spec/BarPosition_spec.rb +52 -0
  26. data/spec/BarcodeId_spec.rb +118 -0
  27. data/spec/Barcode_spec.rb +213 -0
  28. data/spec/CharacterPosition_spec.rb +25 -0
  29. data/spec/CodewordMap_spec.rb +22 -0
  30. data/spec/Crc_spec.rb +21 -0
  31. data/spec/MailerId_spec.rb +114 -0
  32. data/spec/NumericConversions_spec.rb +23 -0
  33. data/spec/RoutingCode_spec.rb +180 -0
  34. data/spec/SerialNumber_spec.rb +117 -0
  35. data/spec/ServiceType_spec.rb +93 -0
  36. data/spec/spec_helper.rb +1 -0
  37. metadata +160 -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(:barcode) 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
+ bar_map.barcode(characters).should == barcode
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,52 @@
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(:characters) {mock 'array of characters'}
10
+ let(:descender_character_position) {mock CharacterPosition}
11
+ let(:ascender_character_position) {mock CharacterPosition}
12
+ let(:bar_position) do
13
+ BarPosition.new(descender_character_position,
14
+ ascender_character_position)
15
+ end
16
+
17
+ before(:each) do
18
+ descender_character_position.stub(:extract_bit_from_characters)\
19
+ .with(characters).and_return(descender_bit)
20
+ ascender_character_position.stub(:extract_bit_from_characters)\
21
+ .with(characters).and_return(ascender_bit)
22
+ end
23
+
24
+ context 'without ascender, without descender' do
25
+ let(:ascender_bit) {0}
26
+ let(:descender_bit) {0}
27
+ specify {bar_position.map(characters).should == 0}
28
+ end
29
+
30
+ context 'without ascender, with descender' do
31
+ let(:ascender_bit) {0}
32
+ let(:descender_bit) {1}
33
+ specify {bar_position.map(characters).should == 1}
34
+ end
35
+
36
+ context 'with ascender, without descender' do
37
+ let(:ascender_bit) {1}
38
+ let(:descender_bit) {0}
39
+ specify {bar_position.map(characters).should == 2}
40
+ end
41
+
42
+ context 'with ascender, with descender' do
43
+ let(:ascender_bit) {1}
44
+ let(:descender_bit) {1}
45
+ specify {bar_position.map(characters).should == 3}
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,118 @@
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 {o1.should == o1}
49
+ specify {o1.should == o2}
50
+ specify {o1.should_not == o3}
51
+ specify {o1.should_not == o4}
52
+ end
53
+
54
+ describe '#most_significant_digit' do
55
+ specify do
56
+ BarcodeId.new(12).most_significant_digit.should == 1
57
+ end
58
+ end
59
+
60
+ describe '#least_significant_digit' do
61
+ specify do
62
+ BarcodeId.new(12).least_significant_digit.should == 2
63
+ end
64
+ end
65
+
66
+ describe '#validate' do
67
+
68
+ let(:long_mailer_id?) {mock 'long_mailer_id?'}
69
+
70
+ def validate(value)
71
+ BarcodeId.new(value).validate(long_mailer_id?)
72
+ end
73
+
74
+ def self.is_valid(value)
75
+ context "#{value}" do
76
+ specify {validate(value)}
77
+ end
78
+ end
79
+
80
+ def self.is_out_of_range(value)
81
+ context "#{value}" do
82
+ specify do
83
+ expect {
84
+ validate(value)
85
+ }.to raise_error ArgumentError, 'Must be 0..94'
86
+ end
87
+ end
88
+ end
89
+
90
+ def self.has_bad_least_significant_digit(value)
91
+ context "#{value}" do
92
+ specify do
93
+ expect {
94
+ validate(value)
95
+ }.to raise_error(ArgumentError,
96
+ 'Least significant digit must be 0..4')
97
+ end
98
+ end
99
+ end
100
+
101
+ is_out_of_range -1
102
+ is_valid 0
103
+ is_valid 4
104
+ has_bad_least_significant_digit 5
105
+ is_valid 94
106
+ is_out_of_range 95
107
+
108
+ end
109
+
110
+ describe '#shift_and_add_to' do
111
+ let(:barcode_id) {BarcodeId.new(12)}
112
+ let(:long_mailer_id?) {mock 'long mailer id'}
113
+ specify {barcode_id.shift_and_add_to(1, long_mailer_id?).should == 57}
114
+ end
115
+
116
+ end
117
+
118
+ 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 {extract(0, 0).should == 1}
17
+ specify {extract(0, 1).should == 0}
18
+ specify {extract(1, 0).should == 0}
19
+ specify {extract(1, 1).should == 1}
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ module Imb
4
+
5
+ describe CodewordMap do
6
+
7
+ let(:characters) do
8
+ [
9
+ 0x001F, 0x001F, 0x001F, 0x001F, 0x1524,
10
+ 0x01A3, 0x043C, 0x1838, 0x012B, 0x0076,
11
+ ]
12
+ end
13
+ let(:codewords) {[0, 0, 0, 0, 559, 202, 508, 451, 124, 34]}
14
+ let(:codeword_map) {CodewordMap.new}
15
+
16
+ specify do
17
+ codeword_map.characters(codewords).should == characters
18
+ end
19
+
20
+ end
21
+
22
+ end