codebreaker-rg-te 0.1.12 → 0.1.13
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/codebreaker.rb +2 -2
- data/lib/codebreaker/console.rb +47 -46
- data/lib/codebreaker/game.rb +37 -17
- data/lib/codebreaker/{stats.rb → statistics.rb} +3 -5
- data/lib/codebreaker/storage/{StorageInterceptor.rb → storage_interceptor.rb} +3 -3
- data/lib/codebreaker/validation.rb +4 -10
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95180783a53441f9238daf38e89e7818b2eb51e2
|
4
|
+
data.tar.gz: 97dbc87d1f613e04071b3e8c1d419d796ebd7535
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8bb7985bb6db6152e9ffadc330a7dd3f739b1ac53d63d3f2f36e199011cfacfe5cbcc1ce5565ce0ec91fc2bdea313da0e5882a0faaf2710f88deb2b331c0acb
|
7
|
+
data.tar.gz: 5cd985bf9e82107998fddb8275209b540ddf9fb32e1d465b3cac1a07895a647dd9df2146c318538447e9722f63971dd558d6d8867d1ce515608aa4894ba260f0
|
data/lib/codebreaker.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'i18n'
|
2
2
|
require 'yaml'
|
3
|
-
require 'codebreaker/storage/
|
3
|
+
require 'codebreaker/storage/storage_interceptor.rb'
|
4
4
|
require 'codebreaker/console.rb'
|
5
5
|
require 'codebreaker/localization.rb'
|
6
6
|
require 'codebreaker/validation.rb'
|
7
|
-
require 'codebreaker/
|
7
|
+
require 'codebreaker/statistics.rb'
|
8
8
|
require 'codebreaker/game.rb'
|
9
9
|
require 'codebreaker.rb'
|
10
10
|
|
data/lib/codebreaker/console.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Codebreaker
|
2
|
-
class Console
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
class Console
|
5
|
+
COMMANDS = {
|
6
|
+
start: 'start',
|
7
|
+
rules: 'rules',
|
8
|
+
stats: 'stats',
|
9
|
+
exit: 'exit'
|
10
|
+
}.freeze
|
9
11
|
|
10
|
-
|
12
|
+
HINT = 'hint'
|
11
13
|
|
12
|
-
|
13
|
-
@game = Codebreaker::Game.new
|
14
|
-
@stat = Codebreaker::Stats.new
|
15
|
-
end
|
14
|
+
ANSWERS = { yes: 'yes' }.freeze
|
16
15
|
|
17
16
|
def launch
|
18
17
|
loop do
|
19
18
|
message(:start_game)
|
20
|
-
message(:wel_instruct,
|
19
|
+
message(:wel_instruct, COMMANDS)
|
21
20
|
@answer = read_from_console
|
22
|
-
check_answer
|
21
|
+
return check_answer
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
26
25
|
def start_game
|
26
|
+
@game = Codebreaker::Game.new
|
27
27
|
enter_name
|
28
28
|
enter_level
|
29
29
|
@game.new_game
|
@@ -31,36 +31,30 @@ class Console
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def round_game
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
message(:
|
38
|
-
user_answer = read_from_console
|
39
|
-
hint_show if user_answer == HINT
|
40
|
-
next message(:invalid_number) unless @game.validate_answer(user_answer)
|
34
|
+
while @game.attempts.positive?
|
35
|
+
user_answer = message_game_read_console
|
36
|
+
next hint_show if user_answer == HINT
|
37
|
+
next message(:invalid_number) unless @game.validate_code(user_answer)
|
41
38
|
|
42
|
-
@game.
|
43
|
-
@game.set_user_code(user_answer)
|
39
|
+
@game.handle_guess(user_answer)
|
44
40
|
return win if @game.equal_codes?(user_answer)
|
45
41
|
|
46
|
-
|
42
|
+
message_game_result
|
47
43
|
end
|
44
|
+
loose
|
48
45
|
end
|
49
46
|
|
50
47
|
def hint_show
|
51
|
-
if @game.hints.zero?
|
52
|
-
|
53
|
-
round_game
|
54
|
-
end
|
48
|
+
return message(:over_hint) if @game.hints.zero?
|
49
|
+
|
55
50
|
puts @game.show_hints
|
56
51
|
@game.take_hints
|
57
|
-
round_game
|
58
52
|
end
|
59
53
|
|
60
54
|
def win
|
61
55
|
message(:win)
|
62
56
|
message(:progress)
|
63
|
-
@game.save if read_from_console.eql?
|
57
|
+
@game.save if read_from_console.eql? ANSWERS[:yes]
|
64
58
|
continue_game? ? start_game : exit
|
65
59
|
end
|
66
60
|
|
@@ -71,20 +65,19 @@ class Console
|
|
71
65
|
|
72
66
|
def continue_game?
|
73
67
|
message(:new_game)
|
74
|
-
read_from_console.eql?
|
68
|
+
read_from_console.eql? ANSWERS[:yes]
|
75
69
|
end
|
76
70
|
|
77
71
|
def stats_show
|
78
|
-
|
79
|
-
|
80
|
-
return message(:empty_stat) unless data
|
72
|
+
@stat = Codebreaker::Statistics.new
|
73
|
+
return message(:empty_stat) unless data = @stat.stats
|
81
74
|
|
82
75
|
message(:stats)
|
83
76
|
message(:col_table)
|
84
|
-
data.each_with_index do |
|
77
|
+
data.each_with_index do |row, index|
|
85
78
|
print "#{index}\t"
|
86
|
-
|
87
|
-
print "#{
|
79
|
+
row.each do |_key, cell|
|
80
|
+
print "#{cell}\t"
|
88
81
|
end
|
89
82
|
print "\n"
|
90
83
|
end
|
@@ -94,10 +87,10 @@ class Console
|
|
94
87
|
|
95
88
|
def check_answer
|
96
89
|
case @answer
|
97
|
-
when
|
98
|
-
when
|
99
|
-
when
|
100
|
-
when
|
90
|
+
when COMMANDS[:start] then start_game
|
91
|
+
when COMMANDS[:rules] then message(:rulegame)
|
92
|
+
when COMMANDS[:stats] then stats_show
|
93
|
+
when COMMANDS[:exit] then exit
|
101
94
|
end
|
102
95
|
end
|
103
96
|
|
@@ -109,17 +102,25 @@ class Console
|
|
109
102
|
gets.chomp
|
110
103
|
end
|
111
104
|
|
105
|
+
def message_game_read_console
|
106
|
+
message(:question_num, attempts: @game.attempts, hints: @game.hints)
|
107
|
+
read_from_console
|
108
|
+
end
|
109
|
+
|
110
|
+
def message_game_result
|
111
|
+
puts @game.game_result
|
112
|
+
end
|
113
|
+
|
112
114
|
def enter_name
|
113
115
|
message(:username)
|
114
|
-
|
115
|
-
return enter_name unless @game.enter_name(name)
|
116
|
+
return enter_name unless @game.enter_name(read_from_console)
|
116
117
|
|
117
|
-
message(:hello, name: name)
|
118
|
+
message(:hello, name: @game.name)
|
118
119
|
end
|
119
120
|
|
120
121
|
def enter_level
|
121
|
-
message(:choose_difficulty, difficulties:
|
122
|
-
return
|
122
|
+
message(:choose_difficulty, difficulties: Codebreaker::Game::GAME_LEVELS.keys.join(' '))
|
123
|
+
return enter_level unless @game.enter_level(read_from_console)
|
123
124
|
end
|
124
125
|
end
|
125
126
|
end
|
data/lib/codebreaker/game.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Codebreaker
|
3
4
|
class Game
|
4
5
|
include Validation
|
@@ -13,29 +14,27 @@ module Codebreaker
|
|
13
14
|
hard: { attempts: 10, hints: 1, level_num: 2 }
|
14
15
|
}.freeze
|
15
16
|
|
17
|
+
COUNTS_OF_HINTS = (0..3).freeze
|
16
18
|
DIGITS_COUNT = 4
|
19
|
+
USER_ANSWER_REX = /^[1-6]{4}$/.freeze
|
17
20
|
|
18
21
|
def new_game
|
19
22
|
@secret_code = Array.new(DIGITS_COUNT) { rand(RANGE) }
|
20
23
|
end
|
21
24
|
|
22
|
-
def set_user_code(enter_code)
|
23
|
-
@user_code = enter_code.each_char.map(&:to_i)
|
24
|
-
end
|
25
|
-
|
26
25
|
def enter_level(level)
|
27
|
-
return unless
|
26
|
+
return unless GAME_LEVELS.key?(level.to_sym)
|
28
27
|
|
29
28
|
@level = level
|
30
29
|
|
31
30
|
@attempts = GAME_LEVELS.dig(level.to_sym, :attempts)
|
32
31
|
@hints = GAME_LEVELS.dig(level.to_sym, :hints)
|
33
32
|
@level_num = GAME_LEVELS.dig(level.to_sym, :level_num)
|
34
|
-
@hints_index =
|
33
|
+
@hints_index = COUNTS_OF_HINTS.to_a.sample @hints
|
35
34
|
end
|
36
35
|
|
37
36
|
def enter_name(name)
|
38
|
-
return unless
|
37
|
+
return unless validate_length(name)
|
39
38
|
|
40
39
|
@name = name
|
41
40
|
end
|
@@ -56,27 +55,48 @@ module Codebreaker
|
|
56
55
|
secret_code[hints_index.shift]
|
57
56
|
end
|
58
57
|
|
58
|
+
def set_user_code(enter_code)
|
59
|
+
@user_code = enter_code.each_char.map(&:to_i)
|
60
|
+
end
|
61
|
+
|
62
|
+
def handle_guess(user_answer)
|
63
|
+
take_attempts
|
64
|
+
set_user_code(user_answer)
|
65
|
+
end
|
66
|
+
|
59
67
|
def game_result
|
68
|
+
return '++++' if equal_codes?(@user_code.join)
|
69
|
+
|
60
70
|
result = ''
|
61
|
-
|
62
|
-
|
71
|
+
@secret_code_clone = @secret_code.clone
|
72
|
+
@user_code.each_with_index do |digit, index|
|
73
|
+
next unless digit == @secret_code_clone[index]
|
74
|
+
|
75
|
+
result += '+'
|
76
|
+
@secret_code_clone[index] = nil
|
77
|
+
@user_code[index] = nil
|
63
78
|
end
|
64
|
-
return result if result.eql?('++++')
|
65
79
|
|
66
|
-
|
67
|
-
|
80
|
+
@user_code.compact.each_with_index do |digit, _index|
|
81
|
+
next unless @secret_code_clone.include?(digit)
|
82
|
+
|
83
|
+
result += '-'
|
84
|
+
@secret_code_clone[@secret_code_clone.index(digit)] = nil
|
68
85
|
end
|
69
86
|
result
|
70
87
|
end
|
71
88
|
|
72
|
-
def
|
73
|
-
di = StorageInterceptor.new
|
74
|
-
codebreaker_data = di.read_database || []
|
89
|
+
def storage_data(codebreaker_data)
|
75
90
|
attempts_used = GAME_LEVELS.dig(level.to_sym, :attempts) - attempts
|
76
91
|
hints_used = GAME_LEVELS.dig(level.to_sym, :hints) - hints
|
77
92
|
hash_stat = { name: @name, level: @level, level_num: @level_num, attempts: @attempts, attempts_used: attempts_used, hints: @hints, hints_used: hints_used }
|
78
93
|
codebreaker_data << hash_stat
|
79
|
-
|
94
|
+
end
|
95
|
+
|
96
|
+
def save
|
97
|
+
storage = StorageInterceptor.new
|
98
|
+
codebreaker_data = storage.read_database || []
|
99
|
+
storage.write_database(storage_data(codebreaker_data))
|
80
100
|
end
|
81
101
|
end
|
82
|
-
end
|
102
|
+
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module Codebreaker
|
2
|
-
class
|
2
|
+
class Statistics
|
3
3
|
def stats
|
4
|
-
|
5
|
-
codebreaker_data =
|
6
|
-
|
7
|
-
return unless codebreaker_data
|
4
|
+
storage = StorageInterceptor.new
|
5
|
+
return unless codebreaker_data = storage.read_database
|
8
6
|
|
9
7
|
codebreaker_data.sort_by! { |stat| [stat[:level_num], stat[:hints], stat[:attempts]] }
|
10
8
|
codebreaker_data.each { |stat| stat.delete_if { |key, _value| key == :level_num } }
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Codebreaker
|
2
|
-
class StorageInterceptor
|
2
|
+
class StorageInterceptor
|
3
3
|
DEFAULT_PATH_TO_FILE = './data/stat.yml'.freeze
|
4
4
|
|
5
5
|
def initialize(path_to_file = DEFAULT_PATH_TO_FILE)
|
@@ -10,8 +10,8 @@ class StorageInterceptor
|
|
10
10
|
YAML.load_file(@path_to_file) if File.exist?(@path_to_file)
|
11
11
|
end
|
12
12
|
|
13
|
-
def write_database(
|
14
|
-
File.open(@path_to_file, 'w') { |file| file.write(
|
13
|
+
def write_database(data)
|
14
|
+
File.open(@path_to_file, 'w') { |file| file.write(data.to_yaml) }
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -1,15 +1,9 @@
|
|
1
1
|
module Validation
|
2
|
-
|
3
|
-
|
4
|
-
def validate_name(name)
|
5
|
-
name.size > 2 && name.size < 21
|
6
|
-
end
|
7
|
-
|
8
|
-
def validate_level(level)
|
9
|
-
%w[easy medium hard].include? level
|
2
|
+
def validate_length(word)
|
3
|
+
word.size > 2 && word.size < 21
|
10
4
|
end
|
11
5
|
|
12
|
-
def
|
13
|
-
|
6
|
+
def validate_code(code)
|
7
|
+
code =~ Codebreaker::Game::USER_ANSWER_REX
|
14
8
|
end
|
15
9
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codebreaker-rg-te
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eugene Tereschenko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.16.1
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.16.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: fasterer
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -161,8 +161,8 @@ files:
|
|
161
161
|
- lib/codebreaker/console.rb
|
162
162
|
- lib/codebreaker/game.rb
|
163
163
|
- lib/codebreaker/localization.rb
|
164
|
-
- lib/codebreaker/
|
165
|
-
- lib/codebreaker/storage/
|
164
|
+
- lib/codebreaker/statistics.rb
|
165
|
+
- lib/codebreaker/storage/storage_interceptor.rb
|
166
166
|
- lib/codebreaker/validation.rb
|
167
167
|
homepage: https://github.com/EugeneTereschenko/codebreaker
|
168
168
|
licenses: []
|