class Imb::Barcode
This class represents a barcode.
Attributes
@return [BarcodeId]
@return [MailerId]
@return [RoutingCode]
@return [SerialNumber]
@return [ServiceType]
Public Class Methods
Create a new barcode
@param barcode_id
[String] Nominally a String, but can be
anything that {BarcodeId.coerce} will accept.
@param service_type
[String] Nominally a String, but can be
anything that {ServiceType.coerce} will accept.
@param mailer_id
[String] Nominally a String, but can be
anything that {MailerId.coerce} will accept.
@param serial_number
[String] Nominally a String, but can be
anything that {SerialNumber.coerce} will accept.
@param routing_code
[String] Nominally a String, but can be
anything that {RoutingCode.coerce} will accept.
# File lib/usps_intelligent_barcode/barcode.rb, line 43 def initialize( barcode_id, service_type, mailer_id, serial_number, routing_code ) @barcode_id = BarcodeId.coerce(barcode_id) @service_type = ServiceType.coerce(service_type) @mailer_id = MailerId.coerce(mailer_id) @serial_number = SerialNumber.coerce(serial_number) @routing_code = RoutingCode.coerce(routing_code) validate_components end
Public Instance Methods
Return a string to print using one of the USPS Intelligent Mail Barcode
fonts. Each character of the string will be one of:
-
'T' for a tracking mark (neither ascender nor descender)
-
'A' for an ascender mark
-
'D' for a descender mark
-
'F' for a full mark (both ascender and descender)
@return [String] A string that represents the barcode.
# File lib/usps_intelligent_barcode/barcode.rb, line 65 def barcode_letters symbols.map(&:letter).join end
Private Instance Methods
The components (“fields” in the spec) are turned into a single number that the spec calls “binary_data”). This is done through a series of multiplications and additions. See spec. section 2.2.1 (“Step 1–Conversion of Data Fields into Binary Data”).
@return [Integer]
# File lib/usps_intelligent_barcode/barcode.rb, line 103 def binary_data components.inject(0) do |data, component| component.shift_and_add_to(data, long_mailer_id?) end end
Convert the codewords to “characters”. Each character is a 13-bit integer; there are 10 of them, labeled “A” through “J” by the spec. See spec. section 2.2.5 (“Step 5–Conversion from Codewords to Characters”), para. “A”.
@return [Array<Integer>] 10 “characters.”
# File lib/usps_intelligent_barcode/barcode.rb, line 165 def characters CODEWORD_MAP.characters(codewords_with_fcs_bit_in_character_a) end
Fold the least-significant 10 bits of the FCS into the “characters”. See spec. section 2.2.5 (“Step 5–Conversion from Codewords to Characters”), para. “B”.
@return [Array<Integer>] 10 “characters”.
# File lib/usps_intelligent_barcode/barcode.rb, line 174 def characters_with_fcs_bits_0_through_9 characters.each_with_index.map do |character, i| if frame_check_sequence[i] == 1 character ^ 0b1111111111111 else character end end end
Compute the “code words.” This is an array of 10 integers computed from the binary data. See spec. section 2.2.3 (“Step 3–Conversion from Binary Data to Codewords”).
@return [Array<Integer>] 10 “characters.”
# File lib/usps_intelligent_barcode/barcode.rb, line 124 def codewords codewords = [] data = binary_data data, codewords[9] = data.divmod 636 8.downto(0) do |i| data, codewords[i] = data.divmod 1365 end codewords end
Insert the most significant bit of the FCS into codeword A. See spec. section 2.4.4 (“Step 4–Inserting Additional Information into Codewords”).
@return [Array<Integer>] 10 “characters.”
# File lib/usps_intelligent_barcode/barcode.rb, line 153 def codewords_with_fcs_bit_in_character_a result = codewords_with_orientation_in_character_j.dup result[0] += 659 if frame_check_sequence[10] == 1 result end
Insert the orientation into the codewords. The spec. doesn't say much about this, other than to multiply codeword “J” by two. This will cause the LSB to be zero, which is presumably the orientation. See spec. section 2.4.4 (“Step 4–Inserting Additional Information into Codewords”).
@return [Array<Integer>] 10 “characters.”
# File lib/usps_intelligent_barcode/barcode.rb, line 142 def codewords_with_orientation_in_character_j result = codewords.dup result[9] *= 2 result end
# File lib/usps_intelligent_barcode/barcode.rb, line 83 def components [ @routing_code, @barcode_id, @service_type, @mailer_id, @serial_number, ] end
Compute the “frame check sequence.” See spec. section 2.2.2 (“Step 2–Generation of 11-Bit CRC on Binary Data”).
@return [Integer]
# File lib/usps_intelligent_barcode/barcode.rb, line 114 def frame_check_sequence CRC.crc(binary_data) end
# File lib/usps_intelligent_barcode/barcode.rb, line 93 def long_mailer_id? @mailer_id.long? end
Map the “characters” to symbols. Here is where the barcode is made.
@return [Array<BarSymbol>]
# File lib/usps_intelligent_barcode/barcode.rb, line 187 def symbols BAR_MAP.symbols(characters_with_fcs_bits_0_through_9) end
# File lib/usps_intelligent_barcode/barcode.rb, line 77 def validate_components components.each do |component| component.validate(long_mailer_id?) end end