class RomLoader::RomLoaderCli

The CLI class

Public Class Methods

new() click to toggle source
# File lib/romloader/romloader_cli.rb, line 4
def initialize
  RomLoader::GameSystem.create_from_collection(RomLoader::FreeromsScraper.system_scrape("https://freeroms.com"))
  raise RomLoader::ScrapingError::NoElementFound.exception("ERROR: Systems index is currently unavailable. Exiting the program.") if RomLoader::GameSystem.all.size == 0
end

Public Instance Methods

display_rom_details(game) click to toggle source

List the details of the selected game (e.g. Chrono Trigger | SNES | 5.38 MB | .zip)

# File lib/romloader/romloader_cli.rb, line 159
def display_rom_details(game)
  puts "Rom details:"
  puts "#{game.name} | System: #{game.system.name} | File size: #{game.size} | File type: #{game.file_ext}"
  print "\n"
end
download_rom(game) click to toggle source

Downloads the selected game to the local directory (~/videogame_roms)

# File lib/romloader/romloader_cli.rb, line 192
def download_rom(game)
  file_or_dir_to_open = nil
  extract_dir = RomLoader::ArchiveExtractor.create_extract_dir(game)
  if !File.exist?(File.join(extract_dir,game.filename))
    puts "Downloading #{game.name} (#{game.size})..."
    if isWindows?
      result = Dir.chdir(extract_dir) { system("powershell -command \"& { Invoke-WebRequest '#{game.download_url}' -OutFile '#{game.filename}' }\"") }
    else
      result = Dir.chdir(extract_dir) { system("curl -Og# \"#{game.download_url}\"") }
    end

    if result && !isWindows? && game.system.name != "MAME"
      puts "Finished downloading #{game.filename} to #{extract_dir}. Extracting..."
      file_or_dir_to_open = RomLoader::ArchiveExtractor.extract(File.join(extract_dir,game.filename),extract_dir,game)
      RomLoader::ArchiveExtractor.delete_archive(File.join(extract_dir,game.filename))
    elsif result && !isWindows? && game.system.name == "MAME"
      puts "Finished downloading #{game.filename} to #{extract_dir}."
      puts "NOTE: No archive extraction. MAME roms must remain zipped to play."
      file_or_dir_to_open = extract_dir
    elsif result && isWindows?
      puts "Finished downloading #{game.filename} to #{extract_dir}."
      file_or_dir_to_open = extract_dir
    else
      puts "An error occured, the rom couldn't be downloaded.\n\n"
    end
  else
    puts "File already exists.\n\n"
  end

  sleep 2
  file_or_dir_to_open
end
flow_controller(input,control_flow_level,input_stack) click to toggle source

Sets control_flow_level in RomLoaderCli#start, manipulates input_stack in RomLoaderCli#start

# File lib/romloader/romloader_cli.rb, line 100
def flow_controller(input,control_flow_level,input_stack)
  if input == "exit"
    0
  elsif input == "back"
    input_stack.shift
    control_flow_level - 1
  else
    input_stack.unshift(input)
    control_flow_level + 1
  end
end
input_prompt(message,accepted_input,control_flow_level=nil) click to toggle source

Prints a custom message, takes user input, asesses whether the input is valid, and returns the input

# File lib/romloader/romloader_cli.rb, line 166
def input_prompt(message,accepted_input,control_flow_level=nil)
  valid = false
  until valid 
    print message + " "
    input = gets.chomp.strip.downcase
    if accepted_input.class == Regexp && accepted_input.match(input)
      valid = true
    elsif accepted_input.class == Range && /\A\d+\Z/.match(input) && accepted_input.include?(input.to_i)
      valid = true
    elsif input == "exit" || (input == "back" &&  control_flow_level && control_flow_level.between?(2,3))
      valid = true
    elsif input == "" && control_flow_level == 4
      valid = true
    else
      print "Invalid input! "
    end
  end
  print "\n"
  input
end
isWindows?() click to toggle source
# File lib/romloader/romloader_cli.rb, line 187
def isWindows?
  /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
end
list_games(games) click to toggle source

List all the games available for the selected index (e.g. “S”: 1. Super Castlevania, 2. Super Mario World, etc…)

# File lib/romloader/romloader_cli.rb, line 146
def list_games(games)
  games.each_with_index {|game,index| puts "#{index+1}. #{game.name}"}
  print "\n"
end
list_system_index(selected_system) click to toggle source

List game index for the selected system by letter (e.g. A B C D…)

# File lib/romloader/romloader_cli.rb, line 126
def list_system_index(selected_system)
  if selected_system.get_rom_indices.empty?
    selected_system.rom_indices = RomLoader::FreeromsScraper.rom_index_scrape(selected_system.rom_index_url)
  end
  
  puts "#{selected_system.name} index:"
  selected_system.get_rom_indices.each {|letter| print letter + " "}
  puts "\n\n"
end
list_systems() click to toggle source

Lists the game systems scraped from freeroms.com and saved in Romloader::GameSystem.all (e.g. 1. Amiga, 2. Atari, etc…)

# File lib/romloader/romloader_cli.rb, line 114
def list_systems 
  RomLoader::GameSystem.all.each_with_index { |game_system, index| puts "#{index+1}. #{game_system.name}"}
  print "\n"
end
select_game(game_collection,index) click to toggle source

Selects an individual game from the provided collection via index

# File lib/romloader/romloader_cli.rb, line 152
def select_game(game_collection,index)
  game_collection[index-1].set_rom_details(RomLoader::FreeromsScraper.rom_details(game_collection[index-1].rom_detail_url))
  game_collection[index-1]
end
select_game_collection_by_index(system, letter) click to toggle source

Retrieves all the games available for the selected system under the selected index (e.g. NES,“G”)

# File lib/romloader/romloader_cli.rb, line 138
def select_game_collection_by_index(system, letter)
  puts "Loading roms...\n"
  games_list = system.get_roms_by_letter(letter)
  games_list ||= system.add_roms_to_collection_by_letter(letter,RomLoader::GameRom.create_collection(RomLoader::FreeromsScraper.rom_scrape(system.get_rom_collection_url(letter))))
end
select_system(index) click to toggle source

Retrieves an individual Romloader::GameSystem object from Romloader::GameSystem.all

# File lib/romloader/romloader_cli.rb, line 120
def select_system(index)
  RomLoader::GameSystem.all[index-1]
end
start() click to toggle source

Starts the CLI, called in romloader.rb

# File lib/romloader/romloader_cli.rb, line 10
def start
  input_stack = []
  control_flow_level = 1

  puts "\nThanks for using RomLoader, powered by freeroms.com!\nNOTE: To play the games, please download an emulator for the desired system.\nConnecting to freeroms.com and retrieving the systems index...\n\n"
  sleep 3
  while control_flow_level > 0 
    case control_flow_level
    when 1
      list_systems
      input = input_prompt("Select a system (1-#{RomLoader::GameSystem.all.size}) [exit]:",1..RomLoader::GameSystem.all.size)
      if input == "exit"
        control_flow_level = 0
      else
        input_stack.unshift(input)
        control_flow_level += 1
      end
    when 2
      system = select_system(input_stack[0].to_i)
      list_system_index(system)
      if system.get_rom_indices.empty?
        begin
          raise RomLoader::ScrapingError::NoElementFound.exception("ERROR: Requested system is currently unavailable. Try another one.")
        rescue => e
          puts "#{e.message}\n\n"
          sleep 2
          control_flow_level -= 1
          input_stack.shift
        end 
      else
        input = input_prompt("Select a letter [back|exit]:", /\A[#{system.get_rom_indices.join.downcase}]{1}\Z/,control_flow_level)
        control_flow_level = flow_controller(input,control_flow_level,input_stack)
      end
    when 3
      game_collection = select_game_collection_by_index(system,input_stack[0].upcase)
      if game_collection.empty?
        begin
          raise RomLoader::ScrapingError::NoElementFound.exception("ERROR: Requested game index is currently unavailable. Try another one.")
        rescue => e
          puts "#{e.message}\n\n"
          sleep 2
          control_flow_level -= 1
          input_stack.shift
        end
      else
        list_games(game_collection)
        input = input_prompt("Select a game (1-#{game_collection.size}) [back|exit]", 1..game_collection.size,control_flow_level)
        control_flow_level = flow_controller(input,control_flow_level,input_stack)
      end
    when 4
      game = select_game(game_collection,input_stack[0].to_i)
      if game.download_url == nil
        begin
          raise RomLoader::ScrapingError::NoElementFound.exception("ERROR: Requested game is currently unavailable. Try another one.")
        rescue => e
          puts "#{e.message}\n\n"
          sleep 2
          control_flow_level -= 1
          input_stack.shift
        end
      else
        display_rom_details(game)
        input = input_prompt("Download? (Y/n) [exit]:", /\A[yn]{1}\Z/, control_flow_level)
        if input == 'y' || input == ""
          file_or_dir_to_open = download_rom(game)
          if file_or_dir_to_open
            if /\".+\"/.match(file_or_dir_to_open)
              game_file = /\".+\"/.match(file_or_dir_to_open)[0]
              input = input_prompt("Play #{game_file}? (y/N) [exit]:", /\A[yn]{1}\Z/,control_flow_level)
            else
              input = input_prompt("Open #{file_or_dir_to_open}? (y/N) [exit]:", /\A[yn]{1}\Z/,control_flow_level)
            end
            
            if !isWindows?
              system("open #{file_or_dir_to_open}") if input == 'y'
            else
              system("powershell -command \"& { Invoke-Item '#{file_or_dir_to_open}' }\"") if input == 'y'
            end
          end 
        end
        input_stack.shift
        input == "exit" ? control_flow_level = 0 : control_flow_level -= 1
      end
    end
  end

  puts "Happy Gaming!\n\n"
end