Llamar como
Functions.forecast.calculate(platform, history, window, noheals, nodmg, now)
Regístrala como dependencia con el nombre Functions.forecast.calculate (aceptar la sugerencia de autocompletado lo hace por ti) y luego llámala con ese nombre.
Qué hace
Calcula un ritmo comprobado del historial de salud usando una ventana y un reloj finitos explícitos. Conserva la ponderación ordenada, el redondeo canónico en vivo por fila, los flujos omitidos, los huecos de las matrices, las claves fraccionarias y las edades finales recorridas. Un presupuesto fijo de 4096 unidades cubre las filas recorridas y los contenedores de acumulación de ambos flujos; el exceso o la aritmética consumida no válida devuelve no disponible, nunca una estimación parcial ni un valor recortado. Esta API nueva tiene su propia identidad de código; las funciones históricas de tendencia no cambian.
Argumentos
| Nombre | Tipo | Qué hace |
|---|---|---|
platform | RMPlatform | Autoridad de legibilidad para los valores consumidos. |
history | table | Matrices de daño/sanación con filas de tiempo/valor; solo se consumen los flujos seleccionados. |
window | number | Ventana de ponderación explícita y finita; sin alternativa del perfil ni recorte. |
noheals | boolean | True omite todo acceso al flujo de sanación. |
nodmg | boolean | True omite todo acceso al flujo de daño. |
now | number | Instantánea explícita y finita del reloj; los valores con signo y fraccionarios siguen siendo válidos. |
Retornos
| 1 | number | nil | Ritmo combinado finito con signo, o nil si el cálculo no está disponible. |
|---|---|---|
| 2 | number | nil | Edad final finita del flujo, o nil si no está disponible. |
| 3 | string | nil | Motivo de disponibilidad del límite de trabajo, los datos o la aritmética para un ritmo/edad nil. |
Ediciones
Las funciones auxiliares integradas se registran en todas las ediciones. Lo que cambia es la API del juego que leen; donde falta alguna, la función auxiliar recurre a una alternativa o devuelve nil con un motivo.
No lee directamente ninguna API del juego.
Valores secretos (Retail y Forever)
En Retail y Forever, el juego entrega a los addons valores secretos. Esta función auxiliar comprueba lo que lee (addon.Platform:CanReadValue) y, en lugar de un secreto que no puede comparar, devuelve nil con un motivo como restricted-value. Trata nil como no disponible, no como falso.
Ejemplo
local guid = UnitGUID("player")
local history = guid and addon.damageHistory[guid]
if not history then return nil, "no-history" end
local rate, age, reason = Functions.forecast.calculate(addon.Platform, history, 5, false, false, GetTime())
if rate == nil then return nil, reason end
return age >= 2 and rate < 0Dependencias
finite→Functions.forecast.finitereadField→Functions.forecast.readField
Código fuente
Functions/forecast.lua, línea 61. Solo lectura en el juego; Duplicar crea una copia editable.
Functions.forecast.calculate(platform, history, window, noheals, nodmg, now)
if type(platform)~='table' or type(platform.CanReadValue)~='function' then return nil,nil,'invalid-forecast-platform' end
if not platform:CanReadValue(history) or not platform:CanReadValue(noheals) or not platform:CanReadValue(nodmg) then return nil,nil,'restricted-value' end
if type(history)~='table' then return nil,nil,'invalid-forecast-history' end
if type(noheals)~='boolean' or type(nodmg)~='boolean' then return nil,nil,'invalid-forecast-mode' end
local valid,reason=finite(platform,window)
if not valid then return nil,nil,reason end
valid,reason=finite(platform,now)
if not valid then return nil,nil,reason end
local work=0
local function scan(name,skip)
if skip then return 0,0,0 end
local rows,why=readField(platform,history,name)
if why then return nil,nil,nil,why end
if type(rows)~='table' then return nil,nil,nil,'invalid-forecast-stream' end
local maxoffs,data=0,{}
for _,row in ipairs(rows) do
work=work+1
if work>4096 then return nil,nil,nil,'forecast-work-budget' end
local time,problem=readField(platform,row,'time')
if problem then return nil,nil,nil,problem end
local good,numberReason=finite(platform,time)
if not good then return nil,nil,nil,numberReason end
local diff=now-time
good,numberReason=finite(platform,diff)
if not good then return nil,nil,nil,numberReason end
local scale=window-diff
local functions,namespaceReason=readField(platform,addon,'Functions')
if namespaceReason then return nil,nil,nil,namespaceReason end
if type(functions)~='table' then return nil,nil,nil,'forecast-round-unavailable' end
local values
values,namespaceReason=readField(platform,functions,'values')
if namespaceReason then return nil,nil,nil,namespaceReason end
if type(values)~='table' then return nil,nil,nil,'forecast-round-unavailable' end
local round
round,namespaceReason=readField(platform,values,'round')
if namespaceReason then return nil,nil,nil,namespaceReason end
if type(round)~='function' then return nil,nil,nil,'forecast-round-unavailable' end
local ok,rounded=pcall(round,diff)
if not ok then return nil,nil,nil,'forecast-round-error' end
good,numberReason=finite(platform,rounded)
if not good then return nil,nil,nil,numberReason end
maxoffs=rounded
if maxoffs>window then break end
local amount,amountReason=readField(platform,row,'value')
if amountReason then return nil,nil,nil,amountReason end
if amount~=nil and amount~=false then
good,numberReason=finite(platform,amount)
if not good then return nil,nil,nil,numberReason end
good,numberReason=finite(platform,scale)
if not good then return nil,nil,nil,numberReason end
local product=amount*scale
good,numberReason=finite(platform,product)
if not good then return nil,nil,nil,numberReason end
local value=(data[maxoffs] or 0)+product
good,numberReason=finite(platform,value)
if not good then return nil,nil,nil,numberReason end
data[maxoffs]=value
end
end
local bins=maxoffs<0 and 0 or math.floor(maxoffs)+1
if bins>4096-work then return nil,nil,nil,'forecast-work-budget' end
work=work+bins
local total,count=0,0
for i=0,maxoffs do
total=total+(data[i] or 0)
local good,numberReason=finite(platform,total)
if not good then return nil,nil,nil,numberReason end
local scale=window-i
good,numberReason=finite(platform,scale)
if not good then return nil,nil,nil,numberReason end
count=count+scale
good,numberReason=finite(platform,count)
if not good then return nil,nil,nil,numberReason end
end
return total,count,maxoffs
end
local damageTotal,damageCount,damageSeconds,damageReason=scan('damage',nodmg)
if damageReason then return nil,nil,damageReason end
local healTotal,healCount,healSeconds,healReason=scan('heals',noheals)
if healReason then return nil,nil,healReason end
local damageRate=damageCount>0 and -damageTotal/damageCount or 0
valid,reason=finite(platform,damageRate)
if not valid then return nil,nil,reason end
local healRate=healCount>0 and healTotal/healCount or 0
valid,reason=finite(platform,healRate)
if not valid then return nil,nil,reason end
local rate=damageRate+healRate
valid,reason=finite(platform,rate)
if not valid then return nil,nil,reason end
return rate,damageSeconds>healSeconds and damageSeconds or healSeconds