Files
fs25-adsmartpickup/FS25_ADSmartPickup/gui/SmartPickupOutboundTab.lua

220 lines
9.8 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Smart Pickup — fanen Udkørsel
-- Kilder (afkrydsning), varer med politik (Fra/Lager/Salg/Salg, ellers lager) og aktuel pris i
-- % af årets top, regler (pristærskel, lagertærskel, opsamlingsrunde) og status/advarsler.
-- Funktionerne lægges på SmartPickupFrame (indlæses efter SmartPickupFrame.lua).
-- Bedste pris-% for varen over alle salgssteder (uanset vejnet — det er til visning; turen
-- bruger kun nåelige). {percent, stationName} eller nil.
SmartPickupFrame.SELL_MARKERS_CACHE_MS = 30000
-- Salgsstederne slås op over alle markører × stationer; cachet, så det ikke sker pr. vare pr. sekund.
function SmartPickupFrame:getSellMarkersCached(adEnv)
local time = g_time or (os.clock ~= nil and os.clock() * 1000) or 0
if self.sellMarkersCache == nil or (time - (self.sellMarkersCacheTime or 0)) > SmartPickupFrame.SELL_MARKERS_CACHE_MS then
self.sellMarkersCache = ADSources.getSellMarkers(adEnv, g_currentMission:getFarmId())
self.sellMarkersCacheTime = time
end
return self.sellMarkersCache
end
function SmartPickupFrame:getProductQuote(adEnv, fillType)
if ADSources == nil or ADPrices == nil then
return nil
end
local best = nil
for _, entry in ipairs(self:getSellMarkersCached(adEnv)) do
if ADSources.stationAccepts(entry.station, fillType) then
local quote = ADPrices.getQuote(entry.station, fillType)
if quote ~= nil and (best == nil or quote.percent > best.percent) then
best = {percent = quote.percent, stationName = tostring(entry.marker.name)}
end
end
end
return best
end
-- "Sukker — 150.0k l — 78 % af top (Grain Elevator)"
function SmartPickupFrame:describeProduct(adEnv, product)
local price = self.i18n:getText("spu_price_none")
local quote = self:getProductQuote(adEnv, product.fillType)
if quote ~= nil then
price = string.format(self.i18n:getText("spu_price_pct"), quote.percent, quote.stationName)
end
return string.format(self.i18n:getText("spu_product_row"), tostring(product.title), SmartPickupFrame.formatCompact(product.available or 0), price)
end
-- Paller lagres i et palleskur (objektlager) i stedet for en silo — samme politikker som bulk.
function SmartPickupFrame.getPoliciesFor(product)
return SmartPickupFrame.POLICIES
end
function SmartPickupFrame.getPolicyIndex(policies, policy)
for index, name in ipairs(policies) do
if name == policy then
return index
end
end
return 1
end
function SmartPickupFrame:fillSourceRows(adEnv, run)
local chosen = {}
for _, id in ipairs(run.sourceWayPointIds or {}) do
chosen[id] = true
end
local entries = ADRunsController.getSourceMarkers(adEnv, g_currentMission:getFarmId())
for _, entry in ipairs(entries) do
local row = self:addRow(self.ingredientPrefab, {kind = "source", wayPointId = entry.marker.id})
local kindText = self.i18n:getText("spu_source_kind_" .. tostring(entry.kind))
row:getDescendantByName("title"):setText(string.format(" %s — %s (%s)", tostring(entry.marker.name), tostring(entry.name), kindText))
row:getDescendantByName("option"):setState(chosen[entry.marker.id] and SmartPickupFrame.STATE_ON or SmartPickupFrame.STATE_OFF, false)
end
if #entries == 0 then
self:addTextRow(self.i18n:getText("spu_noSources"))
end
end
function SmartPickupFrame:fillProductRows(adEnv, run)
self.productRows = {}
local products = ADRunsController.getRunProducts(adEnv, run)
for _, product in ipairs(products) do
local policies = SmartPickupFrame.getPoliciesFor(product)
local policyTexts = {}
for _, policy in ipairs(policies) do
table.insert(policyTexts, self.i18n:getText("spu_policy_" .. policy))
end
local row = self:addRow(self.productPrefab, {kind = "product", name = product.name, policies = policies})
local option = row:getDescendantByName("option")
option:setTexts(policyTexts)
option:setState(SmartPickupFrame.getPolicyIndex(policies, product.policy), false)
local title = row:getDescendantByName("title")
title:setText(self:describeProduct(adEnv, product))
table.insert(self.productRows, {name = product.name, title = title, option = option})
end
if #products == 0 then
self:addTextRow(#(run.sourceWayPointIds or {}) == 0 and self.i18n:getText("spu_noSources") or self.i18n:getText("spu_noProducts"))
end
end
function SmartPickupFrame:fillOutboundStatusRows(adEnv, run)
self.outboundStatusRows = {}
local status = ADRunsController.getOutboundStatus(adEnv, run)
for _, reason in ipairs(status.reasons or {}) do
table.insert(self.outboundStatusRows, self:addTextRow(string.format(self.i18n:getText("spu_outbound_waiting"), reason)))
end
if status.warning ~= nil then
table.insert(self.outboundStatusRows, self:addTextRow(string.format(self.i18n:getText("spu_outbound_warning"), status.warning)))
end
end
function SmartPickupFrame:rebuildOutboundTab(adEnv, run)
self.sellAtOption:setState(SmartPickupFrame.getStepIndex(self.sellAtSteps, run.sellAtPercent, ADRuns.DEFAULT_SELL_AT_PERCENT), false)
self.storeAboveOption:setState(SmartPickupFrame.getStepIndex(self.storeAboveSteps, run.storeAbovePercent, ADRuns.DEFAULT_STORE_ABOVE_PERCENT), false)
self.collectRoundRowOption = self:addToggleRow("collectRound", self.i18n:getText("spu_collectRound"), {self.i18n:getText("ui_no"), self.i18n:getText("ui_yes")}, run.collectRound == true)
self:addTextRow(self.i18n:getText("spu_section_sources"))
self:fillSourceRows(adEnv, run)
self:addTextRow(self.i18n:getText("spu_section_products"))
self:fillProductRows(adEnv, run)
self:fillOutboundStatusRows(adEnv, run)
end
-- Hvert sekund: produktrækkernes mængde/pris og statuslinjerne (antal linjer ændres kun ved rebuild).
function SmartPickupFrame:refreshOutboundRows(adEnv, run)
local byName = {}
for _, product in ipairs(ADRunsController.getRunProducts(adEnv, run)) do
byName[product.name] = product
end
for _, row in ipairs(self.productRows or {}) do
if byName[row.name] ~= nil then
row.title:setText(self:describeProduct(adEnv, byName[row.name]))
end
end
local status = ADRunsController.getOutboundStatus(adEnv, run)
local lines = {}
for _, reason in ipairs(status.reasons or {}) do
table.insert(lines, string.format(self.i18n:getText("spu_outbound_waiting"), reason))
end
if status.warning ~= nil then
table.insert(lines, string.format(self.i18n:getText("spu_outbound_warning"), status.warning))
end
for index, row in ipairs(self.outboundStatusRows or {}) do
row:setText(lines[index] or "")
end
end
-- Oversigt: "SUGAR 78 % af top (kræver 90), lager 41 % · ⚠ …" eller "Sukker 150.0k l — 92 % af top (…)".
function SmartPickupFrame:describeOutboundOverview(adEnv, run)
local status = ADRunsController.getOutboundStatus(adEnv, run)
local parts = {}
for _, reason in ipairs(status.reasons or {}) do
table.insert(parts, reason)
end
if #parts == 0 then
for _, product in ipairs(status.products or {}) do
if product.policy ~= "off" then
table.insert(parts, self:describeProduct(adEnv, product))
end
end
end
if status.warning ~= nil then
table.insert(parts, string.format(self.i18n:getText("spu_outbound_warning"), status.warning))
end
if #parts == 0 then
return self.i18n:getText("spu_noSources")
end
return table.concat(parts, " · ")
end
-- ---- callbacks ----
function SmartPickupFrame:onClickSource(state, element)
self:safe(function(frame)
local run, data = frame:getRun(), frame.rowData[element]
if run == nil or data == nil then return end
ADRunsController.store = ADRuns.toggleSource(ADRunsController.store, run.id, data.wayPointId)
Logging.info(SmartPickupFrame.LOG_PREFIX .. "run '%s': sources=%s", tostring(run.name), table.concat(ADRuns.getRun(ADRunsController.store, run.id).sourceWayPointIds, " "))
frame:requestRebuild()
end)
end
function SmartPickupFrame:onClickProduct(state, element)
local clicked = self.rowData[element]
if clicked ~= nil and clicked.kind == "storageBuilding" then
return self:safe(function(frame) frame:onClickStorageBuilding(state) end)
end
if clicked ~= nil and SmartPickupFrame.FIELD_ROW_KINDS ~= nil and SmartPickupFrame.FIELD_ROW_KINDS[clicked.kind] then
return self:onClickFieldRow(state, clicked)
end
self:safe(function(frame)
local run, data = frame:getRun(), frame.rowData[element]
if run == nil or data == nil or data.kind ~= "product" then return end
local policy = (data.policies or SmartPickupFrame.POLICIES)[state] or "off"
ADRunsController.store = ADRuns.setProductPolicy(ADRunsController.store, run.id, data.name, policy)
Logging.info(SmartPickupFrame.LOG_PREFIX .. "run '%s': %s=%s", tostring(run.name), tostring(data.name), policy)
end)
end
function SmartPickupFrame:onClickSellAt(state)
self:safe(function(frame)
local run = frame:getRun()
if run == nil then return end
ADRunsController.updateRun(run.id, {sellAtPercent = frame.sellAtSteps[state] or ADRuns.DEFAULT_SELL_AT_PERCENT})
end)
end
function SmartPickupFrame:onClickStoreAbove(state)
self:safe(function(frame)
local run = frame:getRun()
if run == nil then return end
ADRunsController.updateRun(run.id, {storeAbovePercent = frame.storeAboveSteps[state] or ADRuns.DEFAULT_STORE_ABOVE_PERCENT})
end)
end
function SmartPickupFrame:onClickCollectRound(state)
self:safe(function(frame)
local run = frame:getRun()
if run == nil then return end
ADRunsController.updateRun(run.id, {collectRound = state == SmartPickupFrame.STATE_ON})
end)
end