class CodeBreaker extend CodebreakerApi include Validation attr_reader :attempts, :name, :difficulty, :hints LEVEL = { easy: { attempts: 15, hints: 2, difficulty: :easy }, middle: { attempts: 10, hints: 1, difficulty: :middle }, hell: { attempts: 5, hints: 1, difficulty: :hell } }.freeze def self.stats CodeBreaker.load || [] end def initialize(name, chose_level) @codemaker = CodeMaker.new @attempts = LEVEL.dig(chose_level, :attempts) @hints = LEVEL.dig(chose_level, :hints) @difficulty = LEVEL.dig(chose_level, :difficulty) @name = registration(name) @hint_cache = [] end def registration(name) raise CustomErrors::NameInvalidError unless validate_name(name) @name = name.capitalize end def check_code(code) @codemaker.verify(code) dicrement_attemts unless win? save_stats if game_end? result_code end def result_code @codemaker.verified_code end def hint return unless hint? res = @hint_cache.each_with_object(@codemaker.code) do |index, object| object.delete_at(index) end index = rand(0..3) @hint_cache << index @hints -= 1 res[index] end def hint? @hints.positive? end def win? @codemaker.check? && attempts >= 0 end def game_end? lose? || win? end def lose? !win? && attempts.zero? end private def dicrement_attemts @attempts -= 1 end def save_stats CodeBreaker.save(CodeBreaker.stats.push( name: @name, attempts_total: LEVEL[@difficulty][:attempts], hints_total: LEVEL[@difficulty][:hints], attempts_used: LEVEL[@difficulty][:attempts] - attempts, hints_used: LEVEL[@difficulty][:hints] - @hints, difficulty: @difficulty )) end def validate_name(name) name.is_a?(String) && validate_max_length(name, 20) && validate_min_length(name, 4) end end