barby 0.1.2 → 0.2.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/bin/barby +40 -0
  2. data/lib/barby.rb +3 -0
  3. data/lib/barby/barcode.rb +6 -0
  4. data/lib/barby/barcode/code_128.rb +16 -3
  5. data/lib/barby/barcode/code_25.rb +161 -0
  6. data/lib/barby/barcode/code_25_interleaved.rb +73 -0
  7. data/lib/barby/barcode/code_93.rb +225 -0
  8. data/lib/barby/barcode/qr_code.rb +93 -0
  9. data/lib/barby/outputter.rb +56 -2
  10. data/lib/barby/outputter/ascii_outputter.rb +20 -1
  11. data/lib/barby/outputter/cairo_outputter.rb +38 -7
  12. data/lib/barby/outputter/pdfwriter_outputter.rb +44 -35
  13. data/lib/barby/outputter/png_outputter.rb +48 -16
  14. data/lib/barby/outputter/prawn_outputter.rb +100 -0
  15. data/lib/barby/outputter/rmagick_outputter.rb +48 -20
  16. data/lib/barby/vendor.rb +3 -0
  17. data/vendor/rqrcode/CHANGELOG +21 -0
  18. data/vendor/rqrcode/COPYING +19 -0
  19. data/vendor/rqrcode/README +98 -0
  20. data/vendor/rqrcode/Rakefile +65 -0
  21. data/vendor/rqrcode/lib/rqrcode.rb +13 -0
  22. data/vendor/rqrcode/lib/rqrcode/core_ext.rb +5 -0
  23. data/vendor/rqrcode/lib/rqrcode/core_ext/array.rb +5 -0
  24. data/vendor/rqrcode/lib/rqrcode/core_ext/array/behavior.rb +9 -0
  25. data/vendor/rqrcode/lib/rqrcode/core_ext/integer.rb +5 -0
  26. data/vendor/rqrcode/lib/rqrcode/core_ext/integer/bitwise.rb +11 -0
  27. data/vendor/rqrcode/lib/rqrcode/qrcode.rb +4 -0
  28. data/vendor/rqrcode/lib/rqrcode/qrcode/qr_8bit_byte.rb +35 -0
  29. data/vendor/rqrcode/lib/rqrcode/qrcode/qr_bit_buffer.rb +56 -0
  30. data/vendor/rqrcode/lib/rqrcode/qrcode/qr_code.rb +421 -0
  31. data/vendor/rqrcode/lib/rqrcode/qrcode/qr_math.rb +63 -0
  32. data/vendor/rqrcode/lib/rqrcode/qrcode/qr_polynomial.rb +78 -0
  33. data/vendor/rqrcode/lib/rqrcode/qrcode/qr_rs_block.rb +134 -0
  34. data/vendor/rqrcode/lib/rqrcode/qrcode/qr_util.rb +254 -0
  35. data/vendor/rqrcode/test/runtest.rb +78 -0
  36. data/vendor/rqrcode/test/test_data.rb +21 -0
  37. metadata +86 -44
data/bin/barby ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'rubygems'
4
+
5
+ #$: << File.join(File.dirname(__FILE__), '..', 'lib')
6
+ require 'barby'
7
+
8
+ options = {
9
+ :outputter => 'Png',
10
+ :outputter_method => 'to_png'
11
+ }
12
+
13
+ ARGV.options do |o|
14
+ o.banner = " Usage: #{File.basename(__FILE__)} [OPTIONS] data"
15
+ o.define_head ' Generates barcodes and prints the generated output to STDOUT'
16
+
17
+ o.separator ''
18
+ o.separator ' EXPERIMENTAL'
19
+ o.separator ''
20
+
21
+ o.on('-b', '--barcode=ClassName', String, 'Barcode type'){|v| options[:barcode] = v }
22
+ o.on('-o', '--outputter=ClassName', String, 'Outputter'){|v| options[:outputter] = v }
23
+ o.on('-m', '--method=method_name', String, 'Outputter method'){|v| options[:outputter_method] = v }
24
+
25
+ o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
26
+
27
+ o.parse!
28
+ end
29
+
30
+ #p STDIN.read
31
+ #exit
32
+
33
+ require "barby/outputter/#{options[:outputter].gsub(/[A-Z]/){|c| '_'+c.downcase }[1..-1]}_outputter"
34
+
35
+ barcode_class = Barby.const_get(options[:barcode])
36
+ barcode = barcode_class.new($*.empty? ? STDIN.read.chomp : $*)
37
+ outputter_class = Barby.const_get("#{options[:outputter]}Outputter")
38
+ outputter = outputter_class.new(barcode)
39
+
40
+ print eval("outputter.#{options[:outputter_method]}(#{ENV['OPTIONS']})")
data/lib/barby.rb CHANGED
@@ -1,11 +1,14 @@
1
+ require 'barby/vendor'
1
2
  require 'barby/version'
