codebreaker_vk 0.2.3 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0179c213f936b2afec4c93eb28fbf42aea7d4d5a6e8d111b80add0a2ca25d5b7'
4
- data.tar.gz: 7d060ce7f860e3ef1f519eaaea55a420a0415406465bb461ca7496366d46556b
3
+ metadata.gz: '08ab1117ccd9224ff33761dce7aa30a1cd572e67001b7e58b9499b9c3af850b5'
4
+ data.tar.gz: 90ffb5d6bbe399a0a762b6828bd202496818871d714dff4a6716d95e15280163
5
5
  SHA512:
6
- metadata.gz: 44c4e80ab609b6256897557712833a27f1cd55f8c7dd6eb91986f16a91cd9216767bb3f3c73c1ac2f274ef838328d84bb7c037a2355ebeaf8aea2f64d8ae6624
7
- data.tar.gz: 5f2c7a0ddf0092736cc2fd85c2b5e7a67ab20846b7f820058bc956751780e9546fd25bb388418c3ee39480d37bbe80a311e3db204bd32a1b8f676cf5cae74d90
6
+ metadata.gz: 3ca02359a5f01b2cafbb9e9ce3b1724dbe1a0014b994a9e81f931961089e2c188d7f3e2c4ee4cbdc3772f4e09938d59ea7ea1b4e377281e14156280d88450713
7
+ data.tar.gz: 92b9a4df7cc29020a358499c560b3a427f4a07ca07eb2178acc3ebc2497dd1d4005bcda269d5b3e0faea8a9a26ebd0125ede18aaf8bf6ca9a8aeb74fbf5d0267
data/.overcommit.yml CHANGED
@@ -43,14 +43,16 @@ PreCommit:
43
43
  enabled: true
44
44
 
45
45
  BundleOutdated:
46
- enabled: true
46
+ enabled: false
47
47
 
48
48
  ExecutePermissions:
49
49
  enabled: false
50
50
 
51
51
  ForbiddenBranches:
52
- enabled: true
52
+ enabled: false
53
53
  branch_patterns: ['master']
54
54
 
55
55
  LineEndings:
56
- enabled: true
56
+ enabled: false
57
+
58
+
data/.rubocop.yml ADDED
@@ -0,0 +1,10 @@
1
+ equire: rubocop-rspec
2
+
3
+ Metrics/LineLength:
4
+ Max: 120
5
+
6
+ Documentation:
7
+ Enabled: false
8
+
9
+ Metrics/BlockLength:
10
+ ExcludedMethods: ['describe']
data/Gemfile CHANGED
@@ -2,4 +2,5 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in codebreaker_vk.gemspec
4
4
  gemspec
5
- gem 'simplecov', require: false, group: :test
5
+ gem 'simplecov', require: false, group: :test
6
+ gem 'i18n'
data/Gemfile.lock CHANGED
@@ -1,28 +1,30 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- codebreaker_vk (0.2.3)
4
+ codebreaker_vk (0.3.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.0)
10
- childprocess (0.9.0)
11
- ffi (~> 1.0, >= 1.0.11)
10
+ childprocess (1.0.1)
11
+ rake (< 13.0)
12
12
  coderay (1.1.2)
13
13
  colorize (0.8.1)
14
+ concurrent-ruby (1.1.5)
14
15
  diff-lcs (1.3)
15
16
  docile (1.3.2)
16
17
  fasterer (0.5.1)
17
18
  colorize (~> 0.7)
18
19
  ruby_parser (>= 3.13.0)
19
- ffi (1.11.1)
20
+ i18n (1.6.0)
21
+ concurrent-ruby (~> 1.0)
20
22
  iniparse (1.4.4)
21
23
  jaro_winkler (1.5.3)
22
24
  json (2.2.0)
23
25
  method_source (0.9.2)
24
- overcommit (0.48.1)
25
- childprocess (~> 0.6, >= 0.6.3)
26
+ overcommit (0.49.0)
27
+ childprocess (>= 0.6.3, < 2.0)
26
28
  iniparse (~> 1.4)
27
29
  parallel (1.17.0)
28
30
  parser (2.6.3.0)
@@ -74,6 +76,7 @@ DEPENDENCIES
74
76
  bundler (~> 2.0)
