mirror of
https://github.com/Xevion/project-cybersyn.git
synced 2025-12-10 06:08:11 -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: {
|
||||
layout_id: int
|
||||
depot_id: int
|
||||
item_slot_capacity: int
|
||||
fluid_capacity: int
|
||||
}
|
||||
available_trains: [{
|
||||
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)
|
||||
return {}
|
||||
@@ -54,7 +91,7 @@ local function get_station_dist(stations, id0, id1)
|
||||
return INF
|
||||
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
|
||||
local r_station = stations[r_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_dist = INF
|
||||
|
||||
local is_fluid = item_type == "fluid"
|
||||
for k, train in pairs(available_trains.all) do
|
||||
--check cargo capabilities
|
||||
--check layout validity for both stations
|
||||
--TODO: add check for correct cargo type
|
||||
if r_station.accepted_layouts[train.layout_id] and p_station.accepted_layouts[train.layout_id] then
|
||||
if
|
||||
((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 path is shortest so we prioritize locality
|
||||
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
|
||||
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 p_station = stations[p_station_id]
|
||||
|
||||
local requests = {}
|
||||
local orders = {}
|
||||
local has_liquid = false
|
||||
local has_solid = false
|
||||
local manifest = {}
|
||||
|
||||
local r_signals = get_signals(r_station_id)
|
||||
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_count = v.count
|
||||
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]
|
||||
if effective_item_count >= p_station.p_threshold then
|
||||
local r = requests[item_name]
|
||||
if r then
|
||||
orders[item_name] = math.min(r, effective_item_count)
|
||||
if item_type == "liquid" then--TODO: here add liquid detection
|
||||
has_liquid = true
|
||||
local item = {name = item_name, count = math.min(r, effective_item_count), type = item_type}
|
||||
if item_name == primary_item_name then
|
||||
manifest[#manifest + 1] = manifest[1]
|
||||
manifest[1] = item
|
||||
else
|
||||
has_solid = true
|
||||
manifest[#manifest + 1] = item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
r_station.last_delivery_tick = ticks_total
|
||||
p_station.last_delivery_tick = ticks_total
|
||||
--local total_slots_left = 0
|
||||
--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
|
||||
p_station.deliveries_total = p_station.deliveries_total + 1
|
||||
|
||||
for item_name, item_count in pairs(orders) do
|
||||
assert(item_count > 0, "main.lua error, transfer amount was not positive")
|
||||
for _, item in ipairs(manifest) do
|
||||
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
|
||||
p_station.delivery_amount[item_name] = p_station.delivery_amount[item_name] - item_count
|
||||
--set train orders
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
function tick(stations, available_trains, ticks_total)
|
||||
local r_stations_all = {}
|
||||
local p_stations_all = {}
|
||||
local all_items = {}
|
||||
local economy = {
|
||||
r_stations_all = {},
|
||||
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
|
||||
if station.deliveries_total < station.train_limit then
|
||||
@@ -203,9 +292,9 @@ function tick(stations, available_trains, ticks_total)
|
||||
end
|
||||
|
||||
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
|
||||
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 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 <= #p_stations then
|
||||
--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_train = nil
|
||||
local best_dist = INF
|
||||
@@ -234,15 +326,17 @@ function tick(stations, available_trains, ticks_total)
|
||||
end
|
||||
end
|
||||
if best > 0 then
|
||||
send_train_between(stations, r_station_id, p_stations[best], best_train)
|
||||
table.remove(p_stations, best)
|
||||
send_train_between(stations, r_station_id, p_stations[best], best_train, item_name, economy)
|
||||
elseif could_have_been_serviced then
|
||||
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
|
||||
end
|
||||
end
|
||||
until #r_stations == 0
|
||||
else
|
||||
--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_train = nil
|
||||
local lowest_tick = INF
|
||||
@@ -264,12 +358,11 @@ function tick(stations, available_trains, ticks_total)
|
||||
end
|
||||
end
|
||||
if best > 0 then
|
||||
send_train_between(stations, r_stations[best], p_station_id, best_train)
|
||||
table.remove(r_stations, best)
|
||||
send_train_between(stations, r_stations[best], p_station_id, best_train, item_name, economy)
|
||||
elseif could_have_been_serviced then
|
||||
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
|
||||
end
|
||||
end
|
||||
until #p_stations == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user