usps_intelligent_barcode 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,40 +0,0 @@
1
- module Imb
2
-
3
- # @!group Internal
4
-
5
- # Represents a position (one line) in the barcode. This class is
6
- # internal and may change.
7
-
8
- class BarPosition
9
-
10
- # @param [CharacterPosition] descender_character_position
11
- # @param [CharacterPosition] ascender_character_position
12
-
13
- def initialize(descender_character_position, ascender_character_position)
14
- @descender_character_position = descender_character_position
15
- @ascender_character_position = ascender_character_position
16
- end
17
-
18
- # Given an array of characters, return a symbol for this
19
- # barcode position.
20
- # @param [[Integer]] characters character codes
21
- # @return [BarSymbol] symbol code
22
-
23
- def map(characters)
24
- BarSymbol.make(ascender_bit(characters),
25
- descender_bit(characters))
26
- end
27
-
28
- private
29
-
30
- def descender_bit(characters)
31
- @descender_character_position.extract_bit_from_characters(characters)
32
- end
33
-
34
- def ascender_bit(characters)
35
- @ascender_character_position.extract_bit_from_characters(characters)
36
- end
37
-
38
- end
39
-
40
- end
@@ -1,49 +0,0 @@
1
- module Imb
2
-
3
- # @!group Internal
4
-
5
- # Represents a symbol in the barcode.
6
-
7
- class BarSymbol
8
-
9
- # @param [Integer] ascender_bit (0..1)
10
- # @param [Integer] descender_bit (0..1)
11
- # @return [BarSymbol]
12
-
13
- def self.make(ascender_bit, descender_bit)
14
- case [ascender_bit, descender_bit]
15
- when [0, 0]
16
- TRACKER
17
- when [0, 1]
18
- DESCENDER
19
- when [1, 0]
20
- ASCENDER
21
- when [1, 1]
22
- FULL
23
- end
24
- end
25
-
26
- # @return [Integer] the code for this symbol
27
- attr_reader :code
28
-
29
- # @return [String] the letter for this symbol
30
- attr_reader :letter
31
-
32
- # @param [Integer] code (0..3)
33
- # @param [String] letter
34
-
35
- def initialize(code, letter)
36
- @code = code
37
- @letter = letter
38
- end
39
-
40
- private
41
-
42
- TRACKER = BarSymbol.new(0, 'T')
43
- DESCENDER = BarSymbol.new(1, 'D')
44
- ASCENDER = BarSymbol.new(2, 'A')
45
- FULL = BarSymbol.new(3, 'F')
46
-
47
- end
48
-
49
- end
@@ -1,66 +0,0 @@
1
- ---
2
- - [[7, 2], [4, 3]]
3
- - [[1, 10], [0, 0]]
4
- - [[9, 12], [2, 8]]
5
- - [[5, 5], [6, 11]]
6
- - [[8, 9], [3, 1]]
7
- - [[0, 1], [5, 12]]
8
- - [[2, 5], [1, 8]]
9
- - [[4, 4], [9, 11]]
10
- - [[6, 3], [8, 10]]
11
- - [[3, 9], [7, 6]]
12
- - [[5, 11], [1, 4]]
13
- - [[8, 5], [2, 12]]
14
- - [[9, 10], [0, 2]]
15
- - [[7, 1], [6, 7]]
16
- - [[3, 6], [4, 9]]
17
- - [[0, 3], [8, 6]]
18
- - [[6, 4], [2, 7]]
19
- - [[1, 1], [9, 9]]
20
- - [[7, 10], [5, 2]]
21
- - [[4, 0], [3, 8]]
22
- - [[6, 2], [0, 4]]
23
- - [[8, 11], [1, 0]]
24
- - [[9, 8], [3, 12]]
25
- - [[2, 6], [7, 7]]
26
- - [[5, 1], [4, 10]]
27
- - [[1, 12], [6, 9]]
28
- - [[7, 3], [8, 0]]
29
- - [[5, 8], [9, 7]]
30
- - [[4, 6], [2, 10]]
31
- - [[3, 4], [0, 5]]
32
- - [[8, 4], [5, 7]]
33
- - [[7, 11], [1, 9]]
34
- - [[6, 0], [9, 6]]
35
- - [[0, 6], [4, 8]]
36
- - [[2, 1], [3, 2]]
37
- - [[5, 9], [8, 12]]
38
- - [[4, 11], [6, 1]]
39
- - [[9, 5], [7, 4]]
40
- - [[3, 3], [1, 2]]
41
- - [[0, 7], [2, 0]]
42
- - [[1, 3], [4, 1]]
43
- - [[6, 10], [3, 5]]
44
- - [[8, 7], [9, 4]]
45
- - [[2, 11], [5, 6]]
46
- - [[0, 8], [7, 12]]
47
- - [[4, 2], [8, 1]]
48
- - [[5, 10], [3, 0]]
49
- - [[9, 3], [0, 9]]
50
- - [[6, 5], [2, 4]]
51
- - [[7, 8], [1, 7]]
52
- - [[5, 0], [4, 5]]
53
- - [[2, 3], [0, 10]]
54
- - [[6, 12], [9, 2]]
55
- - [[3, 11], [1, 6]]
56
- - [[8, 8], [7, 9]]
57
- - [[5, 4], [0, 11]]
58
- - [[1, 5], [2, 2]]
59
- - [[9, 1], [4, 12]]
60
- - [[8, 3], [6, 6]]
61
- - [[7, 0], [3, 7]]
62
- - [[4, 7], [7, 5]]
63
- - [[0, 12], [1, 11]]
64
- - [[2, 9], [9, 0]]
65
- - [[6, 8], [5, 3]]
66
- - [[3, 10], [8, 2]]
@@ -1,152 +0,0 @@
1
- require 'USPS-intelligent-barcode/codeword_map'
2
- require 'USPS-intelligent-barcode/crc'
3
-
4
- # The namespace for everything in this library.
5
-
6
- module Imb
7
-
8
- # This class represents a barcode.
9
-
10
- class Barcode
11
-
12
- include Memoizer
13
-
14
- # @return [BarcodeId]
15
- attr_reader :barcode_id
16
-
17
- # @return [ServiceType]
18
- attr_reader :service_type
19
-
20
- # @return [MailerId]
21
- attr_reader :mailer_id
22
-
23
- # @return [SerialNumber]
24
- attr_reader :serial_number
25
-
26
- # @return [RoutingCode]
27
- attr_reader :routing_code
28
-
29
- # @param
30
-
31
- # Create a new barcode
32
- #
33
- # @param barcode_id [String] Nominally a String, but can be
34
- # anything that {BarcodeId.coerce} will accept.
35
- # @param service_type [String] Nominally a String, but can be
36
- # anything that {ServiceType.coerce} will accept.
37
- # @param mailer_id [String] Nominally a String, but can be
38
- # anything that {MailerId.coerce} will accept.
39
- # @param serial_number [String] Nominally a String, but can be
40
- # anything that {SerialNumber.coerce} will accept.
41
- # @param routing_code [String] Nominally a String, but can be
42
- # anything that {RoutingCode.coerce} will accept.
43
-
44
- def initialize(barcode_id,
45
- service_type,
46
- mailer_id,
47
- serial_number,
48
- routing_code)
49
- @barcode_id = BarcodeId.coerce(barcode_id)
50
- @service_type = ServiceType.coerce(service_type)
51
- @mailer_id = MailerId.coerce(mailer_id)
52
- @serial_number = SerialNumber.coerce(serial_number)
53
- @routing_code = RoutingCode.coerce(routing_code)
54
- validate_components
55
- end
56
-
57
- # Return a string to print using one of the USPS Intelligent Mail
58
- # Barcode fonts. Each character of the string will be one of:
59
- # * 'T' for a tracking mark (neither ascender nor descender)
60
- # * 'A' for an ascender mark
61
- # * 'D' for a descender mark
62
- # * 'F' for a full mark (both ascender and descender)
63
- # @return [String] A string that represents the barcode.
64
-
65
- def barcode_letters
66
- symbols.map(&:letter).join
67
- end
68
-
69
- private
70
-
71
- # :stopdoc:
72
- BAR_MAP = BarMap.new
73
- CODEWORD_MAP = CodewordMap.new
74
- CRC = Crc.new
75
- # :startdoc:
76
-
77
- def validate_components
78
- components.each do |component|
79
- component.validate(long_mailer_id?)
80
- end
81
- end
82
-
83
- def components
84
- [
85
- @routing_code,
86
- @barcode_id,
87
- @service_type,
88
- @mailer_id,
89
- @serial_number,
90
- ]
91
- end
92
-
93
- def long_mailer_id?
94
- @mailer_id.long?
95
- end
96
-
97
- def binary_data
98
- components.inject(0) do |data, component|
99
- component.shift_and_add_to(data, long_mailer_id?)
100
- end
101
- end
102
- memoize :binary_data
103
-
104
- def frame_check_sequence
105
- CRC.crc(binary_data)
106
- end
107
- memoize :frame_check_sequence
108
-
109
- def codewords
110
- codewords = []
111
- data = binary_data
112
- data, codewords[9] = data.divmod 636
113
- 8.downto(0) do |i|
114
- data, codewords[i] = data.divmod 1365
115
- end
116
- codewords
117
- end
118
- memoize :codewords
119
-
120
- def codewords_with_orientation_in_character_j
121
- result = codewords.dup
122
- result[9] *= 2
123
- result
124
- end
125
-
126
- def codewords_with_fcs_bit_in_character_a
127
- result = codewords_with_orientation_in_character_j.dup
128
- result[0] += 659 if frame_check_sequence[10] == 1
129
- result
130
- end
131
-
132
- def characters
133
- CODEWORD_MAP.characters(codewords_with_fcs_bit_in_character_a)
134
- end
135
-
136
- def characters_with_fcs_bits_0_through_9
137
- characters.each_with_index.map do |character, i|
138
- if frame_check_sequence[i] == 1
139
- character ^ 0b1111111111111
140
- else
141
- character
142
- end
143
- end
144
- end
145
-
146
- def symbols
147
- BAR_MAP.symbols(characters_with_fcs_bits_0_through_9)
148
- end
149
-
150
- end
151
-
152
- end
@@ -1,98 +0,0 @@
1
- module Imb
2
-
3
- # This class represents a Barcode ID
4
-
5
- class BarcodeId
6
-
7
- # The allowable range of a barcode ID
8
- RANGE = 0..94
9
-
10
- # The allowable range of a barcode ID's least significant digit
11
- LSD_RANGE = 0..4
12
-
13
- # Turn the argument into a BarcodeID if possible. Accepts any of:
14
- # * {BarcodeId}
15
- # * String
16
- # * Integer
17
- # @return [BarcodeId]
18
- # @raise [ArgumentError] If the argument cannot be coerced
19
-
20
- def self.coerce(o)
21
- case o
22
- when BarcodeId
23
- o
24
- when String
25
- new(o.to_i)
26
- when Integer
27
- new(o)
28
- else
29
- raise ArgumentError, 'Cannot coerce to BarcodeId'
30
- end
31
- end
32
-
33
- # Create a new BarcodeId
34
- # @param [Integer] value The barcode ID
35
-
36
- def initialize(value)
37
- @value = value
38
- end
39
-
40
- # Return true if this object is equal to o
41
- # @param [Object] o Any object acceptable to {.coerce}
42
-
43
- def ==(o)
44
- BarcodeId.coerce(o).to_i == to_i
45
- rescue ArgumentError
46
- false
47
- end
48
-
49
- # @return [Integer] The integer value of the barcode ID
50
-
51
- def to_i
52
- @value
53
- end
54
-
55
- # @!group Internal
56
-
57
- # Validate the value.
58
- # @param long_mailer_id truthy if the mailer ID is long (9 digits).
59
- # @raise ArgumentError if invalid
60
-
61
- def validate(long_mailer_id)
62
- unless RANGE === @value
63
- raise ArgumentError, "Must be #{RANGE}"
64
- end
65
- unless LSD_RANGE === least_significant_digit
66
- raise ArgumentError, "Least significant digit must be #{LSD_RANGE}"
67
- end
68
- end
69
-
70
- # Add this object's value to target, shifting it left as many
71
- # digts as are needed to make room.
72
- # @param [Integer] target The target to be shifted and added to
73
- # @param long_mailer_id truthy if the mailer ID is long (9 digits).
74
- # @return [Integer] The new value of the target
75
-
76
- def shift_and_add_to(target, long_mailer_id)
77
- target *= 10
78
- target += most_significant_digit
79
- target *= 5
80
- target += least_significant_digit
81
- target
82
- end
83
-
84
- # @!endgroup
85
-
86
- private
87
-
88
- def most_significant_digit
89
- @value / 10
90
- end
91
-
92
- def least_significant_digit
93
- @value % 10
94
- end
95
-
96
- end
97
-
98
- end
@@ -1,28 +0,0 @@
1
- module Imb
2
-
3
- # @!group Internal
4
-
5
- # Represents the position of one bit in the array of intelligent
6
- # barcode "characters".
7
-
8
- class CharacterPosition
9
-
10
- # @param [Integer] character_index
11
- # @param [Integer] bit_number
12
-
13
- def initialize(character_index, bit_number)
14
- @character_index = character_index
15
- @bit_number = bit_number
16
- end
17
-
18
- # Given an array of characters, return the bit for this position.
19
- # @param [[Integer]] characters
20
- # @return [Integer] bit (0 or 1)
21
-
22
- def extract_bit_from_characters(characters)
23
- characters[@character_index][@bit_number]
24
- end
25
-
26
- end
27
-
28
- end
@@ -1,38 +0,0 @@
1
- module Imb
2
-
3
- # @!group Internal
4
-
5
- # Maps codewords to characters.
6
-
7
- class CodewordMap
8
-
9
- # Constructor
10
-
11
- def initialize
12
- @characters = load_characters
13
- end
14
-
15
- # Given an array of codewords, ruturn their characters.
16
- # @param [[Integer]] codewords
17
- # @return [[Integer]] Array of characters
18
-
19
- def characters(codewords)
20
- codewords.map do |codeword|
21
- @characters[codeword]
22
- end
23
- end
24
-
25
- private
26
-
27
- def load_characters
28
- YAML.load_file(characters_path)
29
- end
30
-
31
- def characters_path
32
- File.expand_path('codeword_to_character_mapping.yml',
33
- File.dirname(__FILE__))
34
- end
35
-
36
- end
37
-
38
- end