zxcvbn 0.1.1 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f102d8ba269aad3742c05649bbb698c01d639ee794c8adc9abe66fb285674f42
4
- data.tar.gz: 2f01f158959ed48ad413bb91970c7824efeb42392aca97b91e4d1be50a149e47
3
+ metadata.gz: 8ed77be628881ddd6bd6df0f7a60935e193db7cf91f5c928319eed9ac24295bf
4
+ data.tar.gz: 20906d11011e8ab3f95dcc9f20cae21b6945999a979b11c452b23f02726abda6
5
5
  SHA512:
6
- metadata.gz: c05246356ff182b57ca9acd01b6ee95269c4264a5d9cb1d947229de9ee9974e30a3860e4d860cec946c1ef22d9d9baa90dcf2f89bf843d8f5c749b3a0d64867c
7
- data.tar.gz: 1dc9944425d5a9105ebe59eb0b1dab1a06bb98ff94e032b476714ebc23281560ea78a0ffebb4a086f7da42a6fdcd1502f296a1f45f84d94b99d63461d00c25eb
6
+ metadata.gz: a6ac81d9c47f5f4a006b7e5e071f0f2fd119d0f9f721d28d7725ab07f8eafa4478f727652b7e51a87d82d5022e761550cecc6f83ff2f38b8cd0171d51061f97b
7
+ data.tar.gz: ec59a970bc9037714b93c3d73738b995afa224c25cdca4dd8309e74f7e11df58fe7f618f72805ea004f23ac3387a8f98fa2548d9d2c00419231f7e0e07307db7
data/.rubocop.yml CHANGED
@@ -1,5 +1,31 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.5
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+
6
+ Layout/EndAlignment:
7
+ EnforcedStyleAlignWith: start_of_line
8
+
9
+ Layout/LineLength:
10
+ Max: 120
11
+
12
+ Lint/UnderscorePrefixedVariableName:
13
+ Enabled: false
14
+
15
+ Metrics:
16
+ Enabled: false
17
+
18
+ Naming/VariableNumber:
19
+ Enabled: false
20
+
21
+ Style/Documentation:
22
+ Enabled: false
23
+
24
+ Style/Next:
25
+ Enabled: false
26
+
27
+ Style/NumericPredicate:
28
+ Enabled: false
3
29
 
4
30
  Style/StringLiterals:
5
31
  Enabled: true
@@ -9,5 +35,11 @@ Style/StringLiteralsInInterpolation:
9
35
  Enabled: true
10
36
  EnforcedStyle: double_quotes
11
37
 
12
- Layout/LineLength:
13
- Max: 120
38
+ Style/NegatedIf:
39
+ Enabled: false
40
+
41
+ Style/SymbolArray:
42
+ Enabled: false
43
+
44
+ Style/WordArray:
45
+ Enabled: false
data/.travis.yml CHANGED
@@ -2,5 +2,5 @@
2
2
  language: ruby
3
3
  cache: bundler
4
4
  rvm:
5
- - 2.6.6
5
+ - 2.5.9
6
6
  before_install: gem install bundler -v 2.2.15
data/CHANGELOG.md CHANGED
@@ -1,4 +1,14 @@
1
- ## [Unreleased]
1
+ ## [0.1.6] - 2021-05-28
2
+ - Added test methods for compatibility with zxcvbn-js and zxcvbn-ruby.
3
+
4
+ ## [0.1.5] - 2021-05-27
5
+ - Fix classification of scoring causing differences between js and ruby.
6
+
7
+ ## [0.1.4] - 2021-05-16
8
+
9
+ - Bunch of fixes, all example passwords included have same result as js version.
10
+ - consistent code style applied.
11
+
2
12
 
3
13
  ## [0.1.0] - 2021-05-16
4
14
 
