codebraker_ov 0.0.10 → 0.0.11
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/lib/codebraker_ov.rb +5 -6
- data/lib/codebraker_ov/entities/game.rb +78 -0
- data/lib/codebraker_ov/entities/player.rb +42 -0
- data/lib/codebraker_ov/entities/stats.rb +27 -0
- data/lib/codebraker_ov/utils/errors.rb +15 -0
- data/lib/codebraker_ov/utils/validation.rb +26 -0
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2ffef2cb85988345112647c4ec8e31a60b3c5e4965cb00df0ec83339e24a3f2
|
4
|
+
data.tar.gz: 8d834927953a1dd9cd5780d0d635c9c92e341237af4eac577126b4e0ea88fd06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58d3bc9f0926611847ef8220a6d76e0287e53d64f318d17c776eee4b51e2b252a2b54592ab8ce8e458b1436b47c79dc18d1ce16f8ca4f799c216a57a256cac7d
|
7
|
+
data.tar.gz: 1a97d96d66405876b102b3a61d7ef2493dbdac89f08ea0cbd707d28ef79c6723037f8fbc4ac2fd9917157ae6c4cc6e07c52292bade26530474650c606c9d8465
|
data/lib/codebraker_ov.rb
CHANGED
@@ -2,9 +2,8 @@ require 'yaml'
|
|
2
2
|
require 'i18n'
|
3
3
|
require 'pry'
|
4
4
|
|
5
|
-
require_relative './
|
6
|
-
require_relative './
|
7
|
-
|
8
|
-
require_relative './
|
9
|
-
require_relative './
|
10
|
-
require_relative './codebreaker_ov/entities/player.rb'
|
5
|
+
require_relative './codebraker_ov/utils/errors'
|
6
|
+
require_relative './codebraker_ov/utils/validation'
|
7
|
+
require_relative './codebraker_ov/entities/game'
|
8
|
+
require_relative './codebraker_ov/entities/stats'
|
9
|
+
require_relative './codebraker_ov/entities/player'
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
class Game
|
3
|
+
attr_reader(
|
4
|
+
:secret,
|
5
|
+
:attempts_total,
|
6
|
+
:attempts,
|
7
|
+
:hints_available,
|
8
|
+
:hints_used,
|
9
|
+
:hints_given,
|
10
|
+
:result,
|
11
|
+
:level_name
|
12
|
+
)
|
13
|
+
|
14
|
+
DIFFICULTIES = {
|
15
|
+
low: { attempts: 15, hints: 2 },
|
16
|
+
medium: { attempts: 10, hints: 2 },
|
17
|
+
hell: { attempts: 5, hints: 1 }
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
def initialize(level)
|
21
|
+
@secret = Array.new(4) { rand(1..6).to_s }
|
22
|
+
@level_name = level.to_s
|
23
|
+
@attempts_total = DIFFICULTIES[level][:attempts]
|
24
|
+
@attempts = DIFFICULTIES[level][:attempts]
|
25
|
+
@hints_available = @secret.sample(DIFFICULTIES[level][:hints])
|
26
|
+
@hints_given = []
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def check_full_matches
|
32
|
+
@secret.map.with_index do |number, index|
|
33
|
+
next number unless number == @guess[index]
|
34
|
+
|
35
|
+
@result += '+'
|
36
|
+
@guess[index] = nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_partial_matches(rest)
|
41
|
+
@guess.compact.each do |number|
|
42
|
+
index = rest.index(number)
|
43
|
+
next unless index
|
44
|
+
|
45
|
+
@result += '-'
|
46
|
+
rest[index] = nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
public
|
51
|
+
|
52
|
+
def compare_with(guess)
|
53
|
+
@guess = guess.chars
|
54
|
+
@result = ''
|
55
|
+
|
56
|
+
rest = check_full_matches
|
57
|
+
check_partial_matches(rest)
|
58
|
+
@attempts -= 1
|
59
|
+
@result
|
60
|
+
end
|
61
|
+
|
62
|
+
def receive_hint
|
63
|
+
return unless @hints_available.length.positive?
|
64
|
+
|
65
|
+
@hints_given << @hints_available.pop
|
66
|
+
|
67
|
+
@hints_given.last
|
68
|
+
end
|
69
|
+
|
70
|
+
def win?(guess)
|
71
|
+
@secret == guess.chars
|
72
|
+
end
|
73
|
+
|
74
|
+
def lose?
|
75
|
+
!@attempts.positive?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
class Player
|
3
|
+
attr_accessor(
|
4
|
+
:rating,
|
5
|
+
:name,
|
6
|
+
:difficulty,
|
7
|
+
:attempts_total,
|
8
|
+
:attempts_used,
|
9
|
+
:hints_total,
|
10
|
+
:hints_used,
|
11
|
+
:date
|
12
|
+
)
|
13
|
+
|
14
|
+
def initialize(name, difficulty)
|
15
|
+
@name = name
|
16
|
+
@difficulty = difficulty
|
17
|
+
@attempts_total = Game::DIFFICULTIES[difficulty][:attempts]
|
18
|
+
@attempts_used = nil
|
19
|
+
@hints_total = Game::DIFFICULTIES[difficulty][:hints]
|
20
|
+
@hints_used = nil
|
21
|
+
@rating = nil
|
22
|
+
@date = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def <=>(other)
|
26
|
+
[
|
27
|
+
-@attempts_total,
|
28
|
+
@attempts_used,
|
29
|
+
@hints_used
|
30
|
+
] <=> [
|
31
|
+
-other.attempts_total,
|
32
|
+
other.attempts_used,
|
33
|
+
other.hints_used
|
34
|
+
]
|
35
|
+
end
|
36
|
+
|
37
|
+
def save_score(attempts:, hints:)
|
38
|
+
@attempts_used = @attempts_total - attempts
|
39
|
+
@hints_used = hints
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# :nocov:
|
2
|
+
module Codebreaker
|
3
|
+
class Stats
|
4
|
+
STORE = 'db/stats.yml'.freeze
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def write(player)
|
8
|
+
data = load
|
9
|
+
data.push(player)
|
10
|
+
|
11
|
+
sorted = data.sort
|
12
|
+
|
13
|
+
data.map!.with_index do |record, index|
|
14
|
+
record.rating = index + 1
|
15
|
+
record
|
16
|
+
end
|
17
|
+
|
18
|
+
File.write(STORE, sorted.to_yaml)
|
19
|
+
end
|
20
|
+
|
21
|
+
def load
|
22
|
+
File.exist?(STORE) ? YAML.load_file(STORE) : []
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
# :nocov:
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
module Errors
|
3
|
+
class AnswerError < StandardError
|
4
|
+
def initialize
|
5
|
+
super('Answer must be 4 digits long.')
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class NameError < StandardError
|
10
|
+
def initialize
|
11
|
+
super('Name must be 3-20 characters.')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
module Validation
|
3
|
+
# cause guard clause will be > 80 chars
|
4
|
+
# rubocop:disable Style/GuardClause
|
5
|
+
def self.name_valid?(name)
|
6
|
+
unless string?(name) && name_length_valid?(name)
|
7
|
+
raise Codebreaker::Errors::NameError
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.answer_valid?(guess)
|
12
|
+
unless string?(guess) && guess.match?(/^[123456]{4}$/)
|
13
|
+
raise Codebreaker::Errors::AnswerError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
# rubocop:enable Style/GuardClause
|
17
|
+
|
18
|
+
def self.name_length_valid?(name)
|
19
|
+
name.length > 2 && name.length < 21
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.string?(item)
|
23
|
+
item.instance_of?(String)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codebraker_ov
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleh Volynets
|
@@ -17,6 +17,11 @@ extensions: []
|
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
19
|
- lib/codebraker_ov.rb
|
20
|
+
- lib/codebraker_ov/entities/game.rb
|
21
|
+
- lib/codebraker_ov/entities/player.rb
|
22
|
+
- lib/codebraker_ov/entities/stats.rb
|
23
|
+
- lib/codebraker_ov/utils/errors.rb
|
24
|
+
- lib/codebraker_ov/utils/validation.rb
|
20
25
|
homepage: https://github.com/olehvolynets/codebraker.git
|
21
26
|
licenses:
|
22
27
|
- MIT
|