lib/dry/effects/providers/random.rb in dry-effects-0.1.2 vs lib/dry/effects/providers/random.rb in dry-effects-0.1.3

- old
+ new

@@ -4,10 +4,81 @@ module Dry module Effects module Providers class Random < Provider[:random] - public :rand + DEFAULT = -> _ { ::Random::DEFAULT.rand } + + DEFAULT_RANGE = 0.0...1.0 + + def rand(range_or_limit = nil) + range_or_limit ||= DEFAULT_RANGE + + if range_or_limit.is_a?(::Range) + low = range_or_limit.begin + high = range_or_limit.end + exclude_end = range_or_limit.exclude_end? + elsif range_or_limit >= 1 + low = 0 + high = range_or_limit.floor + exclude_end = true + else + low = 0.0 + high = range_or_limit.to_f + exclude_end = true + end + + if low.is_a?(::Integer) + next_integer(low, high, exclude_end) + else + next_float(low, high) + end + end + + def call(options = Undefined) + @prev = nil + @generator = build_generator(options) + yield + end + + def next_integer(low, high, exclude_end) + @prev = @generator.(@prev) % 1 + + value = low + (@prev * (high - low)).round + + if value.eql?(high) && exclude_end + low + else + value + end + end + + def next_float(low, high) + @prev = @generator.(@prev) % 1 + + low + (@prev * (high - low)) + end + + def build_generator(options) + case options + when Undefined + DEFAULT + when ::Hash + if options.key?(:seed) + random = ::Random.new(options[:seed]) + else + random = ::Random::DEFAULT + end + + -> _ { random.rand } + else + generator = options + + lambda do |prev| + prev.nil? ? generator.() : generator.(prev) + end + end + end end end end end