# frozen_string_literal: true module Codebreaker class Game < BaseClass attr_reader :secret_code, :total_attempts, :used_attempts, :total_hints, :used_hints, :stats, :level def initialize super() @secret_code = generate_code @stat = Statistic.new end def decrease_attempts return secret_code && 'lose' if @used_attempts.zero? @used_attempts -= 1 end def save_stats hash = { user_name: @player_name, difficulty: level, attempts_total: total_attempts, attempts_used: used_attempts, hints_total: total_hints, hints_used: used_hints } @stat.collect_statistic(hash) end def load_stats @stat.show_statistic end def create_settings(name, level) player_name(name) create_level(level) show_errors unless valid? end def player_name(name) user = User.new(name) return @player_name = user.name if user.valid? errors << user.errors end def accept_level(level) current_level = Constants::LEVELS[level.to_sym] handle_errors('entered level is not present') unless current_level current_level end def create_level(level) choice_level = accept_level(level) return if choice_level.nil? add_level(choice_level) end def difficulties Constants::LEVELS.keys end def add_level(choice_level) @level = level @used_hints = choice_level[:hints] @total_hints = choice_level[:hints] @total_attempts = choice_level[:attempts] @used_attempts = choice_level[:attempts] end def check_guess(numbers) return show_errors unless guess_valid?(numbers) array_choose_numbers = numbers.to_s.each_char.map(&:to_i) return win if secret_code == array_choose_numbers decrease_attempts codebreaker_result(array_choose_numbers) end def use_hint return 'Hints are over' if @used_hints.zero? @used_hints -= 1 secret_code.sample end def win "#{Constants::PLUS * Constants::WIN_NUMBER}(win)" end private def generate_code Array.new(Constants::NUMBER_OF_DIGITS) { rand Constants::RANGE } end def codebreaker_result(array_choose_numbers) full_match = [] array_choose_numbers.each_with_index do |code, index| next unless code == secret_code[index] full_match << code array_choose_numbers[index] = nil end partial_match = array_choose_numbers.compact.uniq.select { |number| secret_code.include? number } partial_match = partial_match.reject { |number| full_match.include? number } create_result(full_match, partial_match) end def create_result(full_match, partial_match) result = full_match.map { Constants::PLUS } + partial_match.map { Constants::MINUS } result.join end end end