|
module Simulation |
|
class Config |
|
class << self |
|
# 50..70 (seconds) |
|
attr_accessor :travel_time_range |
|
# 5..35 (seconds) |
|
attr_accessor :departure_rate_range |
|
# key=passengers, value=percentage |
|
# { 1 => 20, 2 => 30, ... } |
|
attr_accessor :passengers_probability |
|
|
|
def passengers |
|
raise "No passenger capacities configured" if self.passengers_probability.empty? |
|
|
|
sample = rand(100) |
|
self.passengers_probability.sort.each do |passengers,probability| |
|
sample -= probability |
|
return passengers if sample <= 0 |
|
end |
|
return 0 |
|
end |
|
|
|
def departure_delay |
|
low = self.departure_rate_range.begin |
|
high = self.departure_rate_range.end |
|
span = high - low + (self.departure_rate_range.exclude_end? ? 0 : 1) |
|
return low + rand(span) |
|
end |
|
def travel_time |
|
low = self.travel_time_range.begin |
|
high = self.travel_time_range.end |
|
span = high - low + (self.travel_time_range.exclude_end? ? 0 : 1) |
|
return low + rand(span) |
|
end |
|
end |
|
end |
|
|
|
class Vehicle |
|
attr_reader :departure_time, :travel_time, :arrival_time |
|
attr_accessor :passengers |
|
def initialize(departs_at) |
|
@departure_time = departs_at |
|
@passengers = Config.passengers |
|
@travel_time = Config.travel_time |
|
@arrival_time = @departure_time + @travel_time |
|
end |
|
|
|
def to_s |
|
"leaves at %4d w/%-2d arriving %4d"%[self.departure_time, |
|
self.passengers, |
|
self.arrival_time] |
|
end |
|
end |
|
end |
|
|
|
Simulation::Config.departure_rate_range = 5..35 # (seconds) |
|
Simulation::Config.travel_time_range = 50..70 # (seconds) |
|
Simulation::Config.passengers_probability = { 1 => 20, 2 => 30, 3 => 10, 4 => 10, 40 => 30 } |
|
|
|
next_departure = 0 |
|
vehicles = [] |
|
simple_sum = 0 |
|
final_count, final_time = 0, 0 |
|
loop do |
|
vehicle = Simulation::Vehicle.new(next_departure) |
|
vehicles << vehicle |
|
simple_sum += vehicle.passengers |
|
final_count, final_time = vehicles.sort_by {|v| v.arrival_time }.inject([0,0]) do |(count,time),v| |
|
if count >= 500 |
|
[count,time] |
|
else |
|
[count+v.passengers, v.arrival_time] |
|
end |
|
end |
|
puts "#{vehicle} [#{simple_sum}] [#{final_count} @ #{final_time}]" if $VERBOSE |
|
next_departure += Simulation::Config.departure_delay |
|
break if final_count >= 500 && next_departure > final_time |
|
end |
|
puts "=> #{final_count} @ #{final_time}" |