comparison Lists.lua @ 42:72055fc7e115

A lot of work to reign in namespacing (inspiration: WIM)
author John@Doomsday
date Thu, 15 Mar 2012 08:47:41 -0400
parents dc9bfacca238
children 4109683c3172
comparison
equal deleted inserted replaced
41:dc9bfacca238 42:72055fc7e115
60 -- * actually, fuck it. I'll give them an unlock command and 60 -- * actually, fuck it. I'll give them an unlock command and
61 -- let them screw over their lists :) 61 -- let them screw over their lists :)
62 --}}} 62 --}}}
63 63
64 -- there are some dep chains here. for instance, to have a raidIdP value, a 64 -- there are some dep chains here. for instance, to have a raidIdP value, a
65 -- person must have a bsk.persons value which leads to a personName2id which 65 -- person must have a persons value which leads to a personName2id which
66 -- leads to a raidIdP 66 -- leads to a raidIdP
67 67 local bsk = bsk
68 bsk.lists = {} 68 local _G=_G
69 bsk.persons = {} 69 local table=table
70 70 local string=string
71 bsk.raidNameP = {} -- "name" is present in raid
72 bsk.raidIdP = {} -- "id" is present in raid
73 bsk.reserveIdP = {} -- "reserve id present"
74 local personName2id = {} -- given "name" get that person's id
75
76 local tinsert = table.insert 71 local tinsert = table.insert
77 local sformat = string.format 72 local sformat = string.format
78 local getn = table.getn 73 local getn = table.getn
79 74 local wipe = wipe
80 function bsk:SelfDestruct() 75 local pairs=pairs
81 bsk.lists = {} 76 local ipairs=ipairs
82 bsk.persons = {} 77 local tonumber=tonumber
83 bsk.db.profile.persons = {} 78 local tostring=tostring
84 bsk.db.profile.changes = {} 79 local time=time
85 bsk.db.profile.lists = {} 80 local date=date
86 bsk.raidNameP = {} 81 local math=math
87 bsk.raidIdP = {} 82 local type=type
88 bsk.reserveIdP = {} 83 local assert=assert
84 local getmetatable=getmetatable
85 local setmetatable=setmetatable
86 setfenv(1,bsk)
87
88 lists = {}
89 persons = {}
90
91 raidNameP = {} -- "name" is present in raid
92 raidIdP = {} -- "id" is present in raid
93 reserveIdP = {} -- "reserve id present"
94 local personName2id = {} -- given "name" get that person's id
95
96
97 function SelfDestruct()
98 lists = {}
99 persons = {}
100 db.profile.persons = {}
101 db.profile.changes = {}
102 db.profile.lists = {}
103 raidNameP = {}
104 raidIdP = {}
105 reserveIdP = {}
89 personName2id = {} 106 personName2id = {}
90 end 107 end
91 function bsk:tcopy(to, from) 108 function tcopy(to, from)
92 for k,v in pairs(from) do 109 for k,v in pairs(from) do
93 if(type(v)=="table") then 110 if(type(v)=="table") then
94 to[k] = {} 111 to[k] = {}
95 bsk:tcopy(to[k], v); 112 tcopy(to[k], v);
96 else 113 else
97 to[k] = v; 114 to[k] = v;
98 end 115 end
99 end 116 end
100 end 117 end
103 for k, v in pairs(t) do u[k] = v end 120 for k, v in pairs(t) do u[k] = v end
104 return setmetatable(u, getmetatable(t)) 121 return setmetatable(u, getmetatable(t))
105 end 122 end
106 123
107 -- Debugging {{{ 124 -- Debugging {{{
108 function bsk:PrettyPrintList(listIndex) 125 function PrettyPrintList(listIndex)
109 local list = bsk.lists[listIndex] 126 local list = lists[listIndex]
110 bsk:Print("List: " .. list.name .. " (" .. listIndex .. ") - last modified " .. date("%m/%d/%y %H:%M:%S", list.time) .. " (",list.time,")" ) 127 bsk:Print("List: " .. list.name .. " (" .. listIndex .. ") - last modified " .. date("%m/%d/%y %H:%M:%S", list.time) .. " (",list.time,")" )
111 for i = 1,#list do 128 for i = 1,#list do
112 bsk:Print(" " .. i .. " - " .. bsk.persons[list[i].id].main) 129 bsk:Print(" " .. i .. " - " .. persons[list[i].id].main)
113 end 130 end
114 end 131 end
115 function bsk:PrettyPrintLists() 132 function PrettyPrintLists()
116 for i,_ in pairs(bsk.lists) do 133 for i,_ in pairs(lists) do
117 bsk:PrettyPrintList(i) 134 PrettyPrintList(i)
118 end 135 end
119 end 136 end
120 function bsk:PrintLists() 137 function PrintLists()
121 bsk:PrintTable(bsk.lists) 138 PrintTable(lists)
122 end 139 end
123 function bsk:PrintChanges() 140 function PrintChanges()
124 bsk:PrintTable(bsk.db.profile.changes) 141 PrintTable(db.profile.changes)
125 end 142 end
126 function bsk:PrintPersons() 143 function PrintPersons()
127 bsk:PrintTable(bsk.persons) 144 PrintTable(persons)
128 end 145 end
129 function bsk:PrintAPI(object) 146 function PrintAPI(object)
130 for i,v in pairs(object) do 147 for i,v in pairs(object) do
131 if type(v) == "function" then 148 if type(v) == "function" then
132 bsk:Print("function "..i.."()") 149 bsk:Print("function "..i.."()")
133 end 150 end
134 end 151 end
135 end 152 end
136 function bsk:PrintTable(table, depth) 153 function PrintTable(table, depth)
137 depth = depth or "" 154 depth = depth or ""
138 if not table then return end 155 if not table then return end
139 if #depth > 3*5 then self:Print(depth.."Recursion too deep - stopping"); return end 156 if #depth > 3*5 then bsk:Print(depth.."Recursion too deep - stopping"); return end
140 for i,v in pairs(table) do 157 for i,v in pairs(table) do
141 if( type(v) == "string" ) then 158 if( type(v) == "string" ) then
142 self:Print(depth .. i .. " - " .. v) 159 bsk:Print(depth .. i .. " - " .. v)
143 elseif( type(v) == "number" ) then 160 elseif( type(v) == "number" ) then
144 self:Print(depth .. i .. " - " .. tostring(v)) 161 bsk:Print(depth .. i .. " - " .. tostring(v))
145 elseif( type(v) == "table" ) then 162 elseif( type(v) == "table" ) then
146 self:Print(depth .. i .." - ") 163 bsk:Print(depth .. i .." - ")
147 self:PrintTable(v,depth.." ") 164 PrintTable(v,depth.." ")
148 elseif( type(v) == "boolean" ) then 165 elseif( type(v) == "boolean" ) then
149 self:Print(depth .. i .. " - " .. tostring(v)) 166 bsk:Print(depth .. i .. " - " .. tostring(v))
150 elseif( type(v) == "function" ) then 167 elseif( type(v) == "function" ) then
151 self:Print(depth .. "function " .. i .. "()") 168 bsk:Print(depth .. "function " .. i .. "()")
152 else 169 else
153 self:Print(depth .. i .. " - not sure how to print type: " .. type(v) ) 170 bsk:Print(depth .. i .. " - not sure how to print type: " .. type(v) )
154 end 171 end
155 end 172 end
156 end 173 end
157 174
158 function bsk:PrintRaidAndReserve() 175 function PrintRaidAndReserve()
159 bsk:Print("RaidNameP") 176 bsk:Print("RaidNameP")
160 bsk:PrintTable(bsk.raidNameP) 177 PrintTable(raidNameP)
161 bsk:Print("RaidIdP") 178 bsk:Print("RaidIdP")
162 bsk:PrintTable(bsk.raidIdP) 179 PrintTable(raidIdP)
163 bsk:Print("ReserveP") 180 bsk:Print("ReserveP")
164 bsk:PrintTable(bsk.reserveIdP) 181 PrintTable(reserveIdP)
165 bsk:Print("personName2id") 182 bsk:Print("personName2id")
166 bsk:PrintTable(personName2id) 183 PrintTable(personName2id)
167 end 184 end
168 --}}} 185 --}}}
169 186
170 function bsk:UpdatePersonsReverse() 187 function UpdatePersonsReverse()
171 for i,v in pairs(bsk.persons) do 188 for i,v in pairs(persons) do
172 if i ~= "time" then 189 if i ~= "time" then
173 personName2id[v.main] = i 190 personName2id[v.main] = i
174 end 191 end
175 end 192 end
176 end 193 end
177 194
178 -- Change processing {{{ 195 -- Czohange processing {{{
179 function bsk:CreateWorkingStateFromChanges(changes) 196 function CreateWorkingStateFromChanges(changes)
180 local personsBase = self.db.profile.persons 197 local personsBase = db.profile.persons
181 local lists = self.db.profile.lists 198 local lists = db.profile.lists
182 199
183 -- copy the base to the working state 200 -- copy the base to the working state
184 wipe(bsk.lists) 201 wipe(lists)
185 wipe(bsk.persons) 202 wipe(persons)
186 wipe(personName2id) 203 wipe(personName2id)
187 204
188 bsk:tcopy(bsk.lists,lists) 205 tcopy(lists,lists)
189 bsk:tcopy(bsk.persons,personsBase) 206 tcopy(persons,personsBase)
190 207
191 -- now just go through the changes list applying each 208 -- now just go through the changes list applying each
192 for i,v in ipairs(changes) do 209 for i,v in ipairs(changes) do
193 bsk:ProcessChange(v) 210 ProcessChange(v)
194 end 211 end
195 212
196 -- update the persons reverse list 213 -- update the persons reverse list
197 bsk:UpdatePersonsReverse() 214 UpdatePersonsReverse()
198 end 215 end
199 216
200 function bsk:CreateChange(change) 217 function CreateChange(change)
201 -- sanity 218 -- sanity
202 assert(change) 219 assert(change)
203 assert(change.action) 220 assert(change.action)
204 assert(change.arg) 221 assert(change.arg)
205 222
206 bsk:StartChange(change) 223 StartChange(change)
207 bsk:CommitChange(change) 224 CommitChange(change)
208 end 225 end
209 226
210 function bsk:StartChange(change) 227 function StartChange(change)
211 local changes = self.db.profile.changes 228 local changes = db.profile.changes
212 change.time = time() 229 change.time = time()
213 local n = getn(changes) 230 local n = getn(changes)
214 if n > 0 then 231 if n > 0 then
215 if changes[n].time >= change.time then 232 if changes[n].time >= change.time then
216 change.time = changes[n].time + 1 233 change.time = changes[n].time + 1
217 end 234 end
218 end 235 end
219 end 236 end
220 237
221 function bsk:CommitChange(change) 238 function CommitChange(change)
222 local changes = self.db.profile.changes 239 local changes = db.profile.changes
223 tinsert(changes,change) 240 tinsert(changes,change)
224 -- TODO: broadcast change 241 -- TODO: broadcast change
225 end 242 end
226 243
227 function bsk:ProcessChange(change) 244 function ProcessChange(change)
228 if change.action == "AddPerson" then 245 if change.action == "AddPerson" then
229 bsk:DoAddPerson(change) 246 DoAddPerson(change)
230 elseif change.action == "RenameList" then 247 elseif change.action == "RenameList" then
231 bsk:DoRenameList(change) 248 DoRenameList(change)
232 elseif change.action == "CreateList" then 249 elseif change.action == "CreateList" then
233 bsk:DoCreateList(change) 250 DoCreateList(change)
234 elseif change.action == "DeleteList" then 251 elseif change.action == "DeleteList" then
235 bsk:DoDeleteList(change) 252 DoDeleteList(change)
236 elseif change.action == "AddToListEnd" then 253 elseif change.action == "AddToListEnd" then
237 bsk:DoAddPersonToListEnd(change) 254 DoAddPersonToListEnd(change)
238 elseif change.action == "AddToListRand" then 255 elseif change.action == "AddToListRand" then
239 bsk:DoAddPersonToListRandom(change) 256 DoAddPersonToListRandom(change)
240 elseif change.action == "RemovePerson" then 257 elseif change.action == "RemovePerson" then
241 bsk:DoRemovePerson(change) 258 DoRemovePerson(change)
242 elseif change.action == "RemovePersonFromList" then 259 elseif change.action == "RemovePersonFromList" then
243 bsk:DoRemovePersonFromList(change) 260 DoRemovePersonFromList(change)
244 elseif change.action == "SuicidePerson" then 261 elseif change.action == "SuicidePerson" then
245 bsk:DoSuicidePerson(change) 262 DoSuicidePerson(change)
246 else 263 else
247 bsk:Print("Unknown message encountered") 264 bsk:Print("Unknown message encountered")
248 bsk:PrintTable(change) 265 PrintTable(change)
249 assert(false) 266 assert(false)
250 end 267 end
251 end 268 end
252 269
253 --}}} 270 --}}}
271 --
254 -- holy crap long winded {{{ 272 -- holy crap long winded {{{
255 -- timestamp logic: 273 -- timestamp logic:
256 -- use time() for comparisons - local clients use date() to make it pretty. only 274 -- use time() for comparisons - local clients use date() to make it pretty. only
257 -- dowisde - we can't have a server timestamp. Which kind of sucks, but it turns 275 -- dowisde - we can't have a server timestamp. Which kind of sucks, but it turns
258 -- out you can change timezones when you enter an instance server, so you really 276 -- out you can change timezones when you enter an instance server, so you really
284 302
285 -- Action and DoAction defs {{{ 303 -- Action and DoAction defs {{{
286 -- Action Discussion {{{ 304 -- Action Discussion {{{
287 -- The actual actions for changes start here 305 -- The actual actions for changes start here
288 -- 306 --
289 -- Each action occurs as a pair of functions. The bsk:Action() function is from 307 -- Each action occurs as a pair of functions. The Action() function is from
290 -- a list admin's point of view. Each will check for admin status, then create a 308 -- a list admin's point of view. Each will check for admin status, then create a
291 -- change bundle, call the handler for that change (ie the DoAction func), and 309 -- change bundle, call the handler for that change (ie the DoAction func), and
292 -- then record/transmist the bundle. These are simple and repetitive functions. 310 -- then record/transmist the bundle. These are simple and repetitive functions.
293 -- 311 --
294 -- The bsk:DoAction() function is tasked with executing the bundle and is what 312 -- The DoAction() function is tasked with executing the bundle and is what
295 -- non-admins and admins alike will call to transform their working state via a 313 -- non-admins and admins alike will call to transform their working state via a
296 -- change packet. Each Do() function will accept *only* a change packet, and 314 -- change packet. Each Do() function will accept *only* a change packet, and
297 -- it's assumed that the change has been vetted elsewhere. These are very blunt 315 -- it's assumed that the change has been vetted elsewhere. These are very blunt
298 -- routines. 316 -- routines.
299 -- 317 --
300 -- Note that "undo" has no special voodoo to it. It's basically a change that 318 -- Note that "undo" has no special voodoo to it. It's basically a change that
301 -- reverses the prior change on the stack.--}}} 319 -- reverses the prior change on the stack.--}}}
302 function bsk:DoAddPerson(change)--{{{ 320 function DoAddPerson(change)--{{{
303 assert(change) 321 assert(change)
304 assert(change.arg.id) 322 assert(change.arg.id)
305 -- require admin 323 -- require admin
306 local persons = bsk.persons 324 local persons = persons
307 local name = change.arg.name 325 local name = change.arg.name
308 local id = change.arg.id 326 local id = change.arg.id
309 assert(persons[id]==nil) 327 assert(persons[id]==nil)
310 persons[id] = {main=name,class=change.arg.class} 328 persons[id] = {main=name,class=change.arg.class}
311 persons.time=change.time 329 persons.time=change.time
312 personName2id[name] = id 330 personName2id[name] = id
313 return true 331 return true
314 end--}}} 332 end--}}}
315 function bsk:AddPerson(name)--{{{ 333 function AddPerson(name)--{{{
316 local persons = bsk.persons 334 local persons = persons
317 local guid = UnitGUID(name) 335 local guid = _G.UnitGUID(name)
318 -- TODO: check guid to be sure it's a player 336 -- TODO: check guid to be sure it's a player
319 if not guid then 337 if not guid then
320 self:Print(sformat("Could not add player %s - they must be in range or group",name)) 338 bsk:Print(sformat("Could not add player %s - they must be in range or group",name))
321 return 339 return
322 end 340 end
323 local _,englishClass = UnitClass(name) 341 local _,englishClass = _G.UnitClass(name)
324 --bsk:Print("Person " .. name .. " is class " .. englishClass) 342 --bsk:Print("Person " .. name .. " is class " .. englishClass)
325 local id = string.sub(guid,6) -- skip at least 0x0580 ... 343 local id = string.sub(guid,6) -- skip at least 0x0580 ...
326 id = id:gsub("^0*(.*)","%1") -- nom all leading zeroes remaining 344 id = id:gsub("^0*(.*)","%1") -- nom all leading zeroes remaining
327 345
328 if persons[id] and persons[id] ~= name then 346 if persons[id] and persons[id] ~= name then
329 self:Print(sformat("Namechange detected for %s - new is %s, please rename the existing entry", persons[id].main, name)) 347 bsk:Print(sformat("Namechange detected for %s - new is %s, please rename the existing entry", persons[id].main, name))
330 return 348 return
331 end 349 end
332 if persons[id] ~= nil then 350 if persons[id] ~= nil then
333 self:Print(sformat("%s is already in the persons list; disregarding", name)) 351 bsk:Print(sformat("%s is already in the persons list; disregarding", name))
334 return 352 return
335 end 353 end
336 local change = {action="AddPerson",arg={name=name,id=id,class=englishClass}} 354 local change = {action="AddPerson",arg={name=name,id=id,class=englishClass}}
337 if bsk:DoAddPerson(change) then 355 if DoAddPerson(change) then
338 bsk:CreateChange(change) 356 CreateChange(change)
339 end 357 end
340 end--}}} 358 end--}}}
341 function bsk:DoCreateList(change)--{{{ 359 function DoCreateList(change)--{{{
342 --if bsk:GetListIndex(change.arg.name) then 360 --if GetListIndex(change.arg.name) then
343 -- self:Print(sformat("List %s already exists",v.name)) 361 -- bsk:Print(sformat("List %s already exists",v.name))
344 -- return false 362 -- return false
345 --end 363 --end
346 bsk.lists[change.arg.id]={name=change.arg.name,time=change.time} 364 lists[change.arg.id]={name=change.arg.name,time=change.time}
347 return true 365 return true
348 end--}}} 366 end--}}}
349 function bsk:CreateList(name)--{{{ 367 function CreateList(name)--{{{
350 -- require admin 368 -- require admin
351 local change={action="CreateList",arg={name=name}} 369 local change={action="CreateList",arg={name=name}}
352 bsk:StartChange(change) 370 StartChange(change)
353 change.arg.id=change.time -- use the creation timestamp as the list's index. it's as unique as anything... 371 change.arg.id=change.time -- use the creation timestamp as the list's index. it's as unique as anything...
354 self:Print("Creating ... " .. name) 372 bsk:Print("Creating ... " .. name)
355 if bsk:DoCreateList(change) then 373 if DoCreateList(change) then
356 bsk:CommitChange(change) 374 CommitChange(change)
357 end 375 end
358 end--}}} 376 end--}}}
359 function bsk:DoAddPersonToListEnd(change)--{{{ 377 function DoAddPersonToListEnd(change)--{{{
360 local list = bsk.lists[change.arg.listIndex] 378 local list = lists[change.arg.listIndex]
361 local index 379 local index
362 if getn(list) > 0 then 380 if getn(list) > 0 then
363 index = list[#list].index + 0.1 381 index = list[#list].index + 0.1
364 else 382 else
365 index = 0.1 383 index = 0.1
370 list.time = change.time 388 list.time = change.time
371 list.closedRandom = true 389 list.closedRandom = true
372 390
373 return true 391 return true
374 end--}}} 392 end--}}}
375 function bsk:AddPersonToListEnd(name,listName)--{{{ 393 function AddPersonToListEnd(name,listName)--{{{
376 -- require admin 394 -- require admin
377 local listIndex = bsk:GetListIndex(listName) 395 local listIndex = GetListIndex(listName)
378 local id = personName2id[name] 396 local id = personName2id[name]
379 if bsk:IdIsInList(id,bsk.lists[listIndex]) then 397 if IdIsInList(id,lists[listIndex]) then
380 bsk:Print(sformat("Person %s is already on the reqeuested list",name)) 398 bsk:Print(sformat("Person %s is already on the reqeuested list",name))
381 return false 399 return false
382 end 400 end
383 bsk:Print(sformat("Adding %s (%s) to list %s (%s)", name, id, listName, listIndex)) 401 bsk:Print(sformat("Adding %s (%s) to list %s (%s)", name, id, listName, listIndex))
384 local change = {action="AddToListEnd",arg={id=id,listIndex=listIndex}} 402 local change = {action="AddToListEnd",arg={id=id,listIndex=listIndex}}
385 bsk:StartChange(change) 403 StartChange(change)
386 if bsk:DoAddPersonToListEnd(change) then 404 if DoAddPersonToListEnd(change) then
387 bsk:CommitChange(change) 405 CommitChange(change)
388 end 406 end
389 end--}}} 407 end--}}}
390 function bsk:DoAddPersonToListRandom(change)--{{{ 408 function DoAddPersonToListRandom(change)--{{{
391 local list = bsk.lists[change.arg.listIndex] 409 local list = lists[change.arg.listIndex]
392 local entry = {index=change.arg.roll, id=change.arg.id} 410 local entry = {index=change.arg.roll, id=change.arg.id}
393 411
394 tinsert(list,entry) 412 tinsert(list,entry)
395 table.sort(list,function(a,b) return a.index < b.index end) 413 table.sort(list,function(a,b) return a.index < b.index end)
396 list.time = change.time 414 list.time = change.time
397 415
398 return true 416 return true
399 end--}}} 417 end--}}}
400 function bsk:AddPersonToListRandom(name,listName)--{{{ 418 function AddPersonToListRandom(name,listName)--{{{
401 -- require admin 419 -- require admin
402 local listIndex = bsk:GetListIndex(listName) 420 local listIndex = GetListIndex(listName)
403 if bsk.lists[listIndex].closedRandom then 421 if lists[listIndex].closedRandom then
404 self:Print("Cannot add person to list by random roll because an add-to-end operation has already occurred") 422 bsk:Print("Cannot add person to list by random roll because an add-to-end operation has already occurred")
405 return false 423 return false
406 end 424 end
407 local id = personName2id[name] 425 local id = personName2id[name]
408 if bsk:IdIsInList(id,bsk.lists[listIndex]) then 426 if IdIsInList(id,lists[listIndex]) then
409 bsk:Print(sformat("Person %s is already on the reqeuested list",name)) 427 bsk:Print(sformat("Person %s is already on the reqeuested list",name))
410 return false 428 return false
411 end 429 end
412 local roll = math.random() 430 local roll = math.random()
413 bsk:Print(sformat("Adding %s (%s) to list %s (%s) with roll (%f)", name, id, listName, listIndex, roll)) 431 bsk:Print(sformat("Adding %s (%s) to list %s (%s) with roll (%f)", name, id, listName, listIndex, roll))
414 local change = {action="AddToListRand",arg={id=id,listIndex=listIndex,roll=roll}} 432 local change = {action="AddToListRand",arg={id=id,listIndex=listIndex,roll=roll}}
415 bsk:StartChange(change) 433 StartChange(change)
416 if bsk:DoAddPersonToListRandom(change) then 434 if DoAddPersonToListRandom(change) then
417 bsk:CommitChange(change) 435 CommitChange(change)
418 end 436 end
419 end--}}} 437 end--}}}
420 function bsk:DoRemovePerson(change)--{{{ 438 function DoRemovePerson(change)--{{{
421 local person = bsk.persons[change.arg.id] 439 local person = persons[change.arg.id]
422 personName2id[person.main] = nil 440 personName2id[person.main] = nil
423 bsk.persons[change.arg.id] = nil 441 persons[change.arg.id] = nil
424 bsk.persons.time = change.time 442 persons.time = change.time
425 return true 443 return true
426 end--}}} 444 end--}}}
427 function bsk:RemovePerson(name)--{{{ 445 function RemovePerson(name)--{{{
428 local id = personName2id[name] 446 local id = personName2id[name]
429 if not id then 447 if not id then
430 bsk:Print(sformat("%s is not in the persons list, please check your spelling", name)) 448 bsk:Print(sformat("%s is not in the persons list, please check your spelling", name))
431 return false 449 return false
432 end 450 end
433 local listsTheyreOn = {} 451 local listsTheyreOn = {}
434 -- check if they're active on any loot list 452 -- check if they're active on any loot list
435 for i,v in pairs(bsk.lists) do 453 for i,v in pairs(lists) do
436 if bsk:IdIsInList(id,v) then 454 if IdIsInList(id,v) then
437 tinsert(listsTheyreOn,v.name) 455 tinsert(listsTheyreOn,v.name)
438 break 456 break
439 end 457 end
440 end 458 end
441 if getn(listsTheyreOn) > 0 then 459 if getn(listsTheyreOn) > 0 then
442 self:Print(sformat("Cannot remove person %s because they are on one or more lists (%s)",name,table.concat(listsTheyreOn,", "))) 460 bsk:Print(sformat("Cannot remove person %s because they are on one or more lists (%s)",name,table.concat(listsTheyreOn,", ")))
443 return false 461 return false
444 end 462 end
445 local change = {action="RemovePerson",arg={id=id}} 463 local change = {action="RemovePerson",arg={id=id}}
446 bsk:StartChange(change) 464 StartChange(change)
447 if bsk:DoRemovePerson(change) then 465 if DoRemovePerson(change) then
448 bsk:CommitChange(change) 466 CommitChange(change)
449 end 467 end
450 end--}}} 468 end--}}}
451 function bsk:DoSuicidePerson(change)--{{{ 469 function DoSuicidePerson(change)--{{{
452 local list = bsk.lists[change.arg.listIndex] 470 local list = lists[change.arg.listIndex]
453 local affected = shallowCopy(change.arg.affect) 471 local affected = shallowCopy(change.arg.affect)
454 -- the goal here is to rotate the suicide list by 1 472 -- the goal here is to rotate the suicide list by 1
455 -- then we can just mash it on top of the intersection between the original 473 -- then we can just mash it on top of the intersection between the original
456 -- list and the working copy 474 -- list and the working copy
457 475
458 local replacement = shallowCopy(change.arg.affect) 476 local replacement = shallowCopy(change.arg.affect)
459 local temp = table.remove(replacement,1) -- pop 477 local temp = table.remove(replacement,1) -- pop
460 tinsert(replacement,temp) -- push_back 478 tinsert(replacement,temp) -- push_back
461 --bsk:Print(sformat("Before suicide of %s on list %s",slist[1],list.name)) 479 --bsk:Print(sformat("Before suicide of %s on list %s",slist[1],list.name))
462 --bsk:PrintTable(list) 480 --PrintTable(list)
463 for i = 1, #list do 481 for i = 1, #list do
464 if list[i].id == affected[1] then 482 if list[i].id == affected[1] then
465 table.remove(affected,1) 483 table.remove(affected,1)
466 list[i].id = replacement[1] 484 list[i].id = replacement[1]
467 table.remove(replacement,1) 485 table.remove(replacement,1)
468 end 486 end
469 end 487 end
470 list.time=change.time 488 list.time=change.time
471 return true 489 return true
472 end--}}} 490 end--}}}
473 function bsk:SuicidePerson(name,listName)--{{{ 491 function SuicidePerson(name,listName)--{{{
474 -- require admin 492 -- require admin
475 bsk:PopulateRaidList() 493 PopulateRaidList()
476 local listIndex = bsk:GetListIndex(listName) 494 local listIndex = GetListIndex(listName)
477 local id = personName2id[name] 495 local id = personName2id[name]
478 local affect=bsk:GetSuicideList(id,bsk.lists[listIndex]) 496 local affect=GetSuicideList(id,lists[listIndex])
479 local change = {action="SuicidePerson",arg={affect=affect,listIndex=listIndex}} 497 local change = {action="SuicidePerson",arg={affect=affect,listIndex=listIndex}}
480 bsk:StartChange(change) 498 StartChange(change)
481 if bsk:DoSuicidePerson(change) then 499 if DoSuicidePerson(change) then
482 bsk:CommitChange(change) 500 CommitChange(change)
483 end 501 end
484 end--}}} 502 end--}}}
485 function bsk:DoRenameList(change)--{{{ 503 function DoRenameList(change)--{{{
486 bsk.lists[change.arg.listIndex].name = change.arg.name 504 lists[change.arg.listIndex].name = change.arg.name
487 bsk.lists[change.arg.listIndex].time = change.time 505 lists[change.arg.listIndex].time = change.time
488 return true 506 return true
489 end--}}} 507 end--}}}
490 function bsk:RenameList(listName,newListName)--{{{ 508 function RenameList(listName,newListName)--{{{
491 -- require admin 509 -- require admin
492 local listIndex = bsk:GetListIndex(listName) 510 local listIndex = GetListIndex(listName)
493 local change = {action="RenameList",arg={listIndex=listIndex,name=newListName}} 511 local change = {action="RenameList",arg={listIndex=listIndex,name=newListName}}
494 bsk:StartChange(change) 512 StartChange(change)
495 if bsk:DoRenameList(change) then 513 if DoRenameList(change) then
496 bsk:CommitChange(change) 514 CommitChange(change)
497 end 515 end
498 end--}}} 516 end--}}}
499 function bsk:DoDeleteList(change)--{{{ 517 function DoDeleteList(change)--{{{
500 bsk.lists[change.arg.listIndex] = nil 518 lists[change.arg.listIndex] = nil
501 return true 519 return true
502 end--}}} 520 end--}}}
503 function bsk:DeleteList(listName)--{{{ 521 function DeleteList(listName)--{{{
504 local listIndex = bsk:GetListIndex(listName) 522 local listIndex = GetListIndex(listName)
505 local change = {action="DeleteList",arg={listIndex=listIndex}} 523 local change = {action="DeleteList",arg={listIndex=listIndex}}
506 bsk:StartChange(change) 524 StartChange(change)
507 if bsk:DoDeleteList(change) then 525 if DoDeleteList(change) then
508 bsk:CommitChange(change) 526 CommitChange(change)
509 end 527 end
510 end--}}} 528 end--}}}
511 function bsk:DoRemovePersonFromList(change)--{{{ 529 function DoRemovePersonFromList(change)--{{{
512 local list = bsk.lists[change.arg.listIndex] 530 local list = lists[change.arg.listIndex]
513 531
514 for i,v in ipairs(list) do 532 for i,v in ipairs(list) do
515 if v.id == change.arg.id then 533 if v.id == change.arg.id then
516 table.remove(list,i) 534 table.remove(list,i)
517 break 535 break
519 end 537 end
520 table.sort(list,function(a,b) return a.index < b.index end) 538 table.sort(list,function(a,b) return a.index < b.index end)
521 list.time = change.time 539 list.time = change.time
522 return true 540 return true
523 end--}}} 541 end--}}}
524 function bsk:RemovePersonFromList(name,listName)--{{{ 542 function RemovePersonFromList(name,listName)--{{{
525 local listIndex = bsk:GetListIndex(listName) 543 local listIndex = GetListIndex(listName)
526 local pid = personName2id[name] 544 local pid = personName2id[name]
527 -- todo: check that they're on the list in the first place 545 -- todo: check that they're on the list in the first place
528 local change = {action="RemovePersonFromList",arg={id=pid,listIndex=listIndex}} 546 local change = {action="RemovePersonFromList",arg={id=pid,listIndex=listIndex}}
529 bsk:StartChange(change) 547 StartChange(change)
530 if bsk:DoRemovePersonFromList(change) then 548 if DoRemovePersonFromList(change) then
531 bsk:CommitChange(change) 549 CommitChange(change)
532 end 550 end
533 end 551 end
534 --}}} 552 --}}}
535 --}}} 553 --}}}
536 -- Higher order actions (ie calls other standard actions){{{ 554 -- Higher order actions (ie calls other standard actions){{{
537 555
538 function bsk:TrimLists(time) 556 function TrimLists(time)
539 if not bsk:CheckListCausality() then 557 if not CheckListCausality() then
540 self:Print("Unable to trim changelist due to violated causality") 558 bsk:Print("Unable to trim changelist due to violated causality")
541 return false 559 return false
542 end 560 end
543 561
544 if type(time) ~= "number" then 562 if type(time) ~= "number" then
545 time = tonumber(time) 563 time = tonumber(time)
546 end 564 end
547 565
548 -- bisect the changes list by "time" 566 -- bisect the changes list by "time"
549 local before = {} 567 local before = {}
550 for i,v in ipairs(self.db.profile.changes) do 568 for i,v in ipairs(db.profile.changes) do
551 if v.time <= time then 569 if v.time <= time then
552 tinsert(before,v) 570 tinsert(before,v)
553 else 571 else
554 break 572 break
555 end 573 end
556 end 574 end
557 575
558 -- apply first half 576 -- apply first half
559 bsk:CreateWorkingStateFromChanges(before) 577 CreateWorkingStateFromChanges(before)
560 578
561 -- save this state permanently; trim the changes permanently 579 -- save this state permanently; trim the changes permanently
562 bsk:tcopy(bsk.db.profile.persons,bsk.persons) 580 tcopy(db.profile.persons,persons)
563 bsk:tcopy(bsk.db.profile.lists,bsk.lists) 581 tcopy(db.profile.lists,lists)
564 while bsk.db.profile.changes ~= nil and bsk.db.profile.changes[1] ~= nil and bsk.db.profile.changes[1].time <= time do 582 while db.profile.changes ~= nil and db.profile.changes[1] ~= nil and db.profile.changes[1].time <= time do
565 table.remove(bsk.db.profile.changes,1) 583 table.remove(db.profile.changes,1)
566 end 584 end
567 585
568 -- using the trimmed list and the new bases, recreate the working state 586 -- using the trimmed list and the new bases, recreate the working state
569 bsk:CreateWorkingStateFromChanges(bsk.db.profile.changes) 587 CreateWorkingStateFromChanges(db.profile.changes)
570 end 588 end
571 589
572 function bsk:AddMissingPersons() 590 function AddMissingPersons()
573 bsk:PopulateRaidList() 591 PopulateRaidList()
574 local t = {} 592 local t = {}
575 for id,_ in pairs(bsk.persons) do 593 for id,_ in pairs(persons) do
576 t[id] = true 594 t[id] = true
577 end 595 end
578 for name,_ in pairs(bsk.raidNameP) do 596 for name,_ in pairs(raidNameP) do
579 if personName2id[name] == nil then 597 if personName2id[name] == nil then
580 bsk:Print(sformat("Person %s is missing from the persons list - adding",name)) 598 bsk:Print(sformat("Person %s is missing from the persons list - adding",name))
581 bsk:AddPerson(name) 599 AddPerson(name)
582 end 600 end
583 end 601 end
584 -- TODO: batch into a single op - no need to spam 25 messages in a row 602 -- TODO: batch into a single op - no need to spam 25 messages in a row
585 end 603 end
586 604
587 function bsk:PopulateListRandom(listIndex) 605 function PopulateListRandom(listIndex)
588 -- difference (raid+reserve)-list, then random shuffle that, then add 606 -- difference (raid+reserve)-list, then random shuffle that, then add
589 bsk:PopulateRaidList() 607 PopulateRaidList()
590 local list = bsk.lists[listIndex] 608 local list = lists[listIndex]
591 609
592 local t = {} -- after loops, contains intersection of IDs present between raid and reserve 610 local t = {} -- after loops, contains intersection of IDs present between raid and reserve
593 for i,v in pairs(bsk.raidIdP) do 611 for i,v in pairs(raidIdP) do
594 if v then t[i] = true end 612 if v then t[i] = true end
595 end 613 end
596 for i,v in pairs(bsk.reserveIdP) do 614 for i,v in pairs(reserveIdP) do
597 if v then t[i] = true end 615 if v then t[i] = true end
598 end 616 end
599 617
600 -- now remove from t all of the people already present on the list 618 -- now remove from t all of the people already present on the list
601 if list then 619 if list then
607 end 625 end
608 626
609 -- add all remaining 627 -- add all remaining
610 for i,v in pairs(t) do 628 for i,v in pairs(t) do
611 if v then 629 if v then
612 bsk:AddPersonToListRandom(bsk.persons[i].main,list.name) -- TODO: APTLR keys off of string names. probably need to change this. 630 AddPersonToListRandom(persons[i].main,list.name) -- TODO: APTLR keys off of string names. probably need to change this.
613 end 631 end
614 end 632 end
615 end 633 end
616 634
617 function bsk:NukePerson(name) -- delete from all lists and then from persons 635 function NukePerson(name) -- delete from all lists and then from persons
618 local pid = personName2id[name] 636 local pid = personName2id[name]
619 for i,v in pairs(bsk.lists) do 637 for i,v in pairs(lists) do
620 bsk:RemovePersonFromList(name,v.name) 638 RemovePersonFromList(name,v.name)
621 end 639 end
622 bsk:RemovePerson(name) 640 RemovePerson(name)
623 end 641 end
624 --}}} 642 --}}}
625 -- "Soft" actions- ie things that cause nonpermanent state {{{ 643 -- "Soft" actions- ie things that cause nonpermanent state {{{
626 644
627 -- reserves 645 -- reserves
628 function bsk:AddReserve(name) 646 function AddReserve(name)
629 bsk.reserveIdP[personName2id[name]]=true 647 bsk:Print("Reserving" .. name)
648 reserveIdP[personName2id[name]]=true
630 -- TODO: communicate to others. don't store this in any way. 649 -- TODO: communicate to others. don't store this in any way.
631 end 650 end
632 651
633 function bsk:RemoveReserve(name) 652 function RemoveReserve(name)
634 bsk.reserveIdP[personName2id[name]]=false 653 reserveIdP[personName2id[name]]=false
635 -- TODO: communicate to others. don't store this in any way. 654 -- TODO: communicate to others. don't store this in any way.
636 end 655 end
637 656
638 657
639 --function bsk:GetActiveList() 658 --function GetActiveList()
640 -- return bsk.lists[1] -- todo! 659 -- return lists[1] -- todo!
641 --end 660 --end
642 661
643 --}}} 662 --}}}
644 663
645 -- The following (adapted) code is from Xinhuan (wowace forum member) 664 -- The following (adapted) code is from Xinhuan (wowace forum member)
646 -- Pre-create the unitID strings we will use 665 -- Pre-create the unitID strings we will use
647 local pID = {} 666 local pID = {}
648 local rID = {} 667 local rID = {}
649 for i = 1, 4 do 668 for i = 1, 4 do
650 pID[i] = format("party%d", i) 669 pID[i] = sformat("party%d", i)
651 end 670 end
652 for i = 1, 40 do 671 for i = 1, 40 do
653 rID[i] = format("raid%d", i) 672 rID[i] = sformat("raid%d", i)
654 end 673 end
655 function bsk:PopulateRaidList() 674 function PopulateRaidList()
656 local inParty = GetNumPartyMembers() 675 local inParty = _G.GetNumPartyMembers()
657 local inRaid = GetNumRaidMembers() 676 local inRaid = _G.GetNumRaidMembers()
658 local add = function(unitNameArg) 677 local add = function(unitNameArg)
659 local name = UnitName(unitNameArg) 678 local name = _G.UnitName(unitNameArg)
660 bsk.raidNameP[name]=true 679 raidNameP[name]=true
661 if personName2id[name] ~= nil then 680 if personName2id[name] ~= nil then
662 bsk.raidIdP[personName2id[name]]=true 681 raidIdP[personName2id[name]]=true
663 end 682 end
664 end 683 end
665 684
666 wipe(bsk.raidNameP) 685 wipe(raidNameP)
667 wipe(bsk.raidIdP) 686 wipe(raidIdP)
668 if inRaid > 0 then 687 if inRaid > 0 then
669 for i = 1, inRaid do 688 for i = 1, inRaid do
670 add(rID[i]) 689 add(rID[i])
671 end 690 end
672 elseif inParty > 0 then 691 elseif inParty > 0 then
677 add("player") 696 add("player")
678 else 697 else
679 -- You're alone 698 -- You're alone
680 add("player") 699 add("player")
681 end 700 end
682 --bsk:PrintTable(bsk.raidNameP) 701 --PrintTable(raidNameP)
683 end 702 end
684 703
685 -- undo rules! 704 -- undo rules!
686 -- only the most recent event can be undone 705 -- only the most recent event can be undone
687 -- ^^^ on a given list? 706 -- ^^^ on a given list?
689 -- just find A,B,C in the list and replace in order from the s message 708 -- just find A,B,C in the list and replace in order from the s message
690 -- while undo is allowed *per-list*, certain events in the stream will 709 -- while undo is allowed *per-list*, certain events in the stream will
691 -- prevent proper undo, such as add/delete player or add/delete list 710 -- prevent proper undo, such as add/delete player or add/delete list
692 711
693 712
694 function bsk:GetSuicideList(id,list) 713 function GetSuicideList(id,list)
695 --self:Print("Calculating changeset for "..name.." from list -") 714 --bsk:Print("Calculating changeset for "..name.." from list -")
696 --self:PrintTable(list) 715 --PrintTable(list)
697 local t = {} 716 local t = {}
698 local ret = {} 717 local ret = {}
699 local pushing = false 718 local pushing = false
700 for i = 1, #list do 719 for i = 1, #list do
701 if list[i].id == id then 720 if list[i].id == id then
702 pushing = true 721 pushing = true
703 end 722 end
704 if pushing and (bsk.raidIdP[list[i].id] or bsk.reserveIdP[list[i].id]) then 723 if pushing and (raidIdP[list[i].id] or reserveIdP[list[i].id]) then
705 tinsert(ret,list[i].id) 724 tinsert(ret,list[i].id)
706 end 725 end
707 end 726 end
708 --bsk:Print("GSL") 727 --bsk:Print("GSL")
709 --bsk:PrintTable(ret) 728 --PrintTable(ret)
710 --bsk:Print("GSL") 729 --bsk:Print("GSL")
711 return ret 730 return ret
712 end 731 end
713 732
714 function bsk:IdIsInList(id,listRef) 733 function IdIsInList(id,listRef)
715 for i = 1,#listRef do 734 for i = 1,#listRef do
716 if id == listRef[i].id then 735 if id == listRef[i].id then
717 return true 736 return true
718 end 737 end
719 end 738 end
720 return false 739 return false
721 end 740 end
722 741
723 -- returns true if the events in the list are in time order 742 -- returns true if the events in the list are in time order
724 function bsk:CheckListCausality() 743 function CheckListCausality()
725 local t = nil 744 local t = nil
726 for i,v in ipairs(bsk.db.profile.changes) do 745 for i,v in ipairs(db.profile.changes) do
727 if t ~= nil then 746 if t ~= nil then
728 if v.time <= t then 747 if v.time <= t then
729 return false 748 return false
730 end 749 end
731 end 750 end
734 return true 753 return true
735 end 754 end
736 755
737 -- Support functions 756 -- Support functions
738 757
739 function bsk:GetListIndex(name) 758 function GetListIndex(name)
740 for i,v in pairs(bsk.lists) do 759 for i,v in pairs(lists) do
741 if v.name == name then 760 if v.name == name then
742 return i 761 return i
743 end 762 end
744 end 763 end
745 return nil 764 return nil
746 end 765 end
747 766
748 local shuffleArray = function(array) 767
749 local arrayCount = #array
750 for i = arrayCount, 2, -1 do
751 local j = math.random(1, i)
752 array[i], array[j] = array[j], array[i]
753 end
754 return array
755 end
756