2
3
 
3
4
  require 'barby/barcode'
4
5
  require 'barby/barcode/code_128'
5
6
  require 'barby/barcode/gs1_128'
6
7
  require 'barby/barcode/code_39'
8
+ require 'barby/barcode/code_93'
7
9
  require 'barby/barcode/ean_13'
8
10
  require 'barby/barcode/ean_8'
9
11
  require 'barby/barcode/bookland'
12
+ require 'barby/barcode/qr_code'
10
13
 
11
14
  require 'barby/outputter'
data/lib/barby/barcode.rb CHANGED
@@ -41,6 +41,12 @@ module Barby
41
41
  end
42
42
 
43
43
 
44
+ #Is this barcode 2D?
45
+ def two_dimensional?
46
+ is_a? Barcode2D
47
+ end
48
+
49
+
44
50
  def method_missing(name, *args, &b)#:nodoc:
45
51
  #See if an outputter has registered this method
46
52
  if self.class.outputters.include?(name)
@@ -4,6 +4,19 @@ module Barby
4
4
 
5
5
 
6
6
  #Code 128 barcodes
7
+ #
8
+ #Note that you must provide a type for each object, either by passing a string
9
+ #as a second parameter to Code128.new or by instantiating one of the child classes.
10
+ #
11
+ #You can switch type by using the CODEA, CODEB and CODEC characters:
12
+ #
13
+ # "\305" => A
14
+ # "\306" => B
15
+ # "\307" => C
16
+ #
17
+ #As an example, here's one that starts out as type A and then switches to B and then C:
18
+ #
19
+ # Code128A.new("ABC123\306def\3074567")
7
20
  class Code128 < Barcode1D
8
21
 
