codebreaker_gapdn 0.1.1 → 0.1.3
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/Gemfile.lock +2 -2
- data/lib/codebreaker_gapdn/game.rb +49 -55
- data/lib/codebreaker_gapdn/version.rb +1 -1
- data/lib/database/statistic.rb +41 -37
- data/lib/entities/base_class.rb +11 -9
- data/lib/entities/difficulty.rb +15 -13
- data/lib/entities/guess.rb +14 -12
- data/lib/entities/user.rb +14 -12
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d941db157786ec9ac283db477b06ab6c9e77a1466ce33d33c40a6430b04e5ab
|
4
|
+
data.tar.gz: 60f2244f3d0ea8b2f4bad32422e9e0351851d10f64394251da9acdae4804b675
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb9db105b27eda62578d4db3a8a03a5fd0e913399c3b7d1447dafd5b34a9ddd9af9729df953494a4a5e2c298ebb2a5298ee3c935c5b1cf703b3eb494442ca537
|
7
|
+
data.tar.gz: 3f9ac66a396a9a5c0c65c4f04df92d7c9393a69cae72b1099678e60e24ba7ec730ac665a82855ecf8095f2baa1fe36603c5349447093fee6f34a68b8a73131ac
|
data/Gemfile.lock
CHANGED
@@ -1,75 +1,69 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Codebreaker
|
4
|
+
class Game
|
5
|
+
GUESS_PRESENCE = '-'
|
6
|
+
GUESS_PLACE = '+'
|
6
7
|
|
7
|
-
|
8
|
+
attr_reader :secret_code, :attempts_counter, :hinted_numbers, :current_difficulty
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
def initialize(difficulty)
|
11
|
+
@secret_code = create_secret_code
|
12
|
+
@attempts_counter = 0
|
13
|
+
@current_difficulty = difficulty.level
|
14
|
+
@hinted_numbers = @secret_code.sample(@current_difficulty[:hints])
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def check_number_match(guess)
|
18
|
+
@guess = guess
|
19
|
+
@attempts_counter += 1
|
20
|
+
return win_string if @guess == @secret_code
|
20
21
|
|
21
|
-
|
22
|
-
@guess = guess
|
23
|
-
@attempts_counter += 1
|
24
|
-
if @guess == @secret_code
|
25
|
-
@win = true
|
26
|
-
return win_string
|
22
|
+
number_match(exact_match)
|
27
23
|
end
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def take_hint
|
33
|
-
@hinted_numbers.pop
|
34
|
-
end
|
25
|
+
def take_hint
|
26
|
+
@hinted_numbers.pop
|
27
|
+
end
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
|
29
|
+
def win?(string)
|
30
|
+
string == win_string
|
31
|
+
end
|
39
32
|
|
40
|
-
|
41
|
-
|
42
|
-
|
33
|
+
def lose?
|
34
|
+
@attempts_counter >= @current_difficulty[:attempts]
|
35
|
+
end
|
43
36
|
|
44
|
-
|
37
|
+
private
|
45
38
|
|
46
|
-
|
47
|
-
|
48
|
-
|
39
|
+
def win_string
|
40
|
+
GUESS_PLACE * Guess::VALID_GUESS_LENGTH
|
41
|
+
end
|
49
42
|
|
50
|
-
|
51
|
-
|
52
|
-
|
43
|
+
def create_secret_code
|
44
|
+
Array.new(4) { rand(0..6) }
|
45
|
+
end
|
53
46
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
47
|
+
def exact_match
|
48
|
+
array = @secret_code.dup
|
49
|
+
array.map.with_index do |_char, index|
|
50
|
+
next unless array[index] == @guess[index]
|
58
51
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
52
|
+
@guess[index] = nil
|
53
|
+
GUESS_PLACE
|
54
|
+
end.compact
|
55
|
+
end
|
63
56
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
57
|
+
def number_match(pluses)
|
58
|
+
code = @secret_code.map.with_index { |char, index| char if @guess[index] }.compact
|
59
|
+
@guess.compact!
|
60
|
+
code.map.with_index do |_char, index|
|
61
|
+
if code.include? @guess[index]
|
62
|
+
code[code.index(@guess[index])] = nil
|
63
|
+
pluses << GUESS_PRESENCE
|
64
|
+
end
|
71
65
|
end
|
66
|
+
pluses.join
|
72
67
|
end
|
73
|
-
pluses.join
|
74
68
|
end
|
75
69
|
end
|
data/lib/database/statistic.rb
CHANGED
@@ -1,52 +1,56 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module Codebreaker
|
4
|
+
class Statistic
|
5
|
+
include DataHandler
|
5
6
|
|
6
|
-
|
7
|
+
attr_reader :headers
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def initialize(db = __dir__ + '/storage.yml')
|
10
|
+
@db = db
|
11
|
+
@headers = %w[ratign name difficulty attempts_total attempts_used hints_total hints_used]
|
12
|
+
@items = load || []
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def statistic
|
16
|
+
sort
|
17
|
+
@items.each_with_index.map do |item, index|
|
18
|
+
[
|
19
|
+
index.next, item[:name], item[:difficulty], item[:attempts_total],
|
20
|
+
item[:attempts_used], item[:hints_total], item[:hints_used]
|
21
|
+
]
|
22
|
+
end
|
19
23
|
end
|
20
|
-
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
def add_item(game, username)
|
26
|
+
@items << { name: username,
|
27
|
+
difficulty: game.current_difficulty[:name],
|
28
|
+
difficulty_id: game.current_difficulty[:id],
|
29
|
+
attempts_total: game.current_difficulty[:attempts],
|
30
|
+
attempts_used: game.attempts_counter,
|
31
|
+
hints_total: game.current_difficulty[:hints],
|
32
|
+
hints_used: hints_used(game) }
|
33
|
+
save
|
34
|
+
end
|
32
35
|
|
33
|
-
|
36
|
+
private
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
def hints_used(game)
|
39
|
+
game.current_difficulty[:hints] - game.hinted_numbers.size
|
40
|
+
end
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
+
def load
|
43
|
+
DataHandler.load(@db)
|
44
|
+
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
def save
|
47
|
+
DataHandler.save(@db, @items)
|
48
|
+
end
|
46
49
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
+
def sort
|
51
|
+
@items.sort_by! do |item|
|
52
|
+
[-item[:difficulty_id], item[:attempts_used], item[:hints_used]]
|
53
|
+
end
|
50
54
|
end
|
51
55
|
end
|
52
56
|
end
|
data/lib/entities/base_class.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module Codebreaker
|
4
|
+
class BaseClass
|
5
|
+
include Validator
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def valid?
|
8
|
+
validate
|
9
|
+
@errors.empty?
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
+
private
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
def validate
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
data/lib/entities/difficulty.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module Codebreaker
|
4
|
+
class Difficulty < BaseClass
|
5
|
+
LEVELS = {
|
6
|
+
easy: { attempts: 15, hints: 3, name: 'easy', id: 1 },
|
7
|
+
medium: { attempts: 10, hints: 2, name: 'medium', id: 2 },
|
8
|
+
hell: { attempts: 5, hints: 1, name: 'hell', id: 3 }
|
9
|
+
}.freeze
|
9
10
|
|
10
|
-
|
11
|
+
attr_reader :errors, :level
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def initialize(level = :easy)
|
14
|
+
@level = LEVELS[level.to_sym]
|
15
|
+
@errors = []
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
def validate
|
19
|
+
@errors << 'unexpected_comand' unless LEVELS.values.include? @level
|
20
|
+
end
|
19
21
|
end
|
20
22
|
end
|
data/lib/entities/guess.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Codebreaker
|
4
|
+
class Guess < BaseClass
|
5
|
+
VALID_GUESS_LENGTH = 4
|
6
|
+
VALID_GUESS_RANGE = ('0'..'6').freeze
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
attr_accessor :number
|
9
|
+
attr_reader :errors
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def initialize(guess)
|
12
|
+
@number = guess
|
13
|
+
@errors = []
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def validate
|
17
|
+
@errors << 'error_number_length' unless check_length?(@number, VALID_GUESS_LENGTH)
|
18
|
+
@errors << 'error_number_digit' unless check_number_in_range?(@number, VALID_GUESS_RANGE)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
data/lib/entities/user.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
module Codebreaker
|
4
|
+
class User < BaseClass
|
5
|
+
VALID_NAME_RANGE = (3..20).freeze
|
6
|
+
VALID_SYMBOLS_RANGE = ('a'..'z').freeze
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
attr_accessor :name
|
9
|
+
attr_reader :errors
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def initialize(name = 'Codebreaker')
|
12
|
+
@name = name
|
13
|
+
@errors = []
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def validate
|
17
|
+
@errors << 'error_name_length' unless check_length_in_range?(@name, VALID_NAME_RANGE)
|
18
|
+
@errors << 'error_name_chars' unless check_symbols_in_range?(@name, VALID_SYMBOLS_RANGE)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codebreaker_gapdn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- gapdn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|