alex_codebreaker 0.1.6 → 0.1.7
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 +4 -4
- data/README.md +1 -1
- data/lib/alex_codebreaker.rb +3 -2
- data/lib/alex_codebreaker/game.rb +54 -69
- data/lib/alex_codebreaker/modules/arguments_validation.rb +17 -0
- data/lib/alex_codebreaker/modules/difficulty_levels.rb +25 -21
- data/lib/alex_codebreaker/modules/files.rb +6 -2
- data/lib/alex_codebreaker/modules/settings.rb +11 -7
- data/lib/alex_codebreaker/modules/validators.rb +21 -0
- data/lib/alex_codebreaker/players_rating.rb +20 -17
- data/lib/alex_codebreaker/secret_code_generator.rb +17 -0
- data/lib/alex_codebreaker/session.rb +36 -23
- data/lib/alex_codebreaker/version.rb +3 -1
- metadata +19 -18
- data/lib/alex_codebreaker/modules/validators/arguments_validation.rb +0 -13
- data/lib/alex_codebreaker/modules/validators/validators.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9906ea2d8ba009f676ae54c4e40fe92a6c32c2027e925c75b2cc578139d0c0d0
|
4
|
+
data.tar.gz: e1b386d362478ee47deb158c476ed73fe38c33a85f7a2991967552009e399782
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3bf4021bf22dbbfb4bde1d3e8a73898adc68eb7607c0c05511576e41661eb2032588a3a38cc5895f0be61ea19861c4487e294c97bf1f4fba101e243c11e1856
|
7
|
+
data.tar.gz: 61c34662972de0c1e127c3740a04e12b33f4ac2fba86c834661f85c55f8321fddcfda9ac97f749a88ef10d1645bbac0e0bca5491b0fa46226aa83ba868a77e4b
|
data/README.md
CHANGED
data/lib/alex_codebreaker.rb
CHANGED
@@ -4,8 +4,9 @@ require_relative 'alex_codebreaker/version'
|
|
4
4
|
require_relative 'alex_codebreaker/modules/files'
|
5
5
|
require_relative 'alex_codebreaker/modules/settings'
|
6
6
|
require_relative 'alex_codebreaker/modules/difficulty_levels'
|
7
|
-
require_relative 'alex_codebreaker/modules/validators
|
8
|
-
require_relative 'alex_codebreaker/modules/
|
7
|
+
require_relative 'alex_codebreaker/modules/validators'
|
8
|
+
require_relative 'alex_codebreaker/modules/arguments_validation'
|
9
|
+
require_relative 'alex_codebreaker/secret_code_generator'
|
9
10
|
require_relative 'alex_codebreaker/players_rating'
|
10
11
|
require_relative 'alex_codebreaker/session'
|
11
12
|
require_relative 'alex_codebreaker/game'
|
@@ -1,87 +1,72 @@
|
|
1
|
-
|
1
|
+
module AlexCodebreaker
|
2
|
+
class Game
|
3
|
+
include AlexCodebreaker::Modules::ArgumentsValidation
|
2
4
|
|
3
|
-
|
4
|
-
include ArgumentsValidation
|
5
|
+
attr_reader :secret_code, :session, :win_status
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@win_status = false
|
12
|
-
end
|
13
|
-
|
14
|
-
def add_player_name(given_name)
|
15
|
-
name_validation(given_name) ? @session.player_name = given_name : false
|
16
|
-
end
|
17
|
-
|
18
|
-
def choose_difficulty(chosen_difficulty)
|
19
|
-
@session.difficulty_manager(chosen_difficulty.to_sym)
|
20
|
-
end
|
21
|
-
|
22
|
-
def hint
|
23
|
-
return false if @session.hints_used >= @session.hints_total
|
24
|
-
|
25
|
-
@session.hints_used += 1
|
26
|
-
@secret_code_for_hint ||= @secret_code.clone.uniq
|
27
|
-
@secret_code_for_hint.delete(@secret_code_for_hint.sample)
|
28
|
-
end
|
29
|
-
|
30
|
-
def guess(user_input)
|
31
|
-
return false if !guess_validation(user_input) || check_attempts
|
7
|
+
def initialize
|
8
|
+
@secret_code = AlexCodebreaker::SecretCodeGenerator.new.secret_code
|
9
|
+
@secret_code_for_hint = @secret_code.clone.uniq
|
10
|
+
@session = Session.new
|
11
|
+
end
|
32
12
|
|
33
|
-
|
34
|
-
|
35
|
-
comparator(user_input)
|
36
|
-
end
|
13
|
+
def hint
|
14
|
+
return unless @session.check_hints
|
37
15
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
16
|
+
hint_processing
|
17
|
+
end
|
41
18
|
|
42
|
-
|
43
|
-
|
44
|
-
end
|
19
|
+
def guess(user_input)
|
20
|
+
return unless guess_validation(user_input) && @session.check_attempts
|
45
21
|
|
46
|
-
|
47
|
-
|
48
|
-
end
|
22
|
+
comparator(user_input)
|
23
|
+
end
|
49
24
|
|
50
|
-
|
25
|
+
private
|
51
26
|
|
52
|
-
|
53
|
-
|
54
|
-
@secret_code_for_comparison = @secret_code.clone
|
55
|
-
user_input = matching_numbers_and_indexes(user_input)
|
27
|
+
def hint_processing
|
28
|
+
return @secret_code_for_hint.first if @secret_code_for_hint.one?
|
56
29
|
|
57
|
-
|
30
|
+
@secret_code_for_hint.delete(@secret_code_for_hint.sample)
|
31
|
+
end
|
58
32
|
|
59
|
-
|
60
|
-
|
33
|
+
def comparator(user_input)
|
34
|
+
user_input = user_input.chars.map!(&:to_i)
|
35
|
+
secret_code_for_comparison = @secret_code.clone
|
36
|
+
user_input = matching_numbers_and_indexes(user_input, secret_code_for_comparison).compact
|
37
|
+
user_input = matching_only_numbers(user_input, secret_code_for_comparison).compact
|
38
|
+
matching_absent(user_input)
|
39
|
+
end
|
61
40
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
value
|
41
|
+
def matching_numbers_and_indexes(user_input, secret_code_for_comparison)
|
42
|
+
user_input.map.with_index do |value, index|
|
43
|
+
if value == secret_code_for_comparison[index]
|
44
|
+
secret_code_for_comparison[index] = nil
|
45
|
+
AlexCodebreaker::Modules::Settings::MATCHING[:place]
|
46
|
+
else
|
47
|
+
value
|
48
|
+
end
|
71
49
|
end
|
72
50
|
end
|
73
|
-
end
|
74
51
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
Settings::MATCHING[:absent]
|
52
|
+
def matching_only_numbers(user_input, secret_code_for_comparison)
|
53
|
+
user_input.map do |value|
|
54
|
+
if secret_code_for_comparison.include?(value)
|
55
|
+
secret_code_for_comparison.delete_at(secret_code_for_comparison.index(value))
|
56
|
+
AlexCodebreaker::Modules::Settings::MATCHING[:presence]
|
57
|
+
elsif value == AlexCodebreaker::Modules::Settings::MATCHING[:place]
|
58
|
+
value
|
59
|
+
end
|
84
60
|
end
|
85
61
|
end
|
62
|
+
|
63
|
+
def matching_absent(user_input)
|
64
|
+
AlexCodebreaker::Modules::Settings::MATCHING[:place] *
|
65
|
+
user_input.count(AlexCodebreaker::Modules::Settings::MATCHING[:place]) +
|
66
|
+
AlexCodebreaker::Modules::Settings::MATCHING[:presence] *
|
67
|
+
user_input.count(AlexCodebreaker::Modules::Settings::MATCHING[:presence]) +
|
68
|
+
AlexCodebreaker::Modules::Settings::MATCHING[:absent] *
|
69
|
+
(AlexCodebreaker::Modules::Settings::CODE_LENGTH - user_input.length)
|
70
|
+
end
|
86
71
|
end
|
87
72
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module AlexCodebreaker
|
2
|
+
module Modules
|
3
|
+
module ArgumentsValidation
|
4
|
+
include AlexCodebreaker::Modules::Validators
|
5
|
+
def name_validation(name)
|
6
|
+
argument_min_length_check(name, AlexCodebreaker::Modules::Settings::MIN_PLAYER_NAME_LENGTH) &&
|
7
|
+
argument_max_length_check(name, AlexCodebreaker::Modules::Settings::MAX_PLAYER_NAME_LENGTH)
|
8
|
+
end
|
9
|
+
|
10
|
+
def guess_validation(guess)
|
11
|
+
argument_length_check(guess, AlexCodebreaker::Modules::Settings::CODE_LENGTH) &&
|
12
|
+
digits_check(guess, AlexCodebreaker::Modules::Settings::CODE_MIN_DIGIT,
|
13
|
+
AlexCodebreaker::Modules::Settings::CODE_MAX_DIGIT)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,22 +1,26 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
1
|
+
module AlexCodebreaker
|
2
|
+
module Modules
|
3
|
+
module DifficultyLevels
|
4
|
+
DIFFICULTY_LEVELS = {
|
5
|
+
easy: {
|
6
|
+
name: 'Easy',
|
7
|
+
level: 0,
|
8
|
+
attempts_total: 15,
|
9
|
+
hints_total: 2
|
10
|
+
},
|
11
|
+
medium: {
|
12
|
+
name: 'Medium',
|
13
|
+
level: 1,
|
14
|
+
attempts_total: 10,
|
15
|
+
hints_total: 1
|
16
|
+
},
|
17
|
+
hell: {
|
18
|
+
name: 'Hell',
|
19
|
+
level: 2,
|
20
|
+
attempts_total: 5,
|
21
|
+
hints_total: 1
|
22
|
+
}
|
23
|
+
}.freeze
|
24
|
+
end
|
25
|
+
end
|
22
26
|
end
|
@@ -1,8 +1,12 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module AlexCodebreaker
|
2
|
+
module Modules
|
3
|
+
module Settings
|
4
|
+
MATCHING = { place: '+', presence: '-', absent: ' ' }.freeze
|
5
|
+
CODE_MIN_DIGIT = 1
|
6
|
+
CODE_MAX_DIGIT = 6
|
7
|
+
CODE_LENGTH = 4
|
8
|
+
MIN_PLAYER_NAME_LENGTH = 3
|
9
|
+
MAX_PLAYER_NAME_LENGTH = 20
|
10
|
+
end
|
11
|
+
end
|
8
12
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module AlexCodebreaker
|
2
|
+
module Modules
|
3
|
+
module Validators
|
4
|
+
def argument_length_check(arg, length)
|
5
|
+
arg.to_s.length == length
|
6
|
+
end
|
7
|
+
|
8
|
+
def argument_max_length_check(arg, max)
|
9
|
+
arg.length <= max
|
10
|
+
end
|
11
|
+
|
12
|
+
def argument_min_length_check(arg, min)
|
13
|
+
arg.length >= min
|
14
|
+
end
|
15
|
+
|
16
|
+
def digits_check(arg, min_digit, max_digit)
|
17
|
+
arg.split('').all? { |value| value.to_i.between?(min_digit, max_digit) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,26 +1,29 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module AlexCodebreaker
|
2
|
+
class PlayersRating
|
3
|
+
attr_accessor :stats
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def initialize
|
6
|
+
@stats = []
|
7
|
+
stats_loader
|
8
|
+
end
|
7
9
|
|
8
|
-
|
10
|
+
private
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
def stats_loader
|
13
|
+
return unless File.exist?(AlexCodebreaker::Modules::Files::STATS_FILE)
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
load_stats
|
16
|
+
sort_players_rating
|
17
|
+
end
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
def load_stats
|
20
|
+
File.open(AlexCodebreaker::Modules::Files::STATS_FILE) do |file|
|
21
|
+
@stats = Array.new(Psych.load_stream(file))
|
22
|
+
end
|
20
23
|
end
|
21
|
-
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
def sort_players_rating
|
26
|
+
@stats.sort_by! { |value| [-value.difficulty_level, value.attempts_used, value.hints_used] }
|
27
|
+
end
|
25
28
|
end
|
26
29
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module AlexCodebreaker
|
2
|
+
class SecretCodeGenerator
|
3
|
+
attr_reader :secret_code
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@secret_code = generate_secret_code
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def generate_secret_code
|
12
|
+
Array.new(AlexCodebreaker::Modules::Settings::CODE_LENGTH) do
|
13
|
+
rand(AlexCodebreaker::Modules::Settings::CODE_MIN_DIGIT..AlexCodebreaker::Modules::Settings::CODE_MAX_DIGIT)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,34 +1,47 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module AlexCodebreaker
|
2
|
+
class Session
|
3
|
+
include AlexCodebreaker::Modules::ArgumentsValidation
|
4
4
|
|
5
|
-
|
5
|
+
INITIAL_ATTEMPTS_USED = 0
|
6
|
+
INITIAL_HINTS_USED = 0
|
7
|
+
|
8
|
+
attr_reader :hints_used, :attempts_used, :player_name, :hints_total,
|
6
9
|
:difficulty_name, :attempts_total, :difficulty_level
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
def initialize
|
12
|
+
@attempts_used = INITIAL_ATTEMPTS_USED
|
13
|
+
@hints_used = INITIAL_HINTS_USED
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
add_difficulty(DifficultyLevels::DIFFICULTY_LEVELS[difficulty])
|
16
|
+
def add_name(given_name)
|
17
|
+
@player_name = given_name if name_validation(given_name)
|
16
18
|
end
|
17
|
-
return false unless DifficultyLevels::DIFFICULTY_LEVELS.include?(difficulty)
|
18
|
-
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
def add_difficulty(difficulty)
|
21
|
+
return unless AlexCodebreaker::Modules::DifficultyLevels::DIFFICULTY_LEVELS.include?(difficulty.downcase.to_sym)
|
22
|
+
|
23
|
+
difficulty(AlexCodebreaker::Modules::DifficultyLevels::DIFFICULTY_LEVELS[difficulty.downcase.to_sym])
|
23
24
|
end
|
24
|
-
end
|
25
25
|
|
26
|
-
|
26
|
+
def check_hints
|
27
|
+
@hints_used += 1 if @hints_used < @hints_total
|
28
|
+
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def check_attempts
|
31
|
+
@attempts_used += 1 if @attempts_used < @attempts_total - 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def save_statistic
|
35
|
+
File.open(AlexCodebreaker::Modules::Files::STATS_FILE, 'a') { |file| file.write(to_yaml) }
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def difficulty(difficulty)
|
41
|
+
@difficulty_name = difficulty[:name]
|
42
|
+
@difficulty_level = difficulty[:level]
|
43
|
+
@attempts_total = difficulty[:attempts_total]
|
44
|
+
@hints_total = difficulty[:hints_total]
|
45
|
+
end
|
33
46
|
end
|
34
47
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alex_codebreaker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleksandr Loza
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-12-
|
11
|
+
date: 2019-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: i18n
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.7'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.7'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bundler
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +136,20 @@ dependencies:
|
|
150
136
|
- - "~>"
|
151
137
|
- !ruby/object:Gem::Version
|
152
138
|
version: 0.17.1
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: solargraph
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.38.0
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.38.0
|
153
153
|
description: Codebreaker game business logic
|
154
154
|
email:
|
155
155
|
- alexwebq@gmail.com
|
@@ -161,12 +161,13 @@ files:
|
|
161
161
|
- README.md
|
162
162
|
- lib/alex_codebreaker.rb
|
163
163
|
- lib/alex_codebreaker/game.rb
|
164
|
+
- lib/alex_codebreaker/modules/arguments_validation.rb
|
164
165
|
- lib/alex_codebreaker/modules/difficulty_levels.rb
|
165
166
|
- lib/alex_codebreaker/modules/files.rb
|
166
167
|
- lib/alex_codebreaker/modules/settings.rb
|
167
|
-
- lib/alex_codebreaker/modules/validators
|
168
|
-
- lib/alex_codebreaker/modules/validators/validators.rb
|
168
|
+
- lib/alex_codebreaker/modules/validators.rb
|
169
169
|
- lib/alex_codebreaker/players_rating.rb
|
170
|
+
- lib/alex_codebreaker/secret_code_generator.rb
|
170
171
|
- lib/alex_codebreaker/session.rb
|
171
172
|
- lib/alex_codebreaker/version.rb
|
172
173
|
homepage: https://github.com/Alexwell/codebreaker/tree/feature/initial-gem-settings
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module ArgumentsValidation
|
2
|
-
include Validators
|
3
|
-
|
4
|
-
def name_validation(name)
|
5
|
-
argument_min_length_check(name, Settings::MIN_PLAYER_NAME_LENGTH) && \
|
6
|
-
argument_max_length_check(name, Settings::MAX_PLAYER_NAME_LENGTH)
|
7
|
-
end
|
8
|
-
|
9
|
-
def guess_validation(guess)
|
10
|
-
argument_fixed_length_check(guess, Settings::CODE_LENGTH) && \
|
11
|
-
digits_check(guess, min_digit: Settings::CODE_MIN_DIGIT, max_digit: Settings::CODE_MAX_DIGIT)
|
12
|
-
end
|
13
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Validators
|
2
|
-
def argument_fixed_length_check(arg, fixed_length)
|
3
|
-
arg.to_s.length == fixed_length
|
4
|
-
end
|
5
|
-
|
6
|
-
def argument_max_length_check(arg, max)
|
7
|
-
arg.length <= max
|
8
|
-
end
|
9
|
-
|
10
|
-
def argument_min_length_check(arg, min)
|
11
|
-
arg.length >= min
|
12
|
-
end
|
13
|
-
|
14
|
-
def digits_check(arg, min_digit: 1, max_digit: 6)
|
15
|
-
arg.to_s.split('').map { |value| value unless value.to_i.between?(min_digit, max_digit) }.compact.empty?
|
16
|
-
end
|
17
|
-
end
|