9
22
  ENCODINGS = {
@@ -47,7 +60,7 @@ module Barby
47
60
 
48
61
  VALUES = {
49
62
  'A' => {
50
- 0 => "SP", 1 => "!", 2 => "\"",
63
+ 0 => " ", 1 => "!", 2 => "\"",
51
64
  3 => "#", 4 => "$", 5 => "%",
52
65
  6 => "&", 7 => "'", 8 => "(",
53
66
  9 => ")", 10 => "*", 11 => "+",
@@ -80,13 +93,13 @@ module Barby
80
93
  90 => "\032", 91 => "\e", 92 => "\034",
81
94
  93 => "\035", 94 => "\036", 95 => "\037",
82
95
  96 => "\303", 97 => "\302", 98 => "SHIFT",
83
- 99 => "\307", 100 => "\306", 101 => "\304",
96
+ 99 => "\307", 100 => "\306", 101 => "\304",
84
97
  102 => "\301", 103 => "STARTA", 104 => "STARTB",
85
98
  105 => "STARTC"
86
99
  }.invert,
87
100
 
88
101
  'B' => {
89
- 0 => "SP", 1 => "!", 2 => "\"", 3 => "#", 4 => "$", 5 => "%",
102
+ 0 => " ", 1 => "!", 2 => "\"", 3 => "#", 4 => "$", 5 => "%",
90
103
  6 => "&", 7 => "'", 8 => "(", 9 => ")", 10 => "*", 11 => "+",
91
104
  12 => ",", 13 => "-", 14 => ".", 15 => "/", 16 => "0", 17 => "1",
92
105
  18 => "2", 19 => "3", 20 => "4", 21 => "5", 22 => "6", 23 => "7",
@@ -0,0 +1,161 @@
1
+ require 'barby/barcode'
2
+
3
+ module Barby
4
+
5
+
6
+ #Standard/Industrial 2 of 5, non-interleaved
7
+ #
8
+ #Checksum not included by default, to include it,
9
+ #set include_checksum = true
10
+ class Code25 < Barcode1D
11
+
12
+ WIDE = W = true
13
+ NARROW = N = false
14
+
15
+ START_ENCODING = [W,W,N]
16
+ STOP_ENCODING = [W,N,W]
17
+
18
+ ENCODINGS = {
19
+ 0 => [N,N,W,W,N],
20
+ 1 => [W,N,N,N,W],
21
+ 2 => [N,W,N,N,W],
22
+ 3 => [W,W,N,N,N],
23
+ 4 => [N,N,W,N,W],
24
+ 5 => [W,N,W,N,N],
25
+ 6 => [N,W,W,N,N],
26
+ 7 => [N,N,N,W,W],
27
+ 8 => [W,N,N,W,N],
28
+ 9 => [N,W,N,W,N]
29
+ }
30
+
31
+ attr_accessor :data, :narrow_width, :wide_width, :space_width, :include_checksum
32
+
33
+
34
+ def initialize(data)
35
+ self.data = data
36
+ end
37
+
38
+
39
+ def data_encoding
40
+ digit_encodings.join
41
+ end
42
+
43
+ def data_encoding_with_checksum
44
+ data_encoding+checksum_encoding
45
+ end
46
+
47
+ def encoding
48
+ start_encoding+(include_checksum? ? data_encoding_with_checksum : data_encoding)+stop_encoding
49
+ end
50
+
51
+
52
+ def characters
53
+ data.split(//)
54
+ end
55
+
56
+ def digits
57
+ characters.map{|c| c.to_i }
58
+ end
59
+
60
+ def even_and_odd_digits
61
+ alternater = false
62
+ digits.reverse.partition{ alternater = !alternater }
63
+ end
64
+
65
+
66
+ def digit_encodings
67
+ digits.map{|d| encoding_for(d) }
68
+ end
69
+ alias character_encodings digit_encodings
70
+
71
+
72
+ #Returns the encoding for a single digit
73
+ def encoding_for(digit)
74
+ encoding_for_bars(ENCODINGS[digit])
75
+ end
76
+
77
+ #Generate encoding for an array of W,N
78
+ def encoding_for_bars(*bars)
79
+ wide, narrow, space = wide_encoding, narrow_encoding, space_encoding
80
+ bars.flatten.inject '' do |enc,bar|
81
+ enc + (bar == WIDE ? wide : narrow) + space
82
+ end
83
+ end
84
+
85
+
86
+ #Mod10
87
+ def checksum
88
+ evens, odds = even_and_odd_digits
89
+ sum = odds.inject(0){|sum,d| sum + d } + evens.inject(0){|sum,d| sum + (d*3) }
90
+ sum %= 10
91
+ sum.zero? ? 0 : 10-sum
92
+ end
93
+
94
+ def checksum_encoding
95
+ encoding_for(checksum)
96
+ end
97
+
98
+
99
+ #The width of a narrow bar in xdims
100
+ def narrow_width
101
+ @narrow_width || 1
102
+ end
103
+
104
+ #The width of a wide bar in xdims
105
+ #By default three times as wide as a narrow bar
106
+ def wide_width
107
+ @wide_width || narrow_width*3
108
+ end
109
+
110
+ #The width of the space between the bars in xdims
111
+ #By default the same width as a narrow bar
112
+ #
113
+ #A space serves only as a separator for the bars,
114
+ #there is no encoded meaning in them
115
+ def space_width
116
+ @space_width || narrow_width
117
+ end
118
+
119
+
120
+ def include_checksum?
121
+ include_checksum
122
+ end
123
+
124
+
125
+ def data=(data)
126
+ @data = "#{data}"
127
+ end
128
+
129
+
130
+ def start_encoding
131
+ encoding_for_bars(START_ENCODING)
132
+ end
133
+
134
+ def stop_encoding
135
+ #Removes trailing space generated by encoding_for_bars
136
+ encoding_for_bars(STOP_ENCODING).gsub(/0+$/, '')
137
+ end
138
+
139
+
140
+ def narrow_encoding
141
+ '1' * narrow_width
142
+ end
143
+
144
+ def wide_encoding
145
+ '1' * wide_width
146
+ end
147
+
148
+ def space_encoding
149
+ '0' * space_width
150
+ end
151
+
152
+
153
+ def valid?
154
+ data =~ /^[0-9]*$/
155
+ end
156
+
157
+
158
+ end
159
+
160
+
161
+ end
@@ -0,0 +1,73 @@
1
+ require 'barby/barcode/code_25'
2
+
3
+ module Barby
4
+
5
+ class Code25Interleaved < Code25
6
+
7
+ START_ENCODING = [N,N,N,N]
8
+ STOP_ENCODING = [W,N,N]
9
+
10
+
11
+ def data_encoding
12
+ digit_pair_encodings.join
13
+ end
14
+
15
+
16
+ def character_pairs
17
+ chars = characters
18
+ pairs = Array.new((chars.size/2.0).ceil){ [] }
19
+ chars.each_with_index{|c,i| pairs[(i/2.0).floor] << c }
20
+ pairs
21
+ end
22
+
23
+ def digit_pairs
24
+ d = digits
25
+ pairs = Array.new((d.size/2.0).ceil){ [] }
26
+ d.each_with_index{|dd,i| pairs[(i/2.0).floor] << dd }
27
+ pairs
28
+ end
29
+
30
+
31
+ def digit_pair_encodings
32
+ digit_pairs.map{|p| encoding_for_pair(p) }
33
+ end
34
+
35
+
36
+ def encoding_for_pair(pair)
37
+ bars, spaces = ENCODINGS[pair.first], ENCODINGS[pair.last]
38
+ bars.zip(spaces).inject '' do |enc,p|
39
+ bar, space = *p
40
+ enc + ('1' * (bar == WIDE ? wide_width : narrow_width)) +
41
+ ('0' * (space == WIDE ? wide_width : narrow_width))
42
+ end
43
+ end
44
+
45
+ #def encoding_for_bars(*bars_and_spaces)
46
+ # bar = false
47
+ # bars_and_spaces.flatten.inject '' do |enc,bar_or_space|
48
+ # bar = !bar
49
+ # enc + (bar ? '1' : '0')*(bar_or_space == WIDE ? wide_width : narrow_width)
50
+ # end
51
+ #end
52
+
53
+
54
+ def start_encoding
55
+ bar = false
56
+ START_ENCODING.inject '' do |enc,bar_or_space|
57
+ bar = !bar
58
+ enc << (bar ? '1' : '0') * (bar_or_space == WIDE ? wide_width : narrow_width)
59
+ end
60
+ end
61
+
62
+ def stop_encoding
63
+ bar = false
64
+ STOP_ENCODING.inject '' do |enc,bar_or_space|
65
+ bar = !bar
66
+ enc << (bar ? '1' : '0') * (bar_or_space == WIDE ? wide_width : narrow_width)
67
+ end
68
+ end
69
+
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,225 @@
1
+ require 'barby/barcode'
2
+
3
+ module Barby
4
+
5
+ class Code93 < Barcode1D
6
+
7
+ SHIFT_DOLLAR = "\301" # ($)
8
+ SHIFT_PERCENT = "\302" # (%)
9
+ SHIFT_SLASH = "\303" # (/)
10
+ SHIFT_PLUS = "\304" # (+)
11
+
12
+ SHIFT_CHARACTERS = [SHIFT_DOLLAR, SHIFT_PERCENT, SHIFT_SLASH, SHIFT_PLUS]
13
+
14
+ ENCODINGS = {
15
+ "0" => "100010100", "1" => "101001000",
16
+ "2" => "101000100", "3" => "101000010",
17
+ "4" => "100101000", "5" => "100100100",
18
+ "6" => "100100010", "7" => "101010000",
19
+ "8" => "100010010", "9" => "100001010",
20
+ "A" => "110101000", "B" => "110100100",
21
+ "C" => "110100010", "D" => "110010100",
22
+ "E" => "110010010", "F" => "110001010",
23
+ "G" => "101101000", "H" => "101100100",
24
+ "I" => "101100010", "J" => "100110100",
25
+ "K" => "100011010", "L" => "101011000",
26
+ "M" => "101001100", "N" => "101000110",
27
+ "O" => "100101100", "P" => "100010110",
28
+ "Q" => "110110100", "R" => "110110010",
29
+ "S" => "110101100", "T" => "110100110",
30
+ "U" => "110010110", "V" => "110011010",
31
+ "W" => "101101100", "X" => "101100110",
32
+ "Y" => "100110110", "Z" => "100111010",
33
+ "-" => "100101110", "." => "111010100",
34
+ " " => "111010010", "$" => "111001010",
35
+ "/" => "101101110", "+" => "101110110",
36
+ "%" => "110101110",
37
+ SHIFT_DOLLAR => "100100110",
38
+ SHIFT_PERCENT => "111011010",
39
+ SHIFT_SLASH => "111010110",
40
+ SHIFT_PLUS => "100110010"
41
+ }
42
+
43
+ EXTENDED_MAPPING = {
44
+ "\000" => "\302U", " " => " ", "@" => "\302V", "`" => "\302W",
45
+ "\001" => "\301A", "!" => "\303A", "A" => "A", "a" => "\304A",
46
+ "\002" => "\301B", '"' => "\303B", "B" => "B", "b" => "\304B",
47
+ "\003" => "\301C", "#" => "\303C", "C" => "C", "c" => "\304C",
48
+ "\004" => "\301D", "$" => "\303D", "D" => "D", "d" => "\304D",
49
+ "\005" => "\301E", "%" => "\303E", "E" => "E", "e" => "\304E",
50
+ "\006" => "\301F", "&" => "\303F", "F" => "F", "f" => "\304F",
51
+ "\007" => "\301G", "'" => "\303G", "G" => "G", "g" => "\304G",
52
+ "\010" => "\301H", "(" => "\303H", "H" => "H", "h" => "\304H",
53
+ "\011" => "\301I", ")" => "\303I", "I" => "I", "i" => "\304I",
54
+ "\012" => "\301J", "*" => "\303J", "J" => "J", "j" => "\304J",
55
+ "\013" => "\301K", "/" => "\303K", "K" => "K", "k" => "\304K",
56
+ "\014" => "\301L", "," => "\303L", "L" => "L", "l" => "\304L",
57
+ "\015" => "\301M", "-" => "-", "M" => "M", "m" => "\304M",
58
+ "\016" => "\301N", "." => ".", "N" => "N", "n" => "\304N",
59
+ "\017" => "\301O", "+" => "\303O", "O" => "O", "o" => "\304O",
60
+ "\020" => "\301P", "0" => "0", "P" => "P", "p" => "\304P",
61
+ "\021" => "\301Q", "1" => "1", "Q" => "Q", "q" => "\304Q",
62
+ "\022" => "\301R", "2" => "2", "R" => "R", "r" => "\304R",
63
+ "\023" => "\301S", "3" => "3", "S" => "S", "s" => "\304S",
64
+ "\024" => "\301T", "4" => "4", "T" => "T", "t" => "\304T",
65
+ "\025" => "\301U", "5" => "5", "U" => "U", "u" => "\304U",
66
+ "\026" => "\301V", "6" => "6", "V" => "V", "v" => "\304V",
67
+ "\027" => "\301W", "7" => "7", "W" => "W", "w" => "\304W",
68
+ "\030" => "\301X", "8" => "8", "X" => "X", "x" => "\304X",
69
+ "\031" => "\301Y", "9" => "9", "Y" => "Y", "y" => "\304Y",
70
+ "\032" => "\301Z", ":" => "\303Z", "Z" => "Z", "z" => "\304Z",
71
+ "\033" => "\302A", ";" => "\302F", "[" => "\302K", "{" => "\302P",
72
+ "\034" => "\302B", "<" => "\302G", "\\" => "\302L", "|" => "\302Q",
73
+ "\035" => "\302C", "=" => "\302H", "]" => "\302M", "}" => "\302R",
74
+ "\036" => "\302D", ">" => "\302I", "^" => "\302N", "~" => "\302S",
75
+ "\037" => "\302E", "?" => "\302J", "_" => "\302O", "\177" => "\302T"
76
+ }
77
+
78
+ EXTENDED_CHARACTERS = EXTENDED_MAPPING.keys - ENCODINGS.keys
79
+
80
+ CHARACTERS = {
81
+ 0 => "0", 1 => "1", 2 => "2", 3 => "3",
82
+ 4 => "4", 5 => "5", 6 => "6", 7 => "7",
83
+ 8 => "8", 9 => "9", 10 => "A", 11 => "B",
84
+ 12 => "C", 13 => "D", 14 => "E", 15 => "F",
85
+ 16 => "G", 17 => "H", 18 => "I", 19 => "J",
86
+ 20 => "K", 21 => "L", 22 => "M", 23 => "N",
87
+ 24 => "O", 25 => "P", 26 => "Q", 27 => "R",
88
+ 28 => "S", 29 => "T", 30 => "U", 31 => "V",
89
+ 32 => "W", 33 => "X", 34 => "Y", 35 => "Z",
90
+ 36 => "-", 37 => ".", 38 => " ", 39 => "$",
91
+ 40 => "/", 41 => "+", 42 => "%",
92
+ 43 => SHIFT_DOLLAR, 44 => SHIFT_PERCENT,
93
+ 45 => SHIFT_SLASH, 46 => SHIFT_PLUS
94
+ }
95
+
96
+ VALUES = CHARACTERS.invert
97
+
98
+ START_ENCODING = '101011110' # *
99
+ STOP_ENCODING = '101011110'
100
+ TERMINATE_ENCODING = '1'
101
+
102
+ attr_accessor :data
103
+
104
+
105
+ def initialize(data)
106
+ self.data = data
107
+ end
108
+
109
+
110
+ def extended?
111
+ raw_characters.any?{|c| EXTENDED_CHARACTERS.include?(c) }
112
+ end
113
+
114
+
115
+ def raw_characters
116
+ data.split(//)
117
+ end
118
+
119
+ def characters
120
+ raw_characters.map{|c| EXTENDED_MAPPING[c].split(//) }.flatten
121
+ end
122
+
123
+ def encoded_characters
124
+ characters.map{|c| ENCODINGS[c] }
125
+ end
126
+ alias character_encodings encoded_characters
127
+
128
+
129
+ def start_encoding
130
+ START_ENCODING
131
+ end
132
+
133
+ #The stop encoding includes the termination bar
134
+ def stop_encoding
135
+ STOP_ENCODING+TERMINATE_ENCODING
136
+ end
137
+
138
+
139
+ def encoding
140
+ start_encoding+data_encoding_with_checksums+stop_encoding
141
+ end
142
+
143
+ def data_encoding
144
+ character_encodings.join
145
+ end
146
+
147
+ def data_encoding_with_checksums
148
+ (character_encodings + checksum_encodings).join
149
+ end
150
+
151
+ def checksum_encodings
152
+ checksum_characters.map{|c| ENCODINGS[c] }
153
+ end
154
+
155
+ def checksum_encoding
156
+ checksum_encodings.join
157
+ end
158
+
159
+
160
+ def checksums
161
+ [c_checksum, k_checksum]
162
+ end
163
+
164
+ def checksum_characters
165
+ checksums.map{|s| CHARACTERS[s] }
166
+ end
167
+
168
+
169
+ #Returns the values used for computing the C checksum
170
+ #in the "right" order (i.e. reversed)
171
+ def checksum_values
172
+ characters.map{|c| VALUES[c] }.reverse
173
+ end
174
+
175
+ #Returns the normal checksum plus the c_checksum
176
+ #This is used for calculating the k_checksum
177
+ def checksum_values_with_c_checksum
178
+ [c_checksum] + checksum_values
179
+ end
180
+
181
+
182
+ #Calculates the C checksum based on checksum_values
183
+ def c_checksum
184
+ sum = 0
185
+ checksum_values.each_with_index do |value, index|
186
+ sum += ((index % 20) + 1) * value
187
+ end
188
+ sum % 47
189
+ end
190
+
191
+ def c_checksum_character
192
+ CHARACTERS[c_checksum]
193
+ end
194
+
195
+ def c_checksum_encoding
196
+ ENCODINGS[c_checksum_character]
197
+ end
198
+
199
+
200
+ #Calculates the K checksum based on checksum_values_with_c_checksum
201
+ def k_checksum
202
+ sum = 0
203
+ checksum_values_with_c_checksum.each_with_index do |value, index|
204
+ sum += ((index % 15) + 1) * value
205
+ end
206
+ sum % 47
207
+ end
208
+
209
+ def k_checksum_character
210
+ CHARACTERS[k_checksum]
211
+ end
212
+
213
+ def k_checksum_encoding
214
+ ENCODINGS[k_checksum_character]
215
+ end
216
+
217
+
218
+ def valid?
219
+ characters.all?{|c| ENCODINGS.include?(c) }
220
+ end
221
+
222
+
223
+ end
224
+
225
+ end