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