codecal 0.4.0 → 0.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a9497c1ebd3be3858b93cf5b998d449556a2db4
4
- data.tar.gz: 8746807358f6365760509bf8f7d43c99d75a25f2
3
+ metadata.gz: 906b6f9a01fba1bbe351b720d0c627b908cbd1fa
4
+ data.tar.gz: 936507f7d62bb95cd9a4a8b8de08e34fb25e8fa7
5
5
  SHA512:
6
- metadata.gz: 1e574f8ec7fab16a439e042a1035aa294e4159ca9b64db0558698fbf75e2e6352aa7f0802727aa5c08be275800f7db599feef5a246b800fc551a8c926a90ceb0
7
- data.tar.gz: 751d4f1609d91a2d0d7443b264ee2b91f210da0e29ef1617464faa6c9195ccf3822092a7006f08a4ce043d4b00849924eb41f9e9d5e3254496d992508745bb6a
6
+ metadata.gz: 610df9b32e98baaa6209e84aa83c0be8df835a20016b949421846639e8a4fb22dff19916d624e775ad4be5dd5ceb0c87516bfc75f40a8e524cdd67d8c5b26cb1
7
+ data.tar.gz: 0d55b7353a451a50464c27db02d743d1e72afce2475856b1185f4e6e4103207461e1c9bf4cebbc9f218ea62e17cf4deaa708d2e36d2e49f25e163cd240f9be24
data/.gitignore CHANGED
@@ -7,6 +7,6 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
-
10
+ .DS_Store
11
11
  # rspec failure tracking
12
12
  .rspec_status
data/README.md CHANGED
@@ -25,19 +25,9 @@ codecal = Codecal::Calc.new()
25
25
 
26
26
  codecal = Codecal::Calc.new('fdsa32jkh89704lncmxzvrueopwytq')
27
27
 
28
- # Generate customer code for user account
29
- # Parameters:
30
- # number : Integer(<=9) -- code to be calculated and masked
31
- # currency : String --currency name
32
- # Return: Hash
33
- # success : boolean -- generate customer code success
34
- # customer code : String -- 16 numbers string when success == true
35
- # error : String -- error message of parameters when success == false
36
- codecal.bank_customer_code_generate(number, currency)
37
-
38
28
  # Generate simple code for account
39
29
  # Parameters:
40
- # number : Integer(<=9) -- code to be calculated and masked
30
+ # number : Integer -- code to be calculated and masked
41
31
  # Return: Hash
42
32
  # success : boolean -- generate customer code success
43
33
  # customer code : String -- numbers(number.length + 1) string when success == true
@@ -54,13 +44,6 @@ codecal.simple_code_generate(number)
54
44
  # error : String -- error message of parameters when success == false
55
45
  codecal.code_generate_with_mask(mask, number)
56
46
 
57
- # Validate customer code
58
- # Parameters:
59
- # customer_code : String
60
- # Return:
61
- # valid : boolean
62
- codecal.validate_bank_customer_code(String)
63
-
64
47
  # Validate simple code
65
48
  # Parameters:
66
49
  # simple_code : String
@@ -83,10 +66,3 @@ codecal.validate_masked_code(String)
83
66
  # Return:
84
67
  # code : String(>=6) || false : boolean
85
68
  codecal.get_unmasked_code(String)
86
-
87
- # Get currency name
88
- # Parameters:
89
- # currency_code : String(4)
90
- # Return:
91
- # currency name : String -- nil if not found
92
- codecal.get_currency_name(String)
@@ -1,12 +1,16 @@
1
1
  require "codecal/version"
2
- require_relative "./code"
2
+ require_relative "./lib/modulo"
3
+ require_relative "./lib/mask"
4
+ require_relative "./lib/validation"
3
5
 
4
6
  module Codecal
5
7
 
6
8
  class Calc
7
- @@MASK_ALPHABET = ['a','4','p','9','h','r','7','q','c','3','b','2','j','s','6','d','t','8','k','u','e','v','f','w','x','5','m','y','g','z','n']
8
- @@generate_seed = [2,7,5,3,8,9,5,9,1,6,7,3,5]
9
- @@simple_seed = [5,4,6,2,3,1,5,4,6,2,3,1]
9
+ include Validation
10
+ include Modulo
11
+ include Mask
12
+
13
+ @@MASK_ALPHABET = ['a','4','p','9','h','r','7','q','c','3','b','2','j','s','6','d','t','8','k','u','e','v','f','w','x','5','m','y','g','z','n']
10
14
 
11
15
  def initialize(mask_alphabet = nil)
12
16
  if mask_alphabet.is_a?(String) &&
