barcode1dtools 0.9.7.0 → 0.9.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,8 +17,9 @@ module Barcode1DTools
17
17
  # library currently includes EAN-13, EAN-8, UPC-A, UPC-E, UPC
18
18
  # Supplemental 2, UPC Supplemental 5, Interleaved 2 of 5 (I 2/5),
19
19
  # COOP 2 of 5, Matrix 2 of 5, Industrial 2 of 5, IATA 2 of 5,
20
- # PostNet, Code 3 of 9, Code 93, Code 11, and Codabar, but will
21
- # be expanded to include most 1D symbologies in the near future.
20
+ # PostNet, Plessey, MSI (Modified Plessey), Code 3 of 9, Code 93,
21
+ # Code 11, and Codabar, but will be expanded to include most 1D
22
+ # symbologies in the near future.
22
23
  #
23
24
  #== Example
24
25
  # ean13 = Barcode1DTools::EAN13.new('0012676510226', :line_character => 'x', :space_character => ' ')
@@ -127,3 +128,5 @@ require 'barcode1dtools/industrial2of5'
127
128
  require 'barcode1dtools/iata2of5'
128
129
  require 'barcode1dtools/matrix2of5'
129
130
  require 'barcode1dtools/postnet'
131
+ require 'barcode1dtools/plessey'
132
+ require 'barcode1dtools/msi'
@@ -0,0 +1,262 @@
1
+ #--
2
+ # Copyright 2012 Michael Chaney Consulting Corporation
3
+ #
4
+ # Released under the terms of the MIT License or the GNU
5
+ # General Public License, v. 2
6
+ #++
7
+
8
+ module Barcode1DTools
9
+
10
+ # Barcode1DTools::MSI - Create and decode bar patterns for
11
+ # MSI. The value encoded is a string which may contain the
12
+ # digits 0-9.
13
+ #
14
+ # There are four possible check digit calculations, and you
15
+ # may use the option :check_digit => 'x' to choose which
16
+ # one to use. "x" may be one of "mod 10", "mod 11",
17
+ # "mod 1010", or "mod 1110". The default is "mod 10".
18
+ # For a mod 11 check digit, you may use :check_style =>
19
+ # 'ibm' or 'ncr'.
20
+ #
21
+ # MSI is a terrible symbology in modern terms and should
22
+ # not be used in any new applications.
23
+ #
24
+ # val = "2898289238"
25
+ # bc = Barcode1DTools::MSI.new(val)
26
+ # pattern = bc.bars
27
+ # rle_pattern = bc.rle
28
+ # width = bc.width
29
+ #
30
+ # The object created is immutable.
31
+ #
32
+ # Barcode1DTools::MSI creates the patterns that you need to
33
+ # display MSI barcodes. It can also decode a simple w/n
34
+ # string.
35
+ #
36
+ # MSI characters consist of 4 bars and 4 spaces. The
37
+ # representation is simply binary where a binary "0" is
38
+ # represented as a narrow bar followed by a wide space and
39
+ # a binary "1" is a wide bar followed by a narrow space.
40
+ # The bits are ordered descending, so 9 is 1001 binary,
41
+ # "wn nw nw wn" in w/n format.
42
+ #
43
+ # There are three formats for the returned pattern:
44
+ #
45
+ # bars - 1s and 0s specifying black lines and white spaces. Actual
46
+ # characters can be changed from "1" and 0" with options
47
+ # :line_character and :space_character.
48
+ #
49
+ # rle - Run-length-encoded version of the pattern. The first
50
+ # number is always a black line, with subsequent digits
51
+ # alternating between spaces and lines. The digits specify
52
+ # the width of each line or space.
53
+ #
54
+ # wn - The native format for this barcode type. The string
55
+ # consists of a series of "w" and "n" characters. The first
56
+ # item is always a black line, with subsequent characters
57
+ # alternating between spaces and lines. A "wide" item
58
+ # is twice the width of a "narrow" item.
59
+ #
60
+ # The "width" method will tell you the total end-to-end width, in
61
+ # units, of the entire barcode.
62
+ #
63
+ #== Rendering
64
+ #
65
+ # The author is aware of no standards for display.
66
+
67
+ class MSI < Barcode1D
68
+
69
+ # Character sequence - 0-based offset in this string is character
70
+ # number
71
+ CHAR_SEQUENCE = "0123456789"
72
+
73
+ # Patterns for making bar codes
74
+ PATTERNS = {
75
+ '0'=> {'val'=>0 ,'wn'=>'nwnwnwnw'},
76
+ '1'=> {'val'=>1 ,'wn'=>'nwnwnwwn'},
77
+ '2'=> {'val'=>2 ,'wn'=>'nwnwwnnw'},
78
+ '3'=> {'val'=>3 ,'wn'=>'nwnwwnwn'},
79
+ '4'=> {'val'=>4 ,'wn'=>'nwwnnwnw'},
80
+ '5'=> {'val'=>5 ,'wn'=>'nwwnnwwn'},
81
+ '6'=> {'val'=>6 ,'wn'=>'nwwnwnnw'},
82
+ '7'=> {'val'=>7 ,'wn'=>'nwwnwnwn'},
83
+ '8'=> {'val'=>8 ,'wn'=>'wnnwnwnw'},
84
+ '9'=> {'val'=>9 ,'wn'=>'wnnwnwwn'}
85
+ }
86
+
87
+ GUARD_PATTERN_LEFT_WN = 'wn'
88
+ GUARD_PATTERN_RIGHT_WN = 'nwn'
89
+
90
+ DEFAULT_OPTIONS = {
91
+ :line_character => '1',
92
+ :space_character => '0',
93
+ :w_character => 'w',
94
+ :n_character => 'n',
95
+ :wn_ratio => '2',
96
+ :check_digit => 'mod 10',
97
+ :check_style => 'ibm'
98
+ }
99
+
100
+ class << self
101
+ # MSI can encode digits
102
+ def can_encode?(value)
103
+ value.to_s =~ /\A\d+\z/
104
+ end
105
+
106
+ def generate_check_digit_for(value, options = {})
107
+ if options[:check_digit] == 'mod 10'
108
+ generate_mod10_check_digit_for(value).to_s
109
+ elsif options[:check_digit] == 'mod 11'
110
+ generate_mod11_check_digit_for(value, options[:check_style]).to_s
111
+ elsif options[:check_digit] == 'mod 1010'
112
+ mod10 = generate_mod10_check_digit_for(value)
113
+ mod10_2 = generate_mod10_check_digit_for(value + mod10.to_s)
114
+ "#{mod10}#{mod10_2}"
115
+ elsif options[:check_digit] == 'mod 1110'
116
+ mod11 = generate_mod11_check_digit_for(value, options[:check_style])
117
+ mod10_2 = generate_mod10_check_digit_for(value + mod11.to_s)
118
+ "#{mod11}#{mod10_2}"
119
+ end
120
+ end
121
+
122
+ def validate_check_digit_for(value, options = {})
123
+ payload, check_digits = split_payload_and_check_digits(value, options)
124
+ self.generate_check_digit_for(payload, options) == check_digits
125
+ end
126
+
127
+ def split_payload_and_check_digits(value, options = {})
128
+ if options[:check_digit] == 'mod 1010' || options[:check_digit] == 'mod 1110'
129
+ md = value.to_s.match(/\A(.*?)(..)\z/)
130
+ else
131
+ md = value.to_s.match(/\A(.*?)(.)\z/)
132
+ end
133
+ [md[1], md[2]]
134
+ end
135
+
136
+ def generate_mod10_check_digit_for(value)
137
+ value = value.to_s
138
+ valarr = value.scan(/\d\d?/)
139
+ if value.size.odd?
140
+ odd = valarr.collect { |c| c[0,1] }
141
+ even = valarr.collect { |c| c[1,1] }
142
+ else
143
+ odd = valarr.collect { |c| c[1,1] }
144
+ even = valarr.collect { |c| c[0,1] }
145
+ end
146
+ odd = (odd.join.to_i * 2).to_s.split('').inject(0) { |a,c| a + c.to_i }
147
+ even = even.inject(0) { |a,c| a + c.to_i }
148
+ (10 - ((odd + even) % 10)) % 10
149
+ end
150
+
151
+ def generate_mod11_check_digit_for(value, style)
152
+ max = (style == 'ncr' ? 9 : 7)
153
+ value = value.to_s
154
+ weight = 1
155
+ sum = value.split('').reverse.inject(0) { |a,c| weight = (weight == max ? 2 : weight + 1); a + weight * c.to_i }
156
+ (11 - (sum % 11)) % 11
157
+ end
158
+
159
+ # Decode a string in rle format. This will return a MSI
160
+ # object.
161
+ def decode(str, options = {})
162
+ if str =~ /[^1-3]/ && str =~ /[^wn]/
163
+ raise UnencodableCharactersError, "Pattern must be rle or wn"
164
+ end
165
+
166
+ # ensure a wn string
167
+ if str =~ /[1-3]/
168
+ str = str.tr('123','nww')
169
+ end
170
+
171
+ if str.reverse =~ /\A#{GUARD_PATTERN_LEFT_WN}.*?#{GUARD_PATTERN_RIGHT_WN}\z/
172
+ str.reverse!
173
+ end
174
+
175
+ unless str =~ /\A#{GUARD_PATTERN_LEFT_WN}(.*?)#{GUARD_PATTERN_RIGHT_WN}\z/
176
+ raise UnencodableCharactersError, "Start/stop pattern is not detected."
177
+ end
178
+
179
+ wn_pattern = $1
180
+
181
+ # Each pattern is 4 bars and 4 spaces, with a space between.
182
+ unless wn_pattern.size % 8 == 0
183
+ raise UnencodableCharactersError, "Wrong number of bars."
184
+ end
185
+
186
+ decoded_string = ''
187
+
188
+ wn_pattern.scan(/.{8}/).each do |chunk|
189
+
190
+ found = false
191
+
192
+ PATTERNS.each do |char,hsh|
193
+ if chunk == hsh['wn']
194
+ decoded_string += char
195
+ found = true
196
+ break;
197
+ end
198
+ end
199
+
200
+ raise UndecodableCharactersError, "Invalid sequence: #{chunk}" unless found
201
+
202
+ end
203
+
204
+ MSI.new(decoded_string, options)
205
+ end
206
+
207
+ end
208
+
209
+ # Options are :line_character, :space_character, :w_character,
210
+ # :n_character, :checksum_included, and :skip_checksum.
211
+ def initialize(value, options = {})
212
+
213
+ @options = DEFAULT_OPTIONS.merge(options)
214
+
215
+ # Can we encode this value?
216
+ raise UnencodableCharactersError unless self.class.can_encode?(value)
217
+
218
+ if @options[:skip_checksum]
219
+ @encoded_string = value.to_s
220
+ @value = value.to_s
221
+ @check_digit = nil
222
+ elsif @options[:checksum_included]
223
+ raise ChecksumError unless self.class.validate_check_digit_for(value, options)
224
+ @encoded_string = value.to_s
225
+ @value, @check_digit = self.class.split_payload_and_check_digits(value, options)
226
+ else
227
+ @value = value.to_s
228
+ @check_digit = self.class.generate_check_digit_for(@value, options)
229
+ @encoded_string = "#{@value}#{@check_digit}"
230
+ end
231
+ end
232
+
233
+ # Returns a string of "w" or "n" ("wide" and "narrow")
234
+ def wn
235
+ @wn ||= wn_str.tr('wn', @options[:w_character].to_s + @options[:n_character].to_s)
236
+ end
237
+
238
+ # returns a run-length-encoded string representation
239
+ def rle
240
+ @rle ||= self.class.wn_to_rle(self.wn, @options)
241
+ end
242
+
243
+ # returns 1s and 0s (for "black" and "white")
244
+ def bars
245
+ @bars ||= self.class.rle_to_bars(self.rle, @options)
246
+ end
247
+
248
+ # returns the total unit width of the bar code
249
+ def width
250
+ @width ||= rle.split('').inject(0) { |a,c| a + c.to_i }
251
+ end
252
+
253
+ private
254
+
255
+ # Creates the actual w/n pattern. Note that there is a narrow space
256
+ # between each character.
257
+ def wn_str
258
+ @wn_str ||= GUARD_PATTERN_LEFT_WN + @encoded_string.split('').collect { |c| PATTERNS[c]['wn'] }.join + GUARD_PATTERN_RIGHT_WN
259
+ end
260
+
261
+ end
262
+ end
@@ -0,0 +1,208 @@
1
+ #--
2
+ # Copyright 2012 Michael Chaney Consulting Corporation
3
+ #
4
+ # Released under the terms of the MIT License or the GNU
5
+ # General Public License, v. 2
6
+ #++
7
+
8
+ module Barcode1DTools
9
+
10
+ # Barcode1DTools::Plessey - Create and decode bar patterns for
11
+ # Plessey. The value encoded is a string which may contain the
12
+ # digits 0-9 and the letters A-F (0-15 hexadecimal).
13
+ #
14
+ # According to Wikipedia, a Plessey code should contain a two
15
+ # digit CRC8 checksum. This code does not provide checksum
16
+ # generation or validation.
17
+ #
18
+ # Plessey is a terrible symbology in modern terms and should
19
+ # not be used in any new applications.
20
+ #
21
+ # val = "2898289238AF"
22
+ # bc = Barcode1DTools::Plessey.new(val)
23
+ # pattern = bc.bars
24
+ # rle_pattern = bc.rle
25
+ # width = bc.width
26
+ #
27
+ # The object created is immutable.
28
+ #
29
+ # Barcode1DTools::Plessey creates the patterns that you need to
30
+ # display Plessey barcodes. It can also decode a simple w/n
31
+ # string.
32
+ #
33
+ # Plessey characters consist of 4 bars and 4 spaces. The
34
+ # representation is simply binary where a binary "0" is
35
+ # represented as a narrow bar followed by a wide space and
36
+ # a binary "1" is a wide bar followed by a narrow space.
37
+ # The bits are ordered ascending, so 9 is 1001 binary,
38
+ # "wn nw nw wn" in w/n format.
39
+ #
40
+ # There are three formats for the returned pattern:
41
+ #
42
+ # bars - 1s and 0s specifying black lines and white spaces. Actual
43
+ # characters can be changed from "1" and 0" with options
44
+ # :line_character and :space_character.
45
+ #
46
+ # rle - Run-length-encoded version of the pattern. The first
47
+ # number is always a black line, with subsequent digits
48
+ # alternating between spaces and lines. The digits specify
49
+ # the width of each line or space.
50
+ #
51
+ # wn - The native format for this barcode type. The string
52
+ # consists of a series of "w" and "n" characters. The first
53
+ # item is always a black line, with subsequent characters
54
+ # alternating between spaces and lines. A "wide" item
55
+ # is twice the width of a "narrow" item.
56
+ #
57
+ # The "width" method will tell you the total end-to-end width, in
58
+ # units, of the entire barcode.
59
+ #
60
+ #== Rendering
61
+ #
62
+ # The author is aware of no standards for display.
63
+
64
+ class Plessey < Barcode1D
65
+
66
+ # Character sequence - 0-based offset in this string is character
67
+ # number
68
+ CHAR_SEQUENCE = "0123456789ABCDEF"
69
+
70
+ # Patterns for making bar codes
71
+ PATTERNS = {
72
+ '0'=> {'val'=>0 ,'wn'=>'nwnwnwnw'},
73
+ '1'=> {'val'=>1 ,'wn'=>'wnnwnwnw'},
74
+ '2'=> {'val'=>2 ,'wn'=>'nwwnnwnw'},
75
+ '3'=> {'val'=>3 ,'wn'=>'wnwnnwnw'},
76
+ '4'=> {'val'=>4 ,'wn'=>'nwnwwnnw'},
77
+ '5'=> {'val'=>5 ,'wn'=>'wnnwwnnw'},
78
+ '6'=> {'val'=>6 ,'wn'=>'nwwnwnnw'},
79
+ '7'=> {'val'=>7 ,'wn'=>'wnwnwnnw'},
80
+ '8'=> {'val'=>8 ,'wn'=>'nwnwnwwn'},
81
+ '9'=> {'val'=>9 ,'wn'=>'wnnwnwwn'},
82
+ 'A'=> {'val'=>10 ,'wn'=>'nwwnnwwn'},
83
+ 'B'=> {'val'=>11 ,'wn'=>'wnwnnwwn'},
84
+ 'C'=> {'val'=>12 ,'wn'=>'nwnwwnwn'},
85
+ 'D'=> {'val'=>13 ,'wn'=>'wnnwwnwn'},
86
+ 'E'=> {'val'=>14 ,'wn'=>'nwwnwnwn'},
87
+ 'F'=> {'val'=>15 ,'wn'=>'wnwnwnwn'}
88
+ }
89
+
90
+ GUARD_PATTERN_LEFT_WN = 'wnwnnwwn'
91
+ GUARD_PATTERN_RIGHT_WN = 'wnwnnwnw'
92
+
93
+ DEFAULT_OPTIONS = {
94
+ :line_character => '1',
95
+ :space_character => '0',
96
+ :w_character => 'w',
97
+ :n_character => 'n',
98
+ :wn_ratio => '2'
99
+ }
100
+
101
+ class << self
102
+ # Plessey can encode digits and A-F.
103
+ def can_encode?(value)
104
+ value.to_s =~ /\A[0-9A-F]+\z/
105
+ end
106
+
107
+ def generate_check_digit_for(value)
108
+ raise NotImplementedError
109
+ end
110
+
111
+ def validate_check_digit_for(value)
112
+ raise NotImplementedError
113
+ end
114
+
115
+ # Decode a string in rle format. This will return a Plessey
116
+ # object.
117
+ def decode(str, options = {})
118
+ if str =~ /[^1-3]/ && str =~ /[^wn]/
119
+ raise UnencodableCharactersError, "Pattern must be rle or wn"
120
+ end
121
+
122
+ # ensure a wn string
123
+ if str =~ /[1-3]/
124
+ str = str.tr('123','nww')
125
+ end
126
+
127
+ if str.reverse =~ /\A#{GUARD_PATTERN_LEFT_WN}.*?#{GUARD_PATTERN_RIGHT_WN}\z/
128
+ str.reverse!
129
+ end
130
+
131
+ unless str =~ /\A#{GUARD_PATTERN_LEFT_WN}(.*?)#{GUARD_PATTERN_RIGHT_WN}\z/
132
+ raise UnencodableCharactersError, "Start/stop pattern is not detected."
133
+ end
134
+
135
+ wn_pattern = $1
136
+
137
+ # Each pattern is 4 bars and 4 spaces, with a space between.
138
+ unless wn_pattern.size % 8 == 0
139
+ raise UnencodableCharactersError, "Wrong number of bars."
140
+ end
141
+
142
+ decoded_string = ''
143
+
144
+ wn_pattern.scan(/.{8}/).each do |chunk|
145
+
146
+ found = false
147
+
148
+ PATTERNS.each do |char,hsh|
149
+ if chunk == hsh['wn']
150
+ decoded_string += char
151
+ found = true
152
+ break;
153
+ end
154
+ end
155
+
156
+ raise UndecodableCharactersError, "Invalid sequence: #{chunk}" unless found
157
+
158
+ end
159
+
160
+ Plessey.new(decoded_string, options)
161
+ end
162
+
163
+ end
164
+
165
+ # Options are :line_character, :space_character, :w_character,
166
+ # :n_character, :checksum_included, and :skip_checksum.
167
+ def initialize(value, options = {})
168
+
169
+ @options = DEFAULT_OPTIONS.merge(options)
170
+
171
+ # Can we encode this value?
172
+ raise UnencodableCharactersError unless self.class.can_encode?(value)
173
+
174
+ @value = value.to_s
175
+ @encoded_string = value.to_s
176
+ @check_digit = nil
177
+ end
178
+
179
+ # Returns a string of "w" or "n" ("wide" and "narrow")
180
+ def wn
181
+ @wn ||= wn_str.tr('wn', @options[:w_character].to_s + @options[:n_character].to_s)
182
+ end
183
+
184
+ # returns a run-length-encoded string representation
185
+ def rle
186
+ @rle ||= self.class.wn_to_rle(self.wn, @options)
187
+ end
188
+
189
+ # returns 1s and 0s (for "black" and "white")
190
+ def bars
191
+ @bars ||= self.class.rle_to_bars(self.rle, @options)
192
+ end
193
+
194
+ # returns the total unit width of the bar code
195
+ def width
196
+ @width ||= rle.split('').inject(0) { |a,c| a + c.to_i }
197
+ end
198
+
199
+ private
200
+
201
+ # Creates the actual w/n pattern. Note that there is a narrow space
202
+ # between each character.
203
+ def wn_str
204
+ @wn_str ||= GUARD_PATTERN_LEFT_WN + @encoded_string.split('').collect { |c| PATTERNS[c]['wn'] }.join + GUARD_PATTERN_RIGHT_WN
205
+ end
206
+
207
+ end
208
+ end
@@ -0,0 +1,79 @@
1
+ #--
2
+ # Copyright 2012 Michael Chaney Consulting Corporation
3
+ #
4
+ # Released under the terms of the MIT License or the GNU
5
+ # General Public License, v. 2
6
+ #++
7
+
8
+ require 'test/unit'
9
+ require 'barcode1dtools'
10
+
11
+ class Barcode1DToolsMSITest < Test::Unit::TestCase
12
+ def setup
13
+ end
14
+
15
+ def teardown
16
+ end
17
+
18
+ # Creates a random number from 1 to 10 digits long
19
+ def random_msi_value(len)
20
+ (1..1+rand(len)).collect { "0123456789"[rand(11),1] }.join
21
+ end
22
+
23
+ def test_checksum_generation
24
+ assert_equal '4', Barcode1DTools::MSI.generate_check_digit_for('1234567', :check_digit => 'mod 10')
25
+ end
26
+
27
+ def test_checksum_validation
28
+ assert Barcode1DTools::MSI.validate_check_digit_for('12345674', :check_digit => 'mod 10')
29
+ end
30
+
31
+ def test_attr_readers
32
+ msi = Barcode1DTools::MSI.new('1234567', :check_digit => 'mod 10', :checksum_included => false)
33
+ assert_equal '4', msi.check_digit
34
+ assert_equal '1234567', msi.value
35
+ assert_equal '12345674', msi.encoded_string
36
+ end
37
+
38
+ def test_checksum_error
39
+ # proper checksum is 5
40
+ assert_raise(Barcode1DTools::ChecksumError) { Barcode1DTools::MSI.new('12345671', :check_digit => 'mod 10', :checksum_included => true) }
41
+ end
42
+
43
+ def test_skip_checksum
44
+ msi = Barcode1DTools::MSI.new('12345', :skip_checksum => true)
45
+ assert_nil msi.check_digit
46
+ assert_equal '12345', msi.value
47
+ assert_equal '12345', msi.encoded_string
48
+ end
49
+
50
+ def test_bad_character_errors
51
+ # Characters that cannot be encoded
52
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::MSI.new('thisisnotgood', :checksum_included => false) }
53
+ end
54
+
55
+ # Only need to test wn, as bars and rle are based on wn
56
+ def test_barcode_generation
57
+ msi = Barcode1DTools::MSI.new('12345674', :skip_checksum => true, :line_character => '#', :space_character => ' ')
58
+ assert_equal "## # # # ## # # ## # # # ## ## # ## # # # ## # ## # ## ## # # ## ## ## # ## # # # #", msi.bars
59
+ end
60
+
61
+ def test_decode_error
62
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::MSI.decode('x') }
63
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::MSI.decode('x'*60) }
64
+ # proper start & stop, but crap in middle
65
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::MSI.decode('nnwwnnnnnnnnnnnwwn') }
66
+ # wrong start/stop
67
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::MSI.decode('nwwnwnwnwnwnwnw') }
68
+ end
69
+
70
+ def test_decoding
71
+ random_msi_num=random_msi_value(10)
72
+ msi = Barcode1DTools::MSI.new(random_msi_num, :skip_checksum => true)
73
+ msi2 = Barcode1DTools::MSI.decode(msi.wn)
74
+ assert_equal msi.value, msi2.value
75
+ # Should also work in reverse
76
+ msi4 = Barcode1DTools::MSI.decode(msi.wn.reverse)
77
+ assert_equal msi.value, msi4.value
78
+ end
79
+ end
@@ -0,0 +1,53 @@
1
+ #--
2
+ # Copyright 2012 Michael Chaney Consulting Corporation
3
+ #
4
+ # Released under the terms of the MIT License or the GNU
5
+ # General Public License, v. 2
6
+ #++
7
+
8
+ require 'test/unit'
9
+ require 'barcode1dtools'
10
+
11
+ class Barcode1DToolsPlesseyTest < Test::Unit::TestCase
12
+ def setup
13
+ end
14
+
15
+ def teardown
16
+ end
17
+
18
+ # Creates a random number from 1 to 10 digits long
19
+ def random_plessey_value(len)
20
+ (1..1+rand(len)).collect { "0123456789"[rand(11),1] }.join
21
+ end
22
+
23
+ def test_attr_readers
24
+ plessey = Barcode1DTools::Plessey.new('12345')
25
+ assert_nil plessey.check_digit
26
+ assert_equal '12345', plessey.value
27
+ assert_equal '12345', plessey.encoded_string
28
+ end
29
+
30
+ def test_bad_character_errors
31
+ # Characters that cannot be encoded
32
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::Plessey.new('thisisnotgood', :checksum_included => false) }
33
+ end
34
+
35
+ def test_decode_error
36
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::Plessey.decode('x') }
37
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::Plessey.decode('x'*60) }
38
+ # proper start & stop, but crap in middle
39
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::Plessey.decode('nnwwnnnnnnnnnnnwwn') }
40
+ # wrong start/stop
41
+ assert_raise(Barcode1DTools::UnencodableCharactersError) { Barcode1DTools::Plessey.decode('nwwnwnwnwnwnwnw') }
42
+ end
43
+
44
+ def test_decoding
45
+ random_plessey_num=random_plessey_value(10)
46
+ plessey = Barcode1DTools::Plessey.new(random_plessey_num)
47
+ plessey2 = Barcode1DTools::Plessey.decode(plessey.wn)
48
+ assert_equal plessey.value, plessey2.value
49
+ # Should also work in reverse
50
+ plessey4 = Barcode1DTools::Plessey.decode(plessey.wn.reverse)
51
+ assert_equal plessey.value, plessey4.value
52
+ end
53
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: barcode1dtools
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 39
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 7
9
+ - 8
10
10
  - 0
