# frozen_string_literal: true module Codebreaker class Game include Storage private attr_reader :secret_code public attr_reader :user, :attempts, :total_attempts, :hints, :total_hints, :level attr_accessor :status GAME_DIFFICULTIES = { simple: { attempts: 15, hints: 2 }, medium: { attempts: 10, hints: 1 }, hell: { attempts: 5, hints: 1 } }.freeze WIN = :win LOSS = :loss PLUS = '+' MINUS = '-' NUMBER_OF_ENCRYPTED_DIGITS = 4 VALUES_FOR_ENCRYPTED_DIGITS = (1..6).to_a def initialize(user_name) @user = User.new(user_name) @secret_code = SecretCode.new(generate_secret_code).value @status = nil end def add_hints_attempts(level) @level = level.to_sym @total_attempts = Game::GAME_DIFFICULTIES[@level][:attempts] @total_hints = Game::GAME_DIFFICULTIES[@level][:hints] @attempts = @total_attempts @hints = @total_hints end def take_hint raise I18n.t(:out_of_hints) if @hints.zero? @hints -= 1 @secret_code.digits.shuffle.pop end def guess(user_variant) return @status = Game::LOSS if @attempts.zero? answer = SecretCode.new(user_variant.to_i) @attempts -= 1 if answer.valid? if answer.value == @secret_code store_game return @status = Game::WIN end check_user_answer(answer.value) end private def generate_secret_code VALUES_FOR_ENCRYPTED_DIGITS.sample(NUMBER_OF_ENCRYPTED_DIGITS).join.to_i end def check_user_answer(answer) answer_array = answer.digits secret_code_array = @secret_code.digits pros = answer_array.zip(secret_code_array).count { |x, y| x == y } answer_array.each_index do |i| answer_array.delete_at(i) && secret_code_array.delete_at(i) if answer_array[i] == secret_code_array[i] end cons = secret_code_array.select { |x| answer_array.include?(x) }.count generate_response(pros, cons) end def generate_response(pros, cons) response = [] return response.join if pros.zero? && cons.zero? pros.times { response.push(Game::PLUS) } cons.times { response.push(Game::MINUS) } response.join end end end