@@ -15,61 +19,38 @@ module Codecal
15
19
  mask_alphabet.size == mask_alphabet.split('').uniq.size
16
20
  @mask_alphabet = mask_alphabet.split('')
17
21
  else
18
- @mask_alphabet = @@MASK_ALPHABET
19
- end
20
- end
21
-
22
- def bank_customer_code_generate(account_id, currency)
23
- errormsg = ""
24
- if account_id == nil || currency == nil
25
- errormsg += "parameter is nil. "
26
- return {success:false, error: errormsg}
27
- end
28
- errormsg += "parameter 1 type should be Integer and length not longer than 9. " unless account_id.is_a?(Integer) && account_id.to_s.size <= 9
29
- currency.is_a?(String) ? currency.upcase! : errormsg += "parameter 2 type should be String. "
30
- currency_code = Code.new[currency]
31
- errormsg += "currency not found. " unless currency_code
32
- if errormsg.size == 0
33
- cal_array = ("%09d" % account_id + "%04d" % currency_code.to_i).split("").map! {|i| i.to_i}
34
- {success:true,customer_code: code_calculate(cal_array, @@generate_seed) }
35
- else
36
- {success:false, error: errormsg}
22
+ @mask_alphabet = @@MASK_ALPHABET
37
23
  end
38
24
  end
39
25
 
40
- def simple_code_generate(account_id)
26
+ def simple_code_generate(number)
41
27
  errormsg = ""
42
- if account_id == nil
28
+ if number == nil
43
29
  errormsg += "parameter is nil. "
44
30
  return {success:false, error: errormsg}
45
31
  end
46
- errormsg += "the type of the code to be encrypted should be Integer. " unless all_digits?(account_id.to_s)
32
+ errormsg += "the type of the code to be encrypted should be Integer. " unless all_digits?(number.to_s)
47
33
  if errormsg.size == 0
48
- cal_array = (account_id.to_i.to_s).split("").map! {|i| i.to_i}
49
- {success:true,customer_code: simple_code_calculate(cal_array, @@simple_seed) }
34
+ cal_array = (number.to_i.to_s).split("").map! {|i| i.to_i}
35
+ {success:true, customer_code: simple_code_calculate(cal_array) }
50
36
  else
51
37
  {success:false, error: errormsg}
52
38
  end
53
39
  end
54
40
 
55
- def code_generate_with_mask(mask, account_id)
41
+ def code_generate_with_mask(mask, number)
56
42
  errormsg = "mark should be string of letter or number and length should >= 5" unless is_legal_mask?(mask)
57
43
  return {success:false, error: errormsg} if errormsg
58
- result = simple_code_generate(account_id)
44
+ result = simple_code_generate(number)
59
45
  return result unless result[:success]
60
46
  offset = get_mask_offset(mask)
47
+ # puts "masked code: #{result[:customer_code]}"
61
48
  {success:true, customer_code: mask_code(offset, result[:customer_code])}
62
49
  end
63
50
 
64
- def validate_bank_customer_code(customer_code)
65
- return false unless customer_code && customer_code.is_a?(String) && customer_code.size == 16
66
- calcode = code_calculate(customer_code[0..12].split("").map! {|i| i.to_i}, @@generate_seed)
67
- return customer_code == calcode
68
- end
69
-
70
51
  def validate_simple_code(simple_code)
71
52
  return false unless simple_code && simple_code.to_i > 0 && simple_code.size > 1
72
- calcode = simple_code_calculate(simple_code[0..-2].split("").map! {|i| i.to_i}, @@simple_seed)
53
+ calcode = simple_code_calculate(simple_code[0..-2].split("").map! {|i| i.to_i})
73
54
  return simple_code == calcode
74
55
  end
75
56
 
@@ -85,10 +66,6 @@ module Codecal
85
66
  return masked_code == mask_code(offset, result[:customer_code])
86
67
  end
87
68
 
88
- def convert_masked_code_typo(masked_code)
89
- masked_code.gsub('1', 'l')
90
- end
91
-
92
69
  def get_unmasked_code(mask, masked_code)
93
70
  return false unless is_legal_masked_code?(masked_code)
94
71
  return false unless is_legal_mask?(mask)
@@ -99,87 +76,5 @@ module Codecal
99
76
  masked_code.size == code.size ? code : false
100
77
  end
101
78
 
