codebreaker_manfly 0.1.1 → 0.1.2

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: 712151060b79bacafe34e148dedc46708adacf8693e92dc1c7fc34a4c67d0acd
4
- data.tar.gz: 15b66fc81ee87dd9dc5d4e26b7b81ed007daa8f64e7b9255b8d1d3aa1595b458
3
+ metadata.gz: caf1cf44404ee764b74c32a9a2894f98bd2aa73b184ec73399a40a69c17f5165
4
+ data.tar.gz: 980294f275d01d27b699612232b017307c8d4272c2f73c3f7a8c3fab26398089
5
5
  SHA512:
6
- metadata.gz: 8e5b79427b3d0d997407b029d9edde67cb2bd797d95e3b9ba1f2059d5dd0d567cab514d23ce0df5a5505fdec9f670d1fb5a6b46c783a7d054ab76ff9dbf13a61
7
- data.tar.gz: '019a5fdb7dc2fe2292aec262226e1b843bb20cc4d57389e14eed40537dde74af30f1019791acb601689862977dfa3d53c6b94b20384e5d1c763311c4159377c3'
6
+ metadata.gz: 7277c3b2aa8a8ac2eea2c8c0aedeff2d4df7cc128364bbcd4636eeeed52694143848e42fd590c4fe3a6add886d5b730a02908c5696aea02f9f70ca0f3dec6f8b
7
+ data.tar.gz: b382f9504b6448445f2246d1af75a4cfe775897ff1ac39b0a8365dd17d696459915b2ff611e4b5095a097d459c2b6bcaaddf3ea353e5cd15386ae6c597aa254a
data/.rubocop.yml CHANGED
@@ -1,9 +1,13 @@
1
+
1
2
  AllCops:
2
3
  TargetRubyVersion: 2.7
3
4
 
4
5
  Style/Documentation:
5
6
  Enabled: false
6
7
 
8
+ Lint/UnreachableLoop:
9
+ Enabled: false
10
+
7
11
  Metrics/BlockLength:
8
12
  ExcludedMethods: ['describe', 'context']
9
13
 
data/Gemfile CHANGED
@@ -4,7 +4,3 @@ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in codebreaker.gemspec
6
6
  gemspec
7
-
8
- gem 'rake', '~> 13.0'
9
- gem 'rspec', '~> 3.10'
10
- gem 'rubocop', '~> 1.7'
data/Gemfile.lock CHANGED
@@ -1,16 +1,31 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- codebreaker_manfly (0.1.1)
4
+ codebreaker_manfly (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.2)
10
+ byebug (11.1.3)
11
+ coderay (1.1.3)
12
+ concurrent-ruby (1.1.9)
10
13
  diff-lcs (1.4.4)
14
+ docile (1.4.0)
15
+ faker (2.19.0)
16
+ i18n (>= 1.6, < 2)
17
+ i18n (1.8.10)
18
+ concurrent-ruby (~> 1.0)
19
+ method_source (1.0.0)
11
20
  parallel (1.21.0)
12
21
  parser (3.0.2.0)
13
22
  ast (~> 2.4.1)
23
+ pry (0.13.1)
24
+ coderay (~> 1.1)
25
+ method_source (~> 1.0)
26
+ pry-byebug (3.9.0)
27
+ byebug (~> 11.0)
28
+ pry (~> 0.13.0)
14
29
  rainbow (3.0.0)
15
30
  rake (13.0.6)
16
31
  regexp_parser (2.1.1)
@@ -28,7 +43,7 @@ GEM
28
43
  diff-lcs (>= 1.2.0, < 2.0)
29
44
  rspec-support (~> 3.10.0)
30
45
  rspec-support (3.10.2)
31
- rubocop (1.22.1)
46
+ rubocop (1.22.3)
32
47
  parallel (~> 1.10)
33
48
  parser (>= 3.0.0.0)
