Mercurial > wow > breuesk
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 104:9aa2dcbbdc87 | 105:c6c748a5823b |
|---|---|
| 13 local getn=getn | 13 local getn=getn |
| 14 setfenv(1,bsk) | 14 setfenv(1,bsk) |
| 15 | 15 |
| 16 adminList = {} | 16 adminList = {} |
| 17 | 17 |
| 18 local lastZoneTime = 0 | |
| 19 local function ZoneChanged() | |
| 20 lastZoneTime = _G.time() | |
| 21 end | |
| 18 local function GuildRosterUpdate() | 22 local function GuildRosterUpdate() |
| 19 local guildInfoText = _G.GetGuildInfoText() | 23 local guildInfoText = _G.GetGuildInfoText() |
| 24 if lastZoneTime+5 > _G.time() then return end -- silly workaround - GGIT() returns "" when you zone in | |
| 20 local newAdminList = {} | 25 local newAdminList = {} |
| 21 for line in guildInfoText:gmatch("[^\r\n]+") do | 26 for line in guildInfoText:gmatch("[^\r\n]+") do |
| 22 local l,r = line:match("(.*):(.*)") -- could use wow strsplit had I known about it before writing this | 27 local l,r = line:match("(.*):(.*)") -- could use wow strsplit had I known about it before writing this |
| 23 l = string.trim(l or "") | 28 l = string.trim(l or "") |
| 24 r = string.trim(r or "") | 29 r = string.trim(r or "") |
| 65 end | 70 end |
| 66 | 71 |
| 67 function RemoteAdminUpdateReceived(sender,remoteAdminStatusTable) | 72 function RemoteAdminUpdateReceived(sender,remoteAdminStatusTable) |
| 68 if not admin then return end | 73 if not admin then return end |
| 69 | 74 |
| 70 local rs = remoteAdminStatusTable | 75 local rs,base,changes = unpack(remoteAdminStatusTable) |
| 71 local events = {} -- record all timestamps seen in this update | |
| 72 for i,_ in pairs(adminList) do -- update each admin's entry in your own DB | 76 for i,_ in pairs(adminList) do -- update each admin's entry in your own DB |
| 73 | 77 |
| 74 -- grab the db copy and the incoming copy for that admin | 78 if i ~= me then |
| 75 if not db.profile.adminStatus then db.profile.adminStatus = {} end | 79 -- grab the db copy and the incoming copy for that admin |
| 76 local dbs = db.profile.adminStatus[i] or {base=0, changes={}} | 80 if not db.profile.adminStatus then db.profile.adminStatus = {} end |
| 77 local ics = rs[i] or {base=0, changes={}} | 81 local dbs = db.profile.adminStatus[i] or {base=0, changes={}} |
| 78 | 82 local ics = rs[i] or {base=0, changes={}} |
| 79 -- figure out which is better and keep that one | 83 |
| 80 -- winning criteria: | 84 -- figure out which is better and keep that one |
| 81 -- * broadcast was actually from that person (ie best | 85 -- winning criteria: |
| 82 -- verification possible) | 86 -- * broadcast was actually from that person (ie best |
| 83 -- * newer base | 87 -- verification possible) |
| 84 -- * same base, more entries | 88 -- * newer base |
| 85 -- * todo: see if date last observed is a better option | 89 -- * same base, more entries |
| 86 | 90 -- * todo: see if date last observed is a better option |
| 87 if i==sender then | 91 |
| 88 db.profile.adminStatus[i] = ics | 92 if i==sender then |
| 89 elseif ics.base > dbs.base or (ics.base==dbs.base and getn(ics.changes) > getn(dbs.changes)) then | 93 db.profile.adminStatus[i] = ics |
| 90 db.profile.adminStatus[i] = ics | 94 elseif ics.base > dbs.base or (ics.base==dbs.base and getn(ics.changes) > getn(dbs.changes)) then |
| 91 end | 95 db.profile.adminStatus[i] = ics |
| 92 end | 96 end |
| 93 | 97 end |
| 94 local rss = rs[sender] | 98 end |
| 95 | 99 |
| 96 -- now figure out what I'm missing - and ask for it! | 100 if changes and getn(changes)>0 then |
| 97 | 101 IntegrateChangeDiff(base,changes) |
| 98 -- construct a hash table of all entries that the sender has / should have | 102 end |
| 99 local entries = {} | 103 |
| 100 for i,v in pairs(rs) do | 104 -- trim if the replies said it's safe |
| 101 if v.changes then | 105 |
| 102 for j,k in pairs(v.changes) do | 106 local trimPoint = db.profile.time |
| 103 entries[k.time] = true | 107 -- come up with a tentative starting point (max base) |
| 104 end | 108 for i,v in pairs(db.profile.adminStatus) do |
| 105 end | 109 if v.base > trimPoint then trimPoint = v.base end |
| 106 end | 110 end |
| 107 -- now go back and scrub my own keys from that list | 111 |
| 112 local pointer = {} | |
| 113 -- fast forward pointers *past* the trimPoint in each list | |
| 114 for p,l in pairs(db.profile.adminStatus) do | |
| 115 pointer[p] = 1 | |
| 116 for i,v in ipairs(l.changes) do | |
| 117 if v <= trimPoint then | |
| 118 pointer[p] = i+1 -- "past" the trim point - might point to nil | |
| 119 else | |
| 120 break | |
| 121 end | |
| 122 end | |
| 123 end | |
| 124 print("pointers") | |
| 125 PrintTable(pointer) | |
| 126 | |
| 108 for i,v in ipairs(db.profile.changes) do | 127 for i,v in ipairs(db.profile.changes) do |
| 109 entries[v.time] = nil | 128 if v.time > trimPoint then -- advance to the trim point estimate before doing anything |
| 110 end | 129 -- into uncharted territory, let's see how far we can push it |
| 111 -- what's left is what I need to ask for | 130 local continue = true |
| 112 local request = {} | 131 for p,t in pairs(pointer) do |
| 113 for i,v in pairs(entries) do | 132 local dbpapct = db.profile.adminStatus[p].changes[t] |
| 114 if v then table.insert(request,i) end | 133 if dbpapct and dbpapct==v.time then |
| 115 end | 134 pointer[p] = pointer[p]+1 |
| 116 table.sort(request) | 135 else |
| 117 Comm:RequestSpecificChanges(request,sender) | 136 continue=false |
| 118 | 137 break |
| 119 for | 138 end |
| 120 -- specifically leaving this broken. note to self. | 139 trimPoint = v.time |
| 121 -- this still isn't good enough. it doesn't communicate an admin's | 140 end |
| 122 -- present working state. like if they had put in new changes since | 141 if not continue then break end |
| 123 -- loading up. or learned of some changes to fill in an old gap | 142 end |
| 143 end | |
| 144 print("pointers") | |
| 145 PrintTable(pointer) | |
| 146 if trimPoint > db.profile.time then | |
| 147 | |
| 148 -- protect trimming back to beginning of previous month so we're not | |
| 149 -- trimming like madmen | |
| 150 local ct = _G.date("*t",_G.time()) | |
| 151 ct.month = ct.month-1 | |
| 152 if ct.month < 1 then ct.month = 12 end | |
| 153 ct.day = 1 | |
| 154 ct.hour = 1 | |
| 155 ct.minute = 0 | |
| 156 ct.sec = 0 | |
| 157 local ts = _G.time(ct) | |
| 158 print("I think I can trim to",trimPoint,ts) | |
| 159 TrimLists(ts) | |
| 160 else | |
| 161 print("no bother trimming",trimPoint) | |
| 162 end | |
| 124 end | 163 end |
| 125 | 164 |
| 126 function InitializeAdmin() | 165 function InitializeAdmin() |
| 127 if not event then | 166 if not event then |
| 128 _G.error("BSK: Improper order of initialization") | 167 _G.error("BSK: Improper order of initialization") |
| 151 onloadAdminStatus = {} | 190 onloadAdminStatus = {} |
| 152 db.profile.adminStatus = nil | 191 db.profile.adminStatus = nil |
| 153 end | 192 end |
| 154 | 193 |
| 155 event:RegisterEvent("GUILD_ROSTER_UPDATE",GuildRosterUpdate) | 194 event:RegisterEvent("GUILD_ROSTER_UPDATE",GuildRosterUpdate) |
| 195 event:RegisterEvent("ZONE_CHANGED_NEW_AREA",ZoneChanged) | |
| 196 event:RegisterEvent("ZONE_CHANGED_INDOORS",ZoneChanged) | |
| 197 event:RegisterEvent("ZONE_CHANGED",ZoneChanged) | |
| 156 _G.GuildRoster() -- will eventually force the event to fire | 198 _G.GuildRoster() -- will eventually force the event to fire |
| 157 | 199 |
| 158 if me == "Breuemama" then -- debugging only | 200 if me == "Breuemama" then -- debugging only |
| 159 GuildRosterUpdate() | 201 GuildRosterUpdate() |
| 160 end | 202 end |