data/Gemfile CHANGED
@@ -5,8 +5,13 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in zxcvbn.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.0"
8
+ group :development do
9
+ gem "mini_racer"
10
+ gem "rake", "~> 13.0"
11
+ gem "rspec", "~> 3.0"
12
+ gem "rubocop", "~> 1.7"
9
13
 
10
- gem "rspec", "~> 3.0"
11
-
12
- gem "rubocop", "~> 1.7"
14
+ gem "pry"
15
+ gem "pry-byebug"
16
+ gem "simplecov", require: false
17
+ end
data/Gemfile.lock CHANGED
@@ -1,16 +1,30 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- zxcvbn (0.1.0)
4
+ zxcvbn (0.1.6)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.2)
10
+ byebug (11.1.3)
11
+ coderay (1.1.3)
10
12
  diff-lcs (1.4.4)
13
+ docile (1.4.0)
14
+ libv8-node (15.14.0.1-x86_64-darwin-19)
15
+ libv8-node (15.14.0.1-x86_64-linux)
16
+ method_source (1.0.0)
17
+ mini_racer (0.4.0)
18
+ libv8-node (~> 15.14.0.0)
11
19
  parallel (1.20.1)
12
20
  parser (3.0.1.1)
13
21
  ast (~> 2.4.1)
22
+ pry (0.14.1)
23
+ coderay (~> 1.1)
24
+ method_source (~> 1.0)
25
+ pry-byebug (3.8.0)
26
+ byebug (~> 11.0)
27
+ pry (~> 0.10)
14
28
  rainbow (3.0.0)
15
29
  rake (13.0.3)
16
30
  regexp_parser (2.1.1)
@@ -40,15 +54,26 @@ GEM
40
54
  rubocop-ast (1.5.0)
41
55
  parser (>= 3.0.1.1)
42
56
  ruby-progressbar (1.11.0)
57
+ simplecov (0.21.2)
58
+ docile (~> 1.1)
59
+ simplecov-html (~> 0.11)
60
+ simplecov_json_formatter (~> 0.1)
61
+ simplecov-html (0.12.3)
62
+ simplecov_json_formatter (0.1.3)
43
63
  unicode-display_width (2.0.0)
44
64
 
45
65
  PLATFORMS
46
66
  x86_64-darwin-19
67
+ x86_64-linux
47
68
 
48
69
  DEPENDENCIES
70
+ mini_racer
71
+ pry
72
+ pry-byebug
49
73
  rake (~> 13.0)
50
74
  rspec (~> 3.0)
51
75
  rubocop (~> 1.7)
76
+ simplecov
52
77
  zxcvbn!
53
78
 
54
79
  BUNDLED WITH
data/README.md CHANGED
@@ -1,7 +1,11 @@
1
1
  # Zxcvbn
2
2
 
