module Fbe::Award::BTerm

def abstract?

Returns:
  • (Boolean) - Always returns false for BTerm
def abstract?
  false
end

def bill_to(bill)

Raises:
  • (RuntimeError) - If there's a failure processing any term

Returns:
  • (nil) -

Parameters:
  • bill (Fbe::Award::Bill) -- The bill to update
def bill_to(bill)
  case @op
  when :award
    @operands.each do |o|
      o.bill_to(bill)
    rescue StandardError => e
      raise "Failure in #{o}: #{e.message}"
    end
  when :aka
    @operands[0..-2].each do |o|
      o.bill_to(bill)
    rescue StandardError => e
      raise "Failure in #{o}: #{e.message}"
    end
  when :let, :set
    v = to_val(@operands[1], bill)
    raise "Can't #{@op.inspect} #{@operands[0].inspect} to nil" if v.nil?
    bill.set(@operands[0], v)
  when :give
    text = @operands[1]
    text = '' if text.nil?
    bill.line(to_val(@operands[0], bill), text)
  when :explain, :in
    # nothing, just ignore
  else
    raise "Unknown term '#{@op}'"
  end
end

def calc(bill)

Raises:
  • (RuntimeError) - If the term operation is unknown

Returns:
  • (Object) - The calculated value (number, boolean, etc.)

Parameters:
  • bill (Fbe::Award::Bill) -- The bill providing context for calculation
def calc(bill)
  case @op
  when :total
    bill.points
  when :if
    to_val(@operands[0], bill) ? to_val(@operands[1], bill) : to_val(@operands[2], bill)
  when :and
    @operands.all? { |o| to_val(o, bill) }
  when :or
    @operands.any? { |o| to_val(o, bill) }
  when :not
    !to_val(@operands[0], bill)
  when :eq
    to_val(@operands[0], bill) == to_val(@operands[1], bill)
  when :lt
    to_val(@operands[0], bill) < to_val(@operands[1], bill)
  when :lte
    to_val(@operands[0], bill) <= to_val(@operands[1], bill)
  when :gt
    to_val(@operands[0], bill) > to_val(@operands[1], bill)
  when :gte
    to_val(@operands[0], bill) >= to_val(@operands[1], bill)
  when :div
    to_val(@operands[0], bill) / to_val(@operands[1], bill)
  when :times
    to_val(@operands[0], bill) * to_val(@operands[1], bill)
  when :plus
    to_val(@operands[0], bill) + to_val(@operands[1], bill)
  when :minus
    to_val(@operands[0], bill) - to_val(@operands[1], bill)
  when :max
    [to_val(@operands[0], bill), to_val(@operands[1], bill)].max
  when :min
    [to_val(@operands[0], bill), to_val(@operands[1], bill)].min
  when :between
    v = to_val(@operands[0], bill)
    a = to_val(@operands[1], bill)
    b = to_val(@operands[2], bill)
    min, max = [a, b].minmax
    return 0 if (!v.negative? && v < min) || (!v.positive? && v > max)
    v.clamp(min, max)
  else
    raise "Unknown term '#{@op}'"
  end
end

def static?

Returns:
  • (Boolean) - Always returns true for BTerm
def static?
  true
end

def to_s

Returns:
  • (String) - The term as a string in S-expression format
def to_s
  "(#{@op} #{@operands.join(' ')})"
end

def to_val(any, bill)

Raises:
  • (RuntimeError) - If a symbol isn't found in the bill

Returns:
  • (Object) - The evaluated value

Parameters:
  • bill (Fbe::Award::Bill) -- The bill providing context for evaluation
  • any (Object) -- The value to evaluate (symbol, term, or literal)
def to_val(any, bill)
  if any.is_a?(BTerm)
    any.calc(bill)
  elsif any.is_a?(Symbol)
    v = bill.vars[any]
    raise "Unknown name #{any.inspect} among: #{bill.vars.keys.map(&:inspect).join(', ')}" if v.nil?
    v
  else
    any
  end
end