#encoding:utf-8
#==============================================================================
# ■ Kernel 扩展 By_QQEat
#
# 说明:rand 方法扩展
#
#
# rand(a..b) # 返回一个 a~b 的随机数
# rand(a...b) # 返回一个 a~b 的随机数(不包括b本身)
#
# rand(7..9, 10, 3.5, -50..30, 3.0..5.0)
# # 非 Range 参数自动转换为 value..value
# # 整数权重为1000, 比如rand(1..3, 1.5..1.6), 有 3000/3100 的概率随机到1~3, 100/3100 的概率随机到1.5~1.6
#
# 以上参数 Range 范围对象均支持小数、且数字大小不分前后, 例:1..8、10.0..-1 都是可以的。
#
# rand_average(array, max=nil) # 权重随机(权重数组, 权重上限(不填默认为权重总值为上限))
# # rand_average([5, 30, 4]) # 5/39 的概率返回0, 30/39 的概率返回1, 4/39 的概率返回2
# # rand_average([5, 30, 4], 100) # 5/100 的概率返回0, 30/100 的概率返回1, 4/100 的概率返回2
#
#==============================================================================
module Kernel
#--------------------------------------------------------------------------
# ● 随机数方法
#--------------------------------------------------------------------------
alias :qqeat_rand :rand
def rand(*args)
accuracy = 1000 # 小数精度
case args.length
when 0
return qqeat_rand(*args)
when 1
v = args[0]
if v.is_a?(Range)
a, b = v.first, v.last
a, b = b, a if a > b
if f = a.is_a?(Float) || b.is_a?(Float) # 小数
a, b = a*accuracy, b*accuracy
end
return (a+qqeat_rand(b-a+(v.exclude_end? ? 0 : 1))) / (f ? accuracy.to_f : 1)
else
return qqeat_rand(*args)
end
else
# 参数处理
args.map! do |v|
if v.is_a?(Range)
a, b = v.first, v.last
a, b = b, a if a > b # Range 两个数前后自动排列
v.exclude_end? ? a...b : a..b
else
v..v # 非 Range 数值
end
end
# 取小数
f = false; float = args.map{|v| v.first.is_a?(Float) || v.last.is_a?(Float) ? f = true : false }
# 取 Range 元素的差
arr = args.map.with_index do |v, i|
a, b = v.first, v.last
c = (a == b ? 1 : b - a)
c + (v.exclude_end? ? 0 : (i == 0 || c == c.to_i ? 1 : 0))
end
# 处理随机
r = rand(accuracy...(arr.inject(&:+)*accuracy))
arr.each_with_index do |v, i|
temp = v*accuracy
if r > temp
r -= temp
else
re = args[i]
if re.first == re.last and !re.exclude_end?
t = args[i].first
else
t = args[i].first + (r - (i == 0 ? accuracy : 0)) / accuracy.to_f
end
if float[i]
t = (t * 1000).to_i / 1000.0
else
t = f ? t.to_i.to_f : t.to_i
end
return t
end
end
end
end
#--------------------------------------------------------------------------
# ● 均分随机(权重数组, 最大值)
#--------------------------------------------------------------------------
def rand_average(args, max=nil)
arr = [0]; args.inject(0){|a, b| arr << a+b; arr[-1] }
max ||= arr[-1]
r = rand(max)
arr.each_cons(2).each_with_index do |v, i|
return i if r >= v[0] and r < v[1]
end
end
end