Xzanth/pugbot

View on GitHub
lib/pugbot/game.rb

Summary

Maintainability
A
0 mins
Test Coverage
module PugBot
  # This class is an object of a game actually being played, it is created when
  # a queue becomes full, given its players and a link back to the queue it came
  # from and remains until it is ended and finished in the queue.
  class Game
    # @return [Array<Cinch::User>] The list of users playing in this game
    attr_reader :users

    # @return [Symbol] The status of the game, either ingame or finished
    attr_reader :status

    # @return [Cinch::Timer] The timer counting down to the game being deleted
    attr_reader :timer

    # A game that currently exists, with users playing in it. Should not be
    # called directly, should automatically be called by Queue.ready
    # @param [Queue] queue The queue that this game has taken its players from
    # @param [Array<Cinch::User>] users The users playing in this game
    # @see Queue.ready
    def initialize(queue, users)
      @queue = queue
      @users = users
      @status = :ingame
      @queue.queue_list.plugin.integrate(:game_start, self, @queue)
      @start_time = Time.now
    end

    # Ran when the game is manually finished, change the state of all users
    # who played and start a timer for them having to wait to join other
    # games.
    # @see BotPlugin.timer_game_end
    # @see #timeout
    # @return [void]
    def finish
      @timer = @queue.queue_list.plugin.timer_game_end(self)
      @users.each do |user|
        user.status = :finished
        user.track = false
      end
      @status = :finished
      @finish_time = Time.now
      game = Storage::Game.create(queue: @queue.name,
                                  started: @start_time,
                                  finished: @finish_time)
      @users.each do |user|
        Storage::Gameplay.create(host: user.host,
                                 user: user.account,
                                 game: game)
      end
    end

    # Called after the timer after finishing this game has ended, set all the
    # players back to standby and have all games check their waiting pools
    # to account for all the changed statuses also remove from the queue's
    # list of games essentially deleting the object.
    # @return [void]
    def timeout
      @users.each { |user| user.status = :standby }
      @queue.queue_list.queues.each(&:check_waiters)
      @queue.finish(self)
    end

    # Sub a currently playing user for another, changing their states and
    # any other necessary options
    # @param [Cinch::User] user The user currently playing to be replaced
    # @param [Cinch::User] sub The user to be added to the game
    # @return [void]
    def sub(user, sub)
      @users.delete(user)
      user.status = :standby
      user.track = false
      @users.push(sub)
      sub.status = :ingame
      sub.track = true
      @queue.queue_list.remove_from_queues(sub)
    end

    # List the current players of this game
    # @return [String] A list of all the users
    def to_s
      time = (Time.now - @start_time).to_i / 60
      if @status == :ingame
        "Current players: #{@users.join(' ')} - started #{time} minutes ago."
      else
        "Just finished: #{@users.join(' ')} - started #{time} minutes ago."
      end
    end

    def to_hash
      {
        "status": @status,
        "users": @users.map(&:name)
      }
    end

    def to_json(*a)
      to_hash.to_json(*a)
    end
  end
end