andrii_codebreaker 0.1.1 → 0.1.5

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: 4fe12dfef9d161e80cd13690272a4a293527bc887c3dfaddd868b6c21ad01f52
4
- data.tar.gz: 53f29bacf46db43b1a9cc122107c040279d087f80c6a40219c08c808c9683fe6
3
+ metadata.gz: 1743f315c3e1b74182843039b68e4a94274b9b32d29e4006ab50bc40a1b9bef2
4
+ data.tar.gz: 4562d14615ea91676b026d3fa4038c3542c5293cbc3c1e12bc159b08002e9bef
5
5
  SHA512:
6
- metadata.gz: ba3d0da4107f56f16f0957b4fe4b553d206823fd397edfa1421d1a562e7ba4500f670fa1ca74f04a54d0391b8a27833b7ec97f292765a0097d6de4ac6610979e
7
- data.tar.gz: a298375c0632b26d4c4ab7264bc9a7677231ce375bb67be24d3b3c9a2282fae1282d524c044404e49a458f9c69c6aff5d672741a53d6d4b7c46f263bde71e6ea
6
+ metadata.gz: 53365788f599671f07b0b59725ebb0d2e080ec7d62117052807c2995c384f3b7da63cafd4c8b99a0cc486fcfaa78f6e1d83f151c6f15a62d869659907cd32aef
7
+ data.tar.gz: b28fda65ac98bdcf8c5385c068620d5e66fde3ae818a6fe3c044dc85e9cd1b25b432b2cd4167fa06237c842c5d05189ec251f88e299ed7c9ddf9438bee2ea12d
@@ -0,0 +1,62 @@
1
+
2
+ version: 2.1
3
+
4
+ executors:
5
+ default:
6
+ working_directory: ~/repo
7
+ description: The official CircleCI Ruby Docker image
8
+ docker:
9
+ - image: circleci/ruby:2.7.2
10
+
11
+ cashes:
12
+ - &bundle_caches_full v2-repo-{{ checksum "Gemfile.lock" }}
13
+ - &bundle_cache v2-repo-
14
+
15
+ commands:
16
+ defaults:
17
+ steps:
18
+ - checkout
19
+ - restore_cache:
20
+ keys:
21
+ - *bundle_caches_full
22
+ - *bundle_cache
23
+ - run: bundle install --path vendor/bundle
24
+ - save_cache:
25
+ key: *bundle_caches_full
26
+ paths:
27
+ - vendor/bundle
28
+ run_linters:
29
+ description: command to start linters
30
+ steps:
31
+ - run:
32
+ name: rubucop
33
+ command: bundle exec rubocop
34
+ - run:
35
+ name: fasterer
36
+ command: bundle exec fasterer lib/
37
+ run_specs:
38
+ steps:
39
+ - run:
40
+ name: run specs
41
+ command: bundle exec rspec
42
+
43
+ jobs:
44
+ lintering:
45
+ executor: default
46
+ steps:
47
+ - defaults
48
+ - run_linters
49
+ run_specs:
50
+ executor: default
51
+ steps:
52
+ - defaults
53
+ - run_specs
54
+
55
+ workflows:
56
+ version: 2.1
57
+ build:
58
+ jobs:
59
+ - lintering
60
+ - run_specs:
61
+ requires:
62
+ - lintering
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ /.bundle/
2
+ /coverage/
3
+ .rspec_status
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ require: rubocop-rspec
2
+
1
3
  AllCops:
2
4
  NewCops: enable
3
5
  SuggestExtensions: false
@@ -5,12 +7,12 @@ AllCops:
5
7
  Style/Documentation:
6
8
  Enabled: false
7
9
 
8
- Style/FrozenStringLiteralComment:
9
- Enabled: false
10
-
11
10
  Metrics/LineLength:
12
11
  Max: 120
13
12
 
13
+ RSpec/AnyInstance:
14
+ Enabled: false
15
+
14
16
  Metrics/BlockLength:
15
17
  Exclude:
16
18
  - 'Rakefile'
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
data/Gemfile.lock CHANGED
@@ -1,19 +1,21 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- andrii_codebreaker (0.1.0)
5
- simplecov
4
+ andrii_codebreaker (0.1.4)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
9
8
  specs:
10
9
  ast (2.4.2)
11
10
  colorize (0.8.1)
11
+ concurrent-ruby (1.1.9)
12
12
  diff-lcs (1.4.4)
13
13
  docile (1.4.0)
14
14
  fasterer (0.9.0)
15
15
  colorize (~> 0.7)
16
16
  ruby_parser (>= 3.14.1)
17
+ i18n (1.8.11)
18
+ concurrent-ruby (~> 1.0)
17
19
  parallel (1.21.0)
18
20
  parser (3.0.2.0)
19
21
  ast (~> 2.4.1)
@@ -34,7 +36,7 @@ GEM
34
36
  diff-lcs (>= 1.2.0, < 2.0)
35
37
  rspec-support (~> 3.10.0)
36
38
  rspec-support (3.10.2)
37
- rubocop (1.22.2)
39
+ rubocop (1.22.3)
38
40
  parallel (~> 1.10)
39
41
  parser (>= 3.0.0.0)
40
42
  rainbow (>= 2.2.2, < 4.0)
@@ -45,10 +47,12 @@ GEM
45
47
  unicode-display_width (>= 1.4.0, < 3.0)
46
48
  rubocop-ast (1.12.0)
47
49
  parser (>= 3.0.1.1)
50
+ rubocop-rspec (2.5.0)
51
+ rubocop (~> 1.19)
48
52
  ruby-progressbar (1.11.0)
49
- ruby_parser (3.17.0)
50
- sexp_processor (~> 4.15, >= 4.15.1)
51
- sexp_processor (4.15.3)
53
+ ruby_parser (3.18.0)
54
+ sexp_processor (~> 4.16)
55
+ sexp_processor (4.16.0)
52
56
  simplecov (0.21.2)
53
57
  docile (~> 1.1)
54
58
  simplecov-html (~> 0.11)
@@ -63,9 +67,12 @@ PLATFORMS
63
67
  DEPENDENCIES
64
68
  andrii_codebreaker!
65
69
  fasterer
70
+ i18n
66
71
  rake
67
72
  rspec
68
73
  rubocop
74
+ rubocop-rspec
75
+ simplecov
69
76
 
70
77
  BUNDLED WITH
71
78
  2.2.29