11
- version: 0.9.7.0
11
+ version: 0.9.8.0
12
12
  platform: ruby
13
13
  authors:
14
14
  - Michael Chaney
@@ -23,13 +23,13 @@ dependencies: []
23
23
  description: "\t Barcode1D is a small library for handling many kinds of\n\
24
24
  \t 1-dimensional barcodes. Currently implemented are Code 3 of 9, Code\n\
25
25
  \t 93, Code 11, Codabar, Interleaved 2 of 5, COOP 2 of 5, Matrix 2 of\n\
26
- \t 5, Industrial 2 of 5, IATA 2 of 5, PostNet, EAN-13, EAN-8, UPC-A,\n\
27
- \t UPC-E, UPC Supplemental 2, and UPC Supplemental 5. Patterns are\n\
28
- \t created in either a simple format of bars and spaces or as a\n\
29
- \t run-length encoded string. This only generates and decodes the\n\
30
- \t patterns; actual display or reading from a device must be\n\
31
- \t implemented by the programmer. More symbologies will be added as\n\
32
- \t time permits.\n"
26
+ \t 5, Industrial 2 of 5, IATA 2 of 5, PostNet, Plessey, MSI (Modified\n\
27
+ \t Plessey), EAN-13, EAN-8, UPC-A, UPC-E, UPC Supplemental 2, and UPC\n\
28
+ \t Supplemental 5. Patterns are created in either a simple format of\n\
29
+ \t bars and spaces or as a run-length encoded string. This only\n\
30
+ \t generates and decodes the patterns; actual display or reading from a\n\
31
+ \t device must be implemented by the programmer. More symbologies will\n\
32
+ \t be added as time permits.\n"
33
33
  email: mdchaney@michaelchaney.com