75
77
  codebreaker_vk!
76
78
  fasterer (~> 0.5.1)
79
+ i18n
77
80
  overcommit
78
81
  pry (~> 0.12.2)
79
82
  rake (~> 10.0)
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
data/autoload.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n'
4
+ require 'yaml'
5
+ require_relative 'config/i18n'
6
+ require_relative 'lib/codebreaker_vk/uploader/uploader'
7
+ require_relative 'lib/codebreaker_vk/validate/validate'
8
+ require_relative 'lib/codebreaker_vk/validating_data'
9
+ require_relative 'lib/codebreaker_vk/check_errors'
10
+ require_relative 'lib/codebreaker_vk/difficulty'
11
+ require_relative 'lib/codebreaker_vk/game'
12
+ require_relative 'lib/codebreaker_vk/console'
13
+ require_relative 'lib/codebreaker_vk/game_user'
14
+ require_relative 'lib/codebreaker_vk/game_messages'
15
+ require_relative 'lib/codebreaker_vk/game_process'
16
+ require_relative 'lib/codebreaker_vk/version'
Binary file
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path("lib", __dir__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require "codebreaker_vk/version"
5
+ require 'codebreaker_vk/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = "codebreaker_vk"
8
+ spec.name = 'codebreaker_vk'
9
9
  spec.version = CodebreakerVk::VERSION
10
- spec.authors = ["VKuzmich"]
10
+ spec.authors = ['VKuzmich']
11
11
  spec.email = ["vjk1976@ukr.net"]
12
12
 
13
13
  spec.summary = 'Codebreaker game'
@@ -15,15 +15,12 @@ Gem::Specification.new do |spec|
15
15
  spec.homepage = 'https://github.com/VKuzmich/codebreaker_vk'
16
16
  spec.license = 'MIT'
17
17
 
18
-
19
- # Specify which files should be added to the gem when it is released.
20
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
18
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
22
19
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
20
  end
24
- spec.bindir = "exe"
21
+ spec.bindir = 'exe'
25
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
- spec.require_paths = ["lib"]
23
+ spec.require_paths = ['lib']
27
24
 
28
25
  spec.add_development_dependency 'bundler', '~> 2.0'
29
26
  spec.add_development_dependency 'fasterer', '~> 0.5.1'
data/config/i18n.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ I18n.load_path << Dir[File.expand_path('config/locales') + '/*.yml']
@@ -0,0 +1,41 @@
1
+ en:
2
+ goodbye: 'Goodbye'
3
+ console:
4
+ greeting: "Hello, lets play the 'Codebreaker' game"
5
+ choose_the_command: "Choose the command\n
6
+ -Enter %{rules} if you want to see rules of the game\n
7
+ -Enter %{stats} if you want to see the statistics of users results\n
8
+ -Enter %{start} if you want to start the game\n
9
+ -Enter %{exit} if you want to quite the game\n"
10
+ what_name: "What is your name?\nName must be from 3 to 20 characters"
11
+ showed_hint: 'Code contains this number: %{showed}'
12
+ zero_hints: "You don't have any hints"
13
+ result: 'Your result is %{result}'
14
+ make_guess: "Make your guess\nYou need to enter four numbers between 1 and 6 "
15
+ enter_hint: "Or enter 'hint' to open one digit from code"
16
+ left_attempts_and_hints: "You have %{attempts} attempts and %{hints} hints"
17
+ win: "You win\n-Enter %{yes} if you want to save your progress"
18
+ lose: 'Game over, you lose if you want you can start a new game'
19
+ empty_db: 'You are the first one'
20
+ select_difficulty: 'Select difficulty: %{difficulties}'
21
+ stats_user_info: "%{position}) Name: %{name} difficulty: %{level}\n"
22
+ stats_lefts: "Attempts: %{all_attempts}/%{attempts} Hints: %{all_hints}/%{hints}"
23
+ rules: "Game Rules\n
24
+ • Codebreaker is a logic game in which a code-breaker tries to break a secret code created by a code-maker. The codemaker, which will be played by the codebreaker_vk we’re going to write, creates a secret code of four numbers between 1 and 6.\n
25
+ • The codebreaker gets some number of chances to break the code (depends on chosen difficulty). In each turn, the codebreaker makes a guess of 4 numbers. The codemaker then marks the guess with up to 4 signs - + or - or empty spaces.\n
26
+ • 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. For example\n
27
+ Secret number - 1234\n
28
+ Input number - 6264\n
29
+ Number of pluses - 2 (second and fourth position)\n
30
+ • 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. For example\n
31
+ Secret number - 1234\n
32
+ Input number - 6462\n
33
+ Number of minuses - 2 (second and fourth position)\n
34
+ • An empty space indicates that there is not a current digit in a secret number.\n
35
+ • If codebreaker inputs the exact number as a secret number - codebreaker wins the game. If all attempts are spent - codebreaker loses.\n
36
+ • Codebreaker also has some number of hints(depends on chosen difficulty). If a user takes a hint - he receives back a separate digit of the secret code.\n"
37
+ error: "Unexpected input, it was '%{error}', try one more time"
38
+ invalid:
39
+ cover_error: 'Improper size'
40
+ include_error: 'Not include in propose inputs'
41
+ size_error: 'Invalid size'
@@ -1,11 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'codebreaker_vk/game'
4
- require_relative 'codebreaker_vk/game_process'
5
- require_relative 'codebreaker_vk/errors/autoload'
6
3
  require_relative 'codebreaker_vk/version'
7
-
8
- module CodebreakerVk
9
- class Error < StandardError; end
10
- # Your code goes here...
11
- end
4
+ require_relative '../autoload'
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodebreakerVk
4
+ class CheckErrors < ValidatingData
5
+ attr_reader :input, :errors
6
+
7
+ def initialize(input)
8
+ super()
9
+ @input = input
10
+ end
11
+
12
+ def validate
13
+ @errors << I18n.t('invalid.include_error') unless check_include?(@input, Console::COMMANDS.values)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodebreakerVk
4
+ class Console < ValidatingData
5
+ include Uploader
6
+
7
+ ACCEPT_SAVING_RESULT = 'yes'
8
+ COMMANDS = { rules: 'rules',
9
+ start: 'start',
10
+ stats: 'stats',
11
+ exit: 'exit' }.freeze
12
+
13
+ def greeting
14
+ Representer.greeting_msg
15
+ end
16
+
17
+ def main_menu
18
+ loop do
19
+ Representer.what_next_text
20
+ case make_valid_input_for_class(Navigator).input
21
+ when COMMANDS[:start] then return registration
22
+ when COMMANDS[:rules] then Representer.show_rules
23
+ when COMMANDS[:stats] then statistics
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def statistics
31
+ loaded_db = load_db
32
+ loaded_db.empty? ? Representer.empty_db_msg : Representer.show_db(loaded_db)
33
+ end
34
+
35
+ def registration
36
+ Representer.what_name_msg
37
+ @user = make_valid_input_for_class(User)
38
+ @difficulty = choose_difficulty
39
+ @game = Game.new(@difficulty, @user)
40
+ make_guess
41
+ end
42
+
43
+ def choose_difficulty
44
+ Representer.select_difficulty_msg
45
+ loop do
46
+ finded_level = Difficulty.find(user_input)
47
+ return finded_level if finded_level
48
+
49
+ Representer.error_msg(I18n.t('invalid.include_error'))
50
+ end
51
+ end
52
+
53
+ def make_guess
54
+ loop do
55
+ Representer.make_guess_msg
56
+ guess = make_valid_input_for_class(Guess)
57
+ guess.hint? ? show_hint : check_round_result(guess.as_array_of_numbers)
58
+ end
59
+ end
60
+
61
+ def check_round_result(guess)
62
+ return win if @game.win?(guess)
63
+ return lose if @game.lose?(guess)
64
+
65
+ round_result = @game.start_round(guess)
66
+ Representer.round_info_text(round_result, @game.attempts, @game.hints)
67
+ end
68
+
69
+ def show_hint
70
+ @game.hints.positive? ? Representer.showed_hint_msg(@game.hint) : Representer.zero_hints_msg
71
+ end
72
+
73
+ def lose
74
+ Representer.lose_msg
75
+ start_new_game
76
+ end
77
+
78
+ def win
79
+ Representer.win_msg
80
+ save_result if user_input == ACCEPT_SAVING_RESULT
81
+ start_new_game
82
+ end
83
+
84
+ def start_new_game
85
+ Console.new.main_menu
86
+ end
87
+
88
+ def save_result
89
+ save_to_db(@game.to_h)
90
+ end
91
+
92
+ def make_valid_input_for_class(klass)
93
+ loop do
94
+ input = klass.new(user_input)
95
+ return input if input.valid?
96
+
97
+ Representer.error_msg(input.errors.join(', '))
98
+ end
99
+ end
100
+
101
+ def user_input
102
+ input = gets.chomp.downcase
103
+ input == COMMANDS[:exit] ? exit_console : input
104
+ end
105
+
106
+ def exit_console
107
+ Representer.goodbye
108
+ exit
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodebreakerVk
4
+ class Difficulty
5
+ attr_reader :level
6
+
7
+ DIFFICULTIES = {
8
+ simple: {
9
+ hints: 2,
10
+ attempts: 15,
11
+ level: 'simple'
12
+ },
13
+
14
+ middle: {
15
+ hints: 1,
16
+ attempts: 10,
17
+ level: 'middle'
18
+ },
19
+
20
+ hard: {
21
+ hints: 1,
22
+ attempts: 5,
23
+ level: 'hard'
24
+ }
25
+ }.freeze
26
+
27
+ def initialize(input)
28
+ @level = DIFFICULTIES[input]
29
+ end
30
+
31
+ def self.find(input)
32
+ input_as_key = input.to_sym
33
+ return unless DIFFICULTIES.key?(input_as_key)
34
+
35
+ new(input_as_key)
36
+ end
37
+ end
38
+ end
@@ -1,89 +1,82 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'config'
4
-
5
3
  module CodebreakerVk
6
4
  class Game
7
- attr_reader :tries_count, :hints_count, :errors
8
-
9
- def initialize(difficulty: :easy)
10
- validate_difficulty(difficulty)
11
-
12
- @difficulty = difficulty
13
-
14
- @hint_indexes = (0...CODE_LENGTH).to_a
15
-
16
- @secret = Array.new(CODE_LENGTH) { rand(MIN_CODE_NUMBER..MAX_CODE_NUMBER) }
17
-
18
- @tries_count = DIFFICULTIES[@difficulty][:tries]
19
- @hints_count = DIFFICULTIES[@difficulty][:hints]
20
-
21
- @errors = []
22
-
23
- @matches = ''
5
+ attr_reader :hints, :attempts, :difficulty, :breaker_numbers, :showed_hints, :player_name
6
+
7
+ INCLUDE_IN_GAME_NUMBERS = (1..6).freeze
8
+ CODE_SIZE = 4
9
+
10
+ GUESS_PLACE = '+'
11
+ GUESS_PRESENCE = '-'
12
+
13
+ def initialize(difficulty, user)
14
+ @breaker_numbers = generate_random_code
15
+ @breaker_numbers_copy = @breaker_numbers.clone.shuffle
16
+ @hints = difficulty.level[:hints]
17
+ @attempts = difficulty.level[:attempts]
18
+ @difficulty = difficulty.level
19
+ @player_name = user.name
20
+ @showed_hints = []
24
21
  end
25
22
 
26
- def check_guess(input)
27
- input = to_array(input)
28
-
29
- return add_error(FormatError) unless valid? input
30
-
31
- @tries_count -= 1
32
-
33
- resolver = GameProcess.new(@secret, input)
34
-
35
- @matches = resolver.matches
23
+ def start_round(user_input)
24
+ @attempts -= 1
25
+ @game_numbers = { code: @breaker_numbers.clone, input: user_input }
26
+ collect_place_guess + collect_presence_guess
36
27
  end
37
28
 
38
- def generate_hint
39
- return add_error(MaxHintError) if @hints_count.zero?
40
-
41
- index = @hint_indexes.sample
42
-
43
- hint = @secret[index]
29
+ def hint
30
+ return if @hints.zero?
44
31
 
45
- @hint_indexes.delete index
46
-
47
- @hints_count -= 1
48
-
49
- hint
32
+ @hints -= 1
33
+ @showed_hints << @breaker_numbers_copy.pop
34
+ @showed_hints.last
50
35
  end
51
36
 
52
- def win?
53
- @matches == Array.new(CODE_LENGTH, EXACT_MATCH_SIGN).join
37
+ def win?(result)
38
+ @breaker_numbers == result
54
39
  end
55
40
 
56
- def lose?
57
- @tries_count.zero?
41
+ def lose?(result)
42
+ @attempts == 1 && @breaker_numbers != result
58
43
  end
59
44
 
60
- def data
45
+ def to_h
61
46
  {
62
- difficulty: DIFFICULTIES.keys.index(@difficulty),
63
- secret: @secret,
64
- tries_total: DIFFICULTIES[@difficulty][:tries],
65
- hints_total: DIFFICULTIES[@difficulty][:hints],
66
- tries_used: DIFFICULTIES[@difficulty][:tries] - @tries_count,
67
- hints_used: DIFFICULTIES[@difficulty][:hints] - @hints_count
47
+ player_name: @player_name,
48
+ level: @difficulty[:level],
49
+ all_hints: @difficulty[:hints],
50
+ all_attempts: @difficulty[:attempts],
51
+ left_hints: @hints,
52
+ left_attempts: @attempts,
53
+ date: Time.now
68
54
  }
69
55
  end
70
56
 
71
57
  private
72
58
 
73
- def add_error(err)
74
- (@errors << err) && nil
75
- end
59
+ def collect_place_guess
60
+ @game_numbers[:input].map.with_index do |user_num, index|
61
+ next if @game_numbers[:code][index] != user_num
76
62
 
77
- def validate_difficulty(difficulty)
78
- raise DifficultyLevelError unless DIFFICULTIES.include? difficulty.to_sym
63
+ @game_numbers[:code][index] = nil
64
+ @game_numbers[:input][index] = nil
65
+ GUESS_PLACE
66
+ end.compact
79
67
  end
80
68
 
81
- def to_array(input)
82
- input.to_i.digits.reverse
69
+ def collect_presence_guess
70
+ @game_numbers[:input].compact.map do |user_num|
71
+ next unless @game_numbers[:code].include?(user_num)
72
+
73
+ @game_numbers[:code].delete_at(@game_numbers[:code].index(user_num))
74
+ GUESS_PRESENCE
75
+ end.compact
83
76
  end
84
77
 
85
- def valid?(input)
86
- input.size == CODE_LENGTH && input.all? { |number| number.between? MIN_CODE_NUMBER, MAX_CODE_NUMBER }
78
+ def generate_random_code
79
+ Array.new(CODE_SIZE) { rand(INCLUDE_IN_GAME_NUMBERS) }
87
80
  end
88
81
  end
89
- end
82
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodebreakerVk
4
+ class GameMessages
5
+ class << self
6
+ def greeting_msg
7
+ puts I18n.t('console.greeting')
8
+ end
9
+
10
+ def goodbye
11
+ puts I18n.t(:goodbye)
12
+ end
13
+
14
+ def what_next_text
15
+ puts I18n.t('console.choose_the_command', stats: Console::COMMANDS[:stats], rules: Console::COMMANDS[:rules],
16
+ start: Console::COMMANDS[:start], exit: Console::COMMANDS[:exit])
17
+ end
18
+
19
+ def what_name_msg
20
+ puts I18n.t('console.what_name')
21
+ end
22
+
23
+ def select_difficulty_msg
24
+ puts I18n.t('console.select_difficulty', difficulties: Difficulty::DIFFICULTIES.keys.join(', '))
25
+ end
26
+
27
+ def make_guess_msg
28
+ puts I18n.t('console.make_guess')
29
+ end
30
+
31
+ def showed_hint_msg(showed)
32
+ puts I18n.t('console.showed_hint', showed: showed)
33
+ end
34
+
35
+ def zero_hints_msg
36
+ puts I18n.t('console.zero_hints')
37
+ end
38
+
39
+ def round_info_text(result, attempts, hints)
40
+ puts I18n.t('console.result', result: result)
41
+ puts I18n.t('console.left_attempts_and_hints', attempts: attempts, hints: hints)
42
+ puts I18n.t('console.make_guess')
43
+ puts I18n.t('console.enter_hint') if hints.positive?
44
+ end
45
+
46
+ def win_msg
47
+ puts I18n.t('console.win', yes: Console::ACCEPT_SAVING_RESULT)
48
+ end
49
+
50
+ def lose_msg
51
+ puts I18n.t('console.lose')
52
+ end
53
+
54
+ def empty_db_msg
55
+ puts I18n.t('console.empty_db')
56
+ end
57
+
58
+ def show_db(loaded_db)
59
+ sort_db(loaded_db).each_with_index do |user, index|
60
+ puts I18n.t('console.stats_user_info', position: index + 1, name: user[:name], level: user[:level])
61
+ puts I18n.t('console.stats_lefts', attempts: user[:left_attempts], all_attempts: user[:all_attempts],
62
+ hints: user[:left_hints], all_hints: user[:all_hints])
63
+ end
64
+ end
65
+
66
+ def show_rules
67
+ puts I18n.t('console.rules')
68
+ end
69
+
70
+ def error_msg(error)
71
+ puts I18n.t('error', error: error)
72
+ end
73
+
74
+ def sort_db(loaded_db)
75
+ loaded_db.sort_by { |user| [user[:all_attempts], -user[:left_attempts], -user[:left_hints]] }
76
+ end
77
+ end
78
+ end
79
+ end
@@ -1,43 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'config'
3
+ require_relative 'difficulty'
4
4
 
5
5
  module CodebreakerVk
6
- class GameProcess
7
- attr_reader :matches
6
+ class GameProcess < ValidatingData
7
+ attr_reader :input, :errors
8
8
 
9
- def initialize(secret_code, user_code)
10
- @secret_code = secret_code.clone
11
- @user_code = user_code
9
+ HINT = 'hint'
12
10
 
13
- @exact_matches = 0
14
- @number_matches = 0
15
-
16
- @matches = obtain_matches
11
+ def initialize(input)
12
+ super()
13
+ @input = input
17
14
  end
18
15
 
19
- private
20
-
21
- def obtain_matches
22
- calculate_matches unless @secret_code.empty?
16
+ def validate
17
+ return if hint?
23
18
 
24
- EXACT_MATCH_SIGN * @exact_matches << NUMBER_MATCH_SIGN * @number_matches
19
+ @errors << I18n.t('invalid.include_error') unless check_numbers?(@input, valid_numbers)
20
+ @errors << I18n.t('invalid.size_error') unless check_size?(@input, Game::CODE_SIZE)
25
21
  end
26
22
 
27
- def calculate_matches
28
- @secret_code.zip(@user_code).each do |secret_code_number, user_code_number|
29
- next unless @secret_code.include? user_code_number
30
-
31
- next add_match(user_code_number, exact: true) if secret_code_number == user_code_number
23
+ def as_array_of_numbers
24
+ @as_array_of_numbers ||= @input.chars.map(&:to_i)
25
+ end
32
26
 
33
- add_match(user_code_number)
34
- end
27
+ def hint?
28
+ @input == HINT
35
29
  end
36
30
 
37
- def add_match(matched_code_number, exact: false)
38
- exact ? @exact_matches += 1 : @number_matches += 1
31
+ private
39
32
 
40
- @secret_code.delete_at(@secret_code.index(matched_code_number))
33
+ def valid_numbers
34
+ Game::INCLUDE_IN_GAME_NUMBERS.map(&:to_s)
41
35
  end
42
36
  end
43
37
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodebreakerVk
4
+ class GameUser < ValidatingData
5
+ attr_reader :name, :errors
6
+
7
+ VALID_NAME_SIZE = (3..20).freeze
8
+
9
+ def initialize(name)
10
+ super()
11
+ @name = name
12
+ end
13
+
14
+ def validate
15
+ @errors << I18n.t('invalid.cover_error') unless check_cover?(@name, VALID_NAME_SIZE)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodebreakerVk
4
+ module Uploader
5
+ PATH_FOLDER = './data_base/'
6
+ PATH_NAME = 'database'
7
+ PATH_FORMAT = '.yaml'
8
+ PATH = PATH_FOLDER + PATH_NAME + PATH_FORMAT
9
+
10
+ def load_db
11
+ File.exist?(PATH) ? YAML.load_stream(File.open(PATH)) : []
12
+ end
13
+
14
+ def save_to_db(results)
15
+ File.open(PATH, 'a') { |f| f.write results.to_yaml }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodebreakerVk
4
+ module Validate
5
+ def check_cover?(cheackable, valid_numbers)
6
+ valid_numbers.cover?(cheackable.size)
7
+ end
8
+
9
+ def check_include?(cheackable, valid_collection)
10
+ valid_collection.include?(cheackable)
11
+ end
12
+
13
+ def check_size?(cheackable, valid_size)
14
+ cheackable.size == valid_size
15
+ end
16
+
17
+ def check_numbers?(cheackable, valid_numbers)
18
+ cheackable.each_char.all? { |guess_char| valid_numbers.include?(guess_char) }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CodebreakerVk
4
+ class ValidatingData
5
+ include Validate
6
+
7
+ def initialize
8
+ @errors = []
9
+ end
10
+
11
+ def validate
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def valid?
16
+ validate
17
+ @errors.empty?
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CodebreakerVk
4
- VERSION = '0.2.3'
4
+ VERSION = '0.3.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codebreaker_vk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - VKuzmich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-05 00:00:00.000000000 Z
11
+ date: 2019-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -161,6 +161,7 @@ files:
161
161
  - ".gitignore"
162
162
  - ".overcommit.yml"
163
163
  - ".rspec"
164
+ - ".rubocop.yml"
164
165
  - ".ruby-gemset"
165
166
  - ".travis.yml"
166
167
  - CODE_OF_CONDUCT.md
@@ -169,21 +170,28 @@ files:
169
170
  - LICENSE.txt
170
171
  - README.md
171
172
  - Rakefile
173
+ - autoload.rb
172
174
  - bin/console
173
175
  - bin/setup
174
176
  - codebreaker_vk-0.1.0.gem
175
177
  - codebreaker_vk-0.2.0.gem
176
178
  - codebreaker_vk-0.2.1.gem
177
179
  - codebreaker_vk-0.2.2.gem
180
+ - codebreaker_vk-0.2.3.gem
178
181
  - codebreaker_vk.gemspec
182
+ - config/i18n.rb
183
+ - config/locales/en.yml
179
184
  - lib/codebreaker_vk.rb
180
- - lib/codebreaker_vk/config.rb
181
- - lib/codebreaker_vk/errors/autoload.rb
182
- - lib/codebreaker_vk/errors/difficulty_level_error.rb
183
- - lib/codebreaker_vk/errors/format_error.rb
184
- - lib/codebreaker_vk/errors/max_hint_error.rb
185
+ - lib/codebreaker_vk/check_errors.rb
186
+ - lib/codebreaker_vk/console.rb
187
+ - lib/codebreaker_vk/difficulty.rb
185
188
  - lib/codebreaker_vk/game.rb
189
+ - lib/codebreaker_vk/game_messages.rb
186
190
  - lib/codebreaker_vk/game_process.rb
191
+ - lib/codebreaker_vk/game_user.rb
192
+ - lib/codebreaker_vk/uploader/uploader.rb
193
+ - lib/codebreaker_vk/validate/validate.rb
194
+ - lib/codebreaker_vk/validating_data.rb
187
195
  - lib/codebreaker_vk/version.rb
188
196
  homepage: https://github.com/VKuzmich/codebreaker_vk
189
197
  licenses:
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CodebreakerVk
4
- CODE_LENGTH = 4
5
-
6
- EXACT_MATCH_SIGN = '+'
7
- NUMBER_MATCH_SIGN = '-'
8
-
9
- MIN_CODE_NUMBER = 1
10
- MAX_CODE_NUMBER = 6
11
-
12
- DIFFICULTIES = {
13
- easy: { tries: 15, hints: 2 },
14
- medium: { tries: 10, hints: 1 },
15
- hell: { tries: 5, hints: 1 }
16
- }.freeze
17
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'difficulty_level_error'
4
- require_relative 'format_error'
5
- require_relative 'max_hint_error'
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CodebreakerVk
4
- DifficultyLevelError = Class.new(StandardError)
5
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CodebreakerVk
4
- FormatError = Class.new(StandardError)
5
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CodebreakerVk
4
- MaxHintError = Class.new(StandardError)
5
- end