class MatchyMatchy::Matchbook

Small class to maintain a cache of candidates and targets, for use by the MatchMaker. Ensures the following conditions:

Public Class Methods

new() click to toggle source

Initializes the Matchbook with an empty cache.

# File lib/matchy_matchy/matchbook.rb, line 12
def initialize
  @targets = {}
  @candidates = {}
end

Public Instance Methods

build_candidates(candidates) click to toggle source

Builds a list of candidates for the MatchMaker. The parameter is a hash of unwrapped canditate objects to their preferred targets.

@example

matchbook.build_candidates(
  'Harry'    => ['Gryffindor', 'Slytherin'],
  'Hermione' => ['Ravenclaw', 'Gryffindor'],
  'Ron'      => ['Gryffindor'],
  'Neville'  => ['Hufflepuff', 'Gryffindor', 'Ravenclaw', 'Slytherin']
)

@param candidates [Hash<Object, Array<Object>>]

Hash of candidate objects to a list of their preferred targets
# File lib/matchy_matchy/matchbook.rb, line 65
def build_candidates(candidates)
  candidates.to_a.map do |object, preferences|
    candidate(object).tap do |c|
      c.prefer(*preferences.map { |t| target(t) })
    end
  end
end
build_targets(targets) click to toggle source

Builds a list of targets for the MatchMaker. The parameter is a hash of unwrapped target objects to their preferred candidates and maximum capacity (a 2-tuple expressed as an array):

@example With explicit capacities

matchbook.build_targets(
  'Gryffindor' => [['Hermione', 'Ron', 'Harry'], 2],
  'Ravenclaw'  => [['Hermione'], 1],
  'Hufflepuff' => [['Neville', 'Hermione'], 2],
  'Slytherin'  => [['Harry', 'Hermione', 'Ron', 'Neville'], 4]
)

The capacity may also be omitted, in which case it defaults to 1:

@example With explicit capacities

matchbook.build_targets(
  'Gryffindor' => ['Hermione', 'Ron', 'Harry'],
  'Ravenclaw'  => ['Hermione'],
  'Hufflepuff' => ['Neville', 'Hermione'],
  'Slytherin'  => ['Harry', 'Hermione', 'Ron', 'Neville'],
)

@param targets [Hash<Object, Array<Object>>]

Hash of target objects to a list of their preferred candidates
# File lib/matchy_matchy/matchbook.rb, line 41
def build_targets(targets)
  targets.to_a.map do |object, row|
    preferences, capacity = parse_target_row(row)
    target(object).tap do |t|
      t.capacity = capacity
      t.prefer(*preferences.map { |c| candidate(c) })
    end
  end
end

Private Instance Methods

candidate(object) click to toggle source
# File lib/matchy_matchy/matchbook.rb, line 80
def candidate(object)
  return object if object.is_a?(Candidate)
  @candidates[object] ||= Candidate.new(object)
end
parse_target_row(row) click to toggle source
# File lib/matchy_matchy/matchbook.rb, line 85
def parse_target_row(row)
  return row if row.size == 2 &&
      row.first.respond_to?(:map) &&
      row.last.respond_to?(:zero?)
  [row, 1]
end
target(object) click to toggle source
# File lib/matchy_matchy/matchbook.rb, line 75
def target(object)
  return object if object.is_a?(Target)
  @targets[object] ||= Target.new(object)
end