codebreaker_manfly 0.1.1 → 0.1.2
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/.rubocop.yml +4 -0
- data/Gemfile +0 -4
- data/Gemfile.lock +26 -2
- data/README.md +12 -20
- data/lib/codebreaker/base_entity.rb +12 -0
- data/lib/codebreaker/bootstrap.rb +16 -0
- data/lib/codebreaker/code_generate.rb +12 -0
- data/lib/codebreaker/code_matcher.rb +36 -0
- data/lib/codebreaker/difficulty.rb +23 -0
- data/lib/codebreaker/difficulty_factory.rb +33 -0
- data/lib/codebreaker/errors/class_validate_error.rb +8 -0
- data/lib/codebreaker/errors/empty_strings_error.rb +8 -0
- data/lib/codebreaker/errors/invalid_difficulty_error.rb +8 -0
- data/lib/codebreaker/errors/max_length_error.rb +8 -0
- data/lib/codebreaker/errors/min_length_error.rb +8 -0
- data/lib/codebreaker/errors/negative_integer_error.rb +8 -0
- data/lib/codebreaker/errors/non_numeric_string_error.rb +8 -0
- data/lib/codebreaker/errors/not_implemented_error.rb +8 -0
- data/lib/codebreaker/errors/range_error.rb +8 -0
- data/lib/codebreaker/storage.rb +31 -0
- data/lib/codebreaker/user.rb +35 -7
- data/lib/codebreaker/validation.rb +47 -0
- data/lib/codebreaker/version.rb +1 -1
- data/lib/codebreaker/winners.rb +12 -0
- data/lib/codebreaker.rb +47 -79
- metadata +62 -7
- data/.ruby-gemset +0 -0
- data/db/results_test.yml +0 -220
- data/lib/codebreaker/file_loader.rb +0 -30
- data/lib/codebreaker/gameload.rb +0 -39
- data/lib/codebreaker/module/validation.rb +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: caf1cf44404ee764b74c32a9a2894f98bd2aa73b184ec73399a40a69c17f5165
|
4
|
+
data.tar.gz: 980294f275d01d27b699612232b017307c8d4272c2f73c3f7a8c3fab26398089
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7277c3b2aa8a8ac2eea2c8c0aedeff2d4df7cc128364bbcd4636eeeed52694143848e42fd590c4fe3a6add886d5b730a02908c5696aea02f9f70ca0f3dec6f8b
|
7
|
+
data.tar.gz: b382f9504b6448445f2246d1af75a4cfe775897ff1ac39b0a8365dd17d696459915b2ff611e4b5095a097d459c2b6bcaaddf3ea353e5cd15386ae6c597aa254a
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,16 +1,31 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
codebreaker_manfly (0.1.
|
4
|
+
codebreaker_manfly (0.1.0)
|
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)
|
12
|
+
concurrent-ruby (1.1.9)
|
10
13
|
diff-lcs (1.4.4)
|
14
|
+
docile (1.4.0)
|
15
|
+
faker (2.19.0)
|
16
|
+
i18n (>= 1.6, < 2)
|
17
|
+
i18n (1.8.10)
|
18
|
+
concurrent-ruby (~> 1.0)
|
19
|
+
method_source (1.0.0)
|
11
20
|
parallel (1.21.0)
|
12
21
|
parser (3.0.2.0)
|
13
22
|
ast (~> 2.4.1)
|
23
|
+
pry (0.13.1)
|
24
|
+
coderay (~> 1.1)
|
25
|
+
method_source (~> 1.0)
|
26
|
+
pry-byebug (3.9.0)
|
27
|
+
byebug (~> 11.0)
|
28
|
+
pry (~> 0.13.0)
|
14
29
|
rainbow (3.0.0)
|
15
30
|
rake (13.0.6)
|
16
31
|
regexp_parser (2.1.1)
|
@@ -28,7 +43,7 @@ GEM
|
|
28
43
|
diff-lcs (>= 1.2.0, < 2.0)
|
29
44
|
rspec-support (~> 3.10.0)
|
30
45
|
rspec-support (3.10.2)
|
31
|
-
rubocop (1.22.
|
46
|
+
rubocop (1.22.3)
|
32
47
|
parallel (~> 1.10)
|
33
48
|
parser (>= 3.0.0.0)
|
34
49
|
rainbow (>= 2.2.2, < 4.0)
|
@@ -40,6 +55,12 @@ GEM
|
|
40
55
|
rubocop-ast (1.12.0)
|
41
56
|
parser (>= 3.0.1.1)
|
42
57
|
ruby-progressbar (1.11.0)
|
58
|
+
simplecov (0.21.2)
|
59
|
+
docile (~> 1.1)
|
60
|
+
simplecov-html (~> 0.11)
|
61
|
+
simplecov_json_formatter (~> 0.1)
|
62
|
+
simplecov-html (0.12.3)
|
63
|
+
simplecov_json_formatter (0.1.3)
|
43
64
|
unicode-display_width (2.1.0)
|
44
65
|
|
45
66
|
PLATFORMS
|
@@ -47,9 +68,12 @@ PLATFORMS
|
|
47
68
|
|
48
69
|
DEPENDENCIES
|
49
70
|
codebreaker_manfly!
|
71
|
+
faker
|
72
|
+
pry-byebug
|
50
73
|
rake (~> 13.0)
|
51
74
|
rspec (~> 3.10)
|
52
75
|
rubocop (~> 1.7)
|
76
|
+
simplecov
|
53
77
|
|
54
78
|
BUNDLED WITH
|
55
79
|
2.2.28
|
data/README.md
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
# Codebreaker
|
2
2
|
|
3
|
-
|
3
|
+
Codebreaker is a logic game in which a code-breaker tries to break a secret code created by a code-maker. The code-maker, which will be played by the application we’re going to write, creates a secret code of four numbers between 1 and 6.
|
4
4
|
|
5
|
-
|
5
|
+
The code-breaker then gets some number of chances to break the code. In each turn, the code-breaker makes a guess of four numbers. The code-maker then marks the guess with up to four + and - signs.
|
6
|
+
|
7
|
+
A + indicates an exact match: one of the numbers in the guess is the same as one of the numbers in the secret code and in the same position.
|
8
|
+
|
9
|
+
A - indicates a number match: one of the numbers in the guess is the same as one of the numbers in the secret code but in a different position.
|
6
10
|
|
7
11
|
## Installation
|
8
12
|
|
9
13
|
Add this line to your application's Gemfile:
|
10
14
|
|
11
15
|
```ruby
|
12
|
-
gem 'codebreaker_manfly'
|
16
|
+
gem 'codebreaker_manfly', '~> 0.1.0'
|
13
17
|
```
|
14
18
|
|
15
19
|
And then execute:
|
@@ -18,26 +22,14 @@ And then execute:
|
|
18
22
|
|
19
23
|
Or install it yourself as:
|
20
24
|
|
21
|
-
$ gem install
|
25
|
+
$ gem install codebreaker_manfly
|
22
26
|
|
23
27
|
## Usage
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
## Development
|
28
|
-
|
29
|
-
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
-
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
-
|
33
|
-
## Contributing
|
34
|
-
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/codebreaker. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/codebreaker/blob/master/CODE_OF_CONDUCT.md).
|
36
|
-
|
37
|
-
## License
|
29
|
+
To use this game it should be installed in a console or web vesion of the game
|
38
30
|
|
39
|
-
|
31
|
+
Create an instance of the game:
|
40
32
|
|
41
|
-
|
33
|
+
game = Codebreacker::Game.new
|
42
34
|
|
43
|
-
|
35
|
+
During instantiation you can set matcher (object that will be used for guesses matching) and storage (object that will be used for storing scores).
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml/store'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
require_relative 'validation'
|
7
|
+
require_relative 'base_entity'
|
8
|
+
require_relative 'code_generate'
|
9
|
+
require_relative 'code_matcher'
|
10
|
+
require_relative 'difficulty_factory'
|
11
|
+
require_relative 'difficulty'
|
12
|
+
require_relative 'storage'
|
13
|
+
require_relative 'user'
|
14
|
+
require_relative 'winners'
|
15
|
+
require_relative 'version'
|
16
|
+
require_relative '../codebreaker'
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Codebreaker
|
4
|
+
class CodeMatcher
|
5
|
+
EXACT = '+'
|
6
|
+
NON_EXACT = '-'
|
7
|
+
|
8
|
+
attr_reader :guess, :secret_code
|
9
|
+
|
10
|
+
def match(secret_code, guess)
|
11
|
+
@secret_code = secret_code.split('')
|
12
|
+
@guess = guess.split('')
|
13
|
+
handle_matched_digits.join + handle_matched_digits_with_wrong_position.join
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def handle_matched_digits
|
19
|
+
secret_code.map.with_index do |_, index|
|
20
|
+
next unless secret_code[index] == guess[index]
|
21
|
+
|
22
|
+
@guess[index], @secret_code[index] = nil
|
23
|
+
EXACT
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def handle_matched_digits_with_wrong_position
|
28
|
+
guess.compact.map do |number|
|
29
|
+
next unless @secret_code.include?(number)
|
30
|
+
|
31
|
+
@secret_code.delete_at(secret_code.index(number))
|
32
|
+
NON_EXACT
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Codebreaker
|
4
|
+
class Difficulty
|
5
|
+
attr_reader :name, :attempts, :hints
|
6
|
+
|
7
|
+
NEGATIVE_INTEGER = 0
|
8
|
+
|
9
|
+
def initialize(name:, attempts:, hints:)
|
10
|
+
@name = name
|
11
|
+
@attempts = attempts
|
12
|
+
@hints = hints
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def validate
|
18
|
+
raise Errors::ClassValidError unless valid_class?(String, difficulty)
|
19
|
+
raise Errors::NegativeIntegerError unless valid_non_negative_integer?(attempts, NEGATIVE_INTEGER)
|
20
|
+
raise Errors::NegativeIntegerError unless valid_non_negative_integer?(hints, NEGATIVE_INTEGER)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Codebreaker
|
4
|
+
class DifficultyFactory
|
5
|
+
DIFFICULTIES = {
|
6
|
+
|
7
|
+
easy: {
|
8
|
+
name: 'easy',
|
9
|
+
attempts: 15,
|
10
|
+
hints: 2
|
11
|
+
},
|
12
|
+
medium: {
|
13
|
+
name: 'medium',
|
14
|
+
attempts: 10,
|
15
|
+
hints: 1
|
16
|
+
},
|
17
|
+
hell: {
|
18
|
+
name: 'hell',
|
19
|
+
attempts: 5,
|
20
|
+
hints: 1
|
21
|
+
}
|
22
|
+
|
23
|
+
}.freeze
|
24
|
+
def self.generate(difficulty_name)
|
25
|
+
case difficulty_name
|
26
|
+
when DIFFICULTIES[:easy] then Difficulty.new(DIFFICULTIES[:easy])
|
27
|
+
when DIFFICULTIES[:medium] then Difficulty.new(DIFFICULTIES[:medium])
|
28
|
+
when DIFFICULTIES[:hell] then Difficulty.new(DIFFICULTIES[:hell])
|
29
|
+
else raise Errors::InvalidDifficultyError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Codebreaker
|
4
|
+
module Storage
|
5
|
+
FILE_NAME = './store/statistics.yml'
|
6
|
+
|
7
|
+
def init_store
|
8
|
+
save
|
9
|
+
end
|
10
|
+
|
11
|
+
def load
|
12
|
+
store.transaction do
|
13
|
+
@winners = store[:winners]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def save
|
18
|
+
store.transaction do
|
19
|
+
store[:winners] = @winners
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def storage_exists?
|
24
|
+
File.exist?(FILE_NAME)
|
25
|
+
end
|
26
|
+
|
27
|
+
def store
|
28
|
+
@store ||= YAML::Store.new(FILE_NAME)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/codebreaker/user.rb
CHANGED
@@ -1,16 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class User
|
5
|
-
include Validation
|
3
|
+
require_relative 'bootstrap'
|
6
4
|
|
7
|
-
|
5
|
+
module Codebreaker
|
6
|
+
class User < BaseEntity
|
7
|
+
attr_reader :name, :difficulty, :used_attempts, :used_hints
|
8
8
|
|
9
|
-
|
9
|
+
NAME_MIN_LENGTH = 3
|
10
|
+
NAME_MAX_LENGTH = 20
|
10
11
|
|
11
|
-
def initialize(name
|
12
|
-
validate_user_name(name, NAME_LENGTH)
|
12
|
+
def initialize(name, difficulty)
|
13
13
|
@name = name
|
14
|
+
@difficulty = difficulty
|
15
|
+
@used_attempts = 0
|
16
|
+
@used_hints = 0
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def hints?
|
21
|
+
difficulty.hints = used_hints
|
22
|
+
end
|
23
|
+
|
24
|
+
def attempts?
|
25
|
+
difficulty.attempts = used_attempts
|
26
|
+
end
|
27
|
+
|
28
|
+
def hint
|
29
|
+
@used_hints += 1
|
30
|
+
end
|
31
|
+
|
32
|
+
def attempt
|
33
|
+
@used_attempts += 1
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def validate
|
39
|
+
raise Errors::ClassValidError unless valid_class?(String, name)
|
40
|
+
raise Errors::MinLengthError unless valid_string_min_length?(name, NAME_MIN_LENGTH)
|
41
|
+
raise Errors::MaxLengthError unless valid_string_max_length?(name, NAME_MAX_LENGTH)
|
14
42
|
end
|
15
43
|
end
|
16
44
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'errors/range_error'
|
4
|
+
require_relative 'errors/non_numeric_string_error'
|
5
|
+
require_relative 'errors/empty_strings_error'
|
6
|
+
require_relative 'errors/class_validate_error'
|
7
|
+
require_relative 'errors/min_length_error'
|
8
|
+
require_relative 'errors/max_length_error'
|
9
|
+
require_relative 'errors/negative_integer_error'
|
10
|
+
require_relative 'errors/invalid_difficulty_error'
|
11
|
+
|
12
|
+
module Codebreaker
|
13
|
+
module Validation
|
14
|
+
def valid_class?(expected_class, instance)
|
15
|
+
instance.is_a?(expected_class)
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid_non_empty_string?(string)
|
19
|
+
!string.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_positive_integer?(number)
|
23
|
+
number.positive?
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_non_negative_integer?(number)
|
27
|
+
!number.negative?
|
28
|
+
end
|
29
|
+
|
30
|
+
def valid_string_min_length?(string, min_length)
|
31
|
+
string.length >= min_length
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid_string_max_length?(string, max_length)
|
35
|
+
string.length <= max_length
|
36
|
+
end
|
37
|
+
|
38
|
+
def valid_only_numeric_string?(string)
|
39
|
+
/\A\d+\Z/.match?(string)
|
40
|
+
end
|
41
|
+
|
42
|
+
def valid_range?(range, code)
|
43
|
+
code.each { |digit| return false unless range.cover?(digit) }
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/codebreaker/version.rb
CHANGED
data/lib/codebreaker.rb
CHANGED
@@ -1,100 +1,68 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require 'date'
|
3
|
+
require_relative 'codebreaker/bootstrap'
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
require_relative 'codebreaker/user'
|
9
|
-
require_relative 'codebreaker/file_loader'
|
10
|
-
require_relative 'codebreaker/version'
|
5
|
+
class Game
|
6
|
+
extend Codebreaker::Storage
|
11
7
|
|
12
|
-
|
13
|
-
class Game
|
14
|
-
include Validation
|
8
|
+
attr_reader :user
|
15
9
|
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
STATUS_IN_PROGRESS = :in_progress
|
11
|
+
STATUS_WIN = :win
|
12
|
+
STATUS_LOSE = :lose
|
19
13
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
RANGE_GUESS_CODE = (1..6).freeze
|
28
|
-
|
29
|
-
def initialize(difficulty:, user:, date: Date.today)
|
30
|
-
validate_difficulty(difficulty, DIFFICULTIES)
|
31
|
-
|
32
|
-
@user = user
|
33
|
-
@difficulty = difficulty
|
34
|
-
@date = date
|
35
|
-
|
36
|
-
attempts
|
37
|
-
number_of_hints
|
38
|
-
end
|
39
|
-
|
40
|
-
def start_new_game
|
41
|
-
@very_secret_code = generate_random_code
|
42
|
-
@hints = @very_secret_code.clone
|
43
|
-
@attempts_used = 0
|
44
|
-
@hints_used = 0
|
45
|
-
@user_guess = []
|
46
|
-
@clues = []
|
47
|
-
end
|
14
|
+
def initialize
|
15
|
+
@secret_code = Codebreaker::CodeGenerator.generate
|
16
|
+
@status = STATUS_IN_PROGRESS
|
17
|
+
@hints = @secret_code.sample(@secret_code.length)
|
18
|
+
@storage = Game.store
|
19
|
+
save_storage unless Game.storage_exists?
|
20
|
+
end
|
48
21
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
check_guess(guess, very_secret_code)
|
22
|
+
def create_user(name, difficulty)
|
23
|
+
@user = Codebreaker::User.new(name, difficulty)
|
24
|
+
end
|
53
25
|
|
54
|
-
|
55
|
-
|
26
|
+
def create_difficulty(difficulty_name)
|
27
|
+
@difficulty = Codebreaker::DifficultyFactory.generate(difficulty_name)
|
28
|
+
end
|
56
29
|
|
57
|
-
|
58
|
-
|
30
|
+
def win?
|
31
|
+
@status == STATUS_WIN
|
32
|
+
end
|
59
33
|
|
60
|
-
|
61
|
-
|
62
|
-
|
34
|
+
def lose?
|
35
|
+
@status == STATUS_LOSE
|
36
|
+
end
|
63
37
|
|
64
|
-
|
65
|
-
|
66
|
-
end
|
38
|
+
def take_hint
|
39
|
+
user.hint if user.hints?
|
67
40
|
|
68
|
-
|
69
|
-
|
70
|
-
end
|
41
|
+
@hints.pop
|
42
|
+
end
|
71
43
|
|
72
|
-
|
73
|
-
|
74
|
-
end
|
44
|
+
def take_attempt(guess)
|
45
|
+
return equal(@secret_code, guess.to_s) if user.attempts?
|
75
46
|
|
76
|
-
|
77
|
-
|
78
|
-
|
47
|
+
@status = STATUS_LOSE
|
48
|
+
nil
|
49
|
+
end
|
79
50
|
|
80
|
-
|
81
|
-
|
51
|
+
def save_storage
|
52
|
+
@storage.transaction do
|
53
|
+
@storage[:winners] = @winners || []
|
82
54
|
end
|
55
|
+
end
|
83
56
|
|
84
|
-
|
85
|
-
|
86
|
-
def generate_random_code
|
87
|
-
Array.new(CODE_LENGTH) { rand(RANGE_GUESS_CODE) }
|
88
|
-
end
|
57
|
+
private
|
89
58
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
59
|
+
def win
|
60
|
+
@winners << CodebreakerGame::Winner.new(user)
|
61
|
+
@status = STATUS_WIN
|
62
|
+
end
|
95
63
|
|
96
|
-
|
97
|
-
|
98
|
-
|
64
|
+
def equal(_secret_code, guess)
|
65
|
+
user.attempt
|
66
|
+
Codebreaker::CodeMatcher.match(@secret_code, guess)
|
99
67
|
end
|
100
68
|
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codebreaker_manfly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrii Ivaniuk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faker
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry-byebug
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: rake
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +80,20 @@ dependencies:
|
|
52
80
|
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
82
|
version: '1.7'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
55
97
|
description: Longer description or delete this line.
|
56
98
|
email:
|
57
99
|
- aivanuyk0@gmail.com
|
@@ -61,7 +103,6 @@ extra_rdoc_files: []
|
|
61
103
|
files:
|
62
104
|
- ".rspec"
|
63
105
|
- ".rubocop.yml"
|
64
|
-
- ".ruby-gemset"
|
65
106
|
- ".ruby-version"
|
66
107
|
- CHANGELOG.md
|
67
108
|
- CODE_OF_CONDUCT.md
|
@@ -72,13 +113,27 @@ files:
|
|
72
113
|
- Rakefile
|
73
114
|
- bin/console
|
74
115
|
- bin/setup
|
75
|
-
- db/results_test.yml
|
76
116
|
- lib/codebreaker.rb
|
77
|
-
- lib/codebreaker/
|
78
|
-
- lib/codebreaker/
|
79
|
-
- lib/codebreaker/
|
117
|
+
- lib/codebreaker/base_entity.rb
|
118
|
+
- lib/codebreaker/bootstrap.rb
|
119
|
+
- lib/codebreaker/code_generate.rb
|
120
|
+
- lib/codebreaker/code_matcher.rb
|
121
|
+
- lib/codebreaker/difficulty.rb
|
122
|
+
- lib/codebreaker/difficulty_factory.rb
|
123
|
+
- lib/codebreaker/errors/class_validate_error.rb
|
124
|
+
- lib/codebreaker/errors/empty_strings_error.rb
|
125
|
+
- lib/codebreaker/errors/invalid_difficulty_error.rb
|
126
|
+
- lib/codebreaker/errors/max_length_error.rb
|
127
|
+
- lib/codebreaker/errors/min_length_error.rb
|
128
|
+
- lib/codebreaker/errors/negative_integer_error.rb
|
129
|
+
- lib/codebreaker/errors/non_numeric_string_error.rb
|
130
|
+
- lib/codebreaker/errors/not_implemented_error.rb
|
131
|
+
- lib/codebreaker/errors/range_error.rb
|
132
|
+
- lib/codebreaker/storage.rb
|
80
133
|
- lib/codebreaker/user.rb
|
134
|
+
- lib/codebreaker/validation.rb
|
81
135
|
- lib/codebreaker/version.rb
|
136
|
+
- lib/codebreaker/winners.rb
|
82
137
|
homepage:
|
83
138
|
licenses:
|
84
139
|
- MIT
|
data/.ruby-gemset
DELETED
File without changes
|
data/db/results_test.yml
DELETED
@@ -1,220 +0,0 @@
|
|
1
|
-
--- !ruby/object:Codebreaker::Game
|
2
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
3
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
4
|
-
const_name: User
|
5
|
-
__expired: false
|
6
|
-
name:
|
7
|
-
__sending_message:
|
8
|
-
difficulty: :easy
|
9
|
-
date: 2021-10-08
|
10
|
-
attempts: 15
|
11
|
-
number_of_hints: 2
|
12
|
-
--- !ruby/object:Codebreaker::Game
|
13
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
14
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
15
|
-
const_name: User
|
16
|
-
__expired: false
|
17
|
-
name:
|
18
|
-
__sending_message:
|
19
|
-
difficulty: :easy
|
20
|
-
date: 2021-10-08
|
21
|
-
attempts: 15
|
22
|
-
number_of_hints: 2
|
23
|
-
--- !ruby/object:Codebreaker::Game
|
24
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
25
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
26
|
-
const_name: User
|
27
|
-
__expired: false
|
28
|
-
name:
|
29
|
-
__sending_message:
|
30
|
-
difficulty: :easy
|
31
|
-
date: 2021-10-08
|
32
|
-
attempts: 15
|
33
|
-
number_of_hints: 2
|
34
|
-
--- !ruby/object:Codebreaker::Game
|
35
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
36
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
37
|
-
const_name: User
|
38
|
-
__expired: false
|
39
|
-
name:
|
40
|
-
__sending_message:
|
41
|
-
difficulty: :easy
|
42
|
-
date: 2021-10-08
|
43
|
-
attempts: 15
|
44
|
-
number_of_hints: 2
|
45
|
-
--- !ruby/object:Codebreaker::Game
|
46
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
47
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
48
|
-
const_name: User
|
49
|
-
__expired: false
|
50
|
-
name:
|
51
|
-
__sending_message:
|
52
|
-
difficulty: :easy
|
53
|
-
date: 2021-10-08
|
54
|
-
attempts: 15
|
55
|
-
number_of_hints: 2
|
56
|
-
--- !ruby/object:Codebreaker::Game
|
57
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
58
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
59
|
-
const_name: User
|
60
|
-
__expired: false
|
61
|
-
name:
|
62
|
-
__sending_message:
|
63
|
-
difficulty: :easy
|
64
|
-
date: 2021-10-08
|
65
|
-
attempts: 15
|
66
|
-
number_of_hints: 2
|
67
|
-
--- !ruby/object:Codebreaker::Game
|
68
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
69
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
70
|
-
const_name: User
|
71
|
-
__expired: false
|
72
|
-
name:
|
73
|
-
__sending_message:
|
74
|
-
difficulty: :easy
|
75
|
-
date: 2021-10-08
|
76
|
-
attempts: 15
|
77
|
-
number_of_hints: 2
|
78
|
-
--- !ruby/object:Codebreaker::Game
|
79
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
80
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
81
|
-
const_name: User
|
82
|
-
__expired: false
|
83
|
-
name:
|
84
|
-
__sending_message:
|
85
|
-
difficulty: :easy
|
86
|
-
date: 2021-10-08
|
87
|
-
attempts: 15
|
88
|
-
number_of_hints: 2
|
89
|
-
--- !ruby/object:Codebreaker::Game
|
90
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
91
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
92
|
-
const_name: User
|
93
|
-
__expired: false
|
94
|
-
name:
|
95
|
-
__sending_message:
|
96
|
-
difficulty: :easy
|
97
|
-
date: 2021-10-08
|
98
|
-
attempts: 15
|
99
|
-
number_of_hints: 2
|
100
|
-
--- !ruby/object:Codebreaker::Game
|
101
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
102
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
103
|
-
const_name: User
|
104
|
-
__expired: false
|
105
|
-
name:
|
106
|
-
__sending_message:
|
107
|
-
difficulty: :easy
|
108
|
-
date: 2021-10-08
|
109
|
-
attempts: 15
|
110
|
-
number_of_hints: 2
|
111
|
-
--- !ruby/object:Codebreaker::Game
|
112
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
113
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
114
|
-
const_name: User
|
115
|
-
__expired: false
|
116
|
-
name:
|
117
|
-
__sending_message:
|
118
|
-
difficulty: :easy
|
119
|
-
date: 2021-10-19
|
120
|
-
attempts: 15
|
121
|
-
number_of_hints: 2
|
122
|
-
--- !ruby/object:Codebreaker::Game
|
123
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
124
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
125
|
-
const_name: User
|
126
|
-
__expired: false
|
127
|
-
name:
|
128
|
-
__sending_message:
|
129
|
-
difficulty: :easy
|
130
|
-
date: 2021-10-19
|
131
|
-
attempts: 15
|
132
|
-
number_of_hints: 2
|
133
|
-
--- !ruby/object:Codebreaker::Game
|
134
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
135
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
136
|
-
const_name: User
|
137
|
-
__expired: false
|
138
|
-
name:
|
139
|
-
__sending_message:
|
140
|
-
difficulty: :easy
|
141
|
-
date: 2021-10-19
|
142
|
-
attempts: 15
|
143
|
-
number_of_hints: 2
|
144
|
-
--- !ruby/object:Codebreaker::Game
|
145
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
146
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
147
|
-
const_name: User
|
148
|
-
__expired: false
|
149
|
-
name:
|
150
|
-
__sending_message:
|
151
|
-
difficulty: :easy
|
152
|
-
date: 2021-10-19
|
153
|
-
attempts: 15
|
154
|
-
number_of_hints: 2
|
155
|
-
--- !ruby/object:Codebreaker::Game
|
156
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
157
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
158
|
-
const_name: User
|
159
|
-
__expired: false
|
160
|
-
name:
|
161
|
-
__sending_message:
|
162
|
-
difficulty: :easy
|
163
|
-
date: 2021-10-19
|
164
|
-
attempts: 15
|
165
|
-
number_of_hints: 2
|
166
|
-
--- !ruby/object:Codebreaker::Game
|
167
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
168
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
169
|
-
const_name: User
|
170
|
-
__expired: false
|
171
|
-
name:
|
172
|
-
__sending_message:
|
173
|
-
difficulty: :easy
|
174
|
-
date: 2021-10-19
|
175
|
-
attempts: 15
|
176
|
-
number_of_hints: 2
|
177
|
-
--- !ruby/object:Codebreaker::Game
|
178
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
179
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
180
|
-
const_name: User
|
181
|
-
__expired: false
|
182
|
-
name:
|
183
|
-
__sending_message:
|
184
|
-
difficulty: :easy
|
185
|
-
date: 2021-10-19
|
186
|
-
attempts: 15
|
187
|
-
number_of_hints: 2
|
188
|
-
--- !ruby/object:Codebreaker::Game
|
189
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
190
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
191
|
-
const_name: User
|
192
|
-
__expired: false
|
193
|
-
name:
|
194
|
-
__sending_message:
|
195
|
-
difficulty: :easy
|
196
|
-
date: 2021-10-19
|
197
|
-
attempts: 15
|
198
|
-
number_of_hints: 2
|
199
|
-
--- !ruby/object:Codebreaker::Game
|
200
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
201
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
202
|
-
const_name: User
|
203
|
-
__expired: false
|
204
|
-
name:
|
205
|
-
__sending_message:
|
206
|
-
difficulty: :easy
|
207
|
-
date: 2021-10-19
|
208
|
-
attempts: 15
|
209
|
-
number_of_hints: 2
|
210
|
-
--- !ruby/object:Codebreaker::Game
|
211
|
-
user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
|
212
|
-
doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
|
213
|
-
const_name: User
|
214
|
-
__expired: false
|
215
|
-
name:
|
216
|
-
__sending_message:
|
217
|
-
difficulty: :easy
|
218
|
-
date: 2021-10-19
|
219
|
-
attempts: 15
|
220
|
-
number_of_hints: 2
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Codebreaker
|
4
|
-
class FileLoader
|
5
|
-
include Validation
|
6
|
-
|
7
|
-
FILE_PATH = "#{ENV['DB_PATH']}#{ENV['DB_FILE']}"
|
8
|
-
|
9
|
-
def initialize(db_file_path = FILE_PATH)
|
10
|
-
@db_file_path = db_file_path
|
11
|
-
end
|
12
|
-
|
13
|
-
def load
|
14
|
-
validate_file_existens(FILE_PATH)
|
15
|
-
|
16
|
-
File.open(FILE_PATH, 'r') do |file|
|
17
|
-
YAML.load_stream(file)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def save(object)
|
22
|
-
create_directory('DB_PATH') unless Dir.exist?(ENV['DB_PATH'])
|
23
|
-
File.open(FILE_PATH, 'a') { |file| file.write(object.to_yaml) }
|
24
|
-
end
|
25
|
-
|
26
|
-
def create_directory(path)
|
27
|
-
Dir.mkdir(ENV[path])
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/lib/codebreaker/gameload.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Codebreaker
|
4
|
-
class Gameload
|
5
|
-
attr_reader :clues
|
6
|
-
|
7
|
-
CLUES = {
|
8
|
-
exact: :exact,
|
9
|
-
non_exact: :non_exact
|
10
|
-
}.freeze
|
11
|
-
|
12
|
-
def initialize(guess, secret_code)
|
13
|
-
@secret_code = secret_code
|
14
|
-
@guess = guess
|
15
|
-
@clues = []
|
16
|
-
end
|
17
|
-
|
18
|
-
def match
|
19
|
-
collected = @secret_code.zip(@guess).delete_if { |code, guess| write_to_clues(CLUES[:exact]) if code == guess }
|
20
|
-
@secret_code, @guess = collected.transpose
|
21
|
-
return unless @guess
|
22
|
-
|
23
|
-
non_exact_match
|
24
|
-
end
|
25
|
-
|
26
|
-
def non_exact_match
|
27
|
-
@guess.compact.each do |num|
|
28
|
-
next unless @secret_code.any?(num)
|
29
|
-
|
30
|
-
write_to_clues(CLUES[:non_exact])
|
31
|
-
@secret_code[@secret_code.index(num)] = nil
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def write_to_clues(clue)
|
36
|
-
@clues.push(clue)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Codebreaker
|
4
|
-
module Validation
|
5
|
-
ERROR_MESSAGES = {
|
6
|
-
invalid_name: 'Name should be of 3 to 20 characters',
|
7
|
-
invalid_guess: 'Expect 4 digits from 1 to 6',
|
8
|
-
no_hints_left: 'No hints left, mate',
|
9
|
-
no_difficulty: 'No such difficulty',
|
10
|
-
no_save_data: 'No saved data is found'
|
11
|
-
}.freeze
|
12
|
-
|
13
|
-
class GameError < StandardError; end
|
14
|
-
|
15
|
-
class NoSavedData < GameError; end
|
16
|
-
|
17
|
-
class UnknownDifficulty < GameError; end
|
18
|
-
|
19
|
-
class InvalidGuess < GameError; end
|
20
|
-
|
21
|
-
class NoHintsLeft < GameError; end
|
22
|
-
|
23
|
-
class InvalidName < GameError; end
|
24
|
-
|
25
|
-
def validate_user_name(name, length)
|
26
|
-
raise_error(InvalidName, :invalid_name) unless length.cover?(name.length)
|
27
|
-
end
|
28
|
-
|
29
|
-
def validate_difficulty(difficulty, difficulties)
|
30
|
-
raise_error(UnknownDifficulty, :no_difficulty) unless difficulties.keys.any?(difficulty.to_sym)
|
31
|
-
end
|
32
|
-
|
33
|
-
def validate_guess(guess, length, range)
|
34
|
-
raise_error(InvalidGuess, :invalid_guess) unless guess.compact.length == length
|
35
|
-
raise_error(InvalidGuess, :invalid_guess) if guess.compact.any? { |num| !range.cover? num }
|
36
|
-
end
|
37
|
-
|
38
|
-
def validate_hints(hints_used, hints_total)
|
39
|
-
raise_error(NoHintsLeft, :no_hints_left) if hints_used >= hints_total
|
40
|
-
end
|
41
|
-
|
42
|
-
def validate_file_existens(file_path)
|
43
|
-
raise_error(NoSavedData, :no_save_data) unless File.exist?(file_path)
|
44
|
-
end
|
45
|
-
|
46
|
-
def raise_error(error_class, error_message)
|
47
|
-
raise error_class, ERROR_MESSAGES[error_message]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|