diff Admin.lua @ 105:c6c748a5823b tip

Collaborative list trimming 80% functional Updates for the zone-in problem
author John@Yosemite-PC
date Sun, 06 May 2012 08:33:34 -0400
parents d3ea0ab1428d
children
line wrap: on
line diff
--- a/Admin.lua	Sun May 06 08:30:15 2012 -0400
+++ b/Admin.lua	Sun May 06 08:33:34 2012 -0400
@@ -15,8 +15,13 @@
 
 adminList = {}
 
+local lastZoneTime = 0
+local function ZoneChanged()
+    lastZoneTime = _G.time()
+end
 local function GuildRosterUpdate()
     local guildInfoText = _G.GetGuildInfoText()
+    if lastZoneTime+5 > _G.time() then return end -- silly workaround - GGIT() returns "" when you zone in
     local newAdminList = {}
     for line in guildInfoText:gmatch("[^\r\n]+") do
         local l,r = line:match("(.*):(.*)") -- could use wow strsplit had I known about it before writing this
@@ -67,60 +72,94 @@
 function RemoteAdminUpdateReceived(sender,remoteAdminStatusTable)
     if not admin then return end
 
-    local rs = remoteAdminStatusTable
-    local events = {} -- record all timestamps seen in this update
+    local rs,base,changes = unpack(remoteAdminStatusTable)
     for i,_ in pairs(adminList) do -- update each admin's entry in your own DB
 
-        -- grab the db copy and the incoming copy for that admin
-        if not db.profile.adminStatus then db.profile.adminStatus = {} end
-        local dbs = db.profile.adminStatus[i] or {base=0, changes={}}
-        local ics = rs[i] or {base=0, changes={}}
+        if i ~= me then
+            -- grab the db copy and the incoming copy for that admin
+            if not db.profile.adminStatus then db.profile.adminStatus = {} end
+            local dbs = db.profile.adminStatus[i] or {base=0, changes={}}
+            local ics = rs[i] or {base=0, changes={}}
 
-        -- figure out which is better and keep that one
-        -- winning criteria:
-        --  * broadcast was actually from that person (ie best
-        --  verification possible)
-        --  * newer base
-        --  * same base, more entries
-        --  * todo: see if date last observed is a better option
+            -- figure out which is better and keep that one
+            -- winning criteria:
+            --  * broadcast was actually from that person (ie best
+            --  verification possible)
+            --  * newer base
+            --  * same base, more entries
+            --  * todo: see if date last observed is a better option
 
-        if i==sender then
-            db.profile.adminStatus[i] = ics
-        elseif ics.base > dbs.base or (ics.base==dbs.base and getn(ics.changes) > getn(dbs.changes)) then
-            db.profile.adminStatus[i] = ics
+            if i==sender then
+                db.profile.adminStatus[i] = ics
+            elseif ics.base > dbs.base or (ics.base==dbs.base and getn(ics.changes) > getn(dbs.changes)) then
+                db.profile.adminStatus[i] = ics
+            end
         end
     end
 
-    local rss = rs[sender]
+    if changes and getn(changes)>0 then
+        IntegrateChangeDiff(base,changes)
+    end
 
-    -- now figure out what I'm missing - and ask for it!
+    -- trim if the replies said it's safe
 
-    -- construct a hash table of all entries that the sender has / should have
-    local entries = {}
-    for i,v in pairs(rs) do
-        if v.changes then 
-            for j,k in pairs(v.changes) do
-                entries[k.time] = true
+    local trimPoint = db.profile.time
+    -- come up with a tentative starting point (max base)
+    for i,v in pairs(db.profile.adminStatus) do
+        if v.base > trimPoint then trimPoint = v.base end
+    end
+
+    local pointer = {}
+    -- fast forward pointers *past* the trimPoint in each list
+    for p,l in pairs(db.profile.adminStatus) do
+        pointer[p] = 1
+        for i,v in ipairs(l.changes) do
+            if v <= trimPoint then
+                pointer[p] = i+1 -- "past" the trim point - might point to nil
+            else
+                break
             end
         end
     end
-    -- now go back and scrub my own keys from that list
+    print("pointers")
+    PrintTable(pointer)
+
     for i,v in ipairs(db.profile.changes) do
-        entries[v.time] = nil
+        if v.time > trimPoint then -- advance to the trim point estimate before doing anything
+            -- into uncharted territory, let's see how far we can push it
+            local continue = true
+            for p,t in pairs(pointer) do
+                local dbpapct = db.profile.adminStatus[p].changes[t] 
+                if dbpapct and dbpapct==v.time then
+                    pointer[p] = pointer[p]+1
+                else
+                    continue=false
+                    break
+                end
+                trimPoint = v.time
+            end
+            if not continue then break end
+        end
     end
-    -- what's left is what I need to ask for
-    local request = {}
-    for i,v in pairs(entries) do
-        if v then table.insert(request,i) end
+    print("pointers")
+    PrintTable(pointer)
+    if trimPoint > db.profile.time then
+
+        -- protect trimming back to beginning of previous month so we're not
+        -- trimming like madmen
+        local ct = _G.date("*t",_G.time())
+        ct.month = ct.month-1
+        if ct.month < 1 then ct.month = 12 end
+        ct.day = 1
+        ct.hour = 1
+        ct.minute = 0
+        ct.sec = 0
+        local ts = _G.time(ct)
+        print("I think I can trim to",trimPoint,ts)
+        TrimLists(ts)
+    else
+        print("no bother trimming",trimPoint)
     end
-    table.sort(request)
-    Comm:RequestSpecificChanges(request,sender)
-
-    for
-        -- specifically leaving this broken. note to self.
-        -- this still isn't good enough. it doesn't communicate an admin's
-        -- present working state. like if they had put in new changes since
-        -- loading up. or learned of some changes to fill in an old gap
 end
 
 function InitializeAdmin()
@@ -153,6 +192,9 @@
     end
 
     event:RegisterEvent("GUILD_ROSTER_UPDATE",GuildRosterUpdate)
+    event:RegisterEvent("ZONE_CHANGED_NEW_AREA",ZoneChanged)
+    event:RegisterEvent("ZONE_CHANGED_INDOORS",ZoneChanged)
+    event:RegisterEvent("ZONE_CHANGED",ZoneChanged)
     _G.GuildRoster() -- will eventually force the event to fire
 
     if me == "Breuemama" then -- debugging only