DopingControl v0.6.4
This commit is contained in:
+62
-6
@@ -67,6 +67,11 @@ T.ASK_GAP = 5
|
||||
-- do not ask the same player again for this long. Talents change on
|
||||
-- respec, which is rare and never mid-raid.
|
||||
T.REASK_AFTER = 1800
|
||||
-- how long an unfinished reply stays open. A whole reply lands within a
|
||||
-- fraction of a second, so a line arriving this much later cannot belong to
|
||||
-- it -- it is the start of a NEW reply and must not be folded into the old
|
||||
-- accumulator (see T.AccStale).
|
||||
T.ACC_TTL = 10
|
||||
|
||||
-- ==================================================================
|
||||
-- PURE SECTION (offline-testable)
|
||||
@@ -147,9 +152,24 @@ end
|
||||
-- spent = <sum of pointsSpent over the trees that reported>,
|
||||
-- sumRank = <sum of every rank we stored>,
|
||||
-- trees = <how many tab lines arrived>,
|
||||
-- complete = <INSTalentEND seen> }
|
||||
function T.NewAcc()
|
||||
return { ranks = {}, spent = 0, sumRank = 0, trees = 0, complete = false }
|
||||
-- complete = <INSTalentEND seen>,
|
||||
-- at = <when the first line arrived, nil offline> }
|
||||
function T.NewAcc(now)
|
||||
return { ranks = {}, spent = 0, sumRank = 0, trees = 0, complete = false,
|
||||
at = now }
|
||||
end
|
||||
|
||||
-- Has this accumulator been waiting so long that the next line must belong to
|
||||
-- a different reply? Only the END marker drops an accumulator, so a reply
|
||||
-- whose tail was lost would otherwise stay open forever and swallow the next
|
||||
-- one: tab lines add up twice while ranks are deduplicated by name, so
|
||||
-- T.Plausible rejects a perfectly good retry. Without a clock (offline) or an
|
||||
-- opening stamp nothing expires -- the old behaviour, unchanged.
|
||||
function T.AccStale(acc, now)
|
||||
if not acc or not acc.at or not now then
|
||||
return false
|
||||
end
|
||||
return (now - acc.at) > T.ACC_TTL
|
||||
end
|
||||
|
||||
-- Fold one parsed line into the accumulator. Returns the accumulator so
|
||||
@@ -281,6 +301,9 @@ if CreateFrame then
|
||||
return ok
|
||||
end
|
||||
|
||||
-- set below, once the frame exists: arms the paced sender
|
||||
local arm
|
||||
|
||||
-- Called by the scan with the players it can see. Nothing is sent here
|
||||
-- -- names are only lined up; the timer below paces them out.
|
||||
function T.Request(names)
|
||||
@@ -296,6 +319,9 @@ if CreateFrame then
|
||||
table.insert(queue, n)
|
||||
end
|
||||
end
|
||||
if arm and table.getn(queue) > 0 then
|
||||
arm()
|
||||
end
|
||||
end
|
||||
|
||||
local f = CreateFrame("Frame", "DopingControlTalentFrame")
|
||||
@@ -313,9 +339,14 @@ if CreateFrame then
|
||||
if not kind then
|
||||
return
|
||||
end
|
||||
local now = GetTime()
|
||||
local a = acc[sender]
|
||||
if a and T.AccStale(a, now) then
|
||||
-- the previous reply lost its END line; this one starts fresh
|
||||
a = nil
|
||||
end
|
||||
if not a then
|
||||
a = T.NewAcc()
|
||||
a = T.NewAcc(now)
|
||||
acc[sender] = a
|
||||
end
|
||||
T.Feed(a, kind, data)
|
||||
@@ -338,14 +369,26 @@ if CreateFrame then
|
||||
-- queue the scan filled. Deliberately a plain timer rather than a burst
|
||||
-- after each scan -- 40 requests in one frame is what a rate limit
|
||||
-- would punish, and nothing documents where that limit sits.
|
||||
--
|
||||
-- It is installed only while there is something to send and takes itself
|
||||
-- off again the moment the queue runs dry (or the feature is switched
|
||||
-- off): an OnUpdate runs 60+ times a second for the whole session, and a
|
||||
-- player who never scans must not pay for a queue that is always empty.
|
||||
-- Re-arming needs no extra wiring -- every scan calls T.Request.
|
||||
local elapsed = 0
|
||||
f:SetScript("OnUpdate", function()
|
||||
|
||||
local function disarm()
|
||||
f:SetScript("OnUpdate", nil)
|
||||
end
|
||||
|
||||
local function drain()
|
||||
elapsed = elapsed + (arg1 or 0)
|
||||
if elapsed < 1 then
|
||||
return
|
||||
end
|
||||
elapsed = 0
|
||||
if not enabled() or table.getn(queue) == 0 then
|
||||
disarm()
|
||||
return
|
||||
end
|
||||
local now = GetTime()
|
||||
@@ -359,10 +402,23 @@ if CreateFrame then
|
||||
T.Ask(name)
|
||||
end
|
||||
end
|
||||
end)
|
||||
if table.getn(queue) == 0 then
|
||||
disarm()
|
||||
end
|
||||
end
|
||||
|
||||
arm = function()
|
||||
if f:GetScript("OnUpdate") then
|
||||
return
|
||||
end
|
||||
-- a long idle gap must not fire an immediate burst
|
||||
elapsed = 0
|
||||
f:SetScript("OnUpdate", drain)
|
||||
end
|
||||
|
||||
-- forget everything (respec, or a deliberate re-read)
|
||||
function T.Clear()
|
||||
disarm()
|
||||
acc = {}
|
||||
ranks = {}
|
||||
readAt = {}
|
||||
|
||||
Reference in New Issue
Block a user