mirror of
https://github.com/Xevion/project-cybersyn.git
synced 2025-12-10 18:08:13 -06:00
added api integration
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
--require("scripts.controller")
|
||||||
|
--require("scripts.main")
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ station: {
|
|||||||
train: {
|
train: {
|
||||||
layout_id: int
|
layout_id: int
|
||||||
depot_id: int
|
depot_id: int
|
||||||
|
item_slot_capacity: int
|
||||||
|
fluid_capacity: int
|
||||||
}
|
}
|
||||||
available_trains: [{
|
available_trains: [{
|
||||||
layout_id: int
|
layout_id: int
|
||||||
@@ -45,6 +47,41 @@ available_trains: [{
|
|||||||
}]
|
}]
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
local function create_loading_order(station_name, manifest)
|
||||||
|
local condition = {}
|
||||||
|
for _, item in ipairs(manifest) do
|
||||||
|
local cond_type
|
||||||
|
if item.type == "fluid" then
|
||||||
|
cond_type = "fluid_count"
|
||||||
|
else
|
||||||
|
cond_type = "item_count"
|
||||||
|
end
|
||||||
|
|
||||||
|
condition[#condition + 1] = {
|
||||||
|
type = cond_type,
|
||||||
|
compare_type = "and",
|
||||||
|
condition = {comparator = "≥", first_signal = {type = item.type, name = item.name}, constant = item.count}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return {station = station_name, wait_conditions = condition}
|
||||||
|
end
|
||||||
|
|
||||||
|
local create_unloading_order_condition = {type = "empty", compare_type = "and"}
|
||||||
|
local function create_unloading_order(station_name, manifest)
|
||||||
|
return {station = station_name, wait_conditions = create_unloading_order_condition}
|
||||||
|
end
|
||||||
|
|
||||||
|
local create_inactivity_order_condition = {type = "inactivity", compare_type = "and", ticks = 3}
|
||||||
|
local function create_inactivity_order(station_name)
|
||||||
|
return {station = station_name, wait_conditions = create_inactivity_order_condition}
|
||||||
|
end
|
||||||
|
|
||||||
|
local create_direct_to_station_order_condition = {{type = "time", compare_type = "and", ticks = 0}}
|
||||||
|
local function create_direct_to_station_order(rail, rail_direction)
|
||||||
|
return {wait_conditions = create_direct_to_station_order_condition, rail = rail, rail_direction = rail_direction, temporary = false}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function get_signals(stations, station_id)
|
local function get_signals(stations, station_id)
|
||||||
return {}
|
return {}
|
||||||
@@ -54,7 +91,7 @@ local function get_station_dist(stations, id0, id1)
|
|||||||
return INF
|
return INF
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_valid_train(stations, r_station_id, p_station_id, available_trains)
|
local function get_valid_train(stations, r_station_id, p_station_id, available_trains, item_type)
|
||||||
--NOTE: this code is the critical section for run-time optimization
|
--NOTE: this code is the critical section for run-time optimization
|
||||||
local r_station = stations[r_station_id]
|
local r_station = stations[r_station_id]
|
||||||
local p_station = stations[p_station_id]
|
local p_station = stations[p_station_id]
|
||||||
@@ -67,11 +104,14 @@ local function get_valid_train(stations, r_station_id, p_station_id, available_t
|
|||||||
local best_train = nil
|
local best_train = nil
|
||||||
local best_dist = INF
|
local best_dist = INF
|
||||||
|
|
||||||
|
local is_fluid = item_type == "fluid"
|
||||||
for k, train in pairs(available_trains.all) do
|
for k, train in pairs(available_trains.all) do
|
||||||
--check cargo capabilities
|
--check cargo capabilities
|
||||||
--check layout validity for both stations
|
--check layout validity for both stations
|
||||||
--TODO: add check for correct cargo type
|
if
|
||||||
if r_station.accepted_layouts[train.layout_id] and p_station.accepted_layouts[train.layout_id] then
|
((is_fluid and train.fluid_capacity > 0) or (not is_fluid and train.item_slot_capacity > 0))
|
||||||
|
and r_station.accepted_layouts[train.layout_id] and p_station.accepted_layouts[train.layout_id]
|
||||||
|
then
|
||||||
--check if exists valid path
|
--check if exists valid path
|
||||||
--check if path is shortest so we prioritize locality
|
--check if path is shortest so we prioritize locality
|
||||||
local d_to_p_dist = get_station_dist(stations, train.depot_id, p_station_id)
|
local d_to_p_dist = get_station_dist(stations, train.depot_id, p_station_id)
|
||||||
@@ -87,14 +127,12 @@ local function get_valid_train(stations, r_station_id, p_station_id, available_t
|
|||||||
return best_train, best_dist
|
return best_train, best_dist
|
||||||
end
|
end
|
||||||
|
|
||||||
local function send_train_between(stations, r_station_id, p_station_id, train, ticks_total)
|
local function send_train_between(stations, r_station_id, p_station_id, train, primary_item_name, economy)
|
||||||
local r_station = stations[r_station_id]
|
local r_station = stations[r_station_id]
|
||||||
local p_station = stations[p_station_id]
|
local p_station = stations[p_station_id]
|
||||||
|
|
||||||
local requests = {}
|
local requests = {}
|
||||||
local orders = {}
|
local manifest = {}
|
||||||
local has_liquid = false
|
|
||||||
local has_solid = false
|
|
||||||
|
|
||||||
local r_signals = get_signals(r_station_id)
|
local r_signals = get_signals(r_station_id)
|
||||||
for k, v in pairs(r_signals) do
|
for k, v in pairs(r_signals) do
|
||||||
@@ -114,44 +152,95 @@ local function send_train_between(stations, r_station_id, p_station_id, train, t
|
|||||||
local item_name = v.signal.name
|
local item_name = v.signal.name
|
||||||
local item_count = v.count
|
local item_count = v.count
|
||||||
local item_type = v.signal.type
|
local item_type = v.signal.type
|
||||||
if item_name and item_type and item_type ~= "virtual" then
|
if item_name and item_type and item_type ~= "virtual" and item_name ~= primary_item_name then
|
||||||
local effective_item_count = item_count + p_station.delivery_amount[item_name]
|
local effective_item_count = item_count + p_station.delivery_amount[item_name]
|
||||||
if effective_item_count >= p_station.p_threshold then
|
if effective_item_count >= p_station.p_threshold then
|
||||||
local r = requests[item_name]
|
local r = requests[item_name]
|
||||||
if r then
|
if r then
|
||||||
orders[item_name] = math.min(r, effective_item_count)
|
local item = {name = item_name, count = math.min(r, effective_item_count), type = item_type}
|
||||||
if item_type == "liquid" then--TODO: here add liquid detection
|
if item_name == primary_item_name then
|
||||||
has_liquid = true
|
manifest[#manifest + 1] = manifest[1]
|
||||||
|
manifest[1] = item
|
||||||
else
|
else
|
||||||
has_solid = true
|
manifest[#manifest + 1] = item
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
r_station.last_delivery_tick = ticks_total
|
--local total_slots_left = 0
|
||||||
p_station.last_delivery_tick = ticks_total
|
--local total_liquid_left = 0
|
||||||
|
|
||||||
|
local i = 1
|
||||||
|
while i <= #manifest do
|
||||||
|
local item = manifest[i]
|
||||||
|
local keep_item = false
|
||||||
|
if item.type == "fluid" then
|
||||||
|
if total_liquid_left > 0 then
|
||||||
|
if item.count > total_liquid_left then
|
||||||
|
item.count = total_liquid_left
|
||||||
|
end
|
||||||
|
total_liquid_left = 0--no liquid merging
|
||||||
|
keep_item = true
|
||||||
|
end
|
||||||
|
elseif total_slots_left > 0 then
|
||||||
|
local stack_size = game.item_prototypes[item.name].stack_size
|
||||||
|
local slots = math.ceil(item.count/stack_size)
|
||||||
|
if slots > total_slots_left then
|
||||||
|
item.count = total_slots_left*stack_size
|
||||||
|
end
|
||||||
|
total_slots_left = total_slots_left - slots
|
||||||
|
keep_item = true
|
||||||
|
end
|
||||||
|
if keep_item then
|
||||||
|
i = i + 1
|
||||||
|
else
|
||||||
|
manifest[i] = manifest[#manifest]
|
||||||
|
manifest[#manifest] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
r_station.last_delivery_tick = economy.ticks_total
|
||||||
|
p_station.last_delivery_tick = economy.ticks_total
|
||||||
|
|
||||||
r_station.deliveries_total = r_station.deliveries_total + 1
|
r_station.deliveries_total = r_station.deliveries_total + 1
|
||||||
p_station.deliveries_total = p_station.deliveries_total + 1
|
p_station.deliveries_total = p_station.deliveries_total + 1
|
||||||
|
|
||||||
for item_name, item_count in pairs(orders) do
|
for _, item in ipairs(manifest) do
|
||||||
assert(item_count > 0, "main.lua error, transfer amount was not positive")
|
assert(item.count > 0, "main.lua error, transfer amount was not positive")
|
||||||
|
|
||||||
r_station.delivery_amount[item_name] = r_station.delivery_amount[item_name] + item_count
|
r_station.delivery_amount[item.name] = r_station.delivery_amount[item.name] + item.count
|
||||||
p_station.delivery_amount[item_name] = p_station.delivery_amount[item_name] - item_count
|
p_station.delivery_amount[item.name] = p_station.delivery_amount[item.name] - item.count
|
||||||
--set train orders
|
|
||||||
|
|
||||||
|
local r_stations = economy.r_stations_all[item.name]
|
||||||
|
local p_stations = economy.p_stations_all[item.name]
|
||||||
|
for i, id in ipairs(r_stations) do
|
||||||
|
if id == r_station_id then
|
||||||
|
table.remove(r_stations, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i, id in ipairs(p_stations) do
|
||||||
|
if id == p_station_id then
|
||||||
|
table.remove(p_stations, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function tick(stations, available_trains, ticks_total)
|
function tick(stations, available_trains, ticks_total)
|
||||||
local r_stations_all = {}
|
local economy = {
|
||||||
local p_stations_all = {}
|
r_stations_all = {},
|
||||||
local all_items = {}
|
p_stations_all = {},
|
||||||
|
all_items = {},
|
||||||
|
ticks_total = ticks_total,
|
||||||
|
}
|
||||||
|
local r_stations_all = economy.r_stations_all
|
||||||
|
local p_stations_all = economy.p_stations_all
|
||||||
|
local all_items = economy.all_items
|
||||||
|
|
||||||
for station_id, station in pairs(stations) do
|
for station_id, station in pairs(stations) do
|
||||||
if station.deliveries_total < station.train_limit then
|
if station.deliveries_total < station.train_limit then
|
||||||
@@ -203,9 +292,9 @@ function tick(stations, available_trains, ticks_total)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local failed_because_missing_trains_total = 0
|
local failed_because_missing_trains_total = 0
|
||||||
|
--we do not dispatch more than one train per station per tick
|
||||||
--psuedo-randomize what item (and what station) to check first so if trains available is low they choose orders psuedo-randomly
|
--psuedo-randomize what item (and what station) to check first so if trains available is low they choose orders psuedo-randomly
|
||||||
for _, item_name in icpairs(all_items, ticks_total) do
|
for _, item_name in icpairs(all_items, ticks_total) do
|
||||||
--we do not dispatch more than one train per station per tick
|
|
||||||
local r_stations = r_stations_all[item_name]
|
local r_stations = r_stations_all[item_name]
|
||||||
local p_stations = p_stations_all[item_name]
|
local p_stations = p_stations_all[item_name]
|
||||||
|
|
||||||
@@ -213,7 +302,10 @@ function tick(stations, available_trains, ticks_total)
|
|||||||
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
|
||||||
--probably backpressure, prioritize locality
|
--probably backpressure, prioritize locality
|
||||||
for i, r_station_id in icpairs(r_stations, ticks_total) do
|
repeat
|
||||||
|
local i = ticks_total%#r_stations + 1
|
||||||
|
local r_station_id = table.remove(r_stations, i)
|
||||||
|
|
||||||
local best = 0
|
local best = 0
|
||||||
local best_train = nil
|
local best_train = nil
|
||||||
local best_dist = INF
|
local best_dist = INF
|
||||||
@@ -234,15 +326,17 @@ function tick(stations, available_trains, ticks_total)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if best > 0 then
|
if best > 0 then
|
||||||
send_train_between(stations, r_station_id, p_stations[best], best_train)
|
send_train_between(stations, r_station_id, p_stations[best], best_train, item_name, economy)
|
||||||
table.remove(p_stations, best)
|
|
||||||
elseif could_have_been_serviced then
|
elseif could_have_been_serviced then
|
||||||
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
|
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
|
||||||
end
|
end
|
||||||
end
|
until #r_stations == 0
|
||||||
else
|
else
|
||||||
--prioritize round robin
|
--prioritize round robin
|
||||||
for j, p_station_id in icpairs(p_stations, ticks_total) do
|
repeat
|
||||||
|
local j = ticks_total%#p_stations + 1
|
||||||
|
local p_station_id = table.remove(p_stations, j)
|
||||||
|
|
||||||
local best = 0
|
local best = 0
|
||||||
local best_train = nil
|
local best_train = nil
|
||||||
local lowest_tick = INF
|
local lowest_tick = INF
|
||||||
@@ -264,12 +358,11 @@ function tick(stations, available_trains, ticks_total)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if best > 0 then
|
if best > 0 then
|
||||||
send_train_between(stations, r_stations[best], p_station_id, best_train)
|
send_train_between(stations, r_stations[best], p_station_id, best_train, item_name, economy)
|
||||||
table.remove(r_stations, best)
|
|
||||||
elseif could_have_been_serviced then
|
elseif could_have_been_serviced then
|
||||||
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
|
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
|
||||||
end
|
end
|
||||||
end
|
until #p_stations == 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user