3
- This is a direct Ruby port of Dropbox's [zxcvbn.js][zxcvbn.js] JavaScript library.
4
- The intention is to provide all the same features and same results as close to the original JS fucntion would do.
3
+ [![Gem Version](https://badge.fury.io/rb/zxcvbn.svg)](https://badge.fury.io/rb/zxcvbn)
4
+ [![Build Status](https://travis-ci.com/formigarafa/zxcvbn-rb.svg?branch=master)](https://travis-ci.com/formigarafa/zxcvbn-rb)
5
+
6
+ Ruby port of Dropbox's [zxcvbn.js][zxcvbn.js] JavaScript library running completely in Ruby (no need to load execjs or libv8).
7
+
8
+ The intention is to provide an option 100% Ruby solution with all the same features and same results (or as close to the original JS function as possible).
5
9
 
6
10
  ## Installation
7
11
 
@@ -24,49 +28,53 @@ Or install it yourself as:
24
28
  ```
25
29
  Zxcvbn.zxcvbn("password")
26
30
  => {
27
- :password => "pasword",
28
- :guesses => 3566,
29
- :guesses_log10 => 3.5521813388393357,
30
- :sequence => [
31
+ "password" => "password",
32
+ "guesses" => 3,
33
+ "guesses_log10" => 0.47712125471966244,
34
+ "sequence" => [
31
35
  {
32
- :pattern => "dictionary",
33
- :i => 0,
34
- :j => 6,
35
- :token => "pasword",
36
- :matched_word => "pasword",
37
- :rank => 3565,
38
- :dictionary_name => "passwords",
39
- :reversed => false,
40
- :l33t => false,
41
- :base_guesses => 3565,
42
- :uppercase_variations => 1,
43
- :l33t_variations => 1,
44
- :guesses => 3565,
45
- :guesses_log10 => 3.5520595341878844
36
+ "pattern" => "dictionary",
37
+ "i" => 0,
38
+ "j" => 7,
39
+ "token" => "password",
40
+ "matched_word" => "password",
41
+ "rank" => 2,
42
+ "dictionary_name" => "passwords",
43
+ "reversed" => false,
44
+ "l33t" => false,
45
+ "base_guesses" => 2,
46
+ "uppercase_variations" => 1,
47
+ "l33t_variations" => 1,
48
+ "guesses" => 2,
49
+ "guesses_log10" => 0.3010299956639812
46
50
  }
47
51
  ],
48
- :calc_time => 0,
49
- :crack_times_seconds => {
50
- :online_throttling_100_per_hour => 128376.0,
51
- :online_no_throttling_10_per_second => 356.6,
52
- :offline_slow_hashing_1e4_per_second => 0.3566,
53
- :offline_fast_hashing_1e10_per_second => 3.566e-07
54
- },
55
- :crack_times_display => {
56
- :online_throttling_100_per_hour => "1 day",
57
- :online_no_throttling_10_per_second => "6 minutes",
58
- :offline_slow_hashing_1e4_per_second => "less than a second",
59
- :offline_fast_hashing_1e10_per_second => "less than a second"
52
+ "calc_time" => 1,
53
+ "crack_times_seconds" => {
54
+ "online_throttling_100_per_hour" => 108.0,
55
+ "online_no_throttling_10_per_second" => 0.3,
56
+ "offline_slow_hashing_1e4_per_second" => 0.0003,
57
+ "offline_fast_hashing_1e10_per_second" => 3.0e-10},
58
+ "crack_times_display" => {
59
+ "online_throttling_100_per_hour" => "2 minutes",
60
+ "online_no_throttling_10_per_second" => "less than a second",
61
+ "offline_slow_hashing_1e4_per_second" => "less than a second",
62
+ "offline_fast_hashing_1e10_per_second" => "less than a second"
60
63
  },
61
- :score => 1,
62
- :feedback =>
63
- {
64
- :warning => "This is a very common password",
65
- :suggestions => ["Add another word or two. Uncommon words are better."]
64
+ "score" => 0,
65
+ "feedback" => {
66
+ "warning" => "This is a top-10 common password",
67
+ "suggestions" => [
68
+ "Add another word or two. Uncommon words are better."
69
+ ]
66
70
  }
67
71
  }
68
72
  ```
69
73
 
74
+ ### Compatible with `zxcvbn-js` and `zxcvbn-ruby`
75
+
76
+ This gem include a compatible interface so it can be used as a drop-in substitution for `zxcvbn-js` or `zxcvbn-ruby`. You can just call `Zxcvbn.test` or use `Zxcvbn::Tester.new` the same way as you would if you were using `zxcvbn-js` or `zxcvbn-ruby`.
77
+
70
78
  ## Development
71
79
 
72
80
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/bin/console CHANGED
@@ -11,5 +11,8 @@ require "zxcvbn"
11
11
  # require "pry"
12
12
  # Pry.start
13
13
 
14
- require "irb"
15
- IRB.start(__FILE__)
14
+ # require "irb"
15
+ # IRB.start(__FILE__)
16
+
17
+ require "pry"
18
+ Pry.start("main")
data/lib/zxcvbn.rb CHANGED
@@ -14,21 +14,29 @@ module Zxcvbn
14
14
  def self.zxcvbn(password, user_inputs = [])
15
15
  start = (Time.now.to_f * 1000).to_i
16
16
  # reset the user inputs matcher on a per-request basis to keep things stateless
17
- sanitized_inputs = [];
17
+ sanitized_inputs = []
18
18
  user_inputs.each do |arg|
19
- if arg.is_a?(String) || arg.is_a?(Numeric) || arg == true || arg == false
20
- sanitized_inputs << arg.to_s.downcase
21
- end
19
+ sanitized_inputs << arg.to_s.downcase if arg.is_a?(String) || arg.is_a?(Numeric) || arg == true || arg == false
22
20
  end
23
- Matching.set_user_input_dictionary(sanitized_inputs)
21
+ Matching.user_input_dictionary = sanitized_inputs
24
22
  matches = Matching.omnimatch(password)
25
23
  result = Scoring.most_guessable_match_sequence(password, matches)
26
- result[:calc_time] = (Time.now.to_f * 1000).to_i - start
27
- attack_times = TimeEstimates.estimate_attack_times(result[:guesses])
24
+ result["calc_time"] = (Time.now.to_f * 1000).to_i - start
25
+ attack_times = TimeEstimates.estimate_attack_times(result["guesses"])
28
26
  attack_times.each do |prop, val|
29
27
  result[prop] = val
30
28
  end
31
- result[:feedback] = Feedback.get_feedback(result[:score], result[:sequence])
32
- return result
29
+ result["feedback"] = Feedback.get_feedback(result["score"], result["sequence"])
30
+ result
31
+ end
32
+
33
+ def self.test(password, user_inputs = [])
34
+ OpenStruct.new(Zxcvbn.zxcvbn(password, user_inputs))
35
+ end
36
+
37
+ class Tester
38
+ def test(password, user_inputs = [])
39
+ Zxcvbn.test(password, user_inputs)
40
+ end
33
41
  end
34
42
  end
@@ -2,10 +2,12 @@
2
2
 
3
3
  # generated by scripts/build_keyboard_adjacency_graphs.py
4
4
  module Zxcvbn
5
+ # rubocop:disable Layout/SpaceInsideArrayLiteralBrackets
6
+ # rubocop:disable Layout/ExtraSpacing
5
7
  ADJACENCY_GRAPHS = {
6
- qwerty: {
8
+ "qwerty" => {
7
9
  "!" => ["`~", nil, nil, "2@", "qQ", nil],
8
- "\"" => [";:", "[{", "]}", nil, nil, "/?"],
10
+ "\"" => [";:", "[{", "]}", nil, nil, "/?"],
9
11
  "#" => ["2@", nil, nil, "4$", "eE", "wW"],
10
12
  "$" => ["3#", nil, nil, "5%", "rR", "eE"],
11
13
  "%" => ["4$", nil, nil, "6^", "tT", "rR"],
@@ -18,7 +20,7 @@ module Zxcvbn
18
20
  "," => ["mM", "kK", "lL", ".>", nil, nil],
19
21
  "-" => ["0)", nil, nil, "=+", "[{", "pP"],
20
22
  "." => [",<", "lL", ";:", "/?", nil, nil],
21
- "/" => [".>", ";:", "'\"", nil, nil, nil],
23
+ "/" => [".>", ";:", "'\"", nil, nil, nil],
22
24
  "0" => ["9(", nil, nil, "-_", "pP", "oO"],
23
25
  "1" => ["`~", nil, nil, "2@", "qQ", nil],
24
26
  "2" => ["1!", nil, nil, "3#", "wW", "qQ"],
@@ -34,7 +36,7 @@ module Zxcvbn
34
36
  "<" => ["mM", "kK", "lL", ".>", nil, nil],
35
37
  "=" => ["-_", nil, nil, nil, "]}", "[{"],
36
38
  ">" => [",<", "lL", ";:", "/?", nil, nil],
37
- "?" => [".>", ";:", "'\"", nil, nil, nil],
39
+ "?" => [".>", ";:", "'\"", nil, nil, nil],
38
40
  "@" => ["1!", nil, nil, "3#", "wW", "qQ"],
39
41
  "A" => [ nil, "qQ", "wW", "sS", "zZ", nil],
40
42
  "B" => ["vV", "gG", "hH", "nN", nil, nil],
@@ -63,8 +65,8 @@ module Zxcvbn
63
65
  "Y" => ["tT", "6^", "7&", "uU", "hH", "gG"],
64
66
  "Z" => [ nil, "aA", "sS", "xX", nil, nil],
65
67
  "[" => ["pP", "-_", "=+", "]}", "'\"", ";:"],
66
- "\\" => ["]}", nil, nil, nil, nil, nil],
67
- "]" => ["[{", "=+", nil, "\\|", nil, "'\""],
68
+ "\\" => ["]}", nil, nil, nil, nil, nil],
69
+ "]" => ["[{", "=+", nil, "\\|", nil, "'\""],
68
70
  "^" => ["5%", nil, nil, "7&", "yY", "tT"],
69
71
  "_" => ["0)", nil, nil, "=+", "[{", "pP"],
70
72
  "`" => [ nil, nil, nil, "1!", nil, nil],
@@ -96,12 +98,12 @@ module Zxcvbn
96
98
  "z" => [ nil, "aA", "sS", "xX", nil, nil],
97
99
  "{" => ["pP", "-_", "=+", "]}", "'\"", ";:"],
98
100
  "|" => ["]}", nil, nil, nil, nil, nil],
99
- "}" => ["[{", "=+", nil, "\\|", nil, "'\""],
101
+ "}" => ["[{", "=+", nil, "\\|", nil, "'\""],
100
102
  "~" => [ nil, nil, nil, "1!", nil, nil]
101
103
  },
102
- dvorak: {
103
- "!" => ["`~", nil, nil, "2@", "'\"", nil],
104
- "\"" => [ nil, "1!", "2@", ",<", "aA", nil],
104
+ "dvorak" => {
105
+ "!" => ["`~", nil, nil, "2@", "'\"", nil],
106
+ "\"" => [ nil, "1!", "2@", ",<", "aA", nil],
105
107
  "#" => ["2@", nil, nil, "4$", ".>", ",<"],
106
108
  "$" => ["3#", nil, nil, "5%", "pP", ".>"],
107
109
  "%" => ["4$", nil, nil, "6^", "yY", "pP"],
@@ -110,13 +112,13 @@ module Zxcvbn
110
112
  "(" => ["8*", nil, nil, "0)", "rR", "cC"],
111
113
  ")" => ["9(", nil, nil, "[{", "lL", "rR"],
112
114
  "*" => ["7&", nil, nil, "9(", "cC", "gG"],
113
- "+" => ["/?", "]}", nil, "\\|", nil, "-_"],
115
+ "+" => ["/?", "]}", nil, "\\|", nil, "-_"],
114
116
  "," => ["'\"", "2@", "3#", ".>", "oO", "aA"],
115
117
  "-" => ["sS", "/?", "=+", nil, nil, "zZ"],
116
118
  "." => [",<", "3#", "4$", "pP", "eE", "oO"],
117
119
  "/" => ["lL", "[{", "]}", "=+", "-_", "sS"],
118
120
  "0" => ["9(", nil, nil, "[{", "lL", "rR"],
119
- "1" => ["`~", nil, nil, "2@", "'\"", nil],
121
+ "1" => ["`~", nil, nil, "2@", "'\"", nil],
120
122
  "2" => ["1!", nil, nil, "3#", ",<", "'\""],
121
123
  "3" => ["2@", nil, nil, "4$", ".>", ",<"],
122
124
  "4" => ["3#", nil, nil, "5%", "pP", ".>"],
@@ -132,7 +134,7 @@ module Zxcvbn
132
134
  ">" => [",<", "3#", "4$", "pP", "eE", "oO"],
133
135
  "?" => ["lL", "[{", "]}", "=+", "-_", "sS"],
134
136
  "@" => ["1!", nil, nil, "3#", ",<", "'\""],
135
- "A" => [ nil, "'\"", ",<", "oO", ";:", nil],
137
+ "A" => [ nil, "'\"", ",<", "oO", ";:", nil],
136
138
  "B" => ["xX", "dD", "hH", "mM", nil, nil],
137
139
  "C" => ["gG", "8*", "9(", "rR", "tT", "hH"],
138
140
  "D" => ["iI", "fF", "gG", "hH", "bB", "xX"],
@@ -159,12 +161,12 @@ module Zxcvbn
159
161
  "Y" => ["pP", "5%", "6^", "fF", "iI", "uU"],
160
162
  "Z" => ["vV", "sS", "-_", nil, nil, nil],
161
163
  "[" => ["0)", nil, nil, "]}", "/?", "lL"],
162
- "\\" => ["=+", nil, nil, nil, nil, nil],
164
+ "\\" => ["=+", nil, nil, nil, nil, nil],
163
165
  "]" => ["[{", nil, nil, nil, "=+", "/?"],
164
166
  "^" => ["5%", nil, nil, "7&", "fF", "yY"],
165
167
  "_" => ["sS", "/?", "=+", nil, nil, "zZ"],
166
168
  "`" => [ nil, nil, nil, "1!", nil, nil],
167
- "a" => [ nil, "'\"", ",<", "oO", ";:", nil],
169
+ "a" => [ nil, "'\"", ",<", "oO", ";:", nil],
168
170
  "b" => ["xX", "dD", "hH", "mM", nil, nil],
169
171
  "c" => ["gG", "8*", "9(", "rR", "tT", "hH"],
170
172
  "d" => ["iI", "fF", "gG", "hH", "bB", "xX"],
@@ -195,40 +197,42 @@ module Zxcvbn
195
197
  "}" => ["[{", nil, nil, nil, "=+", "/?"],
196
198
  "~" => [ nil, nil, nil, "1!", nil, nil]
197
199
  },
198
- keypad: {
199
- "*" => ["/", nil, nil, nil, "-", "+", "9", "8"],
200
- "+" => ["9", "*", "-", nil, nil, nil, nil, "6"],
201
- "-" => ["*", nil, nil, nil, nil, nil, "+", "9"],
202
- "." => ["0", "2", "3", nil, nil, nil, nil, nil],
203
- "/" => [ nil, nil, nil, nil, "*", "9", "8", "7"],
204
- "0" => [ nil, "1", "2", "3", ".", nil, nil, nil],
205
- "1" => [ nil, nil, "4", "5", "2", "0", nil, nil],
206
- "2" => ["1", "4", "5", "6", "3", ".", "0", nil],
207
- "3" => ["2", "5", "6", nil, nil, nil, ".", "0"],
208
- "4" => [ nil, nil, "7", "8", "5", "2", "1", nil],
200
+ "keypad" => {
201
+ "*" => ["/", nil, nil, nil, "-", "+", "9", "8"],
202
+ "+" => ["9", "*", "-", nil, nil, nil, nil, "6"],
203
+ "-" => ["*", nil, nil, nil, nil, nil, "+", "9"],
204
+ "." => ["0", "2", "3", nil, nil, nil, nil, nil],
205
+ "/" => [nil, nil, nil, nil, "*", "9", "8", "7"],
206
+ "0" => [nil, "1", "2", "3", ".", nil, nil, nil],
207
+ "1" => [nil, nil, "4", "5", "2", "0", nil, nil],
208
+ "2" => ["1", "4", "5", "6", "3", ".", "0", nil],
209
+ "3" => ["2", "5", "6", nil, nil, nil, ".", "0"],
210
+ "4" => [nil, nil, "7", "8", "5", "2", "1", nil],
209
211
  "5" => ["4", "7", "8", "9", "6", "3", "2", "1"],
210
- "6" => ["5", "8", "9", "+", nil, nil, "3", "2"],
211
- "7" => [ nil, nil, nil, "/", "8", "5", "4", nil],
212
- "8" => ["7", nil, "/", "*", "9", "6", "5", "4"],
213
- "9" => ["8", "/", "*", "-", "+", nil, "6", "5"]
212
+ "6" => ["5", "8", "9", "+", nil, nil, "3", "2"],
213
+ "7" => [nil, nil, nil, "/", "8", "5", "4", nil],
214
+ "8" => ["7", nil, "/", "*", "9", "6", "5", "4"],
215
+ "9" => ["8", "/", "*", "-", "+", nil, "6", "5"]
214
216
  },
215
- mac_keypad: {
216
- "*" => ["/", nil, nil, nil, nil, nil, "-", "9"],
217
- "+" => ["6", "9", "-", nil, nil, nil, nil, "3"],
218
- "-" => ["9", "/", "*", nil, nil, nil, "+", "6"],
219
- "." => ["0", "2", "3", nil, nil, nil, nil, nil],
220
- "/" => ["=", nil, nil, nil, "*", "-", "9", "8"],
221
- "0" => [ nil, "1", "2", "3", ".", nil, nil, nil],
222
- "1" => [ nil, nil, "4", "5", "2", "0", nil, nil],
223
- "2" => ["1", "4", "5", "6", "3", ".", "0", nil],
224
- "3" => ["2", "5", "6", "+", nil, nil, ".", "0"],
225
- "4" => [ nil, nil, "7", "8", "5", "2", "1", nil],
217
+ "mac_keypad" => {
218
+ "*" => ["/", nil, nil, nil, nil, nil, "-", "9"],
219
+ "+" => ["6", "9", "-", nil, nil, nil, nil, "3"],
220
+ "-" => ["9", "/", "*", nil, nil, nil, "+", "6"],
221
+ "." => ["0", "2", "3", nil, nil, nil, nil, nil],
222
+ "/" => ["=", nil, nil, nil, "*", "-", "9", "8"],
223
+ "0" => [nil, "1", "2", "3", ".", nil, nil, nil],
224
+ "1" => [nil, nil, "4", "5", "2", "0", nil, nil],
225
+ "2" => ["1", "4", "5", "6", "3", ".", "0", nil],
226
+ "3" => ["2", "5", "6", "+", nil, nil, ".", "0"],
227
+ "4" => [nil, nil, "7", "8", "5", "2", "1", nil],
226
228
  "5" => ["4", "7", "8", "9", "6", "3", "2", "1"],
227
- "6" => ["5", "8", "9", "-", "+", nil, "3", "2"],
228
- "7" => [ nil, nil, nil, "=", "8", "5", "4", nil],
229
- "8" => ["7", nil, "=", "/", "9", "6", "5", "4"],
229
+ "6" => ["5", "8", "9", "-", "+", nil, "3", "2"],
230
+ "7" => [nil, nil, nil, "=", "8", "5", "4", nil],
231
+ "8" => ["7", nil, "=", "/", "9", "6", "5", "4"],
230
232
  "9" => ["8", "=", "/", "*", "-", "+", "6", "5"],
231
- "=" => [ nil, nil, nil, nil, "/", "9", "8", "7"]
233
+ "=" => [nil, nil, nil, nil, "/", "9", "8", "7"]
232
234
  }
233
- }
235
+ }.freeze
236
+ # rubocop:enable Layout/ExtraSpacing
237
+ # rubocop:enable Layout/SpaceInsideArrayLiteralBrackets
234
238
  end