102
- def get_currency_name(currency_code)
103
- return nil if !currency_code || currency_code.size !=4 || !currency_code.is_a?(String)
104
- return Code.new.get_name(currency_code)
105
- end
106
-
107
- private
108
- def code_calculate(array, seed)
109
- code = array.each_with_index.inject(0){|count, (i, index)| count += i*seed[index]}
110
- return array.join + ("%03d" % code).to_s
111
- end
112
-
113
- def simple_code_calculate(array, seed)
114
- code = array.reverse.each_with_index.inject(0){|count, (i, index)| count += i*( index < 11 ? seed.reverse[index + 1] : (index+1).times.inject(1) {|c| c *= 3} % 7 ) }
115
- return (array.join + ( code % 7 ).to_s).to_i.to_s
116
- end
117
-
118
- def mask_code(offset, code)
119
- code_arr = code.size > 5 ? code.split("") : ("%06d" % code).split("")
120
- masked_code = code_arr.each_with_index.inject([]) do |code, (c, i)|
121
- code.push(mask_char(c, offset[ i % offset.size ]))
122
- end
123
- start_code = masked_code.pop
124
- masked_code.unshift(start_code).join
125
- end
126
-
127
- def unmask_code(offset, masked_code)
128
- masked_code = masked_code[1..-1] + masked_code[0]
129
- code = masked_code.downcase.split("").each_with_index.inject([]) do |code, (c, i)|
130
- code.push(un_mask_char(c, offset[ i % offset.size ]))
131
- end
132
- code.join
133
- end
134
-
135
- def get_mask_offset(mask)
136
- mask.split("").inject([]) do |offset,c|
137
- [[*'a'..'z'], [*'A'..'Z'], [*'0'..'9']].each do |m|
138
- if m.include?(c)
139
- offset.push(m.find_index(c))
140
- break
141
- end
142
- end
143
- offset
144
- end
145
- end
146
-
147
- def all_letters_or_digits?(str)
148
- str[/[a-zA-Z0-9]+/] == str
149
- end
150
-
151
- def all_digits?(str)
152
- str[/[0-9]+/] == str
153
- end
154
-
155
- def is_legal_mask?(mask)
156
- return false if !mask.is_a?(String) || mask.size < 6 || !all_letters_or_digits?(mask)
157
- return true
158
- end
159
-
160
- def is_legal_masked_code?(masked_code)
161
- return false unless masked_code.is_a?(String) && masked_code.size > 5
162
- return false unless mask_alphabet_include?(masked_code)
163
- return true
164
- end
165
-
166
- def mask_alphabet_include?(code)
167
- code.split('').each do |c|
168
- return false unless @mask_alphabet.include?(c)
169
- end
170
- true
171
- end
172
-
173
- def mask_char(char, offset)
174
- if all_digits?(char) && char.size == 1
175
- @mask_alphabet[(@mask_alphabet.find_index(@mask_alphabet[char.to_i]) + offset) % @mask_alphabet.size]
176
- end
177
- end
178
-
179
- def un_mask_char(char, offset)
180
- if mask_alphabet_include?(char)
181
- (@mask_alphabet.find_index(char) - offset) % @mask_alphabet.size
182
- end
183
- end
184
79
  end
185
80
  end
