參考資料 › 函式參考 › Functions

Functions.forecast.calculate

公用

呼叫方式

Functions.forecast.calculate(platform, history, window, noheals, nodmg, now)

將它記錄為名為 Functions.forecast.calculate 的相依項目(接受自動完成即可完成此步驟),然後以該名稱呼叫。

作用

使用明確的有限時間區間與時鐘,計算經過檢查的生命力歷史速率。保留有序加權、逐列即時標準捨入、被略過的資料流、陣列空洞、小數鍵以及最終存取時的時長。固定的 4096 單位預算涵蓋兩個資料流中被存取的列與累加區間;超出預算或無效的已消耗運算會傳回無法使用,絕不傳回部分估算或截斷值。這個新 API 有其自己的原始碼身分;歷史趨勢函式保持不變。

參數

名稱類型作用
platformRMPlatform所使用值的可讀性判定依據。
historytable由時間/數值列組成的傷害/治療陣列;只會使用所選的資料流。
windownumber明確的有限加權時間區間;不會改用設定檔或截斷。
nohealsboolean為 true 時略過對治療資料流的所有存取。
nodmgboolean為 true 時略過對傷害資料流的所有存取。
nownumber明確的有限時鐘快照;帶正負號與小數值仍然有效。

傳回值

1number | nil有限的帶正負號合併速率;計算無法使用時為 nil。
2number | nil有限的最終資料流時長;無法使用時為 nil。
3string | nil速率/時長為 nil 時的工作量上限、資料或運算可用性原因。

版本

內建輔助函式在每個版本上都會註冊。不同的是它們讀取的遊戲 API;某個 API 不存在時,輔助函式會改用備用方式,或傳回 nil 並附上原因。

它不會直接讀取任何遊戲 API。

機密值(正式版與永久)

在正式版與永久上,遊戲交給插件的是機密值。此輔助函式會檢查它讀取的內容(addon.Platform:CanReadValue),遇到無法比較的機密值時,會傳回 nil 並附上原因(例如 restricted-value),而不是傳回該機密值。請將 nil 視為無法使用,而非假。

範例

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 < 0

相依項目

原始碼

Functions/forecast.lua,第 61 行。在遊戲中為唯讀;「複製」會產生一份可編輯的複本。

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

返回函式參考