dicey 0.16.2 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -37
  3. data/exe/dicey +2 -2
  4. data/lib/dicey/abstract_die.rb +24 -5
  5. data/lib/dicey/cli/blender.rb +19 -14
  6. data/lib/dicey/{sum_frequency_calculators/runner.rb → cli/calculator_runner.rb} +9 -15
  7. data/lib/dicey/{sum_frequency_calculators/test_runner.rb → cli/calculator_test_runner.rb} +37 -13
  8. data/lib/dicey/cli/formatters/base_list_formatter.rb +36 -0
  9. data/lib/dicey/cli/formatters/base_map_formatter.rb +38 -0
  10. data/lib/dicey/cli/formatters/gnuplot_formatter.rb +28 -0
  11. data/lib/dicey/cli/formatters/json_formatter.rb +14 -0
  12. data/lib/dicey/cli/formatters/list_formatter.rb +14 -0
  13. data/lib/dicey/cli/formatters/null_formatter.rb +17 -0
  14. data/lib/dicey/cli/formatters/yaml_formatter.rb +14 -0
  15. data/lib/dicey/cli/options.rb +15 -11
  16. data/lib/dicey/cli/roller.rb +47 -0
  17. data/lib/dicey/cli.rb +23 -0
  18. data/lib/dicey/die_foundry.rb +6 -5
  19. data/lib/dicey/distribution_calculators/auto_selector.rb +73 -0
  20. data/lib/dicey/{sum_frequency_calculators → distribution_calculators}/base_calculator.rb +44 -37
  21. data/lib/dicey/distribution_calculators/binomial.rb +62 -0
  22. data/lib/dicey/{sum_frequency_calculators → distribution_calculators}/empirical.rb +9 -10
  23. data/lib/dicey/distribution_calculators/iterative.rb +51 -0
  24. data/lib/dicey/{sum_frequency_calculators → distribution_calculators}/multinomial_coefficients.rb +21 -12
  25. data/lib/dicey/{sum_frequency_calculators/kronecker_substitution.rb → distribution_calculators/polynomial_convolution.rb} +15 -8
  26. data/lib/dicey/distribution_calculators/trivial.rb +56 -0
  27. data/lib/dicey/distribution_properties_calculator.rb +5 -2
  28. data/lib/dicey/mixins/missing_math.rb +44 -0
  29. data/lib/dicey/mixins/rational_to_integer.rb +1 -0
  30. data/lib/dicey/mixins/vectorize_dice.rb +17 -12
  31. data/lib/dicey/mixins/warn_about_vector_number.rb +19 -0
  32. data/lib/dicey/numeric_die.rb +1 -1
  33. data/lib/dicey/version.rb +1 -1
  34. data/lib/dicey.rb +26 -5
  35. metadata +30 -26
  36. data/lib/dicey/output_formatters/gnuplot_formatter.rb +0 -24
  37. data/lib/dicey/output_formatters/hash_formatter.rb +0 -36
  38. data/lib/dicey/output_formatters/json_formatter.rb +0 -12
  39. data/lib/dicey/output_formatters/key_value_formatter.rb +0 -34
  40. data/lib/dicey/output_formatters/list_formatter.rb +0 -12
  41. data/lib/dicey/output_formatters/null_formatter.rb +0 -15
  42. data/lib/dicey/output_formatters/yaml_formatter.rb +0 -12
  43. data/lib/dicey/roller.rb +0 -46
  44. data/lib/dicey/sum_frequency_calculators/auto_selector.rb +0 -41
  45. data/lib/dicey/sum_frequency_calculators/brute_force.rb +0 -41
data/lib/dicey/roller.rb DELETED
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "die_foundry"
4
-
5
- require_relative "mixins/rational_to_integer"
6
- require_relative "mixins/vectorize_dice"
7
-
8
- module Dicey
9
- # Let the dice roll!
10
- #
11
- # This is the implementation of roll mode for the CLI.
12
- class Roller
13
- include Mixins::RationalToInteger
14
- include Mixins::VectorizeDice
15
-
16
- # @param arguments [Array<String>] die definitions
17
- # @param format [#call] formatter for output
18
- # @return [nil]
19
- # @raise [DiceyError]
20
- def call(arguments, format:, **)
21
- raise DiceyError, "no dice!" if arguments.empty?
22
-
23
- dice = arguments.flat_map { |definition| die_foundry.cast(definition) }
24
- result = roll_dice(dice)
25
-
26
- format.call({ "roll" => rational_to_integer(result) }, AbstractDie.describe(dice))
27
- rescue TypeError
28
- warn <<~TEXT
29
- Dice with non-numeric sides need gem "vector_number" to be present and available.
30
- If this is intended, please install the gem.
31
- TEXT
32
- raise DiceyError, "can not roll dice with non-numeric sides!"
33
- end
34
-
35
- private
36
-
37
- def die_foundry
38
- @die_foundry ||= DieFoundry.new
39
- end
40
-
41
- def roll_dice(dice)
42
- dice = vectorize_dice(dice) if defined?(VectorNumber)
43
- dice.sum(&:roll)
44
- end
45
- end
46
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "brute_force"
4
- require_relative "kronecker_substitution"
5
- require_relative "multinomial_coefficients"
6
-
7
- module Dicey
8
- module SumFrequencyCalculators
9
- # Tool to automatically select a calculator for a given set of dice.
10
- #
11
- # Calculator is guaranteed to be compatible, with a strong chance of being the most performant.
12
- #
13
- # @see BaseCalculator#heuristic_complexity
14
- class AutoSelector
15
- # Calculators to consider when selecting a match.
16
- AVAILABLE_CALCULATORS = [
17
- KroneckerSubstitution.new,
18
- MultinomialCoefficients.new,
19
- BruteForce.new,
20
- ].freeze
21
-
22
- # @param calculators [Array<BaseCalculator>]
23
- # calculators which this instance will consider
24
- def initialize(calculators = AVAILABLE_CALCULATORS)
25
- @calculators = calculators
26
- end
27
-
28
- # Determine best (or adequate) calculator for a given set of dice
29
- # based on heuristics from the list of available calculators.
30
- #
31
- # @param dice [Enumerable<NumericDie>]
32
- # @return [BaseCalculator, nil] +nil+ if no calculator is compatible
33
- def call(dice)
34
- compatible = @calculators.select { _1.valid_for?(dice) }
35
- return if compatible.empty?
36
-
37
- compatible.min_by { _1.heuristic_complexity(dice) }
38
- end
39
- end
40
- end
41
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "base_calculator"
4
-
5
- require_relative "../mixins/vectorize_dice"
6
-
7
- module Dicey
8
- module SumFrequencyCalculators
9
- # Calculator for a collection of {AbstractDie} using exhaustive search (very slow).
10
- #
11
- # If dice include non-numeric sides, gem +vector_number+ has to be installed.
12
- class BruteForce < BaseCalculator
13
- include Mixins::VectorizeDice
14
-
15
- private
16
-
17
- def validate(dice)
18
- if defined?(VectorNumber) || dice.all?(NumericDie)
19
- true
20
- else
21
- warn <<~TEXT
22
- Dice with non-numeric sides need gem "vector_number" to be present and available.
23
- If this is intended, please install the gem.
24
- TEXT
25
- false
26
- end
27
- end
28
-
29
- def calculate_heuristic(dice_count, sides_count)
30
- 1000 * (sides_count**dice_count)
31
- end
32
-
33
- def calculate(dice, **nil)
34
- dice = vectorize_dice(dice) if defined?(VectorNumber)
35
- dice.map(&:sides_list).reduce { |result, die|
36
- result.flat_map { |roll| die.map { |side| roll + side } }
37
- }.tally
38
- end
39
- end
40
- end
41
- end