data/Rakefile CHANGED
@@ -1,6 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
3
- RSpec::Core::RakeTask.new(:spec)
4
- require 'rubocop/rake_task'
5
- RuboCop::RakeTask.new
6
- task default: %i[spec rubocop]
4
+ task default: :spec
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/andrii_codebreaker/version'
4
+ lib = File.expand_path('lib', __dir__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'andrii_codebreaker'
9
+ spec.version = AndriiCodebreaker::VERSION
10
+ spec.authors = ['Andrii']
11
+ spec.email = ['andrii.okhrimets@rubygarage.org']
12
+
13
+ spec.summary = 'Game in Codebreaker'
14
+ spec.description = 'Game in Codebreaker'
15
+ spec.homepage = 'https://github.com/Andrii-RubyGarage/Codebreker-Gem'
16
+ spec.license = 'MIT'
17
+ spec.required_ruby_version = '>= 2.7.2'
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = spec.homepage
21
+
22
+ spec.add_development_dependency 'fasterer'
23
+ spec.add_development_dependency 'i18n'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'rubocop'
27
+ spec.add_development_dependency 'rubocop-rspec'
28
+ spec.add_development_dependency 'simplecov'
29
+
30
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
32
+ end
33
+
34
+ spec.bindir = 'bin'
35
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ['lib']
37
+ end
data/bin/console CHANGED
@@ -1,15 +1,5 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
1
  require 'bundler/setup'
5
2
  require 'andrii_codebreaker'
6
3
 
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
4
  require 'irb'
15
5
  IRB.start(__FILE__)
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AndriiCodebreaker
4
+ module Constant
5
+ NAME_MIN_LENGTH = 3
6
+ NAME_MAX_LENGTH = 20
7
+ CODE_START_LENGTH = 1
8
+ CODE_LENGTH = 6
9
+ CODE_LENGTH_COUNT = 4
10
+ DIFFICULTY = {
11
+ easy: { attempts: 15, hints: 2 },
12
+ medium: { attempts: 10, hints: 1 },
13
+ hell: { attempts: 5, hints: 1 }
14
+ }.freeze
15
+ DIFFICULTY_SORT = { easy: 1, medium: 2, hell: 3 }.freeze
16
+ end
17
+ end
@@ -1,11 +1,13 @@
1
- require_relative '../andrii_codebreaker'
1
+ # frozen_string_literal: true
2
+
2
3
  module AndriiCodebreaker
3
4
  class Game
4
5
  include Validate
5
- include Model
6
6
  include Statistic
7
- attr_reader :secret_code
8
- attr_accessor :secret_code_copy
7
+ include Constant
8
+
9
+ attr_reader :player_name, :difficulty, :attempts_total, :hints_total, :secret_code
10
+ attr_accessor :hints_left, :attempts_left, :secret_code_cope
9
11
 
10
12
  CONST_COMMAND = {
11
13
  start: 'start',
@@ -14,75 +16,68 @@ module AndriiCodebreaker
14
16
  exit: 'exit'
15
17
  }.freeze
16
18
 
17
- WIN_MATRIX = ['+', '+', '+', '+'].freeze
18
-
19
- def initialize
20
- @secret_code = generate_code
21
- @secret_code_copy = @secret_code.dup
19
+ def initialize(player_name, difficulty)
20
+ @player_name = player_name
21
+ @difficulty = difficulty
22
+ @attempts_left = 0
23
+ @hints_left = 0
24
+ initialize_class
22
25
  end
23
26
 
24
- def hints(user)
25
- return unless user.hints_total > user.hints_now
26
-
27
- user.hints_now += 1
28
- @secret_code_copy.pop
27
+ def initialize_class
28
+ difficult = DIFFICULTY[@difficulty.to_sym]
29
+ @hints_total = difficult[:hints]
30
+ @attempts_total = difficult[:attempts]
31
+ @secret_code = generate_code
32
+ @secret_code_cope = @secret_code.dup
29
33
  end
30
34
 
31
- def compare_codes(user_code)
32
- matches, user_code, code_copy = right_place(user_code)
33
- number_secret_code(user_code, matches, code_copy)
35
+ def show_hints
36
+ hints_left
34
37
  end
35
38
 
36
- def string_to_integer(input_code)
37
- array_int = []
38
- array_chars = input_code.chars
39
- array_chars.each { |i| array_int << i.to_i }
40
- array_int
41
- end
39
+ def compare_codes(guess)
40
+ return '++++' if exact_match(guess)
42
41
 
43
- def save_result(user, file)
44
- save(user, file)
42
+ ('+' * pluses(guess)) + ('-' * minuses(guess))
45
43
  end
46
44
 
47
45
  private
48
46
 
49
- def right_place(user_code)
50
- code_copy = @secret_code.dup
51
- matches = []
52
- user_code.each_index do |i|
53
- next unless @secret_code[i] == user_code[i]
47
+ def exact_match(guess)
48
+ @secret_code == guess
49
+ end
54
50
 
55
- matches.unshift('+')
56
- user_code[i] = nil
57
- code_copy[i] = false
58
- end
59
- [matches, user_code, code_copy]
51
+ def pluses(guess)
52
+ zipped(guess)
53
+ .select { |el| el[0] == el[1] }
54
+ .count
60
55
  end
61
56
 
62
- def number_secret_code(user_code, matches, code_copy)
63
- amount_numbers_secret = Hash.new(0)
64
- amount_numbers_now = Hash.new(0)
65
- code_copy.each { |number| amount_numbers_secret[number.to_s] += 1 }
66
- user_code.each do |element|
67
- next unless include_element?(code_copy, element) &&
68
- amount_of_element?(amount_numbers_now, amount_numbers_secret, element)
57
+ def minuses(guess)
58
+ return 0 if exact_match(guess)
59
+
60
+ arr = delete_pairs(guess)
61
+ arr[1].each do |number|
62
+ next unless arr[0].include?(number)
69
63
 
70
- matches.push('-')
71
- amount_numbers_now[element.to_s] += 1
64
+ arr[0].delete_at(arr[0].index(number))
72
65
  end
73
- matches
66
+ arr[1].size - arr[0].size
74
67
  end
75
68
 
76
- def include_element?(given_array, element)
77
- given_array.include? element
69
+ def zipped(guess)
70
+ @secret_code.chars.zip(guess.chars)
78
71
  end
79
72
 
80
- def amount_of_element?(amount_numbers_now, amount_numbers_secret, element)
81
- amount_numbers_now[element.to_s] < amount_numbers_secret[element.to_s]
73
+ def delete_pairs(guess)
74
+ zipped(guess)
75
+ .delete_if { |el| el[0] == el[1] }
76
+ .transpose
82
77
  end
83
78
 
84
79
  def generate_code
85
- Array.new(4) { rand(1..6) }
80
+ (Array.new(CODE_LENGTH_COUNT) { rand(CODE_START_LENGTH..CODE_LENGTH) }).join.to_s
86
81
  end
87
82
  end
88
83
  end
@@ -1,21 +1,20 @@
1
- require 'yaml'
2
- module AndriiCodebreaker
3
- module Model
4
- def load_file(file)
5
- return nil if File.empty?(file)
1
+ # frozen_string_literal: true
6
2
 
7
- save_data(file)
8
- rescue Errno::ENOENT
9
- nil
10
- end
3
+ module AndriiCodebreaker
4
+ class DbYaml
5
+ class << self
6
+ def load_file(path)
7
+ File.open(path, 'r') do |filename|
8
+ YAML.safe_load(filename)
9
+ end
10
+ end
11
11
 
12
- def save(user, file)
13
- File.open(file, 'a') { |f| YAML.dump(user, f) }
14
- end
12
+ def save(user, path)
13
+ File.open(path, 'a') { |f| YAML.dump(user, f) }
14
+ end
15
15
 
16
- def save_data(file)
17
- File.open(file, 'r') do |filename|
18
- YAML.safe_load(filename)
16
+ def load_file_stats(path)
17
+ YAML.load_stream(File.open(path))
19
18
  end
20
19
  end
21
20
  end
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AndriiCodebreaker
2
4
  module Statistic
5
+ include Constant
6
+
3
7
  def statistics
4
- data = YAML.load_stream(File.open('result.yml'))
5
- hash = { easy: 1, medium: 2, hell: 3 }
6
- data.sort_by { |item| [-hash[item.difficulty.to_sym], item.attempts_now, item.hints_now] }
8
+ data = DbYaml.load_file_stats('result.yml')
9
+ data.sort_by { |item| [-DIFFICULTY_SORT[item.difficulty.to_sym], item.attempts_left, item.hints_left] }
7
10
  end
8
11
  end
9
12
  end
@@ -1,28 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AndriiCodebreaker
2
4
  class User
3
- DIFFICULTY = {
4
- easy: { attempts: 15, hints: 2 },
5
- medium: { attempts: 10, hints: 1 },
6
- hell: { attempts: 5, hints: 1 }
7
- }.freeze
5
+ include AndriiCodebreaker::Validate
8
6
 
9
- attr_reader :name, :difficulty, :attempts_total, :hints_total
10
- attr_accessor :hints_now, :attempts_now
7
+ attr_reader :name
11
8
 
12
- def initialize(name, difficulty)
9
+ def initialize(name)
13
10
  @name = name
14
- @difficulty = difficulty
15
- @attempts_now = 0
16
- @hints_now = 0
17
- set_count_attempt
11
+ validate_name
12
+ end
13
+
14
+ def hints(game)
15
+ return unless game.hints_total > game.hints_left
16
+
17
+ game.hints_left += 1
18
+ game.secret_code_cope.chars.pop
18
19
  end
19
20
 
20
21
  private
21
22
 
22
- def set_count_attempt
23
- difficult = DIFFICULTY[@difficulty.to_sym]
24
- @hints_total = difficult[:hints]
25
- @attempts_total = difficult[:attempts]
23
+ def validate_name
24
+ @name = validates_name(name)
26
25
  end
27
26
  end
28
27
  end
@@ -1,17 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AndriiCodebreaker
2
4
  module Validate
3
- def validate_guess(code)
4
- code.match(/^[1-6]{4}$/)
5
- end
5
+ include Constant
6
6
 
7
- def valide_name(name)
7
+ def validates_name(name)
8
8
  name if valid_name?(name)
9
9
  end
10
10
 
11
+ def validate_guess(code)
12
+ code = string_to_integer(code)
13
+ true if check_code_length?(code) && check_numbers?(code)
14
+ end
15
+
11
16
  private
12
17
 
18
+ def string_to_integer(input_code)
19
+ array_int = []
20
+ array_chars = input_code.chars
21
+ array_chars.each { |i| array_int << i.to_i }
22
+ array_int
23
+ end
24
+
13
25
  def valid_name?(name)
14
- name.length >= 3 && name.length <= 20
26
+ name.length >= NAME_MIN_LENGTH && name.length <= NAME_MAX_LENGTH
27
+ end
28
+
29
+ def check_code_length?(code)
30
+ code.length == CODE_LENGTH_COUNT
31
+ end
32
+
33
+ def check_numbers?(code)
34
+ code.all? { |value| value.between?(CODE_START_LENGTH, CODE_LENGTH) }
15
35
  end
16
36
  end
17
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AndriiCodebreaker
2
- VERSION = '0.1.1'.freeze
4
+ VERSION = '0.1.5'
3
5
  end
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require_relative 'andrii_codebreaker/constants'
5
+ require_relative 'andrii_codebreaker/validate/validate'
1
6
  require_relative 'andrii_codebreaker/model'
2
7
  require_relative 'andrii_codebreaker/user'
3
- require_relative 'andrii_codebreaker/validate/validate'
4
8
  require_relative 'andrii_codebreaker/statistic'
5
9
  require_relative 'andrii_codebreaker/version'
6
10
  require_relative 'andrii_codebreaker/game'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: andrii_codebreaker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrii
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-28 00:00:00.000000000 Z
11
+ date: 2021-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fasterer
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: i18n
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'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,20 @@ dependencies:
66
80
  - - ">="
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rspec
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'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: simplecov
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -73,7 +101,7 @@ dependencies:
73
101
  - - ">="
74
102
  - !ruby/object:Gem::Version
75
103
  version: '0'
76
- type: :runtime
104
+ type: :development
77
105
  prerelease: false
78
106
  version_requirements: !ruby/object:Gem::Requirement
79
107
  requirements:
@@ -87,7 +115,9 @@ executables: []
87
115
  extensions: []
88
116
  extra_rdoc_files: []
89
117
  files:
118
+ - ".circleci/config.yml"
90
119
  - ".fasterer.yml"
120
+ - ".gitignore"
91
121
  - ".rspec"
92
122
  - ".rubocop.yml"
93
123
  - ".ruby-gemset"
@@ -97,9 +127,11 @@ files:
97
127
  - LICENSE.txt
98
128
  - README.md
99
129
  - Rakefile
130
+ - andrii_codebreaker.gemspec
100
131
  - bin/console
101
132
  - bin/setup
102
133
  - lib/andrii_codebreaker.rb
134
+ - lib/andrii_codebreaker/constants.rb
103
135
  - lib/andrii_codebreaker/game.rb
104
136
  - lib/andrii_codebreaker/model.rb
105
137
  - lib/andrii_codebreaker/statistic.rb