codebreaker_PI 0.0.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 +7 -0
- data/.circleci/config.yml +47 -0
- data/.gitignore +13 -0
- data/.overcommit.yml +33 -0
- data/.rake_tasks~ +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/.rubocop_todo.yml +45 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +71 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +6 -0
- data/autoload.rb +12 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/codebreaker.gemspec +41 -0
- data/config.rb +2 -0
- data/index.rb +2 -0
- data/lib/codebreaker.rb +4 -0
- data/lib/codebreaker/version.rb +3 -0
- data/lib/entities/console.rb +125 -0
- data/lib/entities/game.rb +126 -0
- data/lib/entities/player.rb +29 -0
- data/lib/entities/respondent.rb +11 -0
- data/lib/entities/rules.rb +15 -0
- data/lib/entities/statistics.rb +31 -0
- data/lib/messages/en.yml +25 -0
- data/lib/modules/uploader.rb +18 -0
- data/lib/modules/validation.rb +29 -0
- data/rules.txt +27 -0
- metadata +175 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fb57ac9f7f8ee3f0d8b69033150b6915d671fbf7e4d8fd072d8920b1a04745a2
|
4
|
+
data.tar.gz: 602d7f9863f440c992d4f1c515be4daf4f1533e89b19c2afe45b1e1d9f80f8f5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d0c38044d440fe23b0a3f2d9f39d85a30139b35b2f92b448f9b892b79babcbb3fccede80b9883c948c63a264ced3f95b1f0798ab0172db026c14144849a37ed9
|
7
|
+
data.tar.gz: 95742f2c108da194fe45ff9a2e25f7bc2332170c66ed235727a4719f3a734e33c5c43c3543b0c43513c014c244da641a1655ec2eab194d69a28be390cf269b5d
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Ruby CircleCI 2.0 configuration file
|
2
|
+
#
|
3
|
+
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
|
4
|
+
#
|
5
|
+
version: 2
|
6
|
+
jobs:
|
7
|
+
build:
|
8
|
+
docker:
|
9
|
+
- image: circleci/ruby:2.4-node-browsers
|
10
|
+
|
11
|
+
working_directory: ~/repo
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- checkout
|
15
|
+
|
16
|
+
# Download and cache dependencies
|
17
|
+
- restore_cache:
|
18
|
+
keys:
|
19
|
+
- v1-dependencies-{{ checksum "Gemfile.lock" }}
|
20
|
+
# fallback to using the latest cache if no exact match is found
|
21
|
+
- v1-dependencies-
|
22
|
+
|
23
|
+
- run:
|
24
|
+
name: install dependencies
|
25
|
+
command: |
|
26
|
+
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
27
|
+
- save_cache:
|
28
|
+
paths:
|
29
|
+
- ./vendor/bundle
|
30
|
+
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
|
31
|
+
|
32
|
+
- run:
|
33
|
+
name: run tests
|
34
|
+
command: |
|
35
|
+
mkdir /tmp/test-results
|
36
|
+
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
|
37
|
+
|
38
|
+
bundle exec rspec --format progress \
|
39
|
+
--out /tmp/test-results/rspec.xml \
|
40
|
+
--format progress \
|
41
|
+
$TEST_FILES
|
42
|
+
# collect reports
|
43
|
+
- store_test_results:
|
44
|
+
path: /tmp/test-results
|
45
|
+
- store_artifacts:
|
46
|
+
path: /tmp/test-results
|
47
|
+
destination: test-results
|
data/.gitignore
ADDED
data/.overcommit.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Use this file to configure the Overcommit hooks you wish to use. This will
|
2
|
+
# extend the default configuration defined in:
|
3
|
+
# https://github.com/brigade/overcommit/blob/master/config/default.yml
|
4
|
+
#
|
5
|
+
# At the topmost level of this YAML file is a key representing type of hook
|
6
|
+
# being run (e.g. pre-commit, commit-msg, etc.). Within each type you can
|
7
|
+
# customize each hook, such as whether to only run it on certain files (via
|
8
|
+
# `include`), whether to only display output if it fails (via `quiet`), etc.
|
9
|
+
#
|
10
|
+
# For a complete list of hooks, see:
|
11
|
+
# https://github.com/brigade/overcommit/tree/master/lib/overcommit/hook
|
12
|
+
#
|
13
|
+
# For a complete list of options that you can use to customize hooks, see:
|
14
|
+
# https://github.com/brigade/overcommit#configuration
|
15
|
+
#
|
16
|
+
# Uncomment the following lines to make the configuration take effect.
|
17
|
+
|
18
|
+
#PreCommit:
|
19
|
+
# RuboCop:
|
20
|
+
# enabled: true
|
21
|
+
# on_warn: fail # Treat all warnings as failures
|
22
|
+
#
|
23
|
+
# TrailingWhitespace:
|
24
|
+
# enabled: true
|
25
|
+
# exclude:
|
26
|
+
# - '**/db/structure.sql' # Ignore trailing whitespace in generated files
|
27
|
+
#
|
28
|
+
#PostCheckout:
|
29
|
+
# ALL: # Special hook name that customizes all hooks of this type
|
30
|
+
# quiet: true # Change all post-checkout hooks to only display output on failure
|
31
|
+
#
|
32
|
+
# IndexTags:
|
33
|
+
# enabled: true # Generate a tags file with `ctags` each time HEAD changes
|
data/.rake_tasks~
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
Style/FrozenStringLiteralComment:
|
4
|
+
Enabled: false
|
5
|
+
|
6
|
+
Metrics/LineLength:
|
7
|
+
Max: 120
|
8
|
+
|
9
|
+
Style/Documentation:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Metrics/MethodLength:
|
13
|
+
Max: 30
|
14
|
+
|
15
|
+
Metrics/PerceivedComplexity:
|
16
|
+
Max: 10
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2018-11-22 21:41:27 +0200 using RuboCop version 0.60.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Cop supports --auto-correct.
|
11
|
+
# Configuration parameters: TreatCommentsAsGroupSeparators, Include.
|
12
|
+
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
|
13
|
+
Bundler/OrderedGems:
|
14
|
+
Exclude:
|
15
|
+
- 'Gemfile'
|
16
|
+
|
17
|
+
# Offense count: 1
|
18
|
+
# Cop supports --auto-correct.
|
19
|
+
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
|
20
|
+
# SupportedStyles: space, no_space
|
21
|
+
# SupportedStylesForEmptyBraces: space, no_space
|
22
|
+
Layout/SpaceInsideBlockBraces:
|
23
|
+
Exclude:
|
24
|
+
- 'Gemfile'
|
25
|
+
|
26
|
+
# Offense count: 1
|
27
|
+
# Cop supports --auto-correct.
|
28
|
+
Style/BlockComments:
|
29
|
+
Exclude:
|
30
|
+
- 'spec/spec_helper.rb'
|
31
|
+
|
32
|
+
# Offense count: 1
|
33
|
+
Style/Documentation:
|
34
|
+
Exclude:
|
35
|
+
- 'spec/**/*'
|
36
|
+
- 'test/**/*'
|
37
|
+
- 'lib/example.rb'
|
38
|
+
|
39
|
+
# Offense count: 3
|
40
|
+
# Cop supports --auto-correct.
|
41
|
+
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
|
42
|
+
# SupportedStyles: single_quotes, double_quotes
|
43
|
+
Style/StringLiterals:
|
44
|
+
Exclude:
|
45
|
+
- 'Gemfile'
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
codebreaker
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.4.0
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
codebreaker_PI (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.4.0)
|
10
|
+
coderay (1.1.2)
|
11
|
+
concurrent-ruby (1.1.4)
|
12
|
+
diff-lcs (1.3)
|
13
|
+
docile (1.3.1)
|
14
|
+
i18n (0.9.5)
|
15
|
+
concurrent-ruby (~> 1.0)
|
16
|
+
jaro_winkler (1.5.2)
|
17
|
+
json (2.1.0)
|
18
|
+
method_source (0.9.2)
|
19
|
+
parallel (1.12.1)
|
20
|
+
parser (2.6.0.0)
|
21
|
+
ast (~> 2.4.0)
|
22
|
+
powerpack (0.1.2)
|
23
|
+
pry (0.12.2)
|
24
|
+
coderay (~> 1.1.0)
|
25
|
+
method_source (~> 0.9.0)
|
26
|
+
rainbow (3.0.0)
|
27
|
+
rake (10.5.0)
|
28
|
+
rspec (3.8.0)
|
29
|
+
rspec-core (~> 3.8.0)
|
30
|
+
rspec-expectations (~> 3.8.0)
|
31
|
+
rspec-mocks (~> 3.8.0)
|
32
|
+
rspec-core (3.8.0)
|
33
|
+
rspec-support (~> 3.8.0)
|
34
|
+
rspec-expectations (3.8.2)
|
35
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
36
|
+
rspec-support (~> 3.8.0)
|
37
|
+
rspec-mocks (3.8.0)
|
38
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
+
rspec-support (~> 3.8.0)
|
40
|
+
rspec-support (3.8.0)
|
41
|
+
rubocop (0.60.0)
|
42
|
+
jaro_winkler (~> 1.5.1)
|
43
|
+
parallel (~> 1.10)
|
44
|
+
parser (>= 2.5, != 2.5.1.1)
|
45
|
+
powerpack (~> 0.1)
|
46
|
+
rainbow (>= 2.2.2, < 4.0)
|
47
|
+
ruby-progressbar (~> 1.7)
|
48
|
+
unicode-display_width (~> 1.4.0)
|
49
|
+
ruby-progressbar (1.10.0)
|
50
|
+
simplecov (0.16.1)
|
51
|
+
docile (~> 1.1)
|
52
|
+
json (>= 1.8, < 3)
|
53
|
+
simplecov-html (~> 0.10.0)
|
54
|
+
simplecov-html (0.10.2)
|
55
|
+
unicode-display_width (1.4.1)
|
56
|
+
|
57
|
+
PLATFORMS
|
58
|
+
ruby
|
59
|
+
|
60
|
+
DEPENDENCIES
|
61
|
+
bundler (~> 1.17)
|
62
|
+
codebreaker_PI!
|
63
|
+
i18n (~> 0)
|
64
|
+
pry (~> 0)
|
65
|
+
rake (~> 10.0)
|
66
|
+
rspec (~> 3.0)
|
67
|
+
rubocop (~> 0.60.0)
|
68
|
+
simplecov (~> 0)
|
69
|
+
|
70
|
+
BUNDLED WITH
|
71
|
+
1.17.2
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Ivan Pauls
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# NewGem
|
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_Pauls`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'codebreaker_Pauls'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install codebreaker_Pauls
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. 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 tags, 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]/new_gem. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
36
|
+
|
37
|
+
## License
|
38
|
+
|
39
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
40
|
+
|
41
|
+
## Code of Conduct
|
42
|
+
|
43
|
+
Everyone interacting in the NewGem project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/new_gem/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
data/autoload.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'pry'
|
3
|
+
require 'i18n'
|
4
|
+
require_relative './lib/modules/uploader.rb'
|
5
|
+
require_relative './lib/modules/validation.rb'
|
6
|
+
require_relative './lib/entities/rules.rb'
|
7
|
+
require_relative './lib/entities/respondent.rb'
|
8
|
+
require_relative './lib/entities/statistics.rb'
|
9
|
+
require_relative './lib/entities/player.rb'
|
10
|
+
require_relative './lib/entities/game.rb'
|
11
|
+
require_relative './lib/entities/console.rb'
|
12
|
+
require_relative './config.rb'
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "сodebreaker"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/codebreaker.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'codebreaker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'codebreaker_PI'
|
8
|
+
spec.version = Codebreaker::VERSION
|
9
|
+
spec.authors = ['Ivan Pauls']
|
10
|
+
spec.email = ['ivanpauls1705@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = %q{Game for guess secret code}
|
13
|
+
spec.homepage = 'https://github.com/WoLkErSs/codebreaker-gem'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata["allowed_push_host"] = 'https://rubygems.org'
|
20
|
+
else
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
22
|
+
"public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
# Specify which files should be added to the gem when it is released.
|
26
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
27
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
28
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
29
|
+
end
|
30
|
+
spec.bindir = "exe"
|
31
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ["lib"]
|
33
|
+
|
34
|
+
spec.add_development_dependency 'bundler', '~> 1.17'
|
35
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
36
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
37
|
+
spec.add_development_dependency 'rubocop', '~> 0.60.0'
|
38
|
+
spec.add_development_dependency 'simplecov', '~> 0'
|
39
|
+
spec.add_development_dependency 'i18n', '~> 0'
|
40
|
+
spec.add_development_dependency 'pry', '~> 0'
|
41
|
+
end
|
data/config.rb
ADDED
data/index.rb
ADDED
data/lib/codebreaker.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
class Console
|
3
|
+
include Database
|
4
|
+
USER_ACTIONS = {
|
5
|
+
start: 'start',
|
6
|
+
rules: 'rules',
|
7
|
+
stats: 'stats',
|
8
|
+
leave: 'exit'
|
9
|
+
}.freeze
|
10
|
+
ACTIONS_FOR_DATABASE = {
|
11
|
+
save_player: 'y'
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def choose_action
|
15
|
+
respondent.show_message(:greeting)
|
16
|
+
loop do
|
17
|
+
respondent.show_message(:choose_action)
|
18
|
+
case input
|
19
|
+
when USER_ACTIONS[:start] then return process
|
20
|
+
when USER_ACTIONS[:rules] then rules.show_rules
|
21
|
+
when USER_ACTIONS[:stats] then show_statistics
|
22
|
+
else respondent.show_message(:wrong_input_action)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def player
|
30
|
+
@player ||= Player.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def rules
|
34
|
+
@rules ||= Rules.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def game
|
38
|
+
@game ||= Game.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def respondent
|
42
|
+
@respondent ||= Respondent.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def statistic
|
46
|
+
@statistic ||= Statistics.new
|
47
|
+
end
|
48
|
+
|
49
|
+
def process
|
50
|
+
game.game_options(user_difficulty: setup_difficulty, player: setup_player)
|
51
|
+
play_game
|
52
|
+
end
|
53
|
+
|
54
|
+
def setup_player
|
55
|
+
respondent.show_message(:ask_name)
|
56
|
+
loop do
|
57
|
+
player.assign_name(input.capitalize)
|
58
|
+
next respondent.show(player.errors_store) unless player.valid?
|
59
|
+
return player if player.valid?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def setup_difficulty
|
64
|
+
loop do
|
65
|
+
respondent.show_message(:select_difficulty)
|
66
|
+
user_difficulty_input = input
|
67
|
+
return user_difficulty_input if game.valid_difficulties?(user_difficulty_input)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def play_game
|
72
|
+
respondent.show_message(:in_process)
|
73
|
+
while game_state_valid?
|
74
|
+
what_guessed = game.attempt(input)
|
75
|
+
next if game.winner
|
76
|
+
respondent.show(what_guessed) if what_guessed
|
77
|
+
respondent.show(game.errors) unless game.errors.empty?
|
78
|
+
end
|
79
|
+
result_decision
|
80
|
+
end
|
81
|
+
|
82
|
+
def game_state_valid?
|
83
|
+
game.attempts_left.positive? && !game.winner
|
84
|
+
end
|
85
|
+
|
86
|
+
def result_decision
|
87
|
+
game.winner ? win : lose
|
88
|
+
end
|
89
|
+
|
90
|
+
def lose
|
91
|
+
game.remove_instance_helpers
|
92
|
+
respondent.show_message(:when_lose)
|
93
|
+
new_process
|
94
|
+
end
|
95
|
+
|
96
|
+
def win
|
97
|
+
game.remove_instance_helpers
|
98
|
+
respondent.show_message(:when_win)
|
99
|
+
save_to_db(game) if input == ACTIONS_FOR_DATABASE[:save_player]
|
100
|
+
new_process
|
101
|
+
end
|
102
|
+
|
103
|
+
def new_process
|
104
|
+
choose_action
|
105
|
+
end
|
106
|
+
|
107
|
+
def input
|
108
|
+
input = gets.chomp.downcase
|
109
|
+
input == USER_ACTIONS[:leave] ? leave : input
|
110
|
+
end
|
111
|
+
|
112
|
+
def leave
|
113
|
+
respondent.show_message(:leave)
|
114
|
+
exit
|
115
|
+
end
|
116
|
+
|
117
|
+
def show_statistics
|
118
|
+
respondent.show(winners_load)
|
119
|
+
end
|
120
|
+
|
121
|
+
def winners_load
|
122
|
+
statistic.winners(load_db)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
class Game
|
3
|
+
include Validation
|
4
|
+
|
5
|
+
AMOUNT_DIGITS = 4
|
6
|
+
RANGE_DIGITS = 1..6
|
7
|
+
DIFFICULTIES = {
|
8
|
+
easy: { attempts: 15, hints: 2, difficulty: 'easy' },
|
9
|
+
hard: { attempts: 10, hints: 2, difficulty: 'hard' },
|
10
|
+
expert: { attempts: 5, hints: 1, difficulty: 'expert' }
|
11
|
+
}.freeze
|
12
|
+
RANGE_OF_DIGITS = 0..4.freeze
|
13
|
+
GUESS_CODE = { hint: 'hint', leave: 'exit' }.freeze
|
14
|
+
|
15
|
+
attr_reader :name, :hints_total, :have_hints, :attempts_total, :hints_used, :attempts_used, :difficulty, :winner, :attempts_left
|
16
|
+
attr_accessor :errors
|
17
|
+
|
18
|
+
def game_options(user_difficulty:, player:)
|
19
|
+
@got_hints = ''
|
20
|
+
@hints_used = 0
|
21
|
+
@attempts_used = 0
|
22
|
+
@name = player.name
|
23
|
+
assign_difficulty(DIFFICULTIES[user_difficulty.downcase.to_sym])
|
24
|
+
end
|
25
|
+
|
26
|
+
def attempt(input)
|
27
|
+
@errors = []
|
28
|
+
return use_hint if hint?(input)
|
29
|
+
|
30
|
+
converted = convert_to_array(input)
|
31
|
+
return guessing(converted) if valid_input?(input, AMOUNT_DIGITS)
|
32
|
+
miss_input && return
|
33
|
+
end
|
34
|
+
|
35
|
+
def miss_input
|
36
|
+
@errors << I18n.t(:when_incorrect_guess) && return
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid_difficulties?(input)
|
40
|
+
DIFFICULTIES.key?(input.to_sym)
|
41
|
+
end
|
42
|
+
|
43
|
+
def remove_instance_helpers
|
44
|
+
remove_instance_variable(:@winner) if @winner
|
45
|
+
remove_instance_variable(:@errors) if @errors
|
46
|
+
remove_instance_variable(:@hints_array) if @hints_array
|
47
|
+
remove_instance_variable(:@have_hints) if @have_hints
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def hint?(input)
|
53
|
+
input == GUESS_CODE[:hint]
|
54
|
+
end
|
55
|
+
|
56
|
+
def convert_to_array(input)
|
57
|
+
input.chars.map(&:to_i)
|
58
|
+
end
|
59
|
+
|
60
|
+
def assign_difficulty(difficulty_of_variables)
|
61
|
+
@attempts_total = difficulty_of_variables[:attempts]
|
62
|
+
@hints_total = difficulty_of_variables[:hints]
|
63
|
+
@have_hints = difficulty_of_variables[:hints]
|
64
|
+
@attempts_left = @attempts_total
|
65
|
+
@difficulty = difficulty_of_variables[:difficulty]
|
66
|
+
end
|
67
|
+
|
68
|
+
def valid_input?(entity, length)
|
69
|
+
return unless validate_presence?(entity)
|
70
|
+
return unless validate_length(entity, length)
|
71
|
+
return unless validate_match(entity)
|
72
|
+
|
73
|
+
valid_digits?(entity, RANGE_DIGITS)
|
74
|
+
end
|
75
|
+
|
76
|
+
def count_attempt
|
77
|
+
@attempts_left -= 1
|
78
|
+
@attempts_used += 1
|
79
|
+
end
|
80
|
+
|
81
|
+
def use_hint
|
82
|
+
@errors << I18n.t(:when_no_hints) && return unless @have_hints.positive?
|
83
|
+
count_tip
|
84
|
+
end
|
85
|
+
|
86
|
+
def count_tip
|
87
|
+
@have_hints -= 1
|
88
|
+
@hints_used += 1
|
89
|
+
@hints_array ||= secret_code.clone.shuffle
|
90
|
+
hint = @hints_array.pop.to_s
|
91
|
+
@got_hints += hint
|
92
|
+
hint
|
93
|
+
end
|
94
|
+
|
95
|
+
def compare_with_right_code(user_code)
|
96
|
+
user_code == secret_code
|
97
|
+
end
|
98
|
+
|
99
|
+
def secret_code
|
100
|
+
@secret_code ||= Array.new(AMOUNT_DIGITS) { rand(RANGE_OF_DIGITS) }.join('')
|
101
|
+
convert_to_array(@secret_code)
|
102
|
+
end
|
103
|
+
|
104
|
+
def guessing(user_code)
|
105
|
+
count_attempt
|
106
|
+
return @winner = true if compare_with_right_code(user_code)
|
107
|
+
|
108
|
+
pin = []
|
109
|
+
clone_secret_code = secret_code.clone
|
110
|
+
complex_code = user_code.zip(secret_code)
|
111
|
+
complex_code.map do |user_digit, secret_digit|
|
112
|
+
next unless user_digit == secret_digit
|
113
|
+
|
114
|
+
pin << '+'
|
115
|
+
user_code.delete_at(user_code.index(user_digit))
|
116
|
+
clone_secret_code.delete_at(clone_secret_code.index(secret_digit))
|
117
|
+
end
|
118
|
+
clone_secret_code.each do |digit|
|
119
|
+
next unless user_code.include? digit
|
120
|
+
pin << '-'
|
121
|
+
user_code.delete_at(user_code.index(digit))
|
122
|
+
end
|
123
|
+
pin.sort.join('')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
class Player
|
3
|
+
include Validation
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
attr_accessor :errors_store
|
7
|
+
|
8
|
+
LENGTH_RANGE = 3..20
|
9
|
+
|
10
|
+
def assign_name(name)
|
11
|
+
@errors_store = []
|
12
|
+
return @name = name if validate_name(name)
|
13
|
+
|
14
|
+
@errors_store << I18n.t(:when_wrong_name, min: LENGTH_RANGE.first, max: LENGTH_RANGE.last)
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid?
|
18
|
+
@errors_store.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def validate_name(name)
|
24
|
+
return unless validate_presence?(name)
|
25
|
+
|
26
|
+
valid_name?(name, LENGTH_RANGE)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
class Rules
|
3
|
+
FOLDER_PATH = './'.freeze
|
4
|
+
FILE_PATH = 'rules'.freeze
|
5
|
+
FORMAT_PATH = '.txt'.freeze
|
6
|
+
PATH = FOLDER_PATH + FILE_PATH + FORMAT_PATH
|
7
|
+
|
8
|
+
def show_rules
|
9
|
+
File.open(PATH, 'r') do |f|
|
10
|
+
f.each_line { |line| puts line }
|
11
|
+
f.close
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
class Statistics
|
3
|
+
include Database
|
4
|
+
|
5
|
+
def winners(base)
|
6
|
+
data = multi_sort(base)
|
7
|
+
to_table(data)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def to_table(data)
|
13
|
+
rows = []
|
14
|
+
data.map do |i|
|
15
|
+
row = []
|
16
|
+
row << i.name
|
17
|
+
row << i.difficulty
|
18
|
+
row << i.attempts_total
|
19
|
+
row << i.attempts_used
|
20
|
+
row << i.hints_total
|
21
|
+
row << i.hints_used
|
22
|
+
rows << row
|
23
|
+
end
|
24
|
+
rows
|
25
|
+
end
|
26
|
+
|
27
|
+
def multi_sort(items)
|
28
|
+
items.sort_by { |player| [player.difficulty, player.attempts_used, player.hints_used] }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/messages/en.yml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
en:
|
2
|
+
greeting: "welcome to codebreaker\n"
|
3
|
+
choose_action: "Choose actions: start, rules, stats or exit\n"
|
4
|
+
select_difficulty: "Select difficulty of game: easy, hard, expert\n"
|
5
|
+
in_process: "Try to guess a secret code of Da`Vanya\n"
|
6
|
+
ask_name: "Enter your name\n"
|
7
|
+
leave: "Goodbye\n"
|
8
|
+
wrong_input_action: "You have passed unexpected command.\n
|
9
|
+
Please choose one from listed commands\n"
|
10
|
+
when_wrong_name: "Name length must be from %{min} to %{max} words\n"
|
11
|
+
wrong_input_code: "You should enter one of the valid commands - one more time.\n"
|
12
|
+
when_no_hints: "You have not hints\n"
|
13
|
+
when_lose: "Hey loser, still play?\n"
|
14
|
+
when_win: "Congratulation! You won!\n
|
15
|
+
Do you want to save result? -> press 'y'\n"
|
16
|
+
when_incorrect_guess: "Try to enter correct number\n"
|
17
|
+
|
18
|
+
table_fields:
|
19
|
+
name: 'Name'
|
20
|
+
difficulty: 'Difficulty'
|
21
|
+
attempts_total: 'Attempts Total'
|
22
|
+
attempts_used: 'Attempts Used'
|
23
|
+
hints_total: 'Hints Total'
|
24
|
+
hints_used: 'Hints Used'
|
25
|
+
table_heder: 'Codebreaker statistics'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
module Database
|
3
|
+
FOLDER_PATH = './lib/database/'.freeze
|
4
|
+
FILE_PATH = 'stats'.freeze
|
5
|
+
FORMAT_PATH = '.yml'.freeze
|
6
|
+
PATH = FOLDER_PATH + FILE_PATH + FORMAT_PATH
|
7
|
+
|
8
|
+
def save_to_db(player)
|
9
|
+
File.open(PATH, 'a+') { |f| f.write player.to_yaml }
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def load_db
|
15
|
+
YAML.load_stream(File.open(PATH))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Codebreaker
|
2
|
+
module Validation
|
3
|
+
def validate_in_range?(argument, range)
|
4
|
+
range.include? argument
|
5
|
+
end
|
6
|
+
|
7
|
+
def valid_name?(name, range)
|
8
|
+
validate_in_range?(name.length, range)
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid_digits?(digits, range)
|
12
|
+
digits.chars.map(&:to_i).each do |digit|
|
13
|
+
return unless validate_in_range?(digit, range)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_presence?(entity)
|
18
|
+
!entity.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate_match(entity)
|
22
|
+
entity.to_i.to_s == entity
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate_length(entity, set_length)
|
26
|
+
entity.length == set_length
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/rules.txt
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
--- Game Rules
|
3
|
+
Codebreaker is a logic game in which a code-breaker tries to break a secret code created by a code-maker.
|
4
|
+
The codemaker, which will be played by the application we’re going to write, creates a secret code of four numbers between 1 and 6.
|
5
|
+
The codebreaker gets some number of chances to break the code (depends on chosen difficulty).
|
6
|
+
In each turn, the codebreaker makes a guess of 4 numbers.
|
7
|
+
The codemaker then marks the guess with up to 4 signs - + or - or empty spaces.
|
8
|
+
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.
|
9
|
+
For example:
|
10
|
+
|
11
|
+
Secret number - 1234
|
12
|
+
Input number - 6264
|
13
|
+
|
14
|
+
Number of pluses - 2 (second and fourth position)
|
15
|
+
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.
|
16
|
+
For example:
|
17
|
+
|
18
|
+
Secret number - 1234
|
19
|
+
Input number - 6462
|
20
|
+
|
21
|
+
Number of minuses - 2 (second and fourth position)
|
22
|
+
An empty space indicates that there is not a current digit in a secret number.
|
23
|
+
If codebreaker inputs the exact number as a secret number - codebreaker wins the game.
|
24
|
+
If all attempts are spent - codebreaker loses.
|
25
|
+
Codebreaker also has some number of hints(depends on chosen difficulty).
|
26
|
+
If a user takes a hint - he receives back a separate digit of the secret code.
|
27
|
+
---
|
metadata
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: codebreaker_PI
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ivan Pauls
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-01-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.60.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.60.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: i18n
|
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'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- ivanpauls1705@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".circleci/config.yml"
|
119
|
+
- ".gitignore"
|
120
|
+
- ".overcommit.yml"
|
121
|
+
- ".rake_tasks~"
|
122
|
+
- ".rspec"
|
123
|
+
- ".rubocop.yml"
|
124
|
+
- ".rubocop_todo.yml"
|
125
|
+
- ".ruby-gemset"
|
126
|
+
- ".ruby-version"
|
127
|
+
- Gemfile
|
128
|
+
- Gemfile.lock
|
129
|
+
- LICENSE.txt
|
130
|
+
- README.md
|
131
|
+
- Rakefile
|
132
|
+
- autoload.rb
|
133
|
+
- bin/console
|
134
|
+
- bin/setup
|
135
|
+
- codebreaker.gemspec
|
136
|
+
- config.rb
|
137
|
+
- index.rb
|
138
|
+
- lib/codebreaker.rb
|
139
|
+
- lib/codebreaker/version.rb
|
140
|
+
- lib/entities/console.rb
|
141
|
+
- lib/entities/game.rb
|
142
|
+
- lib/entities/player.rb
|
143
|
+
- lib/entities/respondent.rb
|
144
|
+
- lib/entities/rules.rb
|
145
|
+
- lib/entities/statistics.rb
|
146
|
+
- lib/messages/en.yml
|
147
|
+
- lib/modules/uploader.rb
|
148
|
+
- lib/modules/validation.rb
|
149
|
+
- rules.txt
|
150
|
+
homepage: https://github.com/WoLkErSs/codebreaker-gem
|
151
|
+
licenses:
|
152
|
+
- MIT
|
153
|
+
metadata:
|
154
|
+
allowed_push_host: https://rubygems.org
|
155
|
+
post_install_message:
|
156
|
+
rdoc_options: []
|
157
|
+
require_paths:
|
158
|
+
- lib
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubyforge_project:
|
171
|
+
rubygems_version: 2.7.8
|
172
|
+
signing_key:
|
173
|
+
specification_version: 4
|
174
|
+
summary: Game for guess secret code
|
175
|
+
test_files: []
|