34
34
  executables: []
35
35
 
@@ -49,6 +49,8 @@ files:
49
49
  - lib/barcode1dtools/industrial2of5.rb
50
50
  - lib/barcode1dtools/interleaved2of5.rb
51
51
  - lib/barcode1dtools/matrix2of5.rb
52
+ - lib/barcode1dtools/msi.rb
53
+ - lib/barcode1dtools/plessey.rb
52
54
  - lib/barcode1dtools/postnet.rb
53
55
  - lib/barcode1dtools/upc_a.rb
54
56
  - lib/barcode1dtools/upc_e.rb
@@ -68,6 +70,8 @@ files:
68
70
  - test/test_barcode1diata2of5.rb
69
71
  - test/test_barcode1dindustrial2of5.rb
70
72
  - test/test_barcode1dmatrix2of5.rb
73
+ - test/test_barcode1dmsi.rb
74
+ - test/test_barcode1dplessey.rb
71
75
  - test/test_barcode1dpostnet.rb
72
76
  - test/test_barcode1dupca.rb
73
77
  - test/test_barcode1dupce.rb
@@ -123,6 +127,8 @@ test_files:
123
127
  - test/test_barcode1diata2of5.rb
124
128
  - test/test_barcode1dindustrial2of5.rb
125
129
  - test/test_barcode1dmatrix2of5.rb
130
+ - test/test_barcode1dmsi.rb
131
+ - test/test_barcode1dplessey.rb
126
132
  - test/test_barcode1dpostnet.rb
127
133
  - test/test_barcode1dupca.rb
128
134
  - test/test_barcode1dupce.rb