codebreaker_vk 0.2.3 → 0.3.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 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