@@ -1,3 +1,3 @@
1
1
  module Codecal
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -0,0 +1,55 @@
1
+ module Codecal
2
+ module Mask
3
+ def mask_code(offset, code)
4
+ code_arr = code.size > 5 ? code.split("") : ("%06d" % code).split("")
5
+ masked_code = code_arr.each_with_index.inject([]) do |codes, (c, i)|
6
+ codes.push(mask_char(c, offset[ i % offset.size ]))
7
+ end
8
+ start_code = masked_code.pop
9
+ masked_code.unshift(start_code).join
10
+ end
11
+
12
+ def unmask_code(offset, masked_code)
13
+ masked_code = masked_code[1..-1] + masked_code[0]
14
+ masked_code.downcase.split("").each_with_index.inject([]) do |code, (c, i)|
15
+ code.push(un_mask_char(c, offset[ i % offset.size ]))
16
+ end.join
17
+ end
18
+
19
+ def get_mask_offset(mask)
20
+ mask.split("").inject([]) do |offset,c|
21
+ [[*'a'..'z'], [*'A'..'Z'], [*'0'..'9']].each do |m|
22
+ if m.include?(c)
23
+ offset.push(m.find_index(c))
24
+ break
25
+ end
26
+ end
27
+ offset
28
+ end
29
+ end
30
+
31
+ def mask_alphabet_include?(code)
32
+ code.split('').each do |c|
33
+ return false unless @mask_alphabet.include?(c)
34
+ end
35
+ true
36
+ end
37
+
38
+ def mask_char(char, offset)
39
+ if all_digits?(char) && char.size == 1
40
+ @mask_alphabet[(@mask_alphabet.find_index(@mask_alphabet[char.to_i]) + offset) % @mask_alphabet.size]
41
+ end
42
+ end
43
+
44
+ def un_mask_char(char, offset)
45
+ if mask_alphabet_include?(char)
46
+ (@mask_alphabet.find_index(char) - offset) % @mask_alphabet.size
47
+ end
48
+ end
49
+
50
+ # not used
51
+ def convert_masked_code_typo(masked_code)
52
+ masked_code.gsub('1', 'l')
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,46 @@
1
+ # this is a modulo 17 Galois field
2
+
3
+ module Codecal
4
+ module Modulo
5
+ ## module 7
6
+ @@MODULO_NUMBER = 7
7
+ @@MODULO_WEIGHT = [5,4,6,2,3,1,5,4,6,2,3,1]
8
+ ## module 17
9
+ # @@MODULO_NUMBER = 17
10
+ # @@MODULO_WEIGHT = %w[01 06 02 12 04 07 08 14 16 11 15 05 13 10 09 03 01]
11
+ ## module 11
12
+ # @@MODULO_NUMBER = 11
13
+ # @@MODULO_WEIGHT = %w[07 09 10 05 08 04 02 01 06 03 07 09 10 05 08 04 02 01]
14
+ ## module 13
15
+ # @@MODULO_NUMBER = 13
16
+ # @@MODULO_WEIGHT = %w[3 8 4 2 1 7 10 5 9 11 12 6 3 8 4 2 1]
17
+ @@SEVENTEEN_SYMBOL = '0123456789abcdefg'
18
+
19
+ def simple_code_calculate(int_array)
20
+ code = int_array.reverse.each_with_index.inject(0) do |count, (i, index)|
21
+ count += i * ( index < @@MODULO_WEIGHT.size ?
22
+ @@MODULO_WEIGHT.reverse[index + 1].to_i :
23
+ ( index + 1 ).times.inject(1) { |c| c *= 3 } % @@MODULO_NUMBER
24
+ )
25
+ end
26
+ symbol = convert_to_symbol(code % @@MODULO_NUMBER)
27
+ (int_array.join + symbol).to_i.to_s
28
+ end
29
+
30
+ # def simple_code_calculate(array)
31
+ # code = array.reverse.each_with_index.inject(0){|count, (i, index)| count += i*( index < 11 ? @@MODULO_WEIGHT.reverse[index + 1] : (index+1).times.inject(1) {|c| c *= 3} % 7 ) }
32
+ # return (array.join + ( code % 7 ).to_s).to_i.to_s
33
+ # end
34
+
35
+ private
36
+
37
+ def convert_to_symbol(number)
38
+ @@SEVENTEEN_SYMBOL[number]
39
+ end
40
+
41
+ def convert_to_number(symbol)
42
+ @@SEVENTEEN_SYMBOL.find_index(symbol)
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,22 @@
1
+ module Codecal
2
+ module Validation
3
+ def all_letters_or_digits?(str)
4
+ str[/[a-zA-Z0-9]+/] == str
5
+ end
6
+
7
+ def all_digits?(str)
8
+ str[/[0-9]+/] == str
9
+ end
10
+
11
+ def is_legal_mask?(mask)
12
+ return false if !mask.is_a?(String) || mask.size < 6 || !all_letters_or_digits?(mask)
13
+ return true
14
+ end
15
+
16
+ def is_legal_masked_code?(masked_code)
17
+ return false unless masked_code.is_a?(String) && masked_code.size > 5
18
+ return false unless mask_alphabet_include?(masked_code)
19
+ return true
20
+ end
21
+ end
22
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codecal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roger Fang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-05 00:00:00.000000000 Z
11
+ date: 2018-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -73,6 +73,7 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
+ - ".DS_Store"
76
77
  - ".gitignore"
77
78
  - ".rspec"
78
79
  - ".ruby-version"
@@ -86,10 +87,11 @@ files:
86
87
  - bin/console
87
88
  - bin/setup
88
89
  - codecal.gemspec
89
- - lib/code.rb
90
90
  - lib/codecal.rb
91
91
  - lib/codecal/version.rb
92
- - lib/currencies.yml
92
+ - lib/lib/mask.rb
93
+ - lib/lib/modulo.rb
94
+ - lib/lib/validation.rb
93
95
  homepage: https://github.com/roger-fang-bct/codecal.git
94
96
  licenses:
95
97
  - MIT
@@ -1,19 +0,0 @@
1
- require 'yaml'
2
-
3
-
4
- class Code
5
- def data
6
- @data ||= begin
7
- YAML.load_file(File.join(File.dirname(__FILE__),"currencies.yml"))
8
- end
9
- end
10
-
11
- def [] key
12
- data[key]
13
- end
14
-
15
- def get_name value
16
- data.key(value)
17
- end
18
-
19
- end