211 lines
5.9 KiB
Lua

local config = require("config")
local utils = require("utils")
local trains = require("trains")
local format = require("format")
local train_stops = require("train_stops")
local ltn = require("ltn")
local scheduler = {}
function scheduler.build_record(stop, wait)
local record = {
station = stop.name,
wait_conditions = {}
}
for _, item in pairs(wait.items) do
table.insert(record.wait_conditions, {
type = "item_count",
condition = {
first_signal = {
type = "item",
name = item
},
comparator = "=",
constant = 0
},
compare_type = "and"
})
end
for _, fluid in pairs(wait.fluids) do
table.insert(record.wait_conditions, {
type = "fluid_count",
condition = {
first_signal = {
type = "fluid",
name = fluid
},
comparator = "=",
constant = 0
},
compare_type = "and"
})
end
local timeout = config.stop_timeout()
if timeout ~= nil and timeout ~= 0 then
table.insert(record.wait_conditions, {
type = "time",
compare_type = "or",
ticks = timeout
})
end
return record
end
function scheduler.build_temp_record(stop_id)
local rail = ltn.get_rail(stop_id)
if rail ~= nil then
return {
rail = rail,
wait_conditions = {{
type = "time",
compare_type = "or",
ticks = 0
}},
temporary = true
}
end
end
function scheduler.process_any(processes, values)
local index = utils.build_reverse_index(values)
local wait = {}
for _, val in pairs(processes) do
local ind = index[val]
if ind ~= nil then
table.insert(wait, val)
table.remove(values, ind)
index = utils.build_reverse_index(values)
end
end
return {
wait = wait,
values = values
}
end
function scheduler.process_stop(trash, stop)
if stop == nil then
return
end
local wait = {
items = {},
fluids = {}
}
local items_resp = scheduler.process_any(stop.process.items, trash.items)
trash.items = items_resp.values
wait.items = items_resp.wait
local fluids_resp = scheduler.process_any(stop.process.fluids, trash.fluids)
trash.fluids = fluids_resp.values
wait.fluids = fluids_resp.wait
return {
wait = wait,
trash = trash
}
end
function scheduler.build(train, request_stop_id)
local trash = trains.get_all_trash(train)
local surface = trains.get_surface(train)
if surface == nil then
format.warning("Failed to determine train's surface")
return
end
if request_stop_id == nil then
local depot_record = train.schedule.records[1]
local depot_name = depot_record.station
if depot_name ~= nil then
local depot_stop = train_stops.find_depot(depot_name, surface)
if depot_stop ~= nil then
request_stop_id = depot_stop.unit_number
end
end
end
local stops = train_stops.get_all_cleanup(ltn.get_network(request_stop_id), trains.count_carriages(train), surface)
if not train_stops.found_any_stops(stops) then
format.warning("No cleanup stops found")
format.train_depot_alert(train)
return
end
local schedule = {}
local needs_generic = {}
while #trash.items > 0 do
local item_stop = train_stops.find_item(stops, trash.items[1])
if item_stop == nil then
table.insert(needs_generic, trash.items[1])
table.remove(trash.items, 1)
else
local item_resp = scheduler.process_stop(trash, item_stop.stop)
trash = item_resp.trash
local temp = scheduler.build_temp_record(item_stop.id)
if temp ~= nil then
table.insert(schedule, temp)
end
table.insert(schedule, scheduler.build_record(item_stop.stop, item_resp.wait))
end
end
while #trash.fluids > 0 do
local fluid_stop = train_stops.find_fluid(stops, trash.fluids[1])
if fluid_stop == nil then
format.warning("No cleanup stops to process " .. format.fluid(trash.fluids[1]) .. " found")
format.train_depot_alert(train)
return
else
local fluid_resp = scheduler.process_stop(trash, fluid_stop.stop)
trash = fluid_resp.trash
local temp = scheduler.build_temp_record(fluid_stop.id)
if temp ~= nil then
table.insert(schedule, temp)
end
table.insert(schedule, scheduler.build_record(fluid_stop.stop, fluid_resp.wait))
end
end
if #needs_generic > 0 then
local generic_stop = train_stops.find_generic_item(stops)
if generic_stop == nil then
local items = ""
for _, item in pairs(needs_generic) do
items = items .. " " .. format.item(item)
end
format.warning("No generic cleanup stops found to process " .. items)
format.train_depot_alert(train)
return
end
local temp = scheduler.build_temp_record(generic_stop.id)
if temp ~= nil then
table.insert(schedule, temp)
end
table.insert(schedule, scheduler.build_record(generic_stop.stop, {
items = needs_generic,
fluids = {}
}))
end
return schedule
end
function scheduler.train_left_stop(train)
if trains.finished_cleaning(train) and trains.has_trash(train) then
format.train_depot_alert(train)
end
end
return scheduler