34
49
  rainbow (>= 2.2.2, < 4.0)
@@ -40,6 +55,12 @@ GEM
40
55
  rubocop-ast (1.12.0)
41
56
  parser (>= 3.0.1.1)
42
57
  ruby-progressbar (1.11.0)
58
+ simplecov (0.21.2)
59
+ docile (~> 1.1)
60
+ simplecov-html (~> 0.11)
61
+ simplecov_json_formatter (~> 0.1)
62
+ simplecov-html (0.12.3)
63
+ simplecov_json_formatter (0.1.3)
43
64
  unicode-display_width (2.1.0)
44
65
 
45
66
  PLATFORMS
@@ -47,9 +68,12 @@ PLATFORMS
47
68
 
48
69
  DEPENDENCIES
49
70
  codebreaker_manfly!
71
+ faker
72
+ pry-byebug
50
73
  rake (~> 13.0)
51
74
  rspec (~> 3.10)
52
75
  rubocop (~> 1.7)
76
+ simplecov
53
77
 
54
78
  BUNDLED WITH
55
79
  2.2.28
data/README.md CHANGED
@@ -1,15 +1,19 @@
1
1
  # Codebreaker
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/codebreaker`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Codebreaker is a logic game in which a code-breaker tries to break a secret code created by a code-maker. The code-maker, which will be played by the application we’re going to write, creates a secret code of four numbers between 1 and 6.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ The code-breaker then gets some number of chances to break the code. In each turn, the code-breaker makes a guess of four numbers. The code-maker then marks the guess with up to four + and - signs.
6
+
7
+ 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.
8
+
9
+ 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.
6
10
 
7
11
  ## Installation
8
12
 
9
13
  Add this line to your application's Gemfile:
10
14
 
11
15
  ```ruby
12
- gem 'codebreaker_manfly'
16
+ gem 'codebreaker_manfly', '~> 0.1.0'
13
17
  ```
14
18
 
15
19
  And then execute:
@@ -18,26 +22,14 @@ And then execute:
18
22
 
19
23
  Or install it yourself as:
20
24
 
21
- $ gem install codebreaker
25
+ $ gem install codebreaker_manfly
22
26
 
23
27
  ## Usage
24
28
 
25
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
-
33
- ## Contributing
34
-
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/codebreaker. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/codebreaker/blob/master/CODE_OF_CONDUCT.md).
36
-
37
- ## License
29
+ To use this game it should be installed in a console or web vesion of the game
38
30
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
31
+ Create an instance of the game:
40
32
 
41
- ## Code of Conduct
33
+ game = Codebreacker::Game.new
42
34
 
43
- Everyone interacting in the Codebreaker project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/codebreaker/blob/master/CODE_OF_CONDUCT.md).
35
+ During instantiation you can set matcher (object that will be used for guesses matching) and storage (object that will be used for storing scores).
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ class BaseEntity
5
+ include Validation
6
+ def initialize(*)
7
+ validate
8
+ end
9
+
10
+ def validate; end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml/store'
4
+ require 'date'
5
+
6
+ require_relative 'validation'
7
+ require_relative 'base_entity'
8
+ require_relative 'code_generate'
9
+ require_relative 'code_matcher'
10
+ require_relative 'difficulty_factory'
11
+ require_relative 'difficulty'
12
+ require_relative 'storage'
13
+ require_relative 'user'
14
+ require_relative 'winners'
15
+ require_relative 'version'
16
+ require_relative '../codebreaker'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ class CodeGenerator < BaseEntity
5
+ CODE_RANGE = (1..6).freeze
6
+ CODE_LENGTH = 4
7
+
8
+ def self.generate(length = CODE_LENGTH)
9
+ Array.new(length) { rand(CODE_RANGE) }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ class CodeMatcher
5
+ EXACT = '+'
6
+ NON_EXACT = '-'
7
+
8
+ attr_reader :guess, :secret_code
9
+
10
+ def match(secret_code, guess)
11
+ @secret_code = secret_code.split('')
12
+ @guess = guess.split('')
13
+ handle_matched_digits.join + handle_matched_digits_with_wrong_position.join
14
+ end
15
+
16
+ private
17
+
18
+ def handle_matched_digits
19
+ secret_code.map.with_index do |_, index|
20
+ next unless secret_code[index] == guess[index]
21
+
22
+ @guess[index], @secret_code[index] = nil
23
+ EXACT
24
+ end
25
+ end
26
+
27
+ def handle_matched_digits_with_wrong_position
28
+ guess.compact.map do |number|
29
+ next unless @secret_code.include?(number)
30
+
31
+ @secret_code.delete_at(secret_code.index(number))
32
+ NON_EXACT
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ class Difficulty
5
+ attr_reader :name, :attempts, :hints
6
+
7
+ NEGATIVE_INTEGER = 0
8
+
9
+ def initialize(name:, attempts:, hints:)
10
+ @name = name
11
+ @attempts = attempts
12
+ @hints = hints
13
+ end
14
+
15
+ private
16
+
17
+ def validate
18
+ raise Errors::ClassValidError unless valid_class?(String, difficulty)
19
+ raise Errors::NegativeIntegerError unless valid_non_negative_integer?(attempts, NEGATIVE_INTEGER)
20
+ raise Errors::NegativeIntegerError unless valid_non_negative_integer?(hints, NEGATIVE_INTEGER)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ class DifficultyFactory
5
+ DIFFICULTIES = {
6
+
7
+ easy: {
8
+ name: 'easy',
9
+ attempts: 15,
10
+ hints: 2
11
+ },
12
+ medium: {
13
+ name: 'medium',
14
+ attempts: 10,
15
+ hints: 1
16
+ },
17
+ hell: {
18
+ name: 'hell',
19
+ attempts: 5,
20
+ hints: 1
21
+ }
22
+
23
+ }.freeze
24
+ def self.generate(difficulty_name)
25
+ case difficulty_name
26
+ when DIFFICULTIES[:easy] then Difficulty.new(DIFFICULTIES[:easy])
27
+ when DIFFICULTIES[:medium] then Difficulty.new(DIFFICULTIES[:medium])
28
+ when DIFFICULTIES[:hell] then Difficulty.new(DIFFICULTIES[:hell])
29
+ else raise Errors::InvalidDifficultyError
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class ClassValidError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class EmptyStringsError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class InvalidDifficultyError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class MaxLengthError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class MinLengthError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class NegativeIntegerError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class NonNumericStringError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class NotImplementedError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Errors
5
+ class RangeError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ module Storage
5
+ FILE_NAME = './store/statistics.yml'
6
+
7
+ def init_store
8
+ save
9
+ end
10
+
11
+ def load
12
+ store.transaction do
13
+ @winners = store[:winners]
14
+ end
15
+ end
16
+
17
+ def save
18
+ store.transaction do
19
+ store[:winners] = @winners
20
+ end
21
+ end
22
+
23
+ def storage_exists?
24
+ File.exist?(FILE_NAME)
25
+ end
26
+
27
+ def store
28
+ @store ||= YAML::Store.new(FILE_NAME)
29
+ end
30
+ end
31
+ end
@@ -1,16 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Codebreaker
4
- class User
5
- include Validation
3
+ require_relative 'bootstrap'
6
4
 
7
- attr_reader :name
5
+ module Codebreaker
6
+ class User < BaseEntity
7
+ attr_reader :name, :difficulty, :used_attempts, :used_hints
8
8
 
9
- NAME_LENGTH = (3..20).freeze
9
+ NAME_MIN_LENGTH = 3
10
+ NAME_MAX_LENGTH = 20
10
11
 
11
- def initialize(name:)
12
- validate_user_name(name, NAME_LENGTH)
12
+ def initialize(name, difficulty)
13
13
  @name = name
14
+ @difficulty = difficulty
15
+ @used_attempts = 0
16
+ @used_hints = 0
17
+ super
18
+ end
19
+
20
+ def hints?
21
+ difficulty.hints = used_hints
22
+ end
23
+
24
+ def attempts?
25
+ difficulty.attempts = used_attempts
26
+ end
27
+
28
+ def hint
29
+ @used_hints += 1
30
+ end
31
+
32
+ def attempt
33
+ @used_attempts += 1
34
+ end
35
+
36
+ private
37
+
38
+ def validate
39
+ raise Errors::ClassValidError unless valid_class?(String, name)
40
+ raise Errors::MinLengthError unless valid_string_min_length?(name, NAME_MIN_LENGTH)
41
+ raise Errors::MaxLengthError unless valid_string_max_length?(name, NAME_MAX_LENGTH)
14
42
  end
15
43
  end
16
44
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors/range_error'
4
+ require_relative 'errors/non_numeric_string_error'
5
+ require_relative 'errors/empty_strings_error'
6
+ require_relative 'errors/class_validate_error'
7
+ require_relative 'errors/min_length_error'
8
+ require_relative 'errors/max_length_error'
9
+ require_relative 'errors/negative_integer_error'
10
+ require_relative 'errors/invalid_difficulty_error'
11
+
12
+ module Codebreaker
13
+ module Validation
14
+ def valid_class?(expected_class, instance)
15
+ instance.is_a?(expected_class)
16
+ end
17
+
18
+ def valid_non_empty_string?(string)
19
+ !string.empty?
20
+ end
21
+
22
+ def valid_positive_integer?(number)
23
+ number.positive?
24
+ end
25
+
26
+ def valid_non_negative_integer?(number)
27
+ !number.negative?
28
+ end
29
+
30
+ def valid_string_min_length?(string, min_length)
31
+ string.length >= min_length
32
+ end
33
+
34
+ def valid_string_max_length?(string, max_length)
35
+ string.length <= max_length
36
+ end
37
+
38
+ def valid_only_numeric_string?(string)
39
+ /\A\d+\Z/.match?(string)
40
+ end
41
+
42
+ def valid_range?(range, code)
43
+ code.each { |digit| return false unless range.cover?(digit) }
44
+ true
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Codebreaker
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codebreaker
4
+ class Winner
5
+ attr_reader :user, :created_at
6
+
7
+ def initialize(_user)
8
+ @user = user
9
+ @created_at = DateTime.now
10
+ end
11
+ end
12
+ end
data/lib/codebreaker.rb CHANGED
@@ -1,100 +1,68 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml/store'
4
- require 'date'
3
+ require_relative 'codebreaker/bootstrap'
5
4
 
6
- require_relative 'codebreaker/module/validation'
7
- require_relative 'codebreaker/gameload'
8
- require_relative 'codebreaker/user'
9
- require_relative 'codebreaker/file_loader'
10
- require_relative 'codebreaker/version'
5
+ class Game
6
+ extend Codebreaker::Storage
11
7
 
12
- module Codebreaker
13
- class Game
14
- include Validation
8
+ attr_reader :user
15
9
 
16
- attr_reader :clues, :user, :difficulty,
17
- :attempts_used, :hints_used, :very_secret_code,
18
- :date
10
+ STATUS_IN_PROGRESS = :in_progress
11
+ STATUS_WIN = :win
12
+ STATUS_LOSE = :lose
19
13
 
20
- DIFFICULTIES = {
21
- easy: { attempts: 15, hints: 2 },
22
- medium: { attempts: 10, hints: 1 },
23
- hell: { attempts: 5, hints: 1 }
24
- }.freeze
25
-
26
- CODE_LENGTH = 4
27
- RANGE_GUESS_CODE = (1..6).freeze
28
-
29
- def initialize(difficulty:, user:, date: Date.today)
30
- validate_difficulty(difficulty, DIFFICULTIES)
31
-
32
- @user = user
33
- @difficulty = difficulty
34
- @date = date
35
-
36
- attempts
37
- number_of_hints
38
- end
39
-
40
- def start_new_game
41
- @very_secret_code = generate_random_code
42
- @hints = @very_secret_code.clone
43
- @attempts_used = 0
44
- @hints_used = 0
45
- @user_guess = []
46
- @clues = []
47
- end
14
+ def initialize
15
+ @secret_code = Codebreaker::CodeGenerator.generate
16
+ @status = STATUS_IN_PROGRESS
17
+ @hints = @secret_code.sample(@secret_code.length)
18
+ @storage = Game.store
19
+ save_storage unless Game.storage_exists?
20
+ end
48
21
 
49
- def guess(user_guess)
50
- guess = user_guess.each_char.map(&:to_i)
51
- validate_guess(guess, CODE_LENGTH, RANGE_GUESS_CODE)
52
- check_guess(guess, very_secret_code)
22
+ def create_user(name, difficulty)
23
+ @user = Codebreaker::User.new(name, difficulty)
24
+ end
53
25
 
54
- increase_attempts
55
- end
26
+ def create_difficulty(difficulty_name)
27
+ @difficulty = Codebreaker::DifficultyFactory.generate(difficulty_name)
28
+ end
56
29
 
57
- def show_hint
58
- validate_hints(hints_used, number_of_hints)
30
+ def win?
31
+ @status == STATUS_WIN
32
+ end
59
33
 
60
- @hints_used += 1
61
- @hints.shuffle!.pop
62
- end
34
+ def lose?
35
+ @status == STATUS_LOSE
36
+ end
63
37
 
64
- def won?
65
- @user_guess.nil?
66
- end
38
+ def take_hint
39
+ user.hint if user.hints?
67
40
 
68
- def lost?
69
- @attempts_used >= @attempts
70
- end
41
+ @hints.pop
42
+ end
71
43
 
72
- def save_game
73
- FileLoader.new.save(self)
74
- end
44
+ def take_attempt(guess)
45
+ return equal(@secret_code, guess.to_s) if user.attempts?
75
46
 
76
- def attempts
77
- @attempts ||= DIFFICULTIES[difficulty.to_sym][:attempts]
78
- end
47
+ @status = STATUS_LOSE
48
+ nil
49
+ end
79
50
 
80
- def number_of_hints
81
- @number_of_hints ||= DIFFICULTIES[difficulty.to_sym][:hints]
51
+ def save_storage
52
+ @storage.transaction do
53
+ @storage[:winners] = @winners || []
82
54
  end
55
+ end
83
56
 
84
- private
85
-
86
- def generate_random_code
87
- Array.new(CODE_LENGTH) { rand(RANGE_GUESS_CODE) }
88
- end
57
+ private
89
58
 
90
- def check_guess(guess, secret_code)
91
- gameload = Codebreaker::Gameload.new(guess, secret_code)
92
- @user_guess = gameload.match
93
- @clues = gameload.clues
94
- end
59
+ def win
60
+ @winners << CodebreakerGame::Winner.new(user)
61
+ @status = STATUS_WIN
62
+ end
95
63
 
96
- def increase_attempts
97
- @attempts_used += 1
98
- end
64
+ def equal(_secret_code, guess)
65
+ user.attempt
66
+ Codebreaker::CodeMatcher.match(@secret_code, guess)
99
67
  end
100
68
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codebreaker_manfly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrii Ivaniuk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-19 00:00:00.000000000 Z
11
+ date: 2021-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faker
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry-byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: rake
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +80,20 @@ dependencies:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
82
  version: '1.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
55
97
  description: Longer description or delete this line.
56
98
  email:
57
99
  - aivanuyk0@gmail.com
@@ -61,7 +103,6 @@ extra_rdoc_files: []
61
103
  files:
62
104
  - ".rspec"
63
105
  - ".rubocop.yml"
64
- - ".ruby-gemset"
65
106
  - ".ruby-version"
66
107
  - CHANGELOG.md
67
108
  - CODE_OF_CONDUCT.md
@@ -72,13 +113,27 @@ files:
72
113
  - Rakefile
73
114
  - bin/console
74
115
  - bin/setup
75
- - db/results_test.yml
76
116
  - lib/codebreaker.rb
77
- - lib/codebreaker/file_loader.rb
78
- - lib/codebreaker/gameload.rb
79
- - lib/codebreaker/module/validation.rb
117
+ - lib/codebreaker/base_entity.rb
118
+ - lib/codebreaker/bootstrap.rb
119
+ - lib/codebreaker/code_generate.rb
120
+ - lib/codebreaker/code_matcher.rb
121
+ - lib/codebreaker/difficulty.rb
122
+ - lib/codebreaker/difficulty_factory.rb
123
+ - lib/codebreaker/errors/class_validate_error.rb
124
+ - lib/codebreaker/errors/empty_strings_error.rb
125
+ - lib/codebreaker/errors/invalid_difficulty_error.rb
126
+ - lib/codebreaker/errors/max_length_error.rb
127
+ - lib/codebreaker/errors/min_length_error.rb
128
+ - lib/codebreaker/errors/negative_integer_error.rb
129
+ - lib/codebreaker/errors/non_numeric_string_error.rb
130
+ - lib/codebreaker/errors/not_implemented_error.rb
131
+ - lib/codebreaker/errors/range_error.rb
132
+ - lib/codebreaker/storage.rb
80
133
  - lib/codebreaker/user.rb
134
+ - lib/codebreaker/validation.rb
81
135
  - lib/codebreaker/version.rb
136
+ - lib/codebreaker/winners.rb
82
137
  homepage:
83
138
  licenses:
84
139
  - MIT
data/.ruby-gemset DELETED
File without changes
data/db/results_test.yml DELETED
@@ -1,220 +0,0 @@
1
- --- !ruby/object:Codebreaker::Game
2
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
3
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
4
- const_name: User
5
- __expired: false
6
- name:
7
- __sending_message:
8
- difficulty: :easy
9
- date: 2021-10-08
10
- attempts: 15
11
- number_of_hints: 2
12
- --- !ruby/object:Codebreaker::Game
13
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
14
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
15
- const_name: User
16
- __expired: false
17
- name:
18
- __sending_message:
19
- difficulty: :easy
20
- date: 2021-10-08
21
- attempts: 15
22
- number_of_hints: 2
23
- --- !ruby/object:Codebreaker::Game
24
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
25
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
26
- const_name: User
27
- __expired: false
28
- name:
29
- __sending_message:
30
- difficulty: :easy
31
- date: 2021-10-08
32
- attempts: 15
33
- number_of_hints: 2
34
- --- !ruby/object:Codebreaker::Game
35
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
36
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
37
- const_name: User
38
- __expired: false
39
- name:
40
- __sending_message:
41
- difficulty: :easy
42
- date: 2021-10-08
43
- attempts: 15
44
- number_of_hints: 2
45
- --- !ruby/object:Codebreaker::Game
46
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
47
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
48
- const_name: User
49
- __expired: false
50
- name:
51
- __sending_message:
52
- difficulty: :easy
53
- date: 2021-10-08
54
- attempts: 15
55
- number_of_hints: 2
56
- --- !ruby/object:Codebreaker::Game
57
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
58
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
59
- const_name: User
60
- __expired: false
61
- name:
62
- __sending_message:
63
- difficulty: :easy
64
- date: 2021-10-08
65
- attempts: 15
66
- number_of_hints: 2
67
- --- !ruby/object:Codebreaker::Game
68
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
69
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
70
- const_name: User
71
- __expired: false
72
- name:
73
- __sending_message:
74
- difficulty: :easy
75
- date: 2021-10-08
76
- attempts: 15
77
- number_of_hints: 2
78
- --- !ruby/object:Codebreaker::Game
79
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
80
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
81
- const_name: User
82
- __expired: false
83
- name:
84
- __sending_message:
85
- difficulty: :easy
86
- date: 2021-10-08
87
- attempts: 15
88
- number_of_hints: 2
89
- --- !ruby/object:Codebreaker::Game
90
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
91
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
92
- const_name: User
93
- __expired: false
94
- name:
95
- __sending_message:
96
- difficulty: :easy
97
- date: 2021-10-08
98
- attempts: 15
99
- number_of_hints: 2
100
- --- !ruby/object:Codebreaker::Game
101
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
102
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
103
- const_name: User
104
- __expired: false
105
- name:
106
- __sending_message:
107
- difficulty: :easy
108
- date: 2021-10-08
109
- attempts: 15
110
- number_of_hints: 2
111
- --- !ruby/object:Codebreaker::Game
112
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
113
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
114
- const_name: User
115
- __expired: false
116
- name:
117
- __sending_message:
118
- difficulty: :easy
119
- date: 2021-10-19
120
- attempts: 15
121
- number_of_hints: 2
122
- --- !ruby/object:Codebreaker::Game
123
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
124
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
125
- const_name: User
126
- __expired: false
127
- name:
128
- __sending_message:
129
- difficulty: :easy
130
- date: 2021-10-19
131
- attempts: 15
132
- number_of_hints: 2
133
- --- !ruby/object:Codebreaker::Game
134
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
135
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
136
- const_name: User
137
- __expired: false
138
- name:
139
- __sending_message:
140
- difficulty: :easy
141
- date: 2021-10-19
142
- attempts: 15
143
- number_of_hints: 2
144
- --- !ruby/object:Codebreaker::Game
145
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
146
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
147
- const_name: User
148
- __expired: false
149
- name:
150
- __sending_message:
151
- difficulty: :easy
152
- date: 2021-10-19
153
- attempts: 15
154
- number_of_hints: 2
155
- --- !ruby/object:Codebreaker::Game
156
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
157
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
158
- const_name: User
159
- __expired: false
160
- name:
161
- __sending_message:
162
- difficulty: :easy
163
- date: 2021-10-19
164
- attempts: 15
165
- number_of_hints: 2
166
- --- !ruby/object:Codebreaker::Game
167
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
168
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
169
- const_name: User
170
- __expired: false
171
- name:
172
- __sending_message:
173
- difficulty: :easy
174
- date: 2021-10-19
175
- attempts: 15
176
- number_of_hints: 2
177
- --- !ruby/object:Codebreaker::Game
178
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
179
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
180
- const_name: User
181
- __expired: false
182
- name:
183
- __sending_message:
184
- difficulty: :easy
185
- date: 2021-10-19
186
- attempts: 15
187
- number_of_hints: 2
188
- --- !ruby/object:Codebreaker::Game
189
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
190
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
191
- const_name: User
192
- __expired: false
193
- name:
194
- __sending_message:
195
- difficulty: :easy
196
- date: 2021-10-19
197
- attempts: 15
198
- number_of_hints: 2
199
- --- !ruby/object:Codebreaker::Game
200
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
201
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
202
- const_name: User
203
- __expired: false
204
- name:
205
- __sending_message:
206
- difficulty: :easy
207
- date: 2021-10-19
208
- attempts: 15
209
- number_of_hints: 2
210
- --- !ruby/object:Codebreaker::Game
211
- user: !ruby/object:RSpec::Mocks::InstanceVerifyingDouble
212
- doubled_module: !ruby/object:RSpec::Mocks::NamedObjectReference
213
- const_name: User
214
- __expired: false
215
- name:
216
- __sending_message:
217
- difficulty: :easy
218
- date: 2021-10-19
219
- attempts: 15
220
- number_of_hints: 2
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Codebreaker
4
- class FileLoader
5
- include Validation
6
-
7
- FILE_PATH = "#{ENV['DB_PATH']}#{ENV['DB_FILE']}"
8
-
9
- def initialize(db_file_path = FILE_PATH)
10
- @db_file_path = db_file_path
11
- end
12
-
13
- def load
14
- validate_file_existens(FILE_PATH)
15
-
16
- File.open(FILE_PATH, 'r') do |file|
17
- YAML.load_stream(file)
18
- end
19
- end
20
-
21
- def save(object)
22
- create_directory('DB_PATH') unless Dir.exist?(ENV['DB_PATH'])
23
- File.open(FILE_PATH, 'a') { |file| file.write(object.to_yaml) }
24
- end
25
-
26
- def create_directory(path)
27
- Dir.mkdir(ENV[path])
28
- end
29
- end
30
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Codebreaker
4
- class Gameload
5
- attr_reader :clues
6
-
7
- CLUES = {
8
- exact: :exact,
9
- non_exact: :non_exact
10
- }.freeze
11
-
12
- def initialize(guess, secret_code)
13
- @secret_code = secret_code
14
- @guess = guess
15
- @clues = []
16
- end
17
-
18
- def match
19
- collected = @secret_code.zip(@guess).delete_if { |code, guess| write_to_clues(CLUES[:exact]) if code == guess }
20
- @secret_code, @guess = collected.transpose
21
- return unless @guess
22
-
23
- non_exact_match
24
- end
25
-
26
- def non_exact_match
27
- @guess.compact.each do |num|
28
- next unless @secret_code.any?(num)
29
-
30
- write_to_clues(CLUES[:non_exact])
31
- @secret_code[@secret_code.index(num)] = nil
32
- end
33
- end
34
-
35
- def write_to_clues(clue)
36
- @clues.push(clue)
37
- end
38
- end
39
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Codebreaker
4
- module Validation
5
- ERROR_MESSAGES = {
6
- invalid_name: 'Name should be of 3 to 20 characters',
7
- invalid_guess: 'Expect 4 digits from 1 to 6',
8
- no_hints_left: 'No hints left, mate',
9
- no_difficulty: 'No such difficulty',
10
- no_save_data: 'No saved data is found'
11
- }.freeze
12
-
13
- class GameError < StandardError; end
14
-
15
- class NoSavedData < GameError; end
16
-
17
- class UnknownDifficulty < GameError; end
18
-
19
- class InvalidGuess < GameError; end
20
-
21
- class NoHintsLeft < GameError; end
22
-
23
- class InvalidName < GameError; end
24
-
25
- def validate_user_name(name, length)
26
- raise_error(InvalidName, :invalid_name) unless length.cover?(name.length)
27
- end
28
-
29
- def validate_difficulty(difficulty, difficulties)
30
- raise_error(UnknownDifficulty, :no_difficulty) unless difficulties.keys.any?(difficulty.to_sym)
31
- end
32
-
33
- def validate_guess(guess, length, range)
34
- raise_error(InvalidGuess, :invalid_guess) unless guess.compact.length == length
35
- raise_error(InvalidGuess, :invalid_guess) if guess.compact.any? { |num| !range.cover? num }
36
- end
37
-
38
- def validate_hints(hints_used, hints_total)
39
- raise_error(NoHintsLeft, :no_hints_left) if hints_used >= hints_total
40
- end
41
-
42
- def validate_file_existens(file_path)
43
- raise_error(NoSavedData, :no_save_data) unless File.exist?(file_path)
44
- end
45
-
46
- def raise_error(error_class, error_message)
47
- raise error_class, ERROR_MESSAGES[error_message]
48
- end
49
- end
50
- end