module Codebreaker module Entities class Menu include Helpers::Validator attr_reader :storage, :viewer, :game, :guess COMMANDS_LIST = { start: 'start', exit: 'exit', rules: 'rules', stats: 'stats' }.freeze CONFIRM_COMMAND = { yes: 'yes' }.freeze HINT_COMMAND = 'hint'.freeze MIN_SIZE = 3 MAX_SIZE = 25 def initialize @storage = Storage.new @viewer = Viewer.new @game = Game.new @statistics = Statistics.new end def game_menu viewer.start_message choice_menu_process(ask(:choice_options, commands: COMMANDS_LIST.keys.join(' | '))) end def rules viewer.rules game_menu end def start @name = user_registration level_choice game_process end def stats scores = storage.load render_stats(@statistics.stats(scores)) if scores game_menu end def ask(phrase_key = nil, options = {}) viewer.message(phrase_key, options) if phrase_key gets.chomp end def save_result storage.save_game_results(game.to_h(@name)) if ask(:save_results_message) == CONFIRM_COMMAND[:yes] end def name_valid?(name) !empty_check?(name) && size_check(name, MIN_SIZE, MAX_SIZE) end def level_choice loop do level = ask(:difficulty_level, levels: Game::DIFFICULTIES.keys.join(' | ')) return generate_game(Game::DIFFICULTIES[level.to_sym]) if Game::DIFFICULTIES[level.to_sym] return game_menu if level == COMMANDS_LIST[:exit] viewer.command_error end end def generate_game(difficulty) game.init_game(difficulty) viewer.message(:difficulty, hints: difficulty[:hints], attempts: difficulty[:attempts]) end def game_process while game.attempts.positive? @guess = ask return handle_win if game.check_win?(guess) choice_code_process end handle_lose end def choice_code_process case guess when HINT_COMMAND then hint_process when COMMANDS_LIST[:exit] then game_menu else handle_command end end def handle_command return viewer.command_error unless format_check?(guess) p game.start(guess) viewer.round_message game.attempt_wasted end def handle_win viewer.win_game_message save_result game_menu end def handle_lose viewer.lost_game_message(game.code) game_menu end def hint_process return viewer.no_hints_message if game.hints_not_remain? viewer.print_hint(game.hint_take) end def exit_from_game viewer.goodbye_message exit end def choice_menu_process(command) case command when COMMANDS_LIST[:start] then start when COMMANDS_LIST[:exit] then exit_from_game when COMMANDS_LIST[:rules] then rules when COMMANDS_LIST[:stats] then stats else viewer.command_error game_menu end end def user_registration loop do name = ask(:registration) return name if name_valid?(name) viewer.registration_name_length_error end end def render_stats(list) list.each_with_index do |key, index| puts "#{index + 1}: " key.each { |param, value| puts "#{param}:#{value}" } end end end end end