Class: Dicey::DistributionCalculators::BaseCalculator Abstract

Inherits:
Object
  • Object
show all
Includes:
Mixins::VectorizeDice
Defined in:
lib/dicey/distribution_calculators/base_calculator.rb

Overview

This class is abstract.

Base class for implementing distribution calculators.

Calculators have the following methods, each taking an array of dice:

By default, #call returns weights as they are easier to calculate and can be represented with integers (except for Empirical calculator). If probabilities are requested, they are calculated using Rational numbers to produce exact results.

An empty list of dice is considered a degenerate case, always valid for any calculator.

Options:

Calculators may have calculator-specific options, passed as extra keyword arguments to #call. If present, they will be documented under Options heading on the class itself.

Constant Summary collapse

RESULT_TYPES =

Possible values for result_type argument in #call.

%i[weights probabilities].freeze

Instance Method Summary collapse

Instance Method Details

#call(dice, result_type: :weights, **options) ⇒ Hash{Any => Numeric}

Note:

Calculation is supposed to return exact results. Using dice with Float values can break this promise and raise errors. Please use Integer, Rational or BigDecimal instead.

Calculate distribution (probability mass function) for the list of dice.

Returns empty hash for an empty list of dice.

Parameters:

  • dice (Enumerable<AbstractDie>)
  • result_type (Symbol) (defaults to: :weights) —
  • options (Hash{Symbol => Any}) —

    calculator-specific options, refer to the calculator's documentation to see what it accepts

Returns:

  • (Hash{Any => Numeric}) —

    weight or probability for each outcome, sorted by outcome if possible

Raises:

  • (DiceyError) —

    if result_type is invalid

  • (DiceyError) —

    if dice list is invalid for the calculator

  • (DiceyError) —

    if calculator returned obviously wrong results (should not happen in released versions)



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/dicey/distribution_calculators/base_calculator.rb', line 54

def call(dice, result_type: :weights, **options)
  unless RESULT_TYPES.include?(result_type)
    raise DiceyError, "#{result_type} is not a valid result type!"
  end
  raise DiceyError, "dice must be an Enumerable!" unless Enumerable === dice
  # Short-circuit for a degenerate case.
  return {} if dice.empty?

  static_dice, normal_dice = dice.partition { StaticDie === _1 }
  raise DiceyError, "#{self.class} can not handle these dice!" unless valid_for?(normal_dice)

  distribution = prepare_distribution(normal_dice, static_dice, options)
  verify_result(distribution, dice)
  transform_result(distribution, result_type)
end

#heuristic_complexity(dice) ⇒ Integer

Heuristic complexity of the calculator, used to determine best calculator.

Will always return a value, even if the calculator is not valid for the dice.

Parameters:

Returns:

  • (Integer) —

    0 if dice is empty, otherwise can be any value

See Also:



93
94
95
96
97
# File 'lib/dicey/distribution_calculators/base_calculator.rb', line 93

def heuristic_complexity(dice)
  return 0 if dice.empty?

  calculate_heuristic(dice.grep_v(StaticDie).length, dice.map(&:sides_num).max).to_i
end

#valid_for?(dice) ⇒ Boolean

Whether this calculator can be used for the list of dice.

StaticDie instances are always ignored.

Parameters:

Returns:

  • (Boolean)


76
77
78
79
80
81
82
83
# File 'lib/dicey/distribution_calculators/base_calculator.rb', line 76

def valid_for?(dice)
  return false if !(Enumerable === dice) || !dice.all?(AbstractDie)

  normal_dice = dice.grep_v(StaticDie)
  return true if normal_dice.none?

  validate(normal_dice)
end