feat: adPrices — toppris fra årets prisforløb og pris-% pr. salgssted

This commit is contained in:
2026-09-23 09:48:32 +02:00
parent def054ca43
commit 1410ca6ff3
2 changed files with 158 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
-- AD Prices
-- Prisregel for udkørsel: hvor tæt er salgsstedets pris på årets toppris for varen?
-- Toppris = stationens grundpris lige nu × (årets højeste periodefaktor ÷ nuværende periodes
-- faktor) — dvs. det Priser-menuen ville vise som årets bedste måned for netop den station.
-- Effektiv pris (inkl. prisfald efter salg og stor efterspørgsel) ÷ toppris = pris-%;
-- stor efterspørgsel giver > 100 % og opfylder dermed altid reglen.
-- De rene funktioner øverst har ingen spil-API; getQuote er spil-adapteren.
ADPrices = {}
ADPrices.LOG_PREFIX = "ADSmartPickup: "
function ADPrices.maxFactor(factors)
local best = nil
for _, factor in pairs(factors or {}) do
if type(factor) == "number" and (best == nil or factor > best) then
best = factor
end
end
return best or 1
end
function ADPrices.topPrice(baseNow, factorNow, maxFactor)
if baseNow == nil or baseNow <= 0 then
return 0
end
if factorNow == nil or factorNow <= 0 or maxFactor == nil or maxFactor <= 0 then
return baseNow
end
return baseNow * maxFactor / factorNow
end
function ADPrices.percentOfTop(price, top)
if top == nil or top <= 0 or price == nil then
return 0
end
return math.floor(100 * price / top + 0.5)
end
-- Rigtige salgssteder: SellingStation der sælger (fabrikkers aflæsningsstationer er
-- også SellingStation-objekter, men med isSellingPoint = false) og vises i Priser-menuen.
function ADPrices.isSellingStation(station)
return station ~= nil and station.isa ~= nil and SellingStation ~= nil and station:isa(SellingStation) == true
and station.isSellingPoint == true and not station.hideFromPricesMenu
end
local function getCurrentPeriod()
local environment = g_currentMission ~= nil and g_currentMission.environment or nil
return environment ~= nil and environment.currentPeriod or nil
end
local function getDifficultyMultiplier()
local economy = g_currentMission ~= nil and g_currentMission.economyManager or nil
if economy ~= nil and economy.getPriceMultiplier ~= nil then
local ok, value = pcall(economy.getPriceMultiplier, economy)
if ok and type(value) == "number" then
return value
end
end
return 1
end
-- {price, top, percent} for varen ved stationen; nil hvis stationen ikke kan prissætte den.
function ADPrices.getQuote(station, fillType)
if station == nil or station.getEffectiveFillTypePrice == nil then
return nil
end
local ok, effective = pcall(station.getEffectiveFillTypePrice, station, fillType)
if not ok or type(effective) ~= "number" then
return nil
end
local fillTypeDesc = g_fillTypeManager ~= nil and g_fillTypeManager.getFillTypeByIndex ~= nil and g_fillTypeManager:getFillTypeByIndex(fillType) or nil
local factors = fillTypeDesc ~= nil and fillTypeDesc.economy ~= nil and fillTypeDesc.economy.factors or nil
local period = getCurrentPeriod()
local factorNow = factors ~= nil and period ~= nil and tonumber(factors[period]) or 1
local baseNow = station.fillTypePrices ~= nil and tonumber(station.fillTypePrices[fillType]) or nil
if baseNow == nil or baseNow <= 0 then
baseNow = (fillTypeDesc ~= nil and tonumber(fillTypeDesc.pricePerLiter) or 0) * factorNow * getDifficultyMultiplier()
end
local top = ADPrices.topPrice(baseNow, factorNow, ADPrices.maxFactor(factors))
return {price = effective, top = top, percent = ADPrices.percentOfTop(effective, top)}
end
-- Højeste pris-%, ved lighed højeste pris. nil ved tom liste.
function ADPrices.bestQuote(quotes)
local best = nil
for _, quote in ipairs(quotes or {}) do
if best == nil or quote.percent > best.percent or (quote.percent == best.percent and quote.price > best.price) then
best = quote
end
end
return best
end