added missing train handling

This commit is contained in:
Monica Moniot
2022-09-24 17:03:03 -05:00
parent de5b7500c2
commit 5ce9363f90

151
main.lua
View File

@@ -2,37 +2,96 @@ local function get_item_amount(station, item_id)
return 0 return 0
end end
local function get_valid_train(stations, r_station_i, p_station_i, available_trains)
return 0
end
local function get_distance(stations, r_station_i, p_station_i) local function get_distance(stations, r_station_i, p_station_i)
return 0 return 0
end end
local function send_train_between(stations, r_station_i, p_station_i) local function send_train_between(stations, r_station_i, p_station_i, train)
stations[r_station_i].last_p_station_i = p_station_i local r_station = stations[r_station_i]
stations[p_station_i].last_r_station_i = r_station_i local p_station = stations[p_station_i]
r_station.last_p_station_i = p_station_i
p_station.last_r_station_i = r_station_i
r_station.deliveries_total = r_station.deliveries_total + 1
p_station.deliveries_total = p_station.deliveries_total + 1
local r_amount = get_item_amount(r_station, item_id) + r_station.delivery_amount[item_id]
local p_amount = get_item_amount(p_station, item_id) + p_station.delivery_amount[item_id]
local transfer_amount = math.min(train.capacity, -r_amount, p_amount)
assert(transfer_amount > 0, "main.lua error, transfer amount was not positive")
r_station.delivery_amount[item_id] = r_station.delivery_amount[item_id] + transfer_amount
p_station.delivery_amount[item_id] = p_station.delivery_amount[item_id] - transfer_amount
end end
--[[ --[[
station: station: {
deliveries_total: int deliveries_total: int
train_limit: int train_limit: int
requester_limit: int requester_limit: int > 0
provider_limit: int provider_limit: int > 0
priority: int priority: int
last_delivery_tick: int
train_layout: [ [ {
[car_type]: true|nil
} ] ]
accepted_layouts: {
[layout_id]: true|nil
}
}
available_trains: [{
layout_id: int
capacity: int
}]
]] ]]
local function tick(stations, all_items) --local function check_train_layouts(station, available_layouts)
for _, item_id in pairs(all_items) do -- for _, layout_id in ipairs(available_layouts) do
-- if station.accepted_layouts[layout_id] then
-- return true
-- end
-- end
-- return false
--end
local function icpairs(a, start_i)
start_i = start_i%#a + 1
local i = start_i - 1
local flag = true
return function()
i = i%#a + 1
if i ~= start_i or flag then
flag = false
local v = a[i]
if v then
return i, v
end
end
end
end
local function tick(stations, all_items, available_trains, ticks_total)
if #all_items == 0 then
return
end
local failed_because_missing_trains_total = 0
--psuedo-randomize what item (and what station) to check first so if trains available is low they choose orders psuedo-randomly
for _, item_id in icpairs(all_items, ticks_total) do
local r_stations = {} local r_stations = {}
local p_stations = {} local p_stations = {}
for station_i, station in pairs(stations) do for station_i, station in pairs(stations) do
if station.deliveries_total < station.train_limit then if station.deliveries_total < station.train_limit then
local item_amount = get_item_amount(station, item_id) local item_amount = get_item_amount(station, item_id) + station.delivery_amount[item_id]
local delivery_amount = station.delivery_amount
if -(item_amount + delivery_amount) >= station.requester_limit then if -item_amount >= station.requester_limit then
table.insert(r_stations, station_i) table.insert(r_stations, station_i)
elseif item_amount + delivery_amount >= station.provider_limit then elseif item_amount >= station.provider_limit then
table.insert(p_stations, station_i) table.insert(p_stations, station_i)
end end
end end
@@ -43,43 +102,65 @@ local function tick(stations, all_items)
if #r_stations > 0 and #p_stations > 0 then if #r_stations > 0 and #p_stations > 0 then
if #r_stations <= #p_stations then if #r_stations <= #p_stations then
--backpressure, prioritize locality --backpressure, prioritize locality
for i, r_station_i in ipairs(r_stations) do for i, r_station_i in icpairs(r_stations, ticks_total) do
local best = 1
local best = 0
local best_train = nil
local best_dist = math.huge local best_dist = math.huge
local highest_prior = -math.huge local highest_prior = -math.huge
local could_have_been_serviced = false
for j, p_station_i in ipairs(p_stations) do for j, p_station_i in ipairs(p_stations) do
local d = get_distance(stations, r_station_i, p_station_i) local d = get_distance(stations, r_station_i, p_station_i)
local prior = stations[p_station_i].priority local prior = stations[p_station_i].priority
if prior > highest_prior then if prior > highest_prior or (prior == highest_prior and d < best_dist) then
best = j local train, is_possible = get_valid_train(stations, r_station_i, p_station_i, available_trains)
best_dist = d if train then
highest_prior = prior best = j
elseif prior == highest_prior and d < best_dist then best_dist = d
best = j best_train = train
best_dist = d highest_prior = prior
elseif is_possible then
could_have_been_serviced = true
end
end end
end end
send_train_between(stations, r_station_i, p_stations[best]) if best > 0 then
table.remove(p_stations, best) send_train_between(stations, r_station_i, p_stations[best], best_train)
table.remove(p_stations, best)
elseif could_have_been_serviced then
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
end
end end
else else
--prioritize round robin --prioritize round robin
for j, p_station_i in ipairs(p_stations) do for j, p_station_i in icpairs(p_stations, ticks_total) do
local best = 1
local best = 0
local best_train = nil
local lowest_tick = math.huge
local highest_prior = -math.huge local highest_prior = -math.huge
local last_r_station_i = stations[p_station_i].last_r_station_i local could_have_been_serviced = false
for i, r_station_i in ipairs(r_stations) do for i, r_station_i in ipairs(r_stations) do
local prior = stations[r_station_i].priority local r_station = stations[r_station_i]
if r_stations[i] > last_r_station_i then local prior = r_station.priority
prior = prior + .5 if prior > highest_prior or (prior == highest_prior and r_station.last_delivery_tick < lowest_tick) then
end local train, is_possible = get_valid_train(stations, r_station_i, p_station_i, available_trains)
if prior > highest_prior then if train then
best = i best = i
highest_prior = prior best_train = train
lowest_tick = r_station.last_delivery_tick
highest_prior = prior
elseif is_possible then
could_have_been_serviced = true
end
end end
end end
send_train_between(stations, r_stations[best], p_station_i) if best > 0 then
table.remove(r_stations, best) send_train_between(stations, r_stations[best], p_station_i, best_train)
table.remove(r_stations, best)
elseif could_have_been_serviced then
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
end
end end
end end
end end