Files
fs25-adsmartpickup/FS25_ADSmartPickup/adPrices.lua
T

109 lines
4.5 KiB
Lua
Raw 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.
-- AD Prices
-- Prisregel for udkørsel: hvor tæt er salgsstedets pris på årets toppris for varen?
-- Grundlaget er spillets faste sæsonkurve (fillType.economy.factors[1..12], samme data som
-- prisgrafen i Priser-menuen; metode fra Distribution Redux): kurve-% = faktor nu ÷ årets højeste.
-- Oven på det ganges stationens egen afvigelse (effektiv pris ÷ stationens grundpris nu), så
-- prisfald efter salg og stor efterspørgsel tæller med — stor efterspørgsel giver > 100 %.
-- Sværhedsgraden skalerer begge priser ens og falder ud af regnestykket. Flade kurver
-- (top/bund under FLAT_THRESHOLD) regnes som 100 %, så varer uden sæson aldrig strander.
-- De rene funktioner øverst har ingen spil-API; getQuote er spil-adapteren.
ADPrices = {}
ADPrices.LOG_PREFIX = "ADSmartPickup: "
-- top/bund under dette = ingen reel sæson (Distribution Redux bruger samme grænse)
ADPrices.FLAT_THRESHOLD = 1.02
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
function ADPrices.minFactor(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
-- Kurve-%: nuværende periodes faktor ÷ årets højeste, afrundet. 100 uden kurve, uden periode
-- eller når kurven er flad.
function ADPrices.curvePercent(factors, period)
if factors == nil or period == nil then
return 100
end
local now, max, min = tonumber(factors[period]), ADPrices.maxFactor(factors), ADPrices.minFactor(factors)
if now == nil or now <= 0 or max <= 0 or min <= 0 or (max / min) < ADPrices.FLAT_THRESHOLD then
return 100
end
return math.floor(100 * now / max + 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
-- {price, top, percent} for varen ved stationen; nil hvis stationen ikke kan prissætte den.
-- percent = kurve-% × (effektiv ÷ stationens grundpris nu); top = den pris der svarer til 100 %.
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 curve = ADPrices.curvePercent(factors, getCurrentPeriod())
local baseNow = station.fillTypePrices ~= nil and tonumber(station.fillTypePrices[fillType]) or nil
local stationRatio = (baseNow ~= nil and baseNow > 0) and (effective / baseNow) or 1
local percent = math.floor(curve * stationRatio + 0.5)
local top = percent > 0 and (effective * 100 / percent) or effective
return {price = effective, top = top, percent = percent}
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