Mercurial > wow > breuesk
view 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 source
local bsk=bsk local _G=_G local table=table local pairs=pairs local setmetatable=setmetatable local ipairs=ipairs local string=string local sformat=string.format local strsplit=strsplit local tostring=tostring local type=type local unpack=unpack local getn=getn setfenv(1,bsk) 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 l = string.trim(l or "") r = string.trim(r or "") if l == "BSKADMIN" then -- found a juicy line. may contain multiple, comma or space delimited local admins = {strsplit(", ",r)} for _,a in pairs(admins) do a = string.trim(a or "") if a ~= "" then newAdminList[a] = true end end end end if me == "Breuemama" then -- todo: strictly debugging ... newAdminList[me] = true newAdminList["Breue"] = true end if _G.next(adminList) ~= nil then -- had old admins. don't want to spam on initial load -- diff new vs old for a in pairs(adminList) do if not newAdminList[a] then print("Admin removed:", a) end end for a in pairs(newAdminList) do if not adminList[a] then print("Admin added:",a) end end end adminList = newAdminList if adminList[me] then -- I'm an admin! admin = true bsk.db.profile.admin = true RegisterAdminChannels() else admin = false bsk.db.profile.admin = false UnregisterAdminChannels() end end function RemoteAdminUpdateReceived(sender,remoteAdminStatusTable) if not admin then return end local rs,base,changes = unpack(remoteAdminStatusTable) for i,_ in pairs(adminList) do -- update each admin's entry in your own DB 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 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 if changes and getn(changes)>0 then IntegrateChangeDiff(base,changes) end -- trim if the replies said it's safe 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 print("pointers") PrintTable(pointer) for i,v in ipairs(db.profile.changes) do 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 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 end function InitializeAdmin() if not event then _G.error("BSK: Improper order of initialization") end me = _G.UnitName("player") if admin then -- if at last login I was an admin ... -- note that we're not transmitting anything here. we'll do that once we -- know for certain we're an admin -- cache the onload status in case it changes in memory later onloadAdminStatus = {} tcopy(onloadAdminStatus,db.profile.adminStatus) -- update our own entry - safe because comms shouldn't have happened yet if not onloadAdminStatus then onloadAdminStatus = {} end if not onloadAdminStatus[me] then onloadAdminStatus[me] = {} end onloadAdminStatus[me].base = db.profile.time or 0 onloadAdminStatus[me].changes= {} for _,v in ipairs(db.profile.changes) do table.insert(onloadAdminStatus[me].changes,v.time) -- only timestamps end else -- otherwise store a blank slate onloadAdminStatus = {} db.profile.adminStatus = nil 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 GuildRosterUpdate() end end