require "big"
|
|
|
|
module Crystal::Scatter
|
|
|
|
module Servers
|
|
def last_effector_end : UInt64
|
|
UInt64.MAX
|
|
end
|
|
|
|
class Daemon(Ign,T)
|
|
getter range_effector : Nil | Tuple(UInt64,UInt64)
|
|
|
|
def initialize(@weight : UInt64 = 1)
|
|
@reach_at = T.new
|
|
end
|
|
|
|
def set_effectors(last_set : UInt64, split_rate : BigRational, total_weight : UInt64,split_ratio : BigRational) : UInt64
|
|
@range_effector = Tuple.new(
|
|
last_set+1,
|
|
(last_set+1+UInt64::MAX*(split_rate.inv*split_ratio + (@weight*(1-split_ratio))/total_weight)).round.to_big_f.to_u64
|
|
)
|
|
return @range_effector.not_nil!.[1]
|
|
end
|
|
|
|
def get_weight : UInt64
|
|
@weight
|
|
end
|
|
|
|
def add(@weight, elems,@reach_at)
|
|
end
|
|
|
|
def set_end
|
|
@range_effector=Tuple.new(@range_effector.not_nil!.[0],UInt64::MAX)
|
|
end
|
|
end
|
|
|
|
class Container(T,U) < Array(T)
|
|
def set_effectors(last_set : UInt64, split_rate : BigRational, total_weight : UInt64, split_ratio : BigRational) : UInt64
|
|
split_rate *= size
|
|
each do |elem|
|
|
last_set = elem.set_effectors(last_set, split_rate,total_weight,split_ratio)
|
|
end
|
|
return last_set
|
|
end
|
|
|
|
def set_end
|
|
last.set_end
|
|
end
|
|
|
|
def get_weight : UInt64
|
|
total : UInt64 = 0
|
|
each do |elem|
|
|
total += elem.get_weight
|
|
end
|
|
return total
|
|
end
|
|
|
|
def add(nweight, elems, reach_at)
|
|
if elems[0]==size
|
|
push T.new
|
|
elsif elems[0]>size
|
|
raise ArgumentError.new("Tried to insert in an invalid position")
|
|
end
|
|
at(elems[0]).add(nweight, elems.skip(1), reach_at)
|
|
end
|
|
end
|
|
|
|
class Server(U) < Container(Daemon(U,U),U) end
|
|
|
|
class PSU(U) < Container(Server(U),U) end
|
|
|
|
class Rack(U) < Container(PSU(U),U) end
|
|
|
|
class Room(U) < Container(Rack(U),U) end
|
|
|
|
class Datacenter(U) < Container(Room(U),U) end
|
|
|
|
class Root(U) < Container(Datacenter(U),U) end
|
|
end
|
|
|
|
class RingGraph(T) < Servers::Root(T)
|
|
def generate_ring(split_ratio : BigRational)
|
|
set_effectors(UInt64::MAX, BigRational.new(1), get_weight, split_ratio)
|
|
set_end
|
|
end
|
|
end
|
|
|
|
end
|