codebreaker_vukolov_edition 0.1.0 → 0.1.1
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/.gitignore +1 -1
- data/.ruby-version +1 -0
- data/lib/codebreaker_vukolov_edition/version.rb +1 -1
- data/lib/controller.rb +93 -0
- data/lib/game.rb +60 -0
- data/lib/messages.rb +46 -0
- data/lib/services.rb +16 -0
- data/start.rb +4 -0
- metadata +8 -3
- data/lib/codebreaker_vukolov_edition.rb +0 -137
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf336e1325d91902eed033fcfa76c165c6ae67f5
|
4
|
+
data.tar.gz: '0399cabf25a22df600ce4a33fefe3f2cba9c9b98'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0cede4d0212af980e67ae1810ac4cf0a4e71835ecd878188e617c65c2f22cfdfd904d7462d46f6334a5944e9a8ce7ce2fd361014efd999aeb666ba316aab15a
|
7
|
+
data.tar.gz: 31eebfbae302407cd0bebe4e3c51a3519de610f893c25ddcf92665f67c3d43de557f47bae834503d0e38f461c029672cfa250d1e7c398a1821eb855a53ecd2dc
|
data/.gitignore
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.4.0
|
data/lib/controller.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative 'codebreaker_vukolov_edition/version'
|
2
|
+
require_relative 'game'
|
3
|
+
require_relative 'messages'
|
4
|
+
require_relative 'services'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module CodebreakerVukolovEdition
|
8
|
+
class Controller
|
9
|
+
AVAILIABLE_VALUES = %w[hint yes no]
|
10
|
+
attr_accessor :game, :services
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@game = Game.new
|
14
|
+
@messages = Messages.new
|
15
|
+
@services = Services.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def play
|
19
|
+
return total_result(:lose) if @game.turns == Game::MAX_TURNS
|
20
|
+
@messages.before_round_info(@game.turns)
|
21
|
+
show_hint
|
22
|
+
guess = provided_guess
|
23
|
+
result = @game.round_result(guess)
|
24
|
+
round_info(result)
|
25
|
+
@game.add_new_turn
|
26
|
+
play
|
27
|
+
end
|
28
|
+
|
29
|
+
def round_info(result)
|
30
|
+
return total_result(:won) if result == :won
|
31
|
+
@messages.show_messages(:round_result, result)
|
32
|
+
end
|
33
|
+
|
34
|
+
def show_hint
|
35
|
+
return @messages.print_hint(@game.hint) if @game.hint[:used]
|
36
|
+
@messages.hint_info
|
37
|
+
end
|
38
|
+
|
39
|
+
def next_step(decision, *option)
|
40
|
+
if decision == 'yes'
|
41
|
+
yield
|
42
|
+
elsif decision == 'no' && option.include?('save_result')
|
43
|
+
@messages.show_messages(:game_unsaved)
|
44
|
+
else
|
45
|
+
abort
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def total_result(state)
|
50
|
+
@messages.total_game_info(state, @game.turns, @game.secret_code)
|
51
|
+
next_step(make_a_decision(:save_result), 'save_result') do
|
52
|
+
username = get_action(:name)
|
53
|
+
@services.write_result_to_file(username, state, @game.turns, @game.hint, @game.secret_code)
|
54
|
+
end
|
55
|
+
next_step(make_a_decision(:new_game)) do
|
56
|
+
game = CodebreakerVukolovEdition::Controller.new
|
57
|
+
game.play
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def make_a_decision(option)
|
62
|
+
decision = validate(get_action(option))
|
63
|
+
return decision unless decision.nil?
|
64
|
+
@messages.show_messages(:instruction)
|
65
|
+
make_a_decision(option)
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_action(*question)
|
69
|
+
@messages.show_messages(question.first) if question
|
70
|
+
value = gets.chomp
|
71
|
+
value.empty? ? get_action(*question) : value
|
72
|
+
end
|
73
|
+
|
74
|
+
def provided_guess
|
75
|
+
input = validate(get_action(:input))
|
76
|
+
if input.nil?
|
77
|
+
@messages.show_messages(:input_warning)
|
78
|
+
provided_guess
|
79
|
+
elsif input == 'hint'
|
80
|
+
@game.use_hint
|
81
|
+
play
|
82
|
+
else
|
83
|
+
input
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def validate(input)
|
90
|
+
input if (input.to_i.positive? && input.length == 4) || AVAILIABLE_VALUES.include?(input)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/game.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative 'controller'
|
2
|
+
|
3
|
+
module CodebreakerVukolovEdition
|
4
|
+
class Game
|
5
|
+
SECRET_CODE_VALID_VALUES = (1..6)
|
6
|
+
SECRET_CODE_LENGTH = 4
|
7
|
+
MAX_TURNS = 15
|
8
|
+
attr_accessor :turns, :secret_code, :hint
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@secret_code = new_code
|
12
|
+
@turns = 0
|
13
|
+
@hint = { used: false, value: @secret_code.sample }
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_new_turn
|
17
|
+
@turns += 1
|
18
|
+
end
|
19
|
+
|
20
|
+
def use_hint
|
21
|
+
@hint[:used] = true
|
22
|
+
end
|
23
|
+
|
24
|
+
def round_result(guess)
|
25
|
+
result = checker(guess)
|
26
|
+
return :won if result == '++++'
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
def checker(guess)
|
31
|
+
guess_arr = guess.split('').map(&:to_i)
|
32
|
+
temp = @secret_code.zip(guess_arr)
|
33
|
+
get_plusses(temp) + get_minuses(temp)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def new_code
|
39
|
+
Array.new(SECRET_CODE_LENGTH).map { rand(SECRET_CODE_VALID_VALUES) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def count_plusses(temp)
|
43
|
+
temp.select { |el| el.uniq.size == 1 }
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_plusses(temp)
|
47
|
+
'+' * count_plusses(temp).size
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_minuses(temp)
|
51
|
+
minuses = ''
|
52
|
+
code = (temp - count_plusses(temp)).transpose.first
|
53
|
+
user_guess = (temp - count_plusses(temp)).transpose.last
|
54
|
+
code&.each do |code_value|
|
55
|
+
user_guess.delete_at(user_guess.index(code_value) || user_guess.length) && minuses << '-' if user_guess.include?(code_value)
|
56
|
+
end
|
57
|
+
minuses
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/messages.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'controller'
|
2
|
+
|
3
|
+
module CodebreakerVukolovEdition
|
4
|
+
class Messages
|
5
|
+
INFO_MESSAGES = {
|
6
|
+
new_game: '(?) Would you like to play new game? [yes/no]',
|
7
|
+
save_result: '(?) Would you like to save result of your game? [yes/no]',
|
8
|
+
input: '> Please provide your guess',
|
9
|
+
input_warning: "(!) The input should be exactly four digits or 'hint' word",
|
10
|
+
name: 'What is your name?',
|
11
|
+
instruction: "(!) Please follow to instruction. You can type only 'yes' or 'no'",
|
12
|
+
result_saved: 'Result of your game was written to file: ',
|
13
|
+
game_unsaved: 'Ok, nobody will know about your fail LoL, azaza!!!!!!!11)',
|
14
|
+
round_result: 'Your result is: '
|
15
|
+
}
|
16
|
+
|
17
|
+
def before_round_info(turns)
|
18
|
+
puts "====================== round ##{turns + 1} ======================
|
19
|
+
You have #{CodebreakerVukolovEdition::Game::MAX_TURNS - turns} turns for breaking this code"
|
20
|
+
end
|
21
|
+
|
22
|
+
def print_hint(hint)
|
23
|
+
puts "HINT: #{hint[:value]}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def hint_info
|
27
|
+
puts "(*) Also, you can use hint (the system reveals one of the numbers in the secret code). If you need a hint, please put 'hint'"
|
28
|
+
end
|
29
|
+
|
30
|
+
def total_game_info(state, turns, secret_code)
|
31
|
+
case state
|
32
|
+
when :won
|
33
|
+
puts "
|
34
|
+
Congratulation!!!!
|
35
|
+
You have hacked this code by #{turns} turns, the code is #{secret_code.join('')}"
|
36
|
+
when :lose
|
37
|
+
puts "Unfortunately you spent all your turns (#{turns}) and didn't brake the code. Code was #{secret_code.join('')}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def show_messages(symbol, *arg)
|
42
|
+
message = arg.empty? ? INFO_MESSAGES[symbol] : INFO_MESSAGES[symbol] + arg.first
|
43
|
+
puts message
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/services.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'messages'
|
2
|
+
|
3
|
+
module CodebreakerVukolovEdition
|
4
|
+
class Services
|
5
|
+
def initialize
|
6
|
+
@messages = Messages.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def write_result_to_file(username, state, turns, hint, secret_code)
|
10
|
+
filename = 'results.yml'
|
11
|
+
string = "#{Time.now.strftime('%F %T')} | #{username} | #{state} | #{turns} of #{CodebreakerVukolovEdition::Game::MAX_TURNS} | hint #{hint[:used] ? 'used' : 'did not use'} | code was #{secret_code.join('')}"
|
12
|
+
File.open(filename, 'a') {|f| f.write string.to_yaml }
|
13
|
+
@messages.show_messages(:result_saved, filename)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/start.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codebreaker_vukolov_edition
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -64,6 +64,7 @@ extra_rdoc_files: []
|
|
64
64
|
files:
|
65
65
|
- ".gitignore"
|
66
66
|
- ".rspec"
|
67
|
+
- ".ruby-version"
|
67
68
|
- ".travis.yml"
|
68
69
|
- CODE_OF_CONDUCT.md
|
69
70
|
- Gemfile
|
@@ -74,8 +75,12 @@ files:
|
|
74
75
|
- bin/setup
|
75
76
|
- circle.yml
|
76
77
|
- codebreaker_vukolov_edition.gemspec
|
77
|
-
- lib/codebreaker_vukolov_edition.rb
|
78
78
|
- lib/codebreaker_vukolov_edition/version.rb
|
79
|
+
- lib/controller.rb
|
80
|
+
- lib/game.rb
|
81
|
+
- lib/messages.rb
|
82
|
+
- lib/services.rb
|
83
|
+
- start.rb
|
79
84
|
homepage: https://github.com/vatnajokull/
|
80
85
|
licenses:
|
81
86
|
- MIT
|
@@ -1,137 +0,0 @@
|
|
1
|
-
require "codebreaker_vukolov_edition/version"
|
2
|
-
|
3
|
-
module CodebreakerVukolovEdition
|
4
|
-
class Game
|
5
|
-
MAX_TURNS = 15
|
6
|
-
attr_accessor :turns, :secret_code, :max_turns, :hint
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@turns = 0
|
10
|
-
@secret_code = new_code
|
11
|
-
@hint = { used: false, value: @secret_code.sample }
|
12
|
-
end
|
13
|
-
|
14
|
-
def play
|
15
|
-
if @turns < MAX_TURNS
|
16
|
-
puts "====================== round ##{turns + 1} ======================
|
17
|
-
You have #{MAX_TURNS - @turns} turns for breaking this code"
|
18
|
-
show_hint
|
19
|
-
guess = provided_guess
|
20
|
-
result = checker(guess)
|
21
|
-
calculation(result)
|
22
|
-
play
|
23
|
-
else
|
24
|
-
result('lose')
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def show_hint
|
29
|
-
if @hint[:used]
|
30
|
-
puts "HINT: #{@hint[:value]}"
|
31
|
-
else
|
32
|
-
puts "(*) Also, you can use hint (the system reveals one of the numbers in the secret code). If you need a hint, please put 'hint'"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def result(state)
|
37
|
-
case state
|
38
|
-
when 'win'
|
39
|
-
puts "
|
40
|
-
Congratulation #{@user}!!!!
|
41
|
-
You have hacked this code by #{@turns} turns, the code is #{@secret_code.join('')}"
|
42
|
-
when 'lose'
|
43
|
-
puts "#{@user}, unfortunately you spent all your turns (#{@turns}) and didn't brake the code. Code was #{@secret_code.join('')}"
|
44
|
-
end
|
45
|
-
save_result(state, make_a_decision('save result'))
|
46
|
-
play_new_game(make_a_decision('play new game'))
|
47
|
-
end
|
48
|
-
|
49
|
-
def make_a_decision(option)
|
50
|
-
decision = get_action("(?) Would you like to #{option}? [yes/no]")
|
51
|
-
if decision == 'yes' || decision == 'no'
|
52
|
-
decision
|
53
|
-
else
|
54
|
-
puts "(!) Please follow to instruction. You can type only 'yes' or 'no'"
|
55
|
-
make_a_decision(option)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def get_action(*question)
|
60
|
-
puts question
|
61
|
-
value = gets.chomp
|
62
|
-
value.empty? ? get_action : value
|
63
|
-
end
|
64
|
-
|
65
|
-
def save_result(state, decision)
|
66
|
-
case decision
|
67
|
-
when 'yes'
|
68
|
-
username = get_action('What is your name?')
|
69
|
-
write_result_to_file(state, username)
|
70
|
-
when 'no'
|
71
|
-
puts 'Ok, nobody will know about your fail LoL, azaza!!!!!!!11)'
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def play_new_game(decision)
|
76
|
-
case decision
|
77
|
-
when 'yes'
|
78
|
-
game = CodebreakerVukolovEdition::Game.new
|
79
|
-
game.play
|
80
|
-
when 'no' then abort
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def write_result_to_file(state, username)
|
85
|
-
filename = 'results.txt'
|
86
|
-
File.open(filename, 'a') do |file|
|
87
|
-
string = "#{Time.now.strftime('%F %T')} | #{username} | #{state} | #{@turns} of #{MAX_TURNS} | hint #{@hint[:used]? 'used' : 'did not use'} | code was #{@secret_code.join('')}"
|
88
|
-
file.write("\n#{string}")
|
89
|
-
end
|
90
|
-
puts "Result of your game was written to: #{filename}"
|
91
|
-
end
|
92
|
-
|
93
|
-
def new_code
|
94
|
-
secret_code = []
|
95
|
-
4.times { secret_code.push(rand(1..6)) }
|
96
|
-
secret_code
|
97
|
-
end
|
98
|
-
|
99
|
-
def provided_guess
|
100
|
-
input = get_action('> Please provide your guess')
|
101
|
-
if input == 'hint'
|
102
|
-
@hint[:used] = true
|
103
|
-
elsif input.to_i > 0 && input.length == 4
|
104
|
-
add_new_turn
|
105
|
-
else
|
106
|
-
puts "(!) The input should be exactly four digits or 'hint' word"
|
107
|
-
provided_guess
|
108
|
-
end
|
109
|
-
input
|
110
|
-
end
|
111
|
-
|
112
|
-
def add_new_turn
|
113
|
-
@turns += 1
|
114
|
-
end
|
115
|
-
|
116
|
-
def checker(guess)
|
117
|
-
guess_arr = guess.split('').map(&:to_i)
|
118
|
-
result = []
|
119
|
-
guess_arr.each_with_index do |number, index|
|
120
|
-
if number == @secret_code[index]
|
121
|
-
result.unshift('+')
|
122
|
-
elsif @secret_code.include?(number)
|
123
|
-
result.push('-')
|
124
|
-
end
|
125
|
-
end
|
126
|
-
result.join('')
|
127
|
-
end
|
128
|
-
|
129
|
-
def calculation(result)
|
130
|
-
if result == '++++'
|
131
|
-
result('win')
|
132
|
-
else
|
133
|
-
puts "Your result is: #{result}"
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|