class Timequiz

Main program class. All action is within the initialize() method, or, more precisely in the start_game() method which has to be defined by an interface-module.

Public Class Methods

called_as?(executable = nil) click to toggle source

Find out, how the program has been called. In juin 2017 this can be 'timequiz' or 'timequizGtk'. Write a Qt-interface, create a symbolic link 'timequizQt' in ../../bin and add a when-clause to the case-when structure, right below the method (in class-scope). Returns true if the given executable file is named the same as the one called, false if they are not the same. Returns the name of the called executable, if no argument is given.

# File lib/timequiz.rb, line 51
def self.called_as?(executable = nil)
  return File::basename($0) == executable.strip if executable
  return File::basename($0) 
end
new(*args) click to toggle source
# File lib/timequiz.rb, line 122
def initialize(*args)
  @log = @@log
  # adjust log-level, if given.
  # Else use what you know.
  options = ArgParser.parse(*args)
  $LOG_LEVEL = Logger::DEBUG if options.debug
  @log.level = $LOG_LEVEL if $LOG_LEVEL 
  @log.debug('log_level is ' << $LOG_LEVEL.to_s)
  @log.debug('options are ' << options.to_s)
  #    should we add only a new event to the list
  @log.debug('options are : ' << options.to_s)
  add_ok = game_ok = false
  if(options.file)
    @log.debug('shall use non-standard events file')
    add_ok, game_ok = verify_prepare(options.file)
  else
    game_ok = require_relative 'events'
  end
  if(options.add)
    if(add_ok)
      Adder::add(options)
      exit true
    elsif(options.file)
      @log.error('cannot add events to ' << options.file)
      exit false
    else
      @log.error('PSE start the program with -h or --help to see an option-overview')
      exit false
    end
  end

  # start the chosen interface
  if(game_ok)
    start_game 
  else
    @log.error("Cannot play with the events in " << options.file)
    @log.error("PSE verify that there are at least 3 events defined!") 
    exit false
  end
end

Public Instance Methods

verify_prepare(file) click to toggle source
# File lib/timequiz.rb, line 81
def verify_prepare(file)
  if(file && !file.empty? && !file.end_with?('.rb'))
     file << ".rb"
  end
  begin
    ofl = File.open(file, 'a')
    if !File.readable?(file)
      @log.error('The file ' << file << ' cannot be read! Aborting')
      exit false
    end
    if(File.empty?(file)  )
      @log.info("The file " << file << " is empty. You must add some events to it.")
      if(File.writable?(file) )
        orig_file = File.dirname(__FILE__) << File::Separator << 'events.rb'
        @log.debug('orig_file is ' << orig_file)
        File.open(orig_file, 'r') do |ifl|
          ofl.puts("# Events defined for the Timequiz game")
          ofl.puts("# Lines starting with '#' are comments.\n\n# EXAMPLES:")
          3.times do 
            line = ""
            line = ifl.readline.strip until line.start_with?('$')
            ofl.puts('#' << line)
          end
          ofl.puts("\n# Add your own events below this line\n#" << '_' * 60)
        end
        ofl.close
      end
      add_ok = require file 
    else
      add_ok = require file 
      if(add_ok)
        return add_ok, $events.length >= 3
      end
    end
  rescue IOError => ex
    ofl.close
    @log.error('Cannot work with the given file: ' << ex.message)
    exit false
  end
end

Private Instance Methods

good_order(response, event = nil) click to toggle source

Verifies and reports if the user-provided order is correct in the way that it creates a consistent timeline. The argument 'response' may be either an Array of Integers or just one Integer. In the latter case, an Event should be given, too.

# File lib/timequiz.rb, line 184
def good_order(response, event = nil)
  if(response.respond_to?(:to_ary) )
    response_years = []
    # response.each_with_index {|r, i| response_years[r-1] = @m_events[i].year}
    response.each_with_index {|r, i| response_years[i] = @m_events[r-1].year}
    @log.debug('response is ' << response.join(', ') << "\nresponse_years is : " << response_years.join(', ') )
    puts 'response is ' << response.join(', ') << "\nresponse_years is : " << response_years.join(', ') 

    # do not change the displayed index
    sort_years(false)
    event_years = @m_events.collect{|ev| ev.year }

    # Compare the order of years, not the order of events!
    # There may be two or more events in the same year.
    response_years == event_years
  elsif(response.respond_to?(:to_int) )
    # set/change the displayed index
    sort_years(true)
    # Compare the order of years, not the order of events!
    # There may be two or more events in the same year.
    @m_events[response + 1].year == event.year
  end
end
sort_years(index = false) click to toggle source

A dangerous method. Not only because the use of the argument is somewhat esotheric… This sorts the events in the correct order of their years. Any later comparison with user-provided values is based on the correct order, not the one currently at display! Although this is of interest only after the very first round, it caused me some headache, once the user-interfaces had been separated… Mind this when creating a new UI. The argument 'index' controlls if the displayed index should be changed to mirror the correct order of events, meaning the index from the Array + 1 (i.e. [1,2,3…]). I forgot, how this is useful (see in 'good_order', below).

# File lib/timequiz.rb, line 175
def sort_years(index = false)
  @m_events.sort! {|f, s| f.year <=> s.year } 
  @m_events.each_with_index {|ev, i| ev.disp_index = i+1} if index
end