vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | gGroupCalendar_Database = |
2 | { |
||
3 | Format = 11, |
||
4 | Databases = {}, |
||
5 | }; |
||
6 | |||
7 | gGroupCalendar_UserDatabase = nil; |
||
8 | |||
9 | gGroupCalendar_MaximumEventAge = 30; |
||
10 | gGroupCalendar_MinimumEventDate = nil; |
||
11 | |||
12 | gGroupCalendar_PlayerCharacters = {}; |
||
13 | |||
14 | gGroupCalendar_40ManLimits = |
||
15 | { |
||
16 | mClassLimits = |
||
17 | { |
||
18 | P = {mMin = 4, mMax = 6}, |
||
19 | R = {mMin = 4, mMax = 6}, |
||
20 | D = {mMin = 4, mMax = 6}, |
||
21 | W = {mMin = 4, mMax = 6}, |
||
22 | H = {mMin = 4, mMax = 6}, |
||
23 | K = {mMin = 4, mMax = 6}, |
||
24 | M = {mMin = 4, mMax = 6}, |
||
25 | L = {mMin = 4, mMax = 6}, |
||
26 | S = {mMin = 4, mMax = 6}, |
||
27 | }, |
||
28 | |||
29 | mMaxAttendance = 40, |
||
30 | }; |
||
31 | |||
32 | gGroupCalendar_20ManLimits = |
||
33 | { |
||
34 | mClassLimits = |
||
35 | { |
||
36 | P = {mMin = 2, mMax = 3}, |
||
37 | R = {mMin = 2, mMax = 3}, |
||
38 | D = {mMin = 2, mMax = 3}, |
||
39 | W = {mMin = 2, mMax = 3}, |
||
40 | H = {mMin = 2, mMax = 3}, |
||
41 | K = {mMin = 2, mMax = 3}, |
||
42 | M = {mMin = 2, mMax = 3}, |
||
43 | L = {mMin = 2, mMax = 3}, |
||
44 | S = {mMin = 2, mMax = 3}, |
||
45 | }, |
||
46 | |||
47 | mMaxAttendance = 20, |
||
48 | }; |
||
49 | |||
50 | gGroupCalendar_15ManLimits = |
||
51 | { |
||
52 | mClassLimits = |
||
53 | { |
||
54 | P = {mMin = 1, mMax = 3}, |
||
55 | R = {mMin = 1, mMax = 3}, |
||
56 | D = {mMin = 1, mMax = 3}, |
||
57 | W = {mMin = 1, mMax = 3}, |
||
58 | H = {mMin = 1, mMax = 3}, |
||
59 | K = {mMin = 1, mMax = 3}, |
||
60 | M = {mMin = 1, mMax = 3}, |
||
61 | L = {mMin = 1, mMax = 3}, |
||
62 | S = {mMin = 1, mMax = 3}, |
||
63 | }, |
||
64 | |||
65 | mMaxAttendance = 15, |
||
66 | }; |
||
67 | |||
68 | gGroupCalendar_10ManLimits = |
||
69 | { |
||
70 | mClassLimits = |
||
71 | { |
||
72 | P = {mMin = 1, mMax = 2}, |
||
73 | R = {mMin = 1, mMax = 2}, |
||
74 | D = {mMin = 1, mMax = 2}, |
||
75 | W = {mMin = 1, mMax = 2}, |
||
76 | H = {mMin = 1, mMax = 2}, |
||
77 | K = {mMin = 1, mMax = 2}, |
||
78 | M = {mMin = 1, mMax = 2}, |
||
79 | L = {mMin = 1, mMax = 2}, |
||
80 | S = {mMin = 1, mMax = 2}, |
||
81 | }, |
||
82 | |||
83 | mMaxAttendance = 10, |
||
84 | }; |
||
85 | |||
86 | gGroupCalendar_5ManLimits = |
||
87 | { |
||
88 | mClassLimits = |
||
89 | { |
||
90 | P = {mMax = 1}, |
||
91 | R = {mMax = 1}, |
||
92 | D = {mMax = 1}, |
||
93 | W = {mMax = 1}, |
||
94 | H = {mMax = 1}, |
||
95 | K = {mMax = 1}, |
||
96 | M = {mMax = 1}, |
||
97 | L = {mMax = 1}, |
||
98 | S = {mMax = 1}, |
||
99 | }, |
||
100 | |||
101 | mMaxAttendance = 5, |
||
102 | }; |
||
103 | |||
104 | gGroupCalendar_EventTypes = |
||
105 | { |
||
106 | General = |
||
107 | { |
||
108 | Title = GroupCalendar_cGeneralEventGroup, |
||
109 | MenuHint = "FLAT", |
||
110 | Events = |
||
111 | { |
||
112 | {id="Meet", name=GroupCalendar_cMeetingEventName}, |
||
113 | {id="Birth", name=GroupCalendar_cBirthdayEventName}, |
||
114 | }, |
||
115 | }, |
||
116 | |||
117 | Dungeon = |
||
118 | { |
||
119 | Title = GroupCalendar_cDungeonEventGroup, |
||
120 | MenuHint = "FLAT", |
||
121 | Events = |
||
122 | { |
||
123 | {id="AQT", name = GroupCalendar_cAQTEventName, limits = gGroupCalendar_40ManLimits}, |
||
124 | {id="AQR", name = GroupCalendar_cAQREventName, limits = gGroupCalendar_20ManLimits}, |
||
125 | {id="BWL", name = GroupCalendar_cBWLEventName, limits = gGroupCalendar_40ManLimits}, |
||
126 | {id="MC", name = GroupCalendar_cMCEventName, limits = gGroupCalendar_40ManLimits}, |
||
127 | {id="Onyxia", name = GroupCalendar_cOnyxiaEventName, limits = gGroupCalendar_40ManLimits}, |
||
128 | {id="ZG", name = GroupCalendar_cZGEventName, limits = gGroupCalendar_20ManLimits}, |
||
129 | {id="UBRS", name = GroupCalendar_cUBRSEventName, limits = gGroupCalendar_15ManLimits}, |
||
130 | {id="Scholo", name = GroupCalendar_cScholoEventName, limits = gGroupCalendar_5ManLimits}, |
||
131 | {id="DM", name = GroupCalendar_cDMEventName, limits = gGroupCalendar_5ManLimits}, |
||
132 | {id="Strath", name = GroupCalendar_cStrathEventName, limits = gGroupCalendar_5ManLimits}, |
||
133 | {id="LBRS", name = GroupCalendar_cLBRSEventName, limits = gGroupCalendar_5ManLimits}, |
||
134 | {id="BRD", name = GroupCalendar_cBRDEventName, limits = gGroupCalendar_5ManLimits}, |
||
135 | {id="ST", name = GroupCalendar_cSTEventName, limits = gGroupCalendar_5ManLimits}, |
||
136 | {id="ZF", name = GroupCalendar_cZFEventName, limits = gGroupCalendar_5ManLimits}, |
||
137 | {id="Mara", name = GroupCalendar_cMaraEventName, limits = gGroupCalendar_5ManLimits}, |
||
138 | {id="Uld", name = GroupCalendar_cUldEventName, limits = gGroupCalendar_5ManLimits}, |
||
139 | {id="RFD", name = GroupCalendar_cRFDEventName, limits = gGroupCalendar_5ManLimits}, |
||
140 | {id="SM", name = GroupCalendar_cSMEventName, limits = gGroupCalendar_5ManLimits}, |
||
141 | {id="RFK", name = GroupCalendar_cRFKEventName, limits = gGroupCalendar_5ManLimits}, |
||
142 | {id="Gnomer", name = GroupCalendar_cGnomerEventName, limits = gGroupCalendar_5ManLimits}, |
||
143 | {id="BFD", name = GroupCalendar_cBFDEventName, limits = gGroupCalendar_5ManLimits}, |
||
144 | {id="Stockades", name = GroupCalendar_cStockadesEventName, limits = gGroupCalendar_5ManLimits}, |
||
145 | {id="SFK", name = GroupCalendar_cSFKEventName, limits = gGroupCalendar_5ManLimits}, |
||
146 | {id="WC", name = GroupCalendar_cWCEventName, limits = gGroupCalendar_5ManLimits}, |
||
147 | {id="Deadmines", name = GroupCalendar_cDeadminesEventName, limits = gGroupCalendar_5ManLimits}, |
||
148 | {id="RFC", name = GroupCalendar_cRFCEventName, limits = gGroupCalendar_5ManLimits}, |
||
149 | }, |
||
150 | }, |
||
151 | |||
152 | Battleground = |
||
153 | { |
||
154 | Title = GroupCalendar_cBattlegroundEventGroup, |
||
155 | MenuHint = "HIER", |
||
156 | Events = |
||
157 | { |
||
158 | {id="AV", name=GroupCalendar_cAVEventName}, |
||
159 | {id="AB", name=GroupCalendar_cABEventName}, |
||
160 | {id="WSG", name=GroupCalendar_cWSGEventName}, |
||
161 | }, |
||
162 | }, |
||
163 | |||
164 | Reset = |
||
165 | { |
||
166 | Title = nil, |
||
167 | Events = |
||
168 | { |
||
169 | {id="RSOny", name=GroupCalendar_cOnyxiaResetEventName}, -- Onyxia reset |
||
170 | {id="RSMC", name=GroupCalendar_cMCResetEventName}, -- MC reset |
||
171 | {id="RSBWL", name=GroupCalendar_cBWLResetEventName}, -- BWL reset |
||
172 | {id="RSZG", name=GroupCalendar_cZGResetEventName}, -- ZG reset |
||
173 | {id="RSAQT", name=GroupCalendar_cAQTResetEventName}, -- AQT reset |
||
174 | {id="RSAQR", name=GroupCalendar_cAQRResetEventName}, -- AQR reset |
||
175 | {id="RSXmut", name=GroupCalendar_cTransmuteCooldownEventName}, -- Transmute |
||
176 | {id="RSSalt", name=GroupCalendar_cSaltShakerCooldownEventName}, -- Salt shaker |
||
177 | {id="RSMoon", name=GroupCalendar_cMoonclothCooldownEventName}, -- Mooncloth |
||
178 | {id="RSSnow", name=GroupCalendar_cSnowmasterCooldownEventName}, -- Snowmaster 9000 |
||
179 | }, |
||
180 | |||
181 | ResetEventInfo = |
||
182 | { |
||
183 | RSZG = {left = 0.0, top = 0.25, right = 0.25, bottom = 0.5, isDungeon = true, name=GroupCalendar_cRaidInfoZGName, largeIcon="ZG"}, |
||
184 | RSOny = {left = 0.25, top = 0.25, right = 0.5, bottom = 0.5, isDungeon = true, name=GroupCalendar_cRaidInfoOnyxiaName, largeIcon="Onyxia"}, |
||
185 | RSMC = {left = 0.5, top = 0.25, right = 0.75, bottom = 0.5, isDungeon = true, name=GroupCalendar_cRaidInfoMCName, largeIcon="MC"}, |
||
186 | RSBWL = {left = 0.75, top = 0.25, right = 1.0, bottom = 0.5, isDungeon = true, name=GroupCalendar_cRaidInfoBWLName, largeIcon="BWL"}, |
||
187 | RSAQT = {left = 0.0, top = 0.5, right = 0.25, bottom = 1.0, isDungeon = true, name=GroupCalendar_cRaidInfoAQTName, largeIcon="AQT"}, |
||
188 | RSAQR = {left = 0.25, top = 0.5, right = 0.5, bottom = 1.0, isDungeon = true, name=GroupCalendar_cRaidInfoAQRName, largeIcon="AQR"}, |
||
189 | RSXmut = {left = 0.50, top = 0, right = 0.75, bottom = 0.25, isTradeskill = true, id="Alchemy", largeSysIcon="Interface\\Icons\\Trade_Alchemy"}, |
||
190 | RSSalt = {left = 0.25, top = 0, right = 0.5, bottom = 0.25, isTradeskill = true, id="Leatherworking", largeSysIcon="Interface\\Icons\\Trade_Leatherworking"}, |
||
191 | RSMoon = {left = 0, top = 0, right = 0.25, bottom = 0.25, isTradeskill = true, id="Tailoring", largeSysIcon="Interface\\Icons\\Trade_Tailoring"}, |
||
192 | RSSnow = {left = 0.75, top = 0, right = 1.0, bottom = 0.25, isTradeskill = true, id="Snowmaster", largeSysIcon="Interface\\Icons\\Spell_Frost_WindWalkOn"}, |
||
193 | }, |
||
194 | }, |
||
195 | }; |
||
196 | |||
197 | gGroupCalendar_ClassInfoByClassCode = |
||
198 | { |
||
199 | D = {name = GroupCalendar_cDruidClassName, color = GroupCalendar_cDruidClassColorName, element = "Druid"}, |
||
200 | H = {name = GroupCalendar_cHunterClassName, color = GroupCalendar_cHunterClassColorName, element = "Hunter"}, |
||
201 | M = {name = GroupCalendar_cMageClassName, color = GroupCalendar_cMageClassColorName, element = "Mage"}, |
||
202 | L = {name = GroupCalendar_cPaladinClassName, color = GroupCalendar_cPaladinClassColorName, element = "Paladin", faction="Alliance"}, |
||
203 | P = {name = GroupCalendar_cPriestClassName, color = GroupCalendar_cPriestClassColorName, element = "Priest"}, |
||
204 | R = {name = GroupCalendar_cRogueClassName, color = GroupCalendar_cRogueClassColorName, element = "Rogue"}, |
||
205 | S = {name = GroupCalendar_cShamanClassName, color = GroupCalendar_cShamanClassColorName, element = "Shaman", faction="Horde"}, |
||
206 | K = {name = GroupCalendar_cWarlockClassName, color = GroupCalendar_cWarlockClassColorName, element = "Warlock"}, |
||
207 | W = {name = GroupCalendar_cWarriorClassName, color = GroupCalendar_cWarriorClassColorName, element = "Warrior"}, |
||
208 | }; |
||
209 | |||
210 | gGroupCalendar_RaceNamesByRaceCode = |
||
211 | { |
||
212 | A = {name = GroupCalendar_cDraeneiRaceName, faction="Alliance"}, |
||
213 | D = {name = GroupCalendar_cDwarfRaceName, faction="Alliance"}, |
||
214 | G = {name = GroupCalendar_cGnomeRaceName, faction="Alliance"}, |
||
215 | H = {name = GroupCalendar_cHumanRaceName, faction="Alliance"}, |
||
216 | N = {name = GroupCalendar_cNightElfRaceName, faction="Alliance"}, |
||
217 | B = {name = GroupCalendar_cBloodElfRaceName, faction="Horde"}, |
||
218 | O = {name = GroupCalendar_cOrcRaceName, faction="Horde"}, |
||
219 | T = {name = GroupCalendar_cTaurenRaceName, faction="Horde"}, |
||
220 | R = {name = GroupCalendar_cTrollRaceName, faction="Horde"}, |
||
221 | U = {name = GroupCalendar_cUndeadRaceName, faction="Horde"}, |
||
222 | }; |
||
223 | |||
224 | function EventDatabase_DatabaseIsVisible(pDatabase) |
||
225 | return pDatabase |
||
226 | and pDatabase.Realm == gGroupCalendar_RealmName |
||
227 | and (pDatabase.IsPlayerOwned |
||
228 | or (pDatabase.LocalUsers |
||
229 | and pDatabase.LocalUsers[gGroupCalendar_PlayerName])); |
||
230 | end |
||
231 | |||
232 | function EventDatabase_GetDatabase(pUserName, pCreate) |
||
233 | if not pUserName then |
||
234 | Calendar_DebugMessage("EventDatabase_GetDatabase: pUserName is nil"); |
||
235 | return; |
||
236 | end |
||
237 | |||
238 | local vDatabase = gGroupCalendar_Database.Databases[gGroupCalendar_RealmName.."_"..pUserName]; |
||
239 | |||
240 | if not vDatabase then |
||
241 | if pCreate then |
||
242 | vDatabase = {}; |
||
243 | |||
244 | vDatabase.UserName = pUserName; |
||
245 | vDatabase.IsPlayerOwned = pUserName == gGroupCalendar_PlayerName; |
||
246 | vDatabase.CurrentEventID = 0; |
||
247 | vDatabase.Realm = gGroupCalendar_RealmName; |
||
248 | vDatabase.Events = {}; |
||
249 | vDatabase.Changes = nil; |
||
250 | vDatabase.RSVPs = nil; |
||
251 | vDatabase.LocalUsers = {}; |
||
252 | vDatabase.Guild = gGroupCalendar_PlayerGuild; |
||
253 | |||
254 | gGroupCalendar_Database.Databases[gGroupCalendar_RealmName.."_"..pUserName] = vDatabase; |
||
255 | |||
256 | if vDatabase.IsPlayerOwned then |
||
257 | gGroupCalendar_PlayerCharacters[gGroupCalendar_PlayerName] = true; |
||
258 | end |
||
259 | else |
||
260 | return nil; |
||
261 | end |
||
262 | end |
||
263 | |||
264 | if not vDatabase.IsPlayerOwned |
||
265 | and (not vDatabase.LocalUsers |
||
266 | or not vDatabase.LocalUsers[gGroupCalendar_PlayerName]) then |
||
267 | if not pCreate then |
||
268 | return nil; |
||
269 | end |
||
270 | |||
271 | if not vDatabase.LocalUsers then |
||
272 | vDatabase.LocalUsers = {}; |
||
273 | end |
||
274 | |||
275 | vDatabase.LocalUsers[gGroupCalendar_PlayerName] = true; |
||
276 | end |
||
277 | |||
278 | if vDatabase |
||
279 | and not vDatabase.IsPlayerOwned |
||
280 | and pUserName == gGroupCalendar_PlayerName then |
||
281 | vDatabase.IsPlayerOwned = true; |
||
282 | end |
||
283 | |||
284 | return vDatabase; |
||
285 | end |
||
286 | |||
287 | function EventDatabase_GetOwnedDatabases() |
||
288 | local vOwnedDatabases = {}; |
||
289 | |||
290 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
291 | if EventDatabase_DatabaseIsVisible(vDatabase) |
||
292 | and vDatabase.IsPlayerOwned |
||
293 | and vDatabase.PlayerLevel then -- Skip databases which haven't been visited since this version |
||
294 | table.insert(vOwnedDatabases, vDatabase); |
||
295 | end |
||
296 | end |
||
297 | |||
298 | return vOwnedDatabases; |
||
299 | end |
||
300 | |||
301 | function EventDatabase_AssumeDatabase(pUserName) |
||
302 | local vDatabase = gGroupCalendar_Database.Databases[gGroupCalendar_RealmName.."_"..pUserName]; |
||
303 | |||
304 | if not vDatabase then |
||
305 | return nil; |
||
306 | end |
||
307 | |||
308 | if not vDatabase.IsPlayerOwned |
||
309 | and not vDatabase.LocalUsers[gGroupCalendar_PlayerName] then |
||
310 | vDatabase.LocalUsers[gGroupCalendar_PlayerName] = true; |
||
311 | GroupCalendar_MajorDatabaseChange(vDatabase); |
||
312 | end |
||
313 | |||
314 | return vDatabase; |
||
315 | end |
||
316 | |||
317 | function EventDatabase_DeleteDatabase(pUserName) |
||
318 | local vDatabase = gGroupCalendar_Database.Databases[gGroupCalendar_RealmName.."_"..pUserName]; |
||
319 | |||
320 | if not vDatabase then |
||
321 | return; |
||
322 | end |
||
323 | |||
324 | if vDatabase.LocalUsers then |
||
325 | vDatabase.LocalUsers[gGroupCalendar_PlayerName] = nil; |
||
326 | end |
||
327 | |||
328 | if Calendar_ArrayIsEmpty(vDatabase.LocalUsers) then |
||
329 | gGroupCalendar_Database.Databases[gGroupCalendar_RealmName.."_"..pUserName] = nil; |
||
330 | end |
||
331 | |||
332 | GroupCalendar_MajorDatabaseChange(vDatabase); |
||
333 | end |
||
334 | |||
335 | function EventDatabase_GetChanges(pDatabase) |
||
336 | local vChanges = pDatabase.Changes; |
||
337 | |||
338 | if not vChanges then |
||
339 | vChanges = CalendarChanges_New(); |
||
340 | pDatabase.Changes = vChanges; |
||
341 | end |
||
342 | |||
343 | return vChanges; |
||
344 | end |
||
345 | |||
346 | function EventDatabase_SetUserName(pUserName) |
||
347 | gGroupCalendar_UserDatabase = EventDatabase_GetDatabase(gGroupCalendar_PlayerName, true); |
||
348 | |||
349 | gGroupCalendar_UserDatabase.PlayerRaceCode = EventDatabase_GetRaceCodeByRace(UnitRace("PLAYER")); |
||
350 | gGroupCalendar_UserDatabase.PlayerClassCode = EventDatabase_GetClassCodeByClass(UnitClass("PLAYER")); |
||
351 | end |
||
352 | |||
353 | function EventDatabase_NewEvent(pDatabase, pDate) |
||
354 | local vEvent = {}; |
||
355 | |||
356 | vEvent.mType = nil; |
||
357 | vEvent.mTitle = nil; |
||
358 | |||
359 | vEvent.mTime = 1140; |
||
360 | vEvent.mDate = pDate; |
||
361 | vEvent.mDuration = 120; |
||
362 | |||
363 | vEvent.mDescription = nil; |
||
364 | |||
365 | vEvent.mMinLevel = 0; |
||
366 | vEvent.mAttendance = nil; |
||
367 | |||
368 | vEvent.mPrivate = nil; |
||
369 | |||
370 | vEvent.mManualConfirm = false; |
||
371 | vEvent.mLimits = nil; |
||
372 | |||
373 | pDatabase.CurrentEventID = pDatabase.CurrentEventID + 1; |
||
374 | vEvent.mID = pDatabase.CurrentEventID; |
||
375 | |||
376 | return vEvent; |
||
377 | end |
||
378 | |||
379 | function EventDatabase_AddEvent(pDatabase, pEvent, pSilent) |
||
380 | local vSchedule = pDatabase.Events[pEvent.mDate]; |
||
381 | |||
382 | if vSchedule == nil then |
||
383 | vSchedule = {}; |
||
384 | pDatabase.Events[pEvent.mDate] = vSchedule; |
||
385 | end |
||
386 | |||
387 | -- append the event |
||
388 | |||
389 | table.insert(vSchedule, pEvent); |
||
390 | |||
391 | if not pSilent then |
||
392 | EventDatabase_EventAdded(pDatabase, pEvent); |
||
393 | end |
||
394 | end |
||
395 | |||
396 | function EventDatabase_GetDateSchedule(pDate) |
||
397 | return gGroupCalendar_UserDatabase.Events[pDate]; |
||
398 | end |
||
399 | |||
400 | function EventDatabase_GetCompiledSchedule(pDate) |
||
401 | local vCompiledSchedule = {}; |
||
402 | |||
403 | if gGroupCalendar_Settings.ShowEventsInLocalTime then |
||
404 | local vDate2 = nil; |
||
405 | |||
406 | if gGroupCalendar_ServerTimeZoneOffset < 0 then |
||
407 | vDate2 = pDate + 1; |
||
408 | elseif gGroupCalendar_ServerTimeZoneOffset > 0 then |
||
409 | vDate2 = pDate - 1; |
||
410 | end |
||
411 | |||
412 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
413 | if EventDatabase_DatabaseIsVisible(vDatabase) then |
||
414 | for vDateIndex = 1, 2 do |
||
415 | local vDate; |
||
416 | |||
417 | if vDateIndex == 1 then |
||
418 | vDate = pDate; |
||
419 | else |
||
420 | if not vDate2 then |
||
421 | break; |
||
422 | end |
||
423 | |||
424 | vDate = vDate2; |
||
425 | end |
||
426 | |||
427 | local vSchedule = vDatabase.Events[vDate]; |
||
428 | |||
429 | if vSchedule then |
||
430 | for vIndex, vEvent in vSchedule do |
||
431 | -- Calculate the local date/time and see if it's still the right date |
||
432 | |||
433 | local vLocalDate, vLocalTime = Calendar_GetLocalDateTimeFromServerDateTime(vDate, vEvent.mTime); |
||
434 | |||
435 | if vLocalDate == pDate then |
||
436 | local vCompiledEvent = {mOwner = vDatabase.UserName, mEvent = vEvent}; |
||
437 | |||
438 | table.insert(vCompiledSchedule, vCompiledEvent); |
||
439 | end |
||
440 | end |
||
441 | end |
||
442 | end |
||
443 | end |
||
444 | end |
||
445 | else |
||
446 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
447 | if EventDatabase_DatabaseIsVisible(vDatabase) then |
||
448 | local vSchedule = vDatabase.Events[pDate]; |
||
449 | |||
450 | if vSchedule then |
||
451 | for vIndex, vEvent in vSchedule do |
||
452 | local vCompiledEvent = {mOwner = vDatabase.UserName, mEvent = vEvent}; |
||
453 | |||
454 | table.insert(vCompiledSchedule, vCompiledEvent); |
||
455 | end |
||
456 | end |
||
457 | end |
||
458 | end |
||
459 | end |
||
460 | |||
461 | table.sort(vCompiledSchedule, EventDatabase_CompareCompiledEvents); |
||
462 | |||
463 | return vCompiledSchedule; |
||
464 | end |
||
465 | |||
466 | function EventDatabase_CompareCompiledEvents(pCompiledEvent1, pCompiledEvent2) |
||
467 | return EventDatabase_CompareEvents(pCompiledEvent1.mEvent, pCompiledEvent2.mEvent); |
||
468 | end |
||
469 | |||
470 | function EventDatabase_GetEventDisplayName(pEvent) |
||
471 | if pEvent.mTitle and pEvent.mTitle ~= "" then |
||
472 | return Calendar_UnescapeString(pEvent.mTitle); |
||
473 | else |
||
474 | local vName = EventDatabase_GetEventNameByID(pEvent.mType); |
||
475 | |||
476 | if vName ~= nil then |
||
477 | return vName; |
||
478 | else |
||
479 | return ""; |
||
480 | end |
||
481 | end |
||
482 | end |
||
483 | |||
484 | function EventDatabase_CompareEvents(pEvent1, pEvent2) |
||
485 | -- If either event has nil for a time (all day event) then |
||
486 | -- sort based on time or display name |
||
487 | |||
488 | if not pEvent1.mTime or not pEvent2.mTime then |
||
489 | if pEvent1.mTime == pEvent2.mTime then |
||
490 | return EventDatabase_GetEventDisplayName(pEvent1) < EventDatabase_GetEventDisplayName(pEvent2); |
||
491 | elseif pEvent1.mTime == nil then |
||
492 | return true; |
||
493 | else |
||
494 | return false; |
||
495 | end |
||
496 | |||
497 | -- Otherwise compare dates first |
||
498 | |||
499 | elseif pEvent1.mDate < pEvent2.mDate then |
||
500 | return true; |
||
501 | elseif pEvent1.mDate > pEvent2.mDate then |
||
502 | return false; |
||
503 | |||
504 | -- Dates are the same, compare times |
||
505 | |||
506 | elseif pEvent1.mTime == pEvent2.mTime then |
||
507 | return EventDatabase_GetEventDisplayName(pEvent1) < EventDatabase_GetEventDisplayName(pEvent2); |
||
508 | else |
||
509 | return pEvent1.mTime < pEvent2.mTime; |
||
510 | end |
||
511 | end |
||
512 | |||
513 | function EventDatabase_GetEventIndex(pSchedule, pEvent) |
||
514 | for vIndex, vEvent in pSchedule do |
||
515 | if vEvent == pEvent then |
||
516 | return vIndex; |
||
517 | end |
||
518 | end |
||
519 | |||
520 | return 0; |
||
521 | end |
||
522 | |||
523 | function EventDatabase_ScheduleIsEmpty(pSchedule) |
||
524 | for vIndex, vEvent in pSchedule do |
||
525 | return false; |
||
526 | end |
||
527 | |||
528 | return true; |
||
529 | end |
||
530 | |||
531 | function EventDatabase_FindEventByID(pDatabase, pEventID) |
||
532 | for vDate, vSchedule in pDatabase.Events do |
||
533 | for vEventIndex, vEvent in vSchedule do |
||
534 | if vEvent.mID == pEventID then |
||
535 | return vEvent, vDate; |
||
536 | end |
||
537 | end |
||
538 | end |
||
539 | |||
540 | return nil; |
||
541 | end |
||
542 | |||
543 | function EventDatabase_DeleteEvent(pDatabase, pEvent, pSilent) |
||
544 | return EventDatabase_DeleteEventFromDate(pDatabase, pEvent.mDate, pEvent, pSilent); |
||
545 | end |
||
546 | |||
547 | function EventDatabase_DeleteEventFromDate(pDatabase, pDate, pEvent, pSilent) |
||
548 | -- Get the event's schedule |
||
549 | |||
550 | local vSchedule = pDatabase.Events[pDate]; |
||
551 | |||
552 | if vSchedule == nil then |
||
553 | return false; |
||
554 | end |
||
555 | |||
556 | -- Find the event index |
||
557 | |||
558 | local vEventIndex = EventDatabase_GetEventIndex(vSchedule, pEvent); |
||
559 | |||
560 | if vEventIndex == 0 then |
||
561 | return false; |
||
562 | end |
||
563 | |||
564 | -- Notify that the event is being removed |
||
565 | |||
566 | if not pSilent |
||
567 | and pDatabase.IsPlayerOwned then |
||
568 | CalendarNetwork_RemovingEvent(pDatabase, pEvent); |
||
569 | end |
||
570 | |||
571 | -- Remove any pending RSVPs for the event |
||
572 | |||
573 | EventDatabase_RemoveAllRSVPsForEvent(pDatabase, pEvent, false); |
||
574 | |||
575 | -- Remove the event |
||
576 | |||
577 | table.remove(vSchedule, vEventIndex); |
||
578 | |||
579 | if EventDatabase_ScheduleIsEmpty(vSchedule) then |
||
580 | pDatabase.Events[pDate] = nil; |
||
581 | vSchedule = nil; |
||
582 | end |
||
583 | |||
584 | -- Notify that the schedule changed |
||
585 | |||
586 | GroupCalendar_ScheduleChanged(pDatabase, pDate); |
||
587 | |||
588 | return true; |
||
589 | end |
||
590 | |||
591 | function EventDatabase_GetEventInfoByID(pID) |
||
592 | for vGroupID, vEventGroup in gGroupCalendar_EventTypes do |
||
593 | for vIndex, vEventInfo in vEventGroup.Events do |
||
594 | if vEventInfo.id == pID then |
||
595 | return vEventInfo; |
||
596 | end |
||
597 | end |
||
598 | end |
||
599 | |||
600 | return nil; |
||
601 | end |
||
602 | |||
603 | function EventDatabase_GetEventNameByID(pID) |
||
604 | local vEventInfo = EventDatabase_GetEventInfoByID(pID); |
||
605 | |||
606 | if not vEventInfo then |
||
607 | return nil; |
||
608 | end |
||
609 | |||
610 | return vEventInfo.name; |
||
611 | end |
||
612 | |||
613 | function EventDatabase_GetStandardLimitsByID(pID) |
||
614 | local vEventInfo = EventDatabase_GetEventInfoByID(pID); |
||
615 | |||
616 | if not vEventInfo |
||
617 | or not vEventInfo.limits then |
||
618 | return nil; |
||
619 | end |
||
620 | |||
621 | -- Remove limit for classes from the "wrong" faction |
||
622 | |||
623 | for vClassCode, vClassLimit in vEventInfo.limits.mClassLimits do |
||
624 | local vClassInfo = gGroupCalendar_ClassInfoByClassCode[vClassCode]; |
||
625 | |||
626 | if vClassInfo.faction |
||
627 | and vClassInfo.faction ~= gGroupCalendar_PlayerFactionGroup then |
||
628 | vEventInfo.limits.mClassLimits[vClassCode] = nil; |
||
629 | end |
||
630 | end |
||
631 | |||
632 | -- |
||
633 | |||
634 | return vEventInfo.limits; |
||
635 | end |
||
636 | |||
637 | function EventDatabase_EventAdded(pDatabase, pEvent) |
||
638 | -- Notify the calendar |
||
639 | |||
640 | GroupCalendar_ScheduleChanged(pDatabase, pEvent.mDate); |
||
641 | |||
642 | -- Notify the network |
||
643 | |||
644 | CalendarNetwork_NewEvent(pDatabase, pEvent); |
||
645 | end |
||
646 | |||
647 | function EventDatabase_EventChanged(pDatabase, pEvent, pChangedFields) |
||
648 | -- If the date changed then move the event to the appropriate slot |
||
649 | |||
650 | if pChangedFields and pChangedFields.mDate then |
||
651 | local vEvent, vDate = EventDatabase_FindEventByID(pDatabase, pEvent.mID); |
||
652 | |||
653 | if vDate ~= pEvent.mDate then |
||
654 | EventDatabase_DeleteEventFromDate(pDatabase, vDate, pEvent, true); |
||
655 | EventDatabase_AddEvent(pDatabase, pEvent, true); |
||
656 | end |
||
657 | end |
||
658 | |||
659 | -- Update pending RSVPs based on event contents |
||
660 | |||
661 | if pChangedFields and pChangedFields.mAttendance then |
||
662 | if pChangedFields.mAttendance.op == "UPD" then |
||
663 | for vAttendeeName, vRSVPString in pChangedFields.mAttendance.val do |
||
664 | local vDatabase = EventDatabase_GetDatabase(vAttendeeName, false); |
||
665 | |||
666 | if vDatabase then |
||
667 | -- Remove any older (or same) RSVP for this person |
||
668 | |||
669 | local vRSVP = EventDatabase_UnpackEventRSVP(pDatabase.UserName, vAttendeeName, pEvent.mID, vRSVPString); |
||
670 | |||
671 | EventDatabase_RemoveOlderRSVP(vDatabase, vRSVP) |
||
672 | end |
||
673 | end |
||
674 | else |
||
675 | Calendar_DumpArray("EventDatabase_EventChanged: ", pChangedFields); |
||
676 | Calendar_DebugMessage("EventDatabase_EventChanged: Attendance op "..pChangedFields.mAttendance.op.." not recognized"); |
||
677 | end |
||
678 | end |
||
679 | |||
680 | -- Notify the calendar |
||
681 | |||
682 | GroupCalendar_EventChanged(pDatabase, pEvent, pChangedFields); |
||
683 | |||
684 | -- Notify the network |
||
685 | |||
686 | CalendarNetwork_EventChanged(pDatabase, pEvent, pChangedFields); |
||
687 | end |
||
688 | |||
689 | function EventDatabase_GetCurrentChangeList(pDatabase) |
||
690 | local vChanges = EventDatabase_GetChanges(pDatabase); |
||
691 | local vChangeList, vRevisionChanged = CalendarChanges_GetCurrentChangeList(vChanges); |
||
692 | |||
693 | if vRevisionChanged and pDatabase.IsPlayerOwned then |
||
694 | CalendarNetwork_DBRevisionChanged(pDatabase); |
||
695 | end |
||
696 | |||
697 | return vChangeList; |
||
698 | end |
||
699 | |||
700 | function EventDatabase_GetDBRevisionPath(pUserName, pDatabaseID, pRevision, pAuthRevision) |
||
701 | return CalendarChanges_GetRevisionPath("DB", pUserName, pDatabaseID, pRevision, pAuthRevision); |
||
702 | end |
||
703 | |||
704 | function EventDatabase_GetRSVPRevisionPath(pUserName, pDatabaseID, pRevision, pAuthRevision) |
||
705 | return CalendarChanges_GetRevisionPath("RAT", pUserName, pDatabaseID, pRevision, pAuthRevision); |
||
706 | end |
||
707 | |||
708 | function EventDatabase_GetEventPath(pEvent) |
||
709 | return "EVT:"..pEvent.mID.."/"; |
||
710 | end |
||
711 | |||
712 | function EventDatabase_GenerateEventChangeString(pOpcode, pEvent, pEventPath) |
||
713 | local vChange; |
||
714 | |||
715 | -- Basic fields: type, date, time, duration, minLevel, maxLevel |
||
716 | |||
717 | vChange = pEventPath..pOpcode..":"; |
||
718 | |||
719 | if pEvent.mType ~= nil then |
||
720 | vChange = vChange..pEvent.mType..","; |
||
721 | else |
||
722 | vChange = vChange..","; |
||
723 | end |
||
724 | |||
725 | if pEvent.mDate ~= nil then |
||
726 | vChange = vChange..pEvent.mDate..","; |
||
727 | else |
||
728 | vChange = vChange..","; |
||
729 | end |
||
730 | |||
731 | if pEvent.mTime ~= nil then |
||
732 | vChange = vChange..pEvent.mTime..","; |
||
733 | else |
||
734 | vChange = vChange..","; |
||
735 | end |
||
736 | |||
737 | if pEvent.mDuration ~= nil then |
||
738 | vChange = vChange..pEvent.mDuration..","; |
||
739 | else |
||
740 | vChange = vChange..","; |
||
741 | end |
||
742 | |||
743 | if pEvent.mMinLevel ~= nil then |
||
744 | vChange = vChange..pEvent.mMinLevel..","; |
||
745 | else |
||
746 | vChange = vChange..","; |
||
747 | end |
||
748 | |||
749 | if pEvent.mMaxLevel ~= nil then |
||
750 | vChange = vChange..pEvent.mMaxLevel; |
||
751 | end |
||
752 | |||
753 | return vChange; |
||
754 | end |
||
755 | |||
756 | function EventDatabase_AppendNewEvent(pChangeList, pEvent, pEventPath) |
||
757 | -- Basic fields: type, date, time, duration, minLevel, maxLevel |
||
758 | |||
759 | table.insert(pChangeList, EventDatabase_GenerateEventChangeString("NEW", pEvent, pEventPath)); |
||
760 | |||
761 | -- Title |
||
762 | |||
763 | if pEvent.mTitle then |
||
764 | table.insert(pChangeList, pEventPath.."TIT:"..pEvent.mTitle); |
||
765 | end |
||
766 | |||
767 | if pEvent.mDescription ~= nil then |
||
768 | table.insert(pChangeList, pEventPath.."DSC:"..pEvent.mDescription); |
||
769 | end |
||
770 | |||
771 | if pEvent.mManualConfirm then |
||
772 | table.insert(pChangeList, pEventPath.."CNF:MAN"); |
||
773 | elseif pEvent.mLimits then |
||
774 | local vConfConfigString = "CNF:AUT"; |
||
775 | |||
776 | if pEvent.mLimits.mMaxAttendance then |
||
777 | vConfConfigString = vConfConfigString.."/MAX:"..pEvent.mLimits.mMaxAttendance; |
||
778 | end |
||
779 | |||
780 | if pEvent.mLimits.mClassLimits then |
||
781 | for vClassCode, vClassLimit in pEvent.mLimits.mClassLimits do |
||
782 | vConfConfigString = vConfConfigString.."/"..vClassCode..":"; |
||
783 | |||
784 | if vClassLimit.mMin then |
||
785 | vConfConfigString = vConfConfigString..vClassLimit.mMin; |
||
786 | end |
||
787 | |||
788 | if vClassLimit.mMax then |
||
789 | vConfConfigString = vConfConfigString..","..vClassLimit.mMax; |
||
790 | end |
||
791 | end |
||
792 | end |
||
793 | |||
794 | table.insert(pChangeList, pEventPath..vConfConfigString); |
||
795 | end |
||
796 | |||
797 | -- Add attendance info |
||
798 | |||
799 | if pEvent.mAttendance then |
||
800 | for vAttendeeName, vAttendance in pEvent.mAttendance do |
||
801 | table.insert(pChangeList, pEventPath.."ATT:"..vAttendeeName..","..vAttendance); |
||
802 | end |
||
803 | end |
||
804 | |||
805 | table.insert(pChangeList, pEventPath.."END"); |
||
806 | end |
||
807 | |||
808 | function EventDatabase_AppendEventUpdate(pChangeList, pEvent, pEventPath, pChangedFields) |
||
809 | local vNeedUpdateWrapper = false; |
||
810 | |||
811 | -- See if fields sent in the NEW or UPD wrapper are being changed. If so, the |
||
812 | -- wrapper needs to be sent, otherwise it can be omitted to save bandwidth |
||
813 | |||
814 | if pChangedFields.mType |
||
815 | or pChangedFields.mDate |
||
816 | or pChangedFields.mTime |
||
817 | or pChangedFields.mDuration |
||
818 | or pChangedFields.mMinLevel |
||
819 | or pChangedFields.mMaxLevel then |
||
820 | vNeedUpdateWrapper = true; |
||
821 | end |
||
822 | |||
823 | -- Basic fields: type, date, time, duration, minLevel, maxLevel |
||
824 | |||
825 | if vNeedUpdateWrapper then |
||
826 | table.insert(pChangeList, EventDatabase_GenerateEventChangeString("UPD", pEvent, pEventPath)); |
||
827 | end |
||
828 | |||
829 | -- Title |
||
830 | |||
831 | if pChangedFields.mTitle ~= nil then |
||
832 | if pEvent.mTitle then |
||
833 | table.insert(pChangeList, pEventPath.."TIT:"..pEvent.mTitle); |
||
834 | end |
||
835 | end |
||
836 | |||
837 | if pChangedFields.mDescription ~= nil then |
||
838 | if pEvent.mDescription ~= nil then |
||
839 | table.insert(pChangeList, pEventPath.."DSC:"..pEvent.mDescription); |
||
840 | end |
||
841 | end |
||
842 | |||
843 | if pChangedFields.mManualConfirm ~= nil |
||
844 | or pChangedFields.mLimits ~= nil then |
||
845 | if pEvent.mManualConfirm then |
||
846 | table.insert(pChangeList, pEventPath.."CNF:MAN"); |
||
847 | elseif pEvent.mLimits then |
||
848 | local vConfConfigString = "CNF:AUT"; |
||
849 | |||
850 | if pEvent.mLimits.mMaxAttendance then |
||
851 | vConfConfigString = vConfConfigString.."/MAX:"..pEvent.mLimits.mMaxAttendance; |
||
852 | end |
||
853 | |||
854 | if pEvent.mLimits.mClassLimits then |
||
855 | for vClassCode, vClassLimit in pEvent.mLimits.mClassLimits do |
||
856 | vConfConfigString = vConfConfigString.."/"..vClassCode..":"; |
||
857 | |||
858 | if vClassLimit.mMin then |
||
859 | vConfConfigString = vConfConfigString..vClassLimit.mMin; |
||
860 | end |
||
861 | |||
862 | if vClassLimit.mMax then |
||
863 | vConfConfigString = vConfConfigString..","..vClassLimit.mMax; |
||
864 | end |
||
865 | end |
||
866 | end |
||
867 | |||
868 | table.insert(pChangeList, pEventPath..vConfConfigString); |
||
869 | end |
||
870 | end |
||
871 | |||
872 | if pChangedFields.mAttendance ~= nil then |
||
873 | if pChangedFields.mAttendance.op == "UPD" then |
||
874 | for vAttendeeName, vEventRSVPString in pChangedFields.mAttendance.val do |
||
875 | local vAttendeeRSVPString = pEvent.mAttendance[vAttendeeName]; |
||
876 | local vAttendeePath = pEventPath.."ATT:"..vAttendeeName; |
||
877 | |||
878 | if not vAttendeeRSVPString then |
||
879 | table.insert(pChangeList, vAttendeePath); |
||
880 | else |
||
881 | table.insert(pChangeList, vAttendeePath..","..vAttendeeRSVPString); |
||
882 | end |
||
883 | end |
||
884 | else |
||
885 | Calendar_DebugMessage("EventDatabase_AppendEventUpdate: Unknown attendance opcode "..pChangedFields.mAttendance.op); |
||
886 | end |
||
887 | end |
||
888 | |||
889 | if vNeedUpdateWrapper then |
||
890 | table.insert(pChangeList, pEventPath.."END"); |
||
891 | end |
||
892 | end |
||
893 | |||
894 | function EventDatabase_RemoveEventChanges(pDatabase, pEvent) |
||
895 | -- Nothing to do if there are no changes |
||
896 | |||
897 | if not pDatabase.Changes then |
||
898 | return; |
||
899 | end |
||
900 | |||
901 | -- Remove all prior occurances for this event |
||
902 | |||
903 | for vRevision, vChangeList in pDatabase.Changes.ChangeList do |
||
904 | local vEventPath = EventDatabase_GetEventPath(pEvent); |
||
905 | local vPathLength = string.len(vEventPath); |
||
906 | |||
907 | local vNumChanges = table.getn(vChangeList); |
||
908 | local vChangeIndex = 1; |
||
909 | |||
910 | while vChangeIndex <= vNumChanges do |
||
911 | vChange = vChangeList[vChangeIndex]; |
||
912 | |||
913 | if vChange ~= nil |
||
914 | and string.sub(vChange, 1, vPathLength) == vEventPath then |
||
915 | table.remove(vChangeList, vIndex); |
||
916 | vNumChanges = vNumChanges - 1; |
||
917 | else |
||
918 | vChangeIndex = vChangeIndex + 1; |
||
919 | end |
||
920 | end |
||
921 | |||
922 | if vNumChanges == 0 then |
||
923 | pDatabase.Changes.ChangeList[vRevision] = nil; |
||
924 | end |
||
925 | end |
||
926 | end |
||
927 | |||
928 | function EventDatabase_RebuildPlayerDatabases() |
||
929 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
930 | if vDatabase.IsPlayerOwned |
||
931 | and vDatabase.Realm == gGroupCalendar_RealmName then |
||
932 | EventDatabase_RebuildDatabase(vDatabase); |
||
933 | end |
||
934 | end -- for vRealmUser, vDatabase |
||
935 | end |
||
936 | |||
937 | ---------------------------------------- |
||
938 | -- EventDatabase_CalculateHighestUsedEventID |
||
939 | -- Calculates the highest event ID in use by the database |
||
940 | ---------------------------------------- |
||
941 | |||
942 | function EventDatabase_CalculateHighestUsedEventID(pDatabase) |
||
943 | local vHighestID = nil; |
||
944 | |||
945 | for vDate, vSchedule in pDatabase.Events do |
||
946 | for vEventIndex, vEvent in vSchedule do |
||
947 | if not vHighestID |
||
948 | or vHighestID < vEvent.mID then |
||
949 | vHighestID = vEvent.mID; |
||
950 | end |
||
951 | end -- for vEventIndex, vEvent |
||
952 | end -- for vDate, vSchedule |
||
953 | end |
||
954 | |||
955 | ---------------------------------------- |
||
956 | -- EventDatabase_RepairEventIDs |
||
957 | -- Scans the database an ensures that every event has |
||
958 | -- a unique ID |
||
959 | ---------------------------------------- |
||
960 | |||
961 | function EventDatabase_RepairEventIDs(pDatabase) |
||
962 | local vCurrentID = EventDatabase_CalculateHighestUsedEventID(pDatabase); |
||
963 | |||
964 | -- Just return if there are no events |
||
965 | |||
966 | if not vCurrentID then |
||
967 | return; |
||
968 | end |
||
969 | |||
970 | -- Adjust the highest ID if it is lower than current ID |
||
971 | |||
972 | if vCurrentID < pDatabase.CurrentEventID then |
||
973 | vCurrentID = pDatabase.CurrentEventID; |
||
974 | end |
||
975 | |||
976 | -- Start making a map of used event IDs and |
||
977 | -- use up the next ID if a collision is detected |
||
978 | |||
979 | local vUsedIDs = {}; |
||
980 | |||
981 | for vDate, vSchedule in pDatabase.Events do |
||
982 | for vEventIndex, vEvent in vSchedule do |
||
983 | if not vUsedIDs[vEvent.mID] then |
||
984 | vUsedIDs[vEvent.mID] = true; |
||
985 | else |
||
986 | -- Collision |
||
987 | |||
988 | vCurrentID = vCurrentID + 1; |
||
989 | vEvent.mID = vCurrentID; |
||
990 | end |
||
991 | end -- for vEventIndex, vEvent |
||
992 | end -- for vDate, vSchedule |
||
993 | |||
994 | -- Save the new current ID |
||
995 | |||
996 | pDatabase.CurrentEventID = vCurrentID; |
||
997 | end |
||
998 | |||
999 | ---------------------------------------- |
||
1000 | -- EventDatabase_RebuildDatabase |
||
1001 | -- Builds a new change history from the existing events |
||
1002 | ---------------------------------------- |
||
1003 | |||
1004 | function EventDatabase_RebuildDatabase(pDatabase) |
||
1005 | -- Repair event IDs |
||
1006 | |||
1007 | EventDatabase_RepairEventIDs(pDatabase); |
||
1008 | |||
1009 | -- Clear the revisions |
||
1010 | |||
1011 | pDatabase.Changes = nil; |
||
1012 | |||
1013 | -- Start a new revision |
||
1014 | |||
1015 | local vChangeList = nil; |
||
1016 | |||
1017 | -- Add each event to the revision |
||
1018 | |||
1019 | for vDate, vSchedule in pDatabase.Events do |
||
1020 | for vEventIndex, vEvent in vSchedule do |
||
1021 | if not vChangeList then |
||
1022 | vChangeList = EventDatabase_GetCurrentChangeList(pDatabase); |
||
1023 | end |
||
1024 | |||
1025 | local vEventPath = EventDatabase_GetEventPath(vEvent); |
||
1026 | |||
1027 | if not vEvent.mPrivate then |
||
1028 | EventDatabase_AppendNewEvent( |
||
1029 | vChangeList, |
||
1030 | vEvent, |
||
1031 | vEventPath); |
||
1032 | end |
||
1033 | end |
||
1034 | end |
||
1035 | |||
1036 | if not vChangeList then |
||
1037 | CalendarNetwork_SendEmptyChanges(pDatabase.Changes, "DB", pDatabase.UserName) |
||
1038 | end |
||
1039 | |||
1040 | -- Compact the RSVP list and notify that they're updated |
||
1041 | |||
1042 | EventDatabase_RebuildRSVPs(pDatabase); |
||
1043 | |||
1044 | -- Notify the calendar that there was a major change |
||
1045 | |||
1046 | GroupCalendar_MajorDatabaseChange(pDatabase); |
||
1047 | end |
||
1048 | |||
1049 | function EventDatabase_RebuildRSVPs(pDatabase) |
||
1050 | if pDatabase.RSVPs then |
||
1051 | CalendarChanges_Compact(pDatabase.RSVPs); |
||
1052 | end |
||
1053 | |||
1054 | if not CalendarChanges_IsEmpty(pDatabase.RSVPs) then |
||
1055 | CalendarNetwork_RSVPRevisionChanged(pDatabase); |
||
1056 | else |
||
1057 | CalendarNetwork_SendEmptyChanges(pDatabase.RSVPs, "RAT", pDatabase.UserName) |
||
1058 | end |
||
1059 | end |
||
1060 | |||
1061 | ---------------------------------------- |
||
1062 | -- EventDatabase_ReconstructDatabase |
||
1063 | -- Reconstructs the event records by re-playing the |
||
1064 | -- change history |
||
1065 | ---------------------------------------- |
||
1066 | |||
1067 | function EventDatabase_ReconstructDatabase(pDatabase) |
||
1068 | -- Clear the events |
||
1069 | |||
1070 | pDatabase.Events = {}; |
||
1071 | |||
1072 | -- Execute each change |
||
1073 | |||
1074 | if pDatabase.Changes then |
||
1075 | for vRevision, vChangeList in pDatabase.Changes.ChangeList do |
||
1076 | if gGroupCalendar_Settings.DebugReconstruct then |
||
1077 | Calendar_DebugMessage("EventDatabase_ReconstructDatabase: Reconstruction revision "..vRevision.." in "..pDatabase.UserName); |
||
1078 | end |
||
1079 | |||
1080 | EventDatabase_ExecuteChangeList(pDatabase, vChangeList, false); |
||
1081 | end |
||
1082 | end |
||
1083 | |||
1084 | GroupCalendar_MajorDatabaseChange(pDatabase); |
||
1085 | end |
||
1086 | |||
1087 | function EventDatabase_ReprocessAllRSVPs(pDatabase) |
||
1088 | local vRSVPs = pDatabase.RSVPs; |
||
1089 | |||
1090 | if not vRSVPs then |
||
1091 | return; |
||
1092 | end |
||
1093 | |||
1094 | for vRevision, vChangeList in vRSVPs.ChangeList do |
||
1095 | EventDatabase_ExecuteRSVPChangeList(pDatabase, vChangeList, false); |
||
1096 | end |
||
1097 | end |
||
1098 | |||
1099 | function EventDatabase_ExecuteRSVPChangeList(pDatabase, pChangeList, pNotifyChanges) |
||
1100 | pChangeList.IsOpen = nil; -- Make sure IsOpen is cleared, a bug may have caused it to remain open |
||
1101 | |||
1102 | local vIndex = 1; |
||
1103 | local vNumChanges = table.getn(pChangeList); |
||
1104 | |||
1105 | while vIndex <= vNumChanges do |
||
1106 | local vChange = pChangeList[vIndex]; |
||
1107 | |||
1108 | if vChange then |
||
1109 | local vCommands = CalendarNetwork_ParseCommandSubString("/"..vChange); |
||
1110 | |||
1111 | if not vCommands then |
||
1112 | Calendar_DebugMessage("Invalid change entry found in RSVPs for "..pDatabase.UserName); |
||
1113 | return; |
||
1114 | end |
||
1115 | |||
1116 | local vOpcode = vCommands[1].opcode; |
||
1117 | local vOperands = vCommands[1].operands; |
||
1118 | |||
1119 | table.remove(vCommands, 1); |
||
1120 | |||
1121 | if vOpcode == "EVT" then |
||
1122 | local vRSVP = EventDatabase_UnpackRSVPFieldArray(vOperands, pDatabase.UserName); |
||
1123 | |||
1124 | if EventDatabase_ProcessRSVP(pDatabase, vRSVP) then |
||
1125 | -- The request was consumed, remove it from the list |
||
1126 | |||
1127 | table.remove(pChangeList, vIndex); |
||
1128 | |||
1129 | vIndex = vIndex - 1; |
||
1130 | vNumChanges = vNumChanges - 1; |
||
1131 | end |
||
1132 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1133 | Calendar_DebugMessage("GroupCalendar: Unknown RSVP opcode "..vOpcode); |
||
1134 | end |
||
1135 | end |
||
1136 | |||
1137 | vIndex = vIndex + 1; |
||
1138 | end |
||
1139 | end |
||
1140 | |||
1141 | function EventDatabase_ExecuteChangeList(pDatabase, pChangeList, pNotifyChanges) |
||
1142 | local vEvent = nil; |
||
1143 | local vNewEvent = false; |
||
1144 | local vQuickEvent = false; |
||
1145 | local vEventDateChanged = false; |
||
1146 | |||
1147 | pChangeList.IsOpen = nil; -- Make sure IsOpen is cleared, a bug may have caused it to remain open |
||
1148 | |||
1149 | for vIndex, vChange in pChangeList do |
||
1150 | local vCommands = CalendarNetwork_ParseCommandSubString("/"..vChange); |
||
1151 | |||
1152 | if not vCommands then |
||
1153 | Calendar_DebugMessage("Invalid change entry found in database for "..pDatabase.UserName); |
||
1154 | return; |
||
1155 | end |
||
1156 | |||
1157 | local vOpcode = vCommands[1].opcode; |
||
1158 | local vOperands = vCommands[1].operands; |
||
1159 | |||
1160 | table.remove(vCommands, 1); |
||
1161 | |||
1162 | if vOpcode == "EVT" then |
||
1163 | local vEventID = tonumber(vOperands[1]); |
||
1164 | |||
1165 | local vEvtOpcode = vCommands[1].opcode; |
||
1166 | local vEvtOperands = vCommands[1].operands; |
||
1167 | |||
1168 | table.remove(vCommands, 1); |
||
1169 | |||
1170 | if vEvtOpcode == "NEW" then |
||
1171 | if vEvent and gGroupCalendar_Settings.DebugErrors then |
||
1172 | Calendar_DebugMessage("GroupCalendar: Starting new event while previous event is still open in database for "..pDatabase.UserName); |
||
1173 | end |
||
1174 | |||
1175 | if gGroupCalendar_Settings.Debug then |
||
1176 | Calendar_DebugMessage("Adding event "..vEventID.." for "..pDatabase.UserName); |
||
1177 | end |
||
1178 | |||
1179 | if not EventDatabase_FindEventByID(pDatabase, vEventID) then |
||
1180 | local vDate = tonumber(vEvtOperands[2]); |
||
1181 | |||
1182 | if vDate >= gGroupCalendar_MinimumEventDate then |
||
1183 | -- Create the event record |
||
1184 | |||
1185 | vEvent = {}; |
||
1186 | vNewEvent = true; |
||
1187 | |||
1188 | vEvent.mID = vEventID; |
||
1189 | vEvent.mType = vEvtOperands[1]; |
||
1190 | vEvent.mDate = tonumber(vEvtOperands[2]); |
||
1191 | vEvent.mTime = tonumber(vEvtOperands[3]); |
||
1192 | vEvent.mDuration = tonumber(vEvtOperands[4]); |
||
1193 | vEvent.mMinLevel = tonumber(vEvtOperands[5]); |
||
1194 | vEvent.mMaxLevel = tonumber(vEvtOperands[6]); |
||
1195 | |||
1196 | EventDatabase_AddEvent(pDatabase, vEvent, true); |
||
1197 | end |
||
1198 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1199 | Calendar_DebugMessage("GroupCalendar: Event "..vEventID.." already exists in database for "..pDatabase.UserName); |
||
1200 | end |
||
1201 | |||
1202 | elseif vEvtOpcode == "UPD" then |
||
1203 | if vEvent and gGroupCalendar_Settings.DebugErrors then |
||
1204 | Calendar_DebugMessage("GroupCalendar: Updating event while previous event is still open in database for "..pDatabase.UserName); |
||
1205 | end |
||
1206 | |||
1207 | vEvent = EventDatabase_FindEventByID(pDatabase, vEventID); |
||
1208 | |||
1209 | if vEvent then |
||
1210 | local vDate = vEvent.mDate; |
||
1211 | |||
1212 | vEvent.mID = vEventID; |
||
1213 | vEvent.mType = vEvtOperands[1]; |
||
1214 | vEvent.mDate = tonumber(vEvtOperands[2]); |
||
1215 | vEvent.mTime = tonumber(vEvtOperands[3]); |
||
1216 | vEvent.mDuration = tonumber(vEvtOperands[4]); |
||
1217 | vEvent.mMinLevel = tonumber(vEvtOperands[5]); |
||
1218 | vEvent.mMaxLevel = tonumber(vEvtOperands[6]); |
||
1219 | |||
1220 | vNewEvent = false; |
||
1221 | vEventDateChanged = vEvent.mDate ~= vDate; |
||
1222 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1223 | Calendar_DebugMessage("GroupCalendar: Event "..vEventID.." not found in database for "..pDatabase.UserName); |
||
1224 | end |
||
1225 | |||
1226 | elseif vEvtOpcode == "TIT" then |
||
1227 | if not vEvent then |
||
1228 | vEvent = EventDatabase_FindEventByID(pDatabase, vEventID); |
||
1229 | vQuickEvent = true; |
||
1230 | end |
||
1231 | |||
1232 | if vEvent then |
||
1233 | vEvent.mTitle = vEvtOperands[1]; |
||
1234 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1235 | Calendar_DebugMessage("GroupCalendar: Event "..vEventID.." not found in database for "..pDatabase.UserName); |
||
1236 | end |
||
1237 | |||
1238 | elseif vEvtOpcode == "DSC" then |
||
1239 | if not vEvent then |
||
1240 | vEvent = EventDatabase_FindEventByID(pDatabase, vEventID); |
||
1241 | vQuickEvent = true; |
||
1242 | end |
||
1243 | |||
1244 | if vEvent then |
||
1245 | vEvent.mDescription = vEvtOperands[1]; |
||
1246 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1247 | Calendar_DebugMessage("GroupCalendar: Event "..vEventID.." not found in database for "..pDatabase.UserName); |
||
1248 | end |
||
1249 | |||
1250 | elseif vEvtOpcode == "ATT" then |
||
1251 | if not vEvent then |
||
1252 | vEvent = EventDatabase_FindEventByID(pDatabase, vEventID); |
||
1253 | vQuickEvent = true; |
||
1254 | end |
||
1255 | |||
1256 | if vEvent then |
||
1257 | local vAttendeeName = vEvtOperands[1]; |
||
1258 | |||
1259 | if not vEvent.mAttendance then |
||
1260 | vEvent.mAttendance = {}; |
||
1261 | end |
||
1262 | |||
1263 | -- Add/update their attendance |
||
1264 | |||
1265 | local vNumOperands = table.getn(vEvtOperands); |
||
1266 | local vAttendanceString = nil; |
||
1267 | |||
1268 | if vNumOperands > 1 then |
||
1269 | for vOperandIndex = 2, vNumOperands do |
||
1270 | local vOperand = vEvtOperands[vOperandIndex]; |
||
1271 | |||
1272 | if vAttendanceString == nil then |
||
1273 | vAttendanceString = ""; |
||
1274 | else |
||
1275 | vAttendanceString = vAttendanceString..","; |
||
1276 | end |
||
1277 | |||
1278 | if vOperand then |
||
1279 | vAttendanceString = vAttendanceString..vOperand; |
||
1280 | end |
||
1281 | end |
||
1282 | |||
1283 | end |
||
1284 | |||
1285 | vEvent.mAttendance[vAttendeeName] = vAttendanceString; |
||
1286 | |||
1287 | -- Remove any older (or same) RSVP for this person |
||
1288 | |||
1289 | EventDatabase_RemoveOldAttendeeRSVP(vAttendeeName, pDatabase.UserName, vEventID, vAttendanceString); |
||
1290 | |||
1291 | -- Didn't find the specified event |
||
1292 | |||
1293 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1294 | Calendar_DebugMessage("GroupCalendar: Event "..vEventID.." not found in database for "..pDatabase.UserName); |
||
1295 | end |
||
1296 | |||
1297 | elseif vEvtOpcode == "END" then |
||
1298 | if vEvent then |
||
1299 | if pNotifyChanges then |
||
1300 | -- Notify the calendar |
||
1301 | |||
1302 | if vNewEvent then |
||
1303 | GroupCalendar_ScheduleChanged(pDatabase, vEvent.mDate); |
||
1304 | else |
||
1305 | if vEventDateChanged then |
||
1306 | local vEvent2, vDate = EventDatabase_FindEventByID(pDatabase, vEvent.mID); |
||
1307 | |||
1308 | if vDate ~= vEvent.mDate then |
||
1309 | EventDatabase_DeleteEventFromDate(pDatabase, vDate, pEvent, true); |
||
1310 | EventDatabase_AddEvent(pDatabase, vEvent, true); |
||
1311 | end |
||
1312 | end |
||
1313 | |||
1314 | GroupCalendar_EventChanged(pDatabase, vEvent, nil); -- only notify the calendar |
||
1315 | end |
||
1316 | end |
||
1317 | |||
1318 | vEvent = nil; |
||
1319 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1320 | Calendar_DebugMessage("GroupCalendar: Event not open when attemping to end update for "..pDatabase.UserName); |
||
1321 | end |
||
1322 | |||
1323 | elseif vEvtOpcode == "DEL" then |
||
1324 | vEvent = EventDatabase_FindEventByID(pDatabase, vEventID); |
||
1325 | vQuickEvent = true; |
||
1326 | |||
1327 | if vEvent then |
||
1328 | EventDatabase_DeleteEvent(pDatabase, vEvent, true); |
||
1329 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1330 | Calendar_DebugMessage("GroupCalendar: Can't delete event "..vEventID..": Event not found in database for "..pDatabase.UserName); |
||
1331 | end |
||
1332 | |||
1333 | elseif gGroupCalendar_Settings.DebugErrors then |
||
1334 | Calendar_DebugMessage("GroupCalendar: Unknown change operator "..vEvtOpcode); |
||
1335 | end |
||
1336 | |||
1337 | if vQuickEvent then |
||
1338 | vEvent = nil; |
||
1339 | end |
||
1340 | end |
||
1341 | end |
||
1342 | end |
||
1343 | |||
1344 | function EventDatabase_PurgeDatabase(pDatabase, pDatabaseID) |
||
1345 | EventDatabase_RemoveAllRSVPsForDatabase(pDatabase, false) |
||
1346 | |||
1347 | pDatabase.CurrentEventID = 0; |
||
1348 | pDatabase.Events = {}; |
||
1349 | |||
1350 | pDatabase.Changes = CalendarChanges_New(); |
||
1351 | pDatabase.Changes.ID = pDatabaseID; |
||
1352 | |||
1353 | GroupCalendar_MajorDatabaseChange(pDatabase); |
||
1354 | end |
||
1355 | |||
1356 | function EventDatabase_PurgeRSVPs(pDatabase, pDatabaseID) |
||
1357 | pDatabase.RSVPs = CalendarChanges_New(); |
||
1358 | pDatabase.RSVPs.ID = pDatabaseID; |
||
1359 | |||
1360 | GroupCalendar_MajorDatabaseChange(pDatabase); |
||
1361 | end |
||
1362 | |||
1363 | function EventDatabase_CheckDatabase(pDatabase) |
||
1364 | -- Remove empty RSVP changelists |
||
1365 | |||
1366 | if pDatabase.RSVPs then |
||
1367 | for vRevision, vChangeList in pDatabase.RSVPs.ChangeList do |
||
1368 | if table.getn(vChangeList) == 0 then |
||
1369 | pDatabase.RSVPs.ChangeList[vRevision] = nil; |
||
1370 | end |
||
1371 | end |
||
1372 | end |
||
1373 | |||
1374 | -- Remove events with duplicate IDs |
||
1375 | |||
1376 | for vDate, vEvents in pDatabase.Events do |
||
1377 | local vEventIndex = 1; |
||
1378 | local vNumEvents = table.getn(vEvents); |
||
1379 | |||
1380 | while vEventIndex <= vNumEvents do |
||
1381 | local vEvent = vEvents[vEventIndex]; |
||
1382 | |||
1383 | if not vEvent |
||
1384 | or EventDatabase_FindEventByID(pDatabase, vEvent.mID) ~= vEvent then |
||
1385 | Calendar_DebugMessage("EventDatabase_CheckDatabase: Removing extra event ID "..vEvent.mID.." from database for "..pDatabase.UserName); |
||
1386 | |||
1387 | table.remove(vEvents, vEventIndex); |
||
1388 | vNumEvents = vNumEvents - 1; |
||
1389 | else |
||
1390 | vEventIndex = vEventIndex + 1; |
||
1391 | end |
||
1392 | end |
||
1393 | end |
||
1394 | end |
||
1395 | |||
1396 | function EventDatabase_ScanForNewlines(pDatabase) |
||
1397 | for vDate, vEvents in pDatabase.Events do |
||
1398 | for vEventID, vEvent in vEvents do |
||
1399 | if vEvent.mDescription then |
||
1400 | vEvent.mDescription = string.gsub(vEvent.mDescription, "\n", "&n;"); |
||
1401 | end |
||
1402 | end |
||
1403 | end |
||
1404 | |||
1405 | if pDatabase.Changes and pDatabase.Changes.ChangeList then |
||
1406 | for vRevision, vChanges in pDatabase.Changes.ChangeList do |
||
1407 | for vIndex, vChange in vChanges do |
||
1408 | if type(vIndex) == "number" then |
||
1409 | vChanges[vIndex] = string.gsub(vChange, "\n", "&n;"); |
||
1410 | end |
||
1411 | end |
||
1412 | end |
||
1413 | end |
||
1414 | end |
||
1415 | |||
1416 | function EventDatabase_Initialize() |
||
1417 | EventDatabase_CheckDatabases(); |
||
1418 | |||
1419 | -- Update the list of player-owned databases |
||
1420 | |||
1421 | gGroupCalendar_PlayerCharacters = {}; |
||
1422 | |||
1423 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1424 | if EventDatabase_DatabaseIsVisible(vDatabase) |
||
1425 | and vDatabase.IsPlayerOwned then |
||
1426 | gGroupCalendar_PlayerCharacters[vDatabase.UserName] = true; |
||
1427 | end |
||
1428 | end |
||
1429 | end |
||
1430 | |||
1431 | function EventDatabase_CheckDatabases() |
||
1432 | -- Upgrade the database to format 4 (just purge all non-owned databases |
||
1433 | -- and rebuild the owned ones) |
||
1434 | |||
1435 | if gGroupCalendar_Database.Format < 4 then |
||
1436 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1437 | if vDatabase.IsPlayerOwned then |
||
1438 | EventDatabase_RebuildDatabase(vDatabase); |
||
1439 | else |
||
1440 | gGroupCalendar_Database.Databases[vRealmUser] = nil; |
||
1441 | end |
||
1442 | end |
||
1443 | |||
1444 | gGroupCalendar_Database.Format = 4; |
||
1445 | end |
||
1446 | |||
1447 | -- Upgrade the database to format 5 (scan for newlines in event fields and escape them) |
||
1448 | |||
1449 | if gGroupCalendar_Database.Format < 5 then |
||
1450 | for vRealmUser, vSettings in gGroupCalendar_Settings do |
||
1451 | if type(vSettings) == "array" and vSettings.EventTemplates then |
||
1452 | for vEventID, vEventTemplate in vSettings.EventTemplates do |
||
1453 | if vEventTemplate.mDescription then |
||
1454 | vEventTemplate.mDescription = string.gsub(vEventTemplate.mDescription, "\n", "&n;"); |
||
1455 | end |
||
1456 | end |
||
1457 | end |
||
1458 | end |
||
1459 | |||
1460 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1461 | EventDatabase_ScanForNewlines(vDatabase); |
||
1462 | end |
||
1463 | |||
1464 | gGroupCalendar_Database.Format = 5; |
||
1465 | end |
||
1466 | |||
1467 | -- Upgrade the database to format 6 (just purge all non-owned databases |
||
1468 | -- and rebuild the owned ones again) |
||
1469 | |||
1470 | if gGroupCalendar_Database.Format < 6 then |
||
1471 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1472 | if vDatabase.IsPlayerOwned then |
||
1473 | EventDatabase_RebuildDatabase(vDatabase); |
||
1474 | else |
||
1475 | gGroupCalendar_Database.Databases[vRealmUser] = nil; |
||
1476 | end |
||
1477 | end |
||
1478 | |||
1479 | gGroupCalendar_Database.Format = 6; |
||
1480 | end |
||
1481 | |||
1482 | -- Upgrade to format 7 (just purge all non-owned databases) |
||
1483 | |||
1484 | if gGroupCalendar_Database.Format < 7 then |
||
1485 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1486 | if not vDatabase.IsPlayerOwned then |
||
1487 | gGroupCalendar_Database.Databases[vRealmUser] = nil; |
||
1488 | end |
||
1489 | end |
||
1490 | |||
1491 | gGroupCalendar_Database.Format = 7; |
||
1492 | end |
||
1493 | |||
1494 | -- Upgrade to format 8 (rebuild all owned databases to force |
||
1495 | -- them to the new version numbering system) |
||
1496 | |||
1497 | if gGroupCalendar_Database.Format < 8 then |
||
1498 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1499 | if vDatabase.IsPlayerOwned then |
||
1500 | EventDatabase_RebuildDatabase(vDatabase); |
||
1501 | end |
||
1502 | end |
||
1503 | |||
1504 | gGroupCalendar_Database.Format = 8; |
||
1505 | end |
||
1506 | |||
1507 | -- Upgrade to format 9 (reconstruct non-owned databases to correct |
||
1508 | -- parsing errors) |
||
1509 | |||
1510 | if gGroupCalendar_Database.Format < 9 then |
||
1511 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1512 | if not vDatabase.IsPlayerOwned then |
||
1513 | EventDatabase_ReconstructDatabase(vDatabase); |
||
1514 | end |
||
1515 | end |
||
1516 | |||
1517 | gGroupCalendar_Database.Format = 9; |
||
1518 | end |
||
1519 | |||
1520 | -- Upgrade the database to format 10 (just purge all non-owned databases) |
||
1521 | |||
1522 | if gGroupCalendar_Database.Format < 10 then |
||
1523 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1524 | if not vDatabase.IsPlayerOwned then |
||
1525 | gGroupCalendar_Database.Databases[vRealmUser] = nil; |
||
1526 | end |
||
1527 | end |
||
1528 | |||
1529 | gGroupCalendar_Database.Format = 10; |
||
1530 | end |
||
1531 | |||
1532 | -- Upgrade the database to format 11 (ensure that RSVPs for deleted events have been removed |
||
1533 | -- and that event IDs are numbers and not strings) |
||
1534 | |||
1535 | if gGroupCalendar_Database.Format < 11 then |
||
1536 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1537 | -- Convert all event IDs to a number to fix a bug |
||
1538 | -- caused by earlier versions |
||
1539 | |||
1540 | for vDate, vEvents in vDatabase.Events do |
||
1541 | for vIndex, vEvent in vEvents do |
||
1542 | vEvent.mID = tonumber(vEvent.mID); |
||
1543 | end |
||
1544 | end |
||
1545 | end |
||
1546 | |||
1547 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1548 | if vDatabase.IsPlayerOwned then |
||
1549 | EventDatabase_RemoveObsoleteRSVPs(vDatabase); |
||
1550 | EventDatabase_RebuildRSVPs(vDatabase); |
||
1551 | else |
||
1552 | EventDatabase_ReprocessAllRSVPs(vDatabase); |
||
1553 | end |
||
1554 | end |
||
1555 | |||
1556 | gGroupCalendar_Database.Format = 11; |
||
1557 | end |
||
1558 | |||
1559 | -- Make sure the realm is set |
||
1560 | |||
1561 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1562 | if not vDatabase.Realm then |
||
1563 | local vStartIndex, vEndIndex, vRealmName = string.find(vRealmUser, "([^_]+)"); |
||
1564 | |||
1565 | if vStartIndex ~= nil then |
||
1566 | vDatabase.Realm = vRealmName; |
||
1567 | end |
||
1568 | end |
||
1569 | |||
1570 | EventDatabase_CheckDatabase(vDatabase); |
||
1571 | end |
||
1572 | |||
1573 | -- Remove old events |
||
1574 | |||
1575 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1576 | EventDatabase_DeleteOldEvents(vDatabase); |
||
1577 | end |
||
1578 | end |
||
1579 | |||
1580 | function EventDatabase_CheckDatabaseTrust() |
||
1581 | -- Return if they're in a guild but the roster isn't loaded |
||
1582 | -- so that we don't go and delete a bunch of guildie calendars |
||
1583 | -- by mistake |
||
1584 | |||
1585 | if IsInGuild() and GetNumGuildMembers() == 0 then |
||
1586 | if gGroupCalendar_Settings.DebugInit then |
||
1587 | Calendar_DebugMessage("CheckDatabaseTrust: Roster isn't loaded, scheduling a load"); |
||
1588 | end |
||
1589 | |||
1590 | CalendarNetwork_LoadGuildRoster(); |
||
1591 | return; |
||
1592 | end |
||
1593 | |||
1594 | if gGroupCalendar_Settings.DebugInit then |
||
1595 | Calendar_DebugMessage("CheckDatabaseTrust: Verifying trust"); |
||
1596 | end |
||
1597 | |||
1598 | -- Verify that each database is still trusted |
||
1599 | |||
1600 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1601 | -- Only check databases for the current realm |
||
1602 | |||
1603 | if EventDatabase_DatabaseIsVisible(vDatabase) then |
||
1604 | |||
1605 | -- See if they're still trusted |
||
1606 | |||
1607 | if not vDatabase.IsPlayerOwned |
||
1608 | and not CalendarTrust_UserIsTrusted(vDatabase.UserName) then |
||
1609 | -- not trusted anymore, remove their database |
||
1610 | |||
1611 | EventDatabase_DeleteDatabase(vDatabase.UserName); |
||
1612 | end |
||
1613 | end |
||
1614 | end |
||
1615 | end |
||
1616 | |||
1617 | function EventDatabase_GetDateTime60Stamp() |
||
1618 | local vYear, vMonth, vDay, vHour, vMinute, vSecond = Calendar_GetCurrentYearMonthDayHourMinute(); |
||
1619 | |||
1620 | local vDate = Calendar_ConvertMDYToDate(vMonth, vDay, vYear); |
||
1621 | local vTime60 = Calendar_ConvertHMSToTime60(vHour, vMinute, vSecond); |
||
1622 | |||
1623 | return vDate, vTime60; |
||
1624 | end |
||
1625 | |||
1626 | function EventDatabase_GetServerDateTime60Stamp() |
||
1627 | local vYear, vMonth, vDay, vHour, vMinute, vSecond = Calendar_GetCurrentYearMonthDayHourMinute(); |
||
1628 | |||
1629 | local vDate = Calendar_ConvertMDYToDate(vMonth, vDay, vYear); |
||
1630 | local vTime = Calendar_ConvertHMToTime(vHour, vMinute); |
||
1631 | |||
1632 | vDate, vTime = Calendar_GetServerDateTimeFromLocalDateTime(vDate, vTime); |
||
1633 | |||
1634 | return vDate, vTime * 60 + vSecond; |
||
1635 | end |
||
1636 | |||
1637 | function EventDatabase_GetRSVPs(pDatabase) |
||
1638 | local vRSVPs = pDatabase.RSVPs; |
||
1639 | |||
1640 | if not vRSVPs then |
||
1641 | vRSVPs = CalendarChanges_New(); |
||
1642 | pDatabase.RSVPs = vRSVPs; |
||
1643 | end |
||
1644 | |||
1645 | return vRSVPs; |
||
1646 | end |
||
1647 | |||
1648 | function EventDatabase_GetCurrentRSVPChangeList(pDatabase) |
||
1649 | local vRSVPs = EventDatabase_GetRSVPs(pDatabase); |
||
1650 | local vChangeList, vRevisionChanged = CalendarChanges_GetCurrentChangeList(vRSVPs); |
||
1651 | |||
1652 | if vRevisionChanged and pDatabase.IsPlayerOwned then |
||
1653 | CalendarNetwork_RSVPRevisionChanged(pDatabase); |
||
1654 | end |
||
1655 | |||
1656 | return vChangeList; |
||
1657 | end |
||
1658 | |||
1659 | function EventDatabase_AddEventRSVP(pDatabase, pEvent, pAttendeeName, pRSVP) |
||
1660 | -- Verify that the attendance request is newer than the existing one |
||
1661 | |||
1662 | local vExistingRSVP = EventDatabase_FindEventRSVP(pDatabase.UserName, pEvent, pAttendeeName); |
||
1663 | |||
1664 | if vExistingRSVP then |
||
1665 | if vExistingRSVP.mDate > pRSVP.mDate |
||
1666 | or (vExistingRSVP.mDate == pRSVP.mDate |
||
1667 | and vExistingRSVP.mTime > pRSVP.mTime) then |
||
1668 | if gGroupCalendar_Settings.Debug then |
||
1669 | Calendar_DebugMessage("EventDatabase_AddEventRSVP: Ignore event attendance request for "..pAttendeeName.." for ".." event "..pRSVP.mEventID..": Request is out-of-date"); |
||
1670 | end |
||
1671 | |||
1672 | return; |
||
1673 | end |
||
1674 | end |
||
1675 | |||
1676 | -- Update the event attendance list |
||
1677 | |||
1678 | if gGroupCalendar_Settings.Debug then |
||
1679 | Calendar_DebugMessage("EventDatabase_AddEventRSVP: Updating event attendance for "..pAttendeeName.." for ".." event "..pRSVP.mEventID); |
||
1680 | end |
||
1681 | |||
1682 | if not pEvent.mAttendance then |
||
1683 | pEvent.mAttendance = {}; |
||
1684 | end |
||
1685 | |||
1686 | local vEventRSVPString = EventDatabase_PackEventRSVP(pRSVP); |
||
1687 | |||
1688 | pEvent.mAttendance[pAttendeeName] = vEventRSVPString; |
||
1689 | |||
1690 | -- Notify the network of the change |
||
1691 | |||
1692 | local vChangedFields = |
||
1693 | { |
||
1694 | mAttendance = |
||
1695 | { |
||
1696 | op = "UPD", |
||
1697 | val = |
||
1698 | { |
||
1699 | } |
||
1700 | } |
||
1701 | }; |
||
1702 | |||
1703 | vChangedFields.mAttendance.val[pAttendeeName] = vEventRSVPString; |
||
1704 | |||
1705 | EventDatabase_EventChanged(pDatabase, pEvent, vChangedFields); |
||
1706 | end |
||
1707 | |||
1708 | function EventDatabase_RemoveEventRSVP(pDatabase, pEvent, pAttendeeName) |
||
1709 | if not pEvent.mAttendance then |
||
1710 | return; |
||
1711 | end |
||
1712 | |||
1713 | pEvent.mAttendance[pAttendeeName] = nil; |
||
1714 | |||
1715 | -- Notify the network of the change |
||
1716 | |||
1717 | local vChangedFields = |
||
1718 | { |
||
1719 | mAttendance = |
||
1720 | { |
||
1721 | op = "UPD", |
||
1722 | val = |
||
1723 | { |
||
1724 | [pAttendeeName] = "-", |
||
1725 | } |
||
1726 | } |
||
1727 | }; |
||
1728 | |||
1729 | EventDatabase_EventChanged(pDatabase, pEvent, vChangedFields); |
||
1730 | end |
||
1731 | |||
1732 | function EventDatabase_AddRSVPRequest(pDatabase, pRSVP) |
||
1733 | -- Remove any existing RSVP for the same event |
||
1734 | |||
1735 | if not EventDatabase_RemoveOlderRSVP(pDatabase, pRSVP) then |
||
1736 | if gGroupCalendar_Settings.Debug then |
||
1737 | Calendar_DebugMessage("EventDatabase_AddRSVPRequest: Ignoring "..pDatabase.UserName..","..pRSVP.mEventID..": "..pRSVP.mStatus); |
||
1738 | end |
||
1739 | |||
1740 | return; -- A newer request already exists so disregard this one |
||
1741 | end |
||
1742 | |||
1743 | -- Add the new RSVP |
||
1744 | |||
1745 | local vChangeList = EventDatabase_GetCurrentRSVPChangeList(pDatabase); |
||
1746 | |||
1747 | local vRSVPString = EventDatabase_PackRSVPRequest(pRSVP); |
||
1748 | local vRSVPAltsString = EventDatabase_GetRSVPAltsString(pRSVP); |
||
1749 | |||
1750 | if vRSVPAltsString then |
||
1751 | vRSVPString = vRSVPString.."/ALTS:"..vRSVPAltsString; |
||
1752 | end |
||
1753 | |||
1754 | if gGroupCalendar_Settings.Debug then |
||
1755 | Calendar_DebugMessage("EventDatabase_AddRSVPRequest: Adding string "..vRSVPString); |
||
1756 | end |
||
1757 | |||
1758 | table.insert(vChangeList, vRSVPString); |
||
1759 | |||
1760 | GroupCalendar_MajorDatabaseChange(pDatabase); |
||
1761 | end |
||
1762 | |||
1763 | function EventDatabase_GetRSVPOriginalDateTime(pRSVP) |
||
1764 | if pRSVP.mOriginalDate then |
||
1765 | return pRSVP.mOriginalDate, pRSVP.mOriginalTime; |
||
1766 | else |
||
1767 | return pRSVP.mDate, pRSVP.mTime; |
||
1768 | end |
||
1769 | end |
||
1770 | |||
1771 | function EventDatabase_RemoveAllRSVPsForEvent(pDatabase, pEvent, pOwnedDatabasesOnly) |
||
1772 | local vPrefix = "EVT:"..pDatabase.UserName..","..pEvent.mID..","; |
||
1773 | local vPrefixLength = string.len(vPrefix); |
||
1774 | |||
1775 | EventDatabase_RemoveAllRSVPsByPrefix(pDatabase.Realm, vPrefix, vPrefixLength, pOwnedDatabasesOnly); |
||
1776 | end |
||
1777 | |||
1778 | function EventDatabase_RemoveAllRSVPsForDatabase(pDatabase, pOwnedDatabasesOnly) |
||
1779 | local vPrefix = "EVT:"..pDatabase.UserName..","; |
||
1780 | local vPrefixLength = string.len(vPrefix); |
||
1781 | |||
1782 | EventDatabase_RemoveAllRSVPsByPrefix(pDatabase.Realm, vPrefix, vPrefixLength, pOwnedDatabasesOnly); |
||
1783 | end |
||
1784 | |||
1785 | function EventDatabase_RemoveAllRSVPsByPrefix(pRealm, pPrefix, pPrefixLength, pOwnedDatabasesOnly) |
||
1786 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
1787 | if vDatabase.Realm == pRealm |
||
1788 | and (not pOwnedDatabasesOnly or vDatabase.IsPlayerOwned) then |
||
1789 | EventDatabase_RemoveRSVPsByPrefix(vDatabase, pPrefix, pPrefixLength); |
||
1790 | end |
||
1791 | end |
||
1792 | end |
||
1793 | |||
1794 | function EventDatabase_RemoveRSVPsByPrefix(pDatabase, pPrefix, pPrefixLength) |
||
1795 | local vRSVPString, vIndex, vRevision = EventDatabase_FindRSVPPrefixString(pDatabase, pPrefix, pPrefixLength) |
||
1796 | |||
1797 | while vRSVPString do |
||
1798 | local vChangeList = pDatabase.RSVPs.ChangeList[vRevision]; |
||
1799 | |||
1800 | table.remove(vChangeList, vIndex); |
||
1801 | |||
1802 | if table.getn(vChangeList) == 0 then |
||
1803 | pDatabase.RSVPs.ChangeList[vRevision] = nil; |
||
1804 | end |
||
1805 | |||
1806 | vRSVPString, vIndex, vRevision = EventDatabase_FindRSVPPrefixString(pDatabase, pPrefix, pPrefixLength) |
||
1807 | end |
||
1808 | end |
||
1809 | |||
1810 | function EventDatabase_ProcessRSVP(pDatabase, pRSVP) |
||
1811 | local vEventDatabase = EventDatabase_GetDatabase(pRSVP.mOrganizerName, false); |
||
1812 | |||
1813 | -- Nothing to do if the database isn't one we own |
||
1814 | |||
1815 | if not vEventDatabase or not vEventDatabase.IsPlayerOwned then |
||
1816 | return false; |
||
1817 | end |
||
1818 | |||
1819 | -- Process the request into our database |
||
1820 | |||
1821 | local vEvent = EventDatabase_FindEventByID(vEventDatabase, pRSVP.mEventID); |
||
1822 | |||
1823 | if not vEvent then |
||
1824 | if gGroupCalendar_Settings.Debug then |
||
1825 | Calendar_DebugMessage("EventDatabase_ProcessRSVP: Discarding request from "..pDatabase.UserName.." for ".." event "..pRSVP.mEventID..": Event no longer exists"); |
||
1826 | end |
||
1827 | |||
1828 | return true; -- Have the request deleted |
||
1829 | end |
||
1830 | |||
1831 | -- Look up an existing RSVP |
||
1832 | |||
1833 | local vExistingRSVP = EventDatabase_FindEventRSVP(pDatabase.UserName, vEvent, pRSVP.mName); |
||
1834 | |||
1835 | -- If the player has been banned (removed) from the event then ignore any |
||
1836 | -- requests from them |
||
1837 | |||
1838 | if vExistingRSVP |
||
1839 | and vExistingRSVP.mStatus == "-" then |
||
1840 | return true; -- Delete the request without processing it |
||
1841 | end |
||
1842 | |||
1843 | -- If the player is requesting attendance then figure out how to handle the request |
||
1844 | |||
1845 | if pRSVP.mStatus == "Y" then |
||
1846 | -- If they're already accepted on the list then preserve their current |
||
1847 | -- status |
||
1848 | |||
1849 | if vExistingRSVP |
||
1850 | and (vExistingRSVP.mStatus == "Y" |
||
1851 | or vExistingRSVP.mStatus == "S") then |
||
1852 | pRSVP.mOriginalDate, pRSVP.mOriginalTime = EventDatabase_GetRSVPOriginalDateTime(vExistingRSVP); |
||
1853 | pRSVP.mStatus = vExistingRSVP.mStatus; |
||
1854 | |||
1855 | -- Otherwise put them on standby if using manual confirmations |
||
1856 | |||
1857 | elseif vEvent.mManualConfirm then |
||
1858 | pRSVP.mStatus = "S"; |
||
1859 | |||
1860 | -- Check availablility to determine how to handle automatic confirmations |
||
1861 | |||
1862 | else |
||
1863 | local vAvailableSlots = EventAvailableSlots_CountSlots(pDatabase, vEvent); |
||
1864 | |||
1865 | if not EventAvailableSlots_AcceptPlayer(vAvailableSlots, pRSVP.mClassCode) then |
||
1866 | pRSVP.mStatus = "S"; |
||
1867 | end |
||
1868 | end |
||
1869 | end |
||
1870 | |||
1871 | -- Add the RSVP |
||
1872 | |||
1873 | EventDatabase_AddEventRSVP(vEventDatabase, vEvent, pDatabase.UserName, pRSVP); |
||
1874 | |||
1875 | return true; |
||
1876 | end |
||
1877 | |||
1878 | function EventDatabase_AddRSVP(pDatabase, pRSVP) |
||
1879 | if gGroupCalendar_Settings.Debug then |
||
1880 | if not pRSVP.mName then |
||
1881 | Calendar_DumpArray("Missing attendee: ", pRSVP); |
||
1882 | return; |
||
1883 | end |
||
1884 | end |
||
1885 | |||
1886 | if not EventDatabase_ProcessRSVP(pDatabase, pRSVP) then |
||
1887 | EventDatabase_AddRSVPRequest(pDatabase, pRSVP); |
||
1888 | end |
||
1889 | end |
||
1890 | |||
1891 | function EventDatabase_RemoveOldAttendeeRSVP(pAttendeeName, pOrganizerName, pEventID, pAttendanceString) |
||
1892 | local vAttendeeDatabase = EventDatabase_GetDatabase(pAttendeeName, false); |
||
1893 | |||
1894 | -- Just leave if we've never heard of them |
||
1895 | |||
1896 | if not vAttendeeDatabase then |
||
1897 | return; |
||
1898 | end |
||
1899 | |||
1900 | -- Just leave if it's a delete request, we don't know how to handle these yet |
||
1901 | |||
1902 | if not pAttendanceString then |
||
1903 | return; |
||
1904 | end |
||
1905 | |||
1906 | -- Remove the RSVP request if it exists in their database |
||
1907 | |||
1908 | local vRSVP = EventDatabase_UnpackEventRSVP(pOrganizerName, pAttendeeName, pEventID, pAttendanceString); |
||
1909 | |||
1910 | EventDatabase_RemoveOlderRSVP(vAttendeeDatabase, vRSVP) |
||
1911 | end |
||
1912 | |||
1913 | function EventDatabase_RemoveOlderRSVP(pDatabase, pRSVP) |
||
1914 | if gGroupCalendar_Settings.Debug then |
||
1915 | Calendar_DebugMessage("EventDatabase_RemoveOlderRSVP: Removing RSVP for "..pRSVP.mName.." from "..pDatabase.UserName..","..pRSVP.mEventID); |
||
1916 | end |
||
1917 | |||
1918 | local vRSVPString, vIndex, vRevision = EventDatabase_FindRSVPRequestString(pDatabase, pRSVP.mOrganizerName, pRSVP.mEventID); |
||
1919 | |||
1920 | while vRSVPString ~= nil do |
||
1921 | if gGroupCalendar_Settings.Debug then |
||
1922 | Calendar_DebugMessage("EventDatabase_RemoveOlderRSVP: "..pRSVP.mOrganizerName..","..pRSVP.mEventID.." from position "..vRevision..","..vIndex); |
||
1923 | end |
||
1924 | |||
1925 | -- If the existing RSVP is newer than the specified date/time then disregard the request |
||
1926 | |||
1927 | if pRSVP.mDate ~= nil then |
||
1928 | local vRSVP = EventDatabase_UnpackRSVPRequest(vRSVPString, pRSVP.mName); |
||
1929 | |||
1930 | if vRSVP.mDate > pRSVP.mDate |
||
1931 | or (vRSVP.mDate == pRSVP.mDate and vRSVP.mTime > pRSVP.mTime) then |
||
1932 | if gGroupCalendar_Settings.Debug then |
||
1933 | Calendar_DebugMessage("EventDatabase_RemoveOlderRSVP: Newer request already exists"); |
||
1934 | end |
||
1935 | |||
1936 | return false; -- Fail to indicate that a newer request is already in the database |
||
1937 | end |
||
1938 | end |
||
1939 | |||
1940 | -- Remove the old one |
||
1941 | |||
1942 | local vChangeList = pDatabase.RSVPs.ChangeList[vRevision]; |
||
1943 | table.remove(vChangeList, vIndex); |
||
1944 | |||
1945 | if table.getn(vChangeList) == 0 then |
||
1946 | pDatabase.RSVPs.ChangeList[vRevision] = nil; |
||
1947 | end |
||
1948 | |||
1949 | -- Keep removing in case the database has become corrupted with multiple copies |
||
1950 | |||
1951 | vRSVPString, vIndex, vRevision = EventDatabase_FindRSVPRequestString(pDatabase, pRSVP.mOrganizerName, pRSVP.mEventID); |
||
1952 | end |
||
1953 | |||
1954 | return true; -- Everything's ok, no newer RSVP was found |
||
1955 | end |
||
1956 | |||
1957 | function EventDatabase_FindRSVPRequestString(pDatabase, pOrganizerName, pEventID) |
||
1958 | if not pEventID then |
||
1959 | Calendar_DebugMessage("EventDatabase_FindRSVPRequestString: pEventID IS NIL!"); |
||
1960 | end |
||
1961 | |||
1962 | if not pOrganizerName then |
||
1963 | Calendar_DebugMessage("EventDatabase_FindRSVPRequestString: pOrganizerName IS NIL!"); |
||
1964 | end |
||
1965 | |||
1966 | local vRSVPPrefix = "EVT:"..pOrganizerName..","..pEventID..","; |
||
1967 | local vRSVPPrefixLength = string.len(vRSVPPrefix); |
||
1968 | |||
1969 | return EventDatabase_FindRSVPPrefixString(pDatabase, vRSVPPrefix, vRSVPPrefixLength); |
||
1970 | end |
||
1971 | |||
1972 | function EventDatabase_FindRSVPPrefixString(pDatabase, pPrefixString, pPrefixLength) |
||
1973 | local vRSVPs = EventDatabase_GetRSVPs(pDatabase); |
||
1974 | |||
1975 | for vRevision, vChangeList in vRSVPs.ChangeList do |
||
1976 | local vNumChanges = table.getn(vChangeList); |
||
1977 | |||
1978 | for vIndex = 1, vNumChanges do |
||
1979 | local vRSVP = vChangeList[vIndex]; |
||
1980 | |||
1981 | if string.sub(vRSVP, 1, pPrefixLength) == pPrefixString then |
||
1982 | return vRSVP, vIndex, vRevision; |
||
1983 | end |
||
1984 | end |
||
1985 | end |
||
1986 | |||
1987 | return nil, nil, nil; |
||
1988 | end |
||
1989 | |||
1990 | function EventDatabase_FindRSVPRequestData(pDatabase, pOrganizerName, pEventID) |
||
1991 | if not pEventID then |
||
1992 | Calendar_DebugMessage("EventDatabase_FindRSVPRequestData: pEventID is nil!"); |
||
1993 | end |
||
1994 | |||
1995 | if not pOrganizerName then |
||
1996 | Calendar_DebugMessage("EventDatabase_FindRSVPRequestData: pOrganizerName IS NIL!"); |
||
1997 | end |
||
1998 | |||
1999 | local vRSVPString = EventDatabase_FindRSVPRequestString(pDatabase, pOrganizerName, pEventID); |
||
2000 | |||
2001 | if not vRSVPString then |
||
2002 | return nil; |
||
2003 | end |
||
2004 | |||
2005 | return EventDatabase_UnpackRSVPRequest(vRSVPString, pDatabase.UserName); |
||
2006 | end |
||
2007 | |||
2008 | function EventDatabase_FindEventRSVPString(pEvent, pAttendeeName) |
||
2009 | if not pEvent.mAttendance then |
||
2010 | return nil; |
||
2011 | end |
||
2012 | |||
2013 | return pEvent.mAttendance[pAttendeeName]; |
||
2014 | end |
||
2015 | |||
2016 | function EventDatabase_FindEventRSVP(pEventOwner, pEvent, pAttendeeName) |
||
2017 | local vEventRSVPString = EventDatabase_FindEventRSVPString(pEvent, pAttendeeName); |
||
2018 | |||
2019 | if not vEventRSVPString then |
||
2020 | return nil; |
||
2021 | end |
||
2022 | |||
2023 | return EventDatabase_UnpackEventRSVP(pEventOwner, pAttendeeName, pEvent.ID, vEventRSVPString); |
||
2024 | end |
||
2025 | |||
2026 | function EventDatabase_EventExists(pEventOwner, pEventID) |
||
2027 | local vDatabase = EventDatabase_GetDatabase(pEventOwner, false); |
||
2028 | |||
2029 | if not vDatabase then |
||
2030 | return false; |
||
2031 | end |
||
2032 | |||
2033 | if not EventDatabase_FindEventByID(vDatabase, pEventID) then |
||
2034 | return false; |
||
2035 | end |
||
2036 | |||
2037 | return true; |
||
2038 | end |
||
2039 | |||
2040 | function EventDatabase_RemoveObsoleteRSVPs(pDatabase) |
||
2041 | local vRSVPs = EventDatabase_GetRSVPs(pDatabase); |
||
2042 | |||
2043 | for vRevision, vChangeList in vRSVPs.ChangeList do |
||
2044 | local vNumChanges = table.getn(vChangeList); |
||
2045 | local vIndex = 1; |
||
2046 | |||
2047 | while vIndex <= vNumChanges do |
||
2048 | local vRSVP = EventDatabase_UnpackRSVPRequest(vChangeList[vIndex], pDatabase.UserName); |
||
2049 | |||
2050 | if not EventDatabase_EventExists(vRSVP.mOrganizerName, vRSVP.mEventID) then |
||
2051 | table.remove(vChangeList, vIndex); |
||
2052 | vNumChanges = vNumChanges - 1; |
||
2053 | else |
||
2054 | vIndex = vIndex + 1; |
||
2055 | end |
||
2056 | end |
||
2057 | |||
2058 | if vNumChanges == 0 then |
||
2059 | vRSVPs.ChangeList[vRevision] = nil; |
||
2060 | end |
||
2061 | end |
||
2062 | end |
||
2063 | |||
2064 | function EventDatabase_GetRSVPAltsString(pRSVP) |
||
2065 | local vAltsString = nil; |
||
2066 | |||
2067 | if not pRSVP.mAlts then |
||
2068 | return nil; |
||
2069 | end |
||
2070 | |||
2071 | for vPlayerName, _ in pRSVP.mAlts do |
||
2072 | if not vAltsString then |
||
2073 | vAltsString = vPlayerName; |
||
2074 | else |
||
2075 | vAltsString = vAltsString..","..vPlayerName; |
||
2076 | end |
||
2077 | end |
||
2078 | |||
2079 | return vAltsString; |
||
2080 | end |
||
2081 | |||
2082 | function EventDatabase_PackRSVPRequest(pRSVP) |
||
2083 | local vRequest = "EVT:"..pRSVP.mOrganizerName..","..pRSVP.mEventID..","..pRSVP.mDate..","..pRSVP.mTime..","..pRSVP.mStatus..","..EventDatabase_PackCharInfo(pRSVP)..","; |
||
2084 | |||
2085 | if pRSVP.mComment then |
||
2086 | vRequest = vRequest..pRSVP.mComment; |
||
2087 | end |
||
2088 | |||
2089 | if pRSVP.mGuild then |
||
2090 | vRequest = vRequest..","..pRSVP.mGuild..","..pRSVP.mGuildRank; |
||
2091 | else |
||
2092 | vRequest = vRequest..",,"; |
||
2093 | end |
||
2094 | |||
2095 | return vRequest; |
||
2096 | end |
||
2097 | |||
2098 | function EventDatabase_UnpackRSVPRequest(pRSVPString, pAttendee) |
||
2099 | local vCommands = CalendarNetwork_ParseCommandSubString("/"..pRSVPString); |
||
2100 | local vOpcode = vCommands[1].opcode; |
||
2101 | |||
2102 | if vOpcode ~= "EVT" then |
||
2103 | return false; |
||
2104 | end |
||
2105 | |||
2106 | local vOperands = vCommands[1].operands; |
||
2107 | |||
2108 | return EventDatabase_UnpackRSVPFieldArray(vOperands, pAttendee); |
||
2109 | end |
||
2110 | |||
2111 | function EventDatabase_FillInRSVPGuildInfo(pRSVP) |
||
2112 | if pRSVP.mGuild then |
||
2113 | return; |
||
2114 | end |
||
2115 | |||
2116 | vIsInGuild, vRankIndex = CalendarNetwork_UserIsInSameGuild(pRSVP.mName); |
||
2117 | |||
2118 | if not vIsInGuild then |
||
2119 | return; |
||
2120 | end |
||
2121 | |||
2122 | pRSVP.mGuild = gGroupCalendar_PlayerGuild; |
||
2123 | pRSVP.mGuildRank = vRankIndex; |
||
2124 | end |
||
2125 | |||
2126 | function EventDatabase_UnpackRSVPFieldArray(pArray, pAttendee) |
||
2127 | local vRSVP = |
||
2128 | { |
||
2129 | mOrganizerName = pArray[1], |
||
2130 | mName = pAttendee; |
||
2131 | mEventID = tonumber(pArray[2]), |
||
2132 | mDate = tonumber(pArray[3]), |
||
2133 | mTime = tonumber(pArray[4]), |
||
2134 | mStatus = pArray[5], |
||
2135 | mComment = pArray[7], |
||
2136 | mGuild = pArray[8], |
||
2137 | mGuildRank = tonumber(pArray[9]), |
||
2138 | }; |
||
2139 | |||
2140 | if vRSVP.mGuild == "" then |
||
2141 | vRSVP.mGuild = nil; |
||
2142 | end |
||
2143 | |||
2144 | EventDatabase_UnpackCharInfo(pArray[6], vRSVP); |
||
2145 | |||
2146 | EventDatabase_FillInRSVPGuildInfo(vRSVP); |
||
2147 | |||
2148 | return vRSVP; |
||
2149 | end |
||
2150 | |||
2151 | function EventDatabase_PackEventRSVP(pEventRSVP) |
||
2152 | local vEventRSVPString = ""..pEventRSVP.mDate..","..pEventRSVP.mTime..","..pEventRSVP.mStatus..","..EventDatabase_PackCharInfo(pEventRSVP)..","; |
||
2153 | |||
2154 | if pEventRSVP.mComment then |
||
2155 | vEventRSVPString = vEventRSVPString..pEventRSVP.mComment; |
||
2156 | end |
||
2157 | |||
2158 | if pEventRSVP.mGuild then |
||
2159 | vEventRSVPString = vEventRSVPString..","..pEventRSVP.mGuild..","..pEventRSVP.mGuildRank; |
||
2160 | else |
||
2161 | vEventRSVPString = vEventRSVPString..",,"; |
||
2162 | end |
||
2163 | |||
2164 | if pEventRSVP.mOriginalDate then |
||
2165 | vEventRSVPString = vEventRSVPString..","..pEventRSVP.mOriginalDate..","..pEventRSVP.mOriginalTime; |
||
2166 | else |
||
2167 | vEventRSVPString = vEventRSVPString..",,"; |
||
2168 | end |
||
2169 | |||
2170 | return vEventRSVPString; |
||
2171 | end |
||
2172 | |||
2173 | function EventDatabase_UnpackEventRSVP(pOrganizerName, pAttendeeName, pEventID, pEventRSVPString) |
||
2174 | local vEventParameters = CalendarNetwork_ParseParameterString(pEventRSVPString); |
||
2175 | |||
2176 | local vRSVPFields = |
||
2177 | { |
||
2178 | mOrganizerName = pOrganizerName, |
||
2179 | mName = pAttendeeName, |
||
2180 | mEventID = pEventID, |
||
2181 | mDate = tonumber(vEventParameters[1]), |
||
2182 | mTime = tonumber(vEventParameters[2]), |
||
2183 | mStatus = vEventParameters[3], |
||
2184 | mComment = vEventParameters[5], |
||
2185 | mGuild = vEventParameters[6], |
||
2186 | mGuildRank = tonumber(vEventParameters[7]), |
||
2187 | mOriginalDate = tonumber(vEventParameters[8]), |
||
2188 | mOriginalTime = tonumber(vEventParameters[9]), |
||
2189 | }; |
||
2190 | |||
2191 | if vRSVPFields.mGuild == "" then |
||
2192 | vRSVPFields.mGuild = nil; |
||
2193 | end |
||
2194 | |||
2195 | EventDatabase_UnpackCharInfo(vEventParameters[4], vRSVPFields); |
||
2196 | |||
2197 | EventDatabase_FillInRSVPGuildInfo(vRSVPFields); |
||
2198 | |||
2199 | return vRSVPFields; |
||
2200 | end |
||
2201 | |||
2202 | function EventDatabase_PackCharInfo(pCharInfo) |
||
2203 | local vRaceCode, vClassCode, vLevel; |
||
2204 | |||
2205 | vRaceCode = pCharInfo.mRaceCode; |
||
2206 | |||
2207 | if not vRaceCode then |
||
2208 | vRaceCode = "?"; |
||
2209 | end |
||
2210 | |||
2211 | vClassCode = pCharInfo.mClassCode; |
||
2212 | |||
2213 | if not vClassCode then |
||
2214 | vClassCode = "?"; |
||
2215 | end |
||
2216 | |||
2217 | if pCharInfo.mLevel then |
||
2218 | vLevel = pCharInfo.mLevel; |
||
2219 | else |
||
2220 | vLevel = 0; |
||
2221 | end |
||
2222 | |||
2223 | return vRaceCode..vClassCode..vLevel; |
||
2224 | end |
||
2225 | |||
2226 | function EventDatabase_GetRaceCodeByRace(pRace) |
||
2227 | for vRaceCode, vRaceInfo in gGroupCalendar_RaceNamesByRaceCode do |
||
2228 | if pRace == vRaceInfo.name then |
||
2229 | return vRaceCode; |
||
2230 | end |
||
2231 | end |
||
2232 | |||
2233 | return "?"; |
||
2234 | end |
||
2235 | |||
2236 | function EventDatabase_GetRaceByRaceCode(pRaceCode) |
||
2237 | local vRaceInfo = gGroupCalendar_RaceNamesByRaceCode[pRaceCode]; |
||
2238 | |||
2239 | if not vRaceInfo then |
||
2240 | return nil; |
||
2241 | end |
||
2242 | |||
2243 | return vRaceInfo.name; |
||
2244 | end |
||
2245 | |||
2246 | function EventDatabase_GetClassCodeByClass(pClass) |
||
2247 | for vClassCode, vClassInfo in gGroupCalendar_ClassInfoByClassCode do |
||
2248 | if pClass == vClassInfo.name then |
||
2249 | return vClassCode; |
||
2250 | end |
||
2251 | end |
||
2252 | |||
2253 | return "?"; |
||
2254 | end |
||
2255 | |||
2256 | function EventDatabase_GetClassByClassCode(pClassCode) |
||
2257 | local vClassInfo = gGroupCalendar_ClassInfoByClassCode[pClassCode]; |
||
2258 | |||
2259 | if not vClassInfo then |
||
2260 | if pClassCode then |
||
2261 | return "Unknown ("..pClassCode..")"; |
||
2262 | else |
||
2263 | return "Unknown (nil)"; |
||
2264 | end |
||
2265 | else |
||
2266 | return vClassInfo.name; |
||
2267 | end |
||
2268 | end |
||
2269 | |||
2270 | function EventDatabase_UnpackCharInfo(pString, rCharInfo) |
||
2271 | if not pString then |
||
2272 | rCharInfo.mRaceCode = "?"; |
||
2273 | rCharInfo.mClassCode = "?"; |
||
2274 | rCharInfo.mLevel = 0; |
||
2275 | else |
||
2276 | rCharInfo.mRaceCode = string.sub(pString, 1, 1); |
||
2277 | rCharInfo.mClassCode = string.sub(pString, 2, 2); |
||
2278 | rCharInfo.mLevel = tonumber(string.sub(pString, 3)); |
||
2279 | end |
||
2280 | end |
||
2281 | |||
2282 | function EventDatabase_IsQuestingEventType(pEventType) |
||
2283 | return pEventType ~= "Meet" and pEventType ~= "Birth"; |
||
2284 | end |
||
2285 | |||
2286 | function EventDatabase_IsResetEventType(pEventType) |
||
2287 | if not pEventType then |
||
2288 | return false; |
||
2289 | end |
||
2290 | |||
2291 | return gGroupCalendar_EventTypes.Reset.ResetEventInfo[pEventType] ~= nil; |
||
2292 | end |
||
2293 | |||
2294 | function EventDatabase_GetResetIconCoords(pEventType) |
||
2295 | if not pEventType then |
||
2296 | return nil; |
||
2297 | end |
||
2298 | |||
2299 | return gGroupCalendar_EventTypes.Reset.ResetEventInfo[pEventType]; |
||
2300 | end |
||
2301 | |||
2302 | function EventDatabase_GetResetEventLargeIconPath(pEventType) |
||
2303 | if not pEventType then |
||
2304 | return nil; |
||
2305 | end |
||
2306 | |||
2307 | local vResetEventInfo = gGroupCalendar_EventTypes.Reset.ResetEventInfo[pEventType]; |
||
2308 | |||
2309 | if vResetEventInfo.largeIcon then |
||
2310 | return vResetEventInfo.largeIcon, false; |
||
2311 | elseif vResetEventInfo.largeSysIcon then |
||
2312 | return vResetEventInfo.largeSysIcon, true; |
||
2313 | else |
||
2314 | return nil; |
||
2315 | end |
||
2316 | end |
||
2317 | |||
2318 | function EventDatabase_IsDungeonResetEventType(pEventType) |
||
2319 | if not pEventType then |
||
2320 | return false; |
||
2321 | end |
||
2322 | |||
2323 | local vResetEventInfo = gGroupCalendar_EventTypes.Reset.ResetEventInfo[pEventType]; |
||
2324 | |||
2325 | if not vResetEventInfo then |
||
2326 | return false; |
||
2327 | end |
||
2328 | |||
2329 | return vResetEventInfo.isDungeon; |
||
2330 | end |
||
2331 | |||
2332 | function EventDatabase_LookupDungeonResetEventTypeByName(pName) |
||
2333 | for vEventType, vResetEventInfo in gGroupCalendar_EventTypes.Reset.ResetEventInfo do |
||
2334 | if vResetEventInfo.isDungeon then |
||
2335 | if vResetEventInfo.name == pName then |
||
2336 | return vEventType; |
||
2337 | end |
||
2338 | end |
||
2339 | end |
||
2340 | |||
2341 | return nil; |
||
2342 | end |
||
2343 | |||
2344 | function EventDatabase_LookupTradeskillEventTypeByID(pID) |
||
2345 | for vEventType, vResetEventInfo in gGroupCalendar_EventTypes.Reset.ResetEventInfo do |
||
2346 | if vResetEventInfo.isTradeskill then |
||
2347 | if vResetEventInfo.id == pID then |
||
2348 | return vEventType; |
||
2349 | end |
||
2350 | end |
||
2351 | end |
||
2352 | |||
2353 | return nil; |
||
2354 | end |
||
2355 | |||
2356 | function EventDatabase_EventTypeUsesAttendance(pEventType) |
||
2357 | if pEventType == "Birth" |
||
2358 | or EventDatabase_IsResetEventType(pEventType) then |
||
2359 | return false; |
||
2360 | end |
||
2361 | |||
2362 | return true; |
||
2363 | end |
||
2364 | |||
2365 | function EventDatabase_EventTypeUsesLevelLimits(pEventType) |
||
2366 | if pEventType == "Birth" |
||
2367 | or pEventType == "Meet" |
||
2368 | or EventDatabase_IsResetEventType(pEventType) then |
||
2369 | return false; |
||
2370 | end |
||
2371 | |||
2372 | return true; |
||
2373 | end |
||
2374 | |||
2375 | function EventDatabase_EventTypeUsesTime(pEventType) |
||
2376 | if pEventType == "Birth" then |
||
2377 | return false; |
||
2378 | end |
||
2379 | |||
2380 | return true; |
||
2381 | end |
||
2382 | |||
2383 | function CalendarChanges_New(pID) |
||
2384 | local vID; |
||
2385 | |||
2386 | if pID then |
||
2387 | vID = pID; |
||
2388 | else |
||
2389 | vID = Calendar_GetCurrentDateTimeUT60(); |
||
2390 | end |
||
2391 | |||
2392 | return |
||
2393 | { |
||
2394 | ID = vID, |
||
2395 | Revision = 0, |
||
2396 | AuthRevision = 0, |
||
2397 | ChangeList = {}, |
||
2398 | }; |
||
2399 | end |
||
2400 | |||
2401 | function CalendarChanges_Rebuild(pChanges) |
||
2402 | pChanges.ID = Calendar_GetCurrentDateTimeUT60(); |
||
2403 | |||
2404 | pChanges.Revision = 0; |
||
2405 | pChanges.AuthRevision = 0; |
||
2406 | pChanges.ChangeList = {}; |
||
2407 | end |
||
2408 | |||
2409 | function CalendarChanges_Compact(pChanges) |
||
2410 | local vNewChanges = nil; |
||
2411 | |||
2412 | for vRevision, vChanges in pChanges.ChangeList do |
||
2413 | for vIndex, vChange in vChanges do |
||
2414 | if not vNewChanges then |
||
2415 | vNewChanges = {}; |
||
2416 | end |
||
2417 | |||
2418 | if type(vIndex) == "number" then |
||
2419 | table.insert(vNewChanges, vChange); |
||
2420 | end |
||
2421 | end |
||
2422 | end |
||
2423 | |||
2424 | pChanges.ID = Calendar_GetCurrentDateTimeUT60(); |
||
2425 | pChanges.ChangeList = {}; |
||
2426 | |||
2427 | if vNewChanges then |
||
2428 | pChanges.Revision = 1; |
||
2429 | pChanges.AuthRevision = 0; |
||
2430 | pChanges.ChangeList[1] = vNewChanges; |
||
2431 | else |
||
2432 | pChanges.Revision = 0; |
||
2433 | pChanges.AuthRevision = 0; |
||
2434 | end |
||
2435 | end |
||
2436 | |||
2437 | function CalendarChanges_Open(pChanges, pRevision) |
||
2438 | local vChangeList = pChanges.ChangeList[pRevision]; |
||
2439 | |||
2440 | if not vChangeList then |
||
2441 | vChangeList = {}; |
||
2442 | pChanges.ChangeList[pRevision] = vChangeList; |
||
2443 | pChanges.Revision = pRevision; |
||
2444 | end |
||
2445 | |||
2446 | vChangeList.IsOpen = true; |
||
2447 | |||
2448 | return vChangeList; |
||
2449 | end |
||
2450 | |||
2451 | function CalendarChanges_Close(pChanges, pRevision) |
||
2452 | local vChangeList = pChanges.ChangeList[pRevision]; |
||
2453 | |||
2454 | if not vChangeList then |
||
2455 | return; |
||
2456 | end |
||
2457 | |||
2458 | vChangeList.IsOpen = nil; |
||
2459 | end |
||
2460 | |||
2461 | function CalendarChanges_SetChangeList(pChanges, pRevision, pChangeList) |
||
2462 | pChanges.ChangeList[pRevision] = pChangeList; |
||
2463 | |||
2464 | if pRevision > pChanges.Revision then |
||
2465 | pChanges.Revision = pRevision; |
||
2466 | end |
||
2467 | end |
||
2468 | |||
2469 | function CalendarChanges_GetCurrentChangeList(pChanges) |
||
2470 | local vChangeList = nil; |
||
2471 | local vRevisionChanged = false; |
||
2472 | |||
2473 | if pChanges.Revision > 0 then |
||
2474 | vChangeList = pChanges.ChangeList[pChanges.Revision]; |
||
2475 | end |
||
2476 | |||
2477 | if vChangeList == nil |
||
2478 | or not vChangeList.IsOpen then |
||
2479 | pChanges.Revision = pChanges.Revision + 1; |
||
2480 | |||
2481 | vChangeList = {}; |
||
2482 | pChanges.ChangeList[pChanges.Revision] = vChangeList; |
||
2483 | |||
2484 | vChangeList.IsOpen = true; |
||
2485 | |||
2486 | vRevisionChanged = true; |
||
2487 | end |
||
2488 | |||
2489 | return vChangeList, vRevisionChanged; |
||
2490 | end |
||
2491 | |||
2492 | function CalendarChanges_LockdownCurrentChangeList(pChanges) |
||
2493 | -- Just return if there are no changes yet |
||
2494 | |||
2495 | if pChanges.Revision == 0 then |
||
2496 | return; |
||
2497 | end |
||
2498 | |||
2499 | -- See if the current list exists and is open |
||
2500 | |||
2501 | local vChangeList = pChanges.ChangeList[pChanges.Revision]; |
||
2502 | |||
2503 | if not vChangeList |
||
2504 | or not vChangeList.IsOpen then |
||
2505 | return; |
||
2506 | end |
||
2507 | |||
2508 | -- Close the change list |
||
2509 | |||
2510 | vChangeList.IsOpen = nil; |
||
2511 | end |
||
2512 | |||
2513 | function CalendarChanges_GetRevisionPath(pLabel, pUserName, pDatabaseID, pRevision, pAuthRevision) |
||
2514 | local vPath = pLabel..":"..pUserName..","; |
||
2515 | |||
2516 | if pDatabaseID then |
||
2517 | vPath = vPath..pDatabaseID; |
||
2518 | end |
||
2519 | |||
2520 | vPath = vPath..","..pRevision; |
||
2521 | |||
2522 | if pAuthRevision then |
||
2523 | vPath = vPath..","..pAuthRevision; |
||
2524 | end |
||
2525 | |||
2526 | return vPath.."/"; |
||
2527 | end |
||
2528 | |||
2529 | function CalendarChanges_IsEmpty(pChanges) |
||
2530 | if not pChanges |
||
2531 | or pChanges.Revision == 0 then |
||
2532 | return true; |
||
2533 | end |
||
2534 | |||
2535 | for vRevision, vChanges in pChanges.ChangeList do |
||
2536 | return false; |
||
2537 | end |
||
2538 | |||
2539 | return true; |
||
2540 | end |
||
2541 | |||
2542 | function CalendarChanges_GetChangeList(pChanges, pRevision) |
||
2543 | return pChanges.ChangeList[pRevision]; |
||
2544 | end |
||
2545 | |||
2546 | function CalendarAttendanceList_New() |
||
2547 | return |
||
2548 | { |
||
2549 | NumCategories = 0, |
||
2550 | NumPlayers = 0, |
||
2551 | NumAttendees = 0, |
||
2552 | Categories = {}, |
||
2553 | SortedCategories = {}, |
||
2554 | ClassTotals = {}, |
||
2555 | Items = {}, |
||
2556 | }; |
||
2557 | end |
||
2558 | |||
2559 | function CalendarAttendanceList_RemoveCategory(pAttendanceList, pCategoryID) |
||
2560 | local vClassInfo = pAttendanceList.Categories[pCategoryID]; |
||
2561 | |||
2562 | if not vClassInfo then |
||
2563 | return false; |
||
2564 | end |
||
2565 | |||
2566 | pAttendanceList.NumPlayers = pAttendanceList.NumPlayers - table.getn(vClassInfo.mAttendees); |
||
2567 | pAttendanceList.NumCategories = pAttendanceList.NumCategories - 1; |
||
2568 | |||
2569 | -- Remove it from the sorted categories |
||
2570 | |||
2571 | for vIndex, vCategoryID in pAttendanceList.SortedCategories do |
||
2572 | if vCategoryID == pCategoryID then |
||
2573 | table.remove(pAttendanceList.SortedCategories, vIndex); |
||
2574 | end |
||
2575 | end |
||
2576 | |||
2577 | pAttendanceList.Categories[pCategoryID] = nil; |
||
2578 | return true; |
||
2579 | end |
||
2580 | |||
2581 | function CalendarAttendanceList_AddItem(pAttendanceList, pCategoryID, pItem) |
||
2582 | if not pItem then |
||
2583 | Calendar_ErrorMessage("CalendarAttendanceList_AddItem: pItem is nil"); |
||
2584 | return; |
||
2585 | end |
||
2586 | |||
2587 | if not pCategoryID then |
||
2588 | Calendar_ErrorMessage("CalendarAttendanceList_AddItem: pCategoryID is nil"); |
||
2589 | return; |
||
2590 | end |
||
2591 | |||
2592 | local vClassInfo = pAttendanceList.Categories[pCategoryID]; |
||
2593 | |||
2594 | if not vClassInfo then |
||
2595 | vClassInfo = {mCount = 1, mClassCode = pCategoryID, mAttendees = {}}; |
||
2596 | pAttendanceList.Categories[pCategoryID] = vClassInfo; |
||
2597 | table.insert(pAttendanceList.SortedCategories, pCategoryID); |
||
2598 | |||
2599 | pAttendanceList.NumCategories = pAttendanceList.NumCategories + 1; |
||
2600 | else |
||
2601 | vClassInfo.mCount = vClassInfo.mCount + 1; |
||
2602 | end |
||
2603 | |||
2604 | pAttendanceList.NumPlayers = pAttendanceList.NumPlayers + 1; |
||
2605 | |||
2606 | table.insert(vClassInfo.mAttendees, pItem); |
||
2607 | end |
||
2608 | |||
2609 | function CalendarAttendanceList_AddPlayer(pAttendanceList, pPlayer) |
||
2610 | return CalendarAttendanceList_AddItem(pAttendanceList, pPlayer.mClassCode, pPlayer); |
||
2611 | end |
||
2612 | |||
2613 | function CalendarAttendanceList_AddWhisper(pAttendanceList, pPlayerName, pWhispers) |
||
2614 | local vPlayer = |
||
2615 | { |
||
2616 | mName = pPlayerName, |
||
2617 | mWhispers = pWhispers.mWhispers, |
||
2618 | }; |
||
2619 | |||
2620 | local vGuildMemberIndex = CalendarNetwork_GetGuildMemberIndex(pPlayerName); |
||
2621 | |||
2622 | if vGuildMemberIndex then |
||
2623 | local vMemberName, vRank, vRankIndex, |
||
2624 | vLevel, vClass, vZone, vNote, |
||
2625 | vOfficerNote, vOnline = GetGuildRosterInfo(vGuildMemberIndex); |
||
2626 | |||
2627 | vPlayer.mLevel = vLevel; |
||
2628 | vPlayer.mClassCode = EventDatabase_GetClassCodeByClass(vClass); |
||
2629 | vPlayer.mZone = vZone; |
||
2630 | vPlayer.mOnline = vOnline; |
||
2631 | end |
||
2632 | |||
2633 | vPlayer.mDate = pWhispers.mDate; |
||
2634 | vPlayer.mTime = pWhispers.mTime; |
||
2635 | vPlayer.mType = "Whisper"; |
||
2636 | |||
2637 | return CalendarAttendanceList_AddItem( |
||
2638 | pAttendanceList, |
||
2639 | "WHISPERS", |
||
2640 | vPlayer); |
||
2641 | end |
||
2642 | |||
2643 | function CalendarAttendanceList_AddEventAttendanceItems(pAttendanceList, pDatabase, pEvent) |
||
2644 | if not pEvent.mAttendance then |
||
2645 | return; |
||
2646 | end |
||
2647 | |||
2648 | for vAttendeeName, vRSVPString in pEvent.mAttendance do |
||
2649 | local vRSVP = EventDatabase_UnpackEventRSVP(pDatabase.UserName, vAttendeeName, pEvent.mID, vRSVPString); |
||
2650 | |||
2651 | pAttendanceList.Items[vRSVP.mName] = vRSVP; |
||
2652 | end |
||
2653 | end |
||
2654 | |||
2655 | function CalendarAttendanceList_AddPendingRequests(pAttendanceList, pDatabase, pEvent) |
||
2656 | for vRealmUser, vDatabase in gGroupCalendar_Database.Databases do |
||
2657 | if EventDatabase_DatabaseIsVisible(vDatabase) then |
||
2658 | local vPendingRSVP = EventDatabase_FindRSVPRequestData(vDatabase, pDatabase.UserName, pEvent.mID); |
||
2659 | |||
2660 | if vPendingRSVP then |
||
2661 | if vPendingRSVP.mStatus == "Y" then |
||
2662 | vPendingRSVP.mStatus = "P"; |
||
2663 | end |
||
2664 | |||
2665 | CalendarAttendanceList_AddItem(pAttendanceList, "PENDING", vPendingRSVP); |
||
2666 | end |
||
2667 | end |
||
2668 | end |
||
2669 | end |
||
2670 | |||
2671 | function CalendarAttendanceList_CalculateClassTotals(pAttendanceList, pIsAttendingFunction) |
||
2672 | pAttendanceList.ClassTotals = {}; |
||
2673 | |||
2674 | for vName, vItem in pAttendanceList.Items do |
||
2675 | if vItem.mClassCode |
||
2676 | and pIsAttendingFunction(vItem) then |
||
2677 | local vTotal = pAttendanceList.ClassTotals[vItem.mClassCode]; |
||
2678 | |||
2679 | if not vTotal then |
||
2680 | pAttendanceList.ClassTotals[vItem.mClassCode] = 1; |
||
2681 | else |
||
2682 | pAttendanceList.ClassTotals[vItem.mClassCode] = vTotal + 1; |
||
2683 | end |
||
2684 | end |
||
2685 | end |
||
2686 | end |
||
2687 | |||
2688 | function CalendarAttendanceList_RSVPIsAttending(pItem) |
||
2689 | return pItem.mStatus ~= "-" |
||
2690 | and pItem.mStatus ~= "N" |
||
2691 | and pItem.mStatus ~= "C"; |
||
2692 | end |
||
2693 | |||
2694 | function CalendarAttendanceList_FindItem(pAttendanceList, pFieldName, pFieldValue, pCategoryID) |
||
2695 | if not pAttendanceList then |
||
2696 | return nil; |
||
2697 | end |
||
2698 | |||
2699 | if not pFieldValue then |
||
2700 | Calendar_DebugMessage("CalendarAttendanceList_FindItem: pFieldValue is nil for "..pFieldName); |
||
2701 | return nil; |
||
2702 | end |
||
2703 | |||
2704 | local vLowerFieldValue = strlower(pFieldValue); |
||
2705 | |||
2706 | -- Search all categories if none is specified |
||
2707 | |||
2708 | if not pCategoryID then |
||
2709 | for vCategoryID, vCategoryInfo in pAttendanceList.Categories do |
||
2710 | for vIndex, vItem in vCategoryInfo.mAttendees do |
||
2711 | local vItemFieldValue = vItem[pFieldName]; |
||
2712 | |||
2713 | if vItemFieldValue |
||
2714 | and strlower(vItemFieldValue) == vLowerFieldValue then |
||
2715 | return vItem; |
||
2716 | end |
||
2717 | end |
||
2718 | end |
||
2719 | |||
2720 | -- Search the specified category |
||
2721 | |||
2722 | else |
||
2723 | local vCategoryInfo = pAttendanceList.Categories[pCategoryID]; |
||
2724 | |||
2725 | if not vCategoryInfo then |
||
2726 | return nil; |
||
2727 | end |
||
2728 | |||
2729 | for vIndex, vItem in vCategoryInfo.mAttendees do |
||
2730 | if strlower(vItem[pFieldName]) == vLowerFieldValue then |
||
2731 | return vItem; |
||
2732 | end |
||
2733 | end |
||
2734 | end |
||
2735 | |||
2736 | return nil; |
||
2737 | end |
||
2738 | |||
2739 | GroupCalendar_cSortByFlags = |
||
2740 | { |
||
2741 | Date = {Class = true, Rank = false}, |
||
2742 | Rank = {Class = true, Rank = true}, |
||
2743 | Name = {Class = false, Rank = false, Name = true}, |
||
2744 | |||
2745 | Status = {Class = true, Rank = false}, |
||
2746 | ClassRank = {Class = true, Rank = true}, |
||
2747 | DateRank = {Class = true, Rank = true}, |
||
2748 | }; |
||
2749 | |||
2750 | function CalendarAttendanceList_SortIntoCategories(pAttendanceList, pGetItemCategoryFunction) |
||
2751 | -- Clear the existing categories |
||
2752 | |||
2753 | pAttendanceList.Categories = {}; |
||
2754 | pAttendanceList.SortedCategories = {}; |
||
2755 | |||
2756 | -- |
||
2757 | |||
2758 | local vTotalAttendees = 0; |
||
2759 | |||
2760 | for vName, vItem in pAttendanceList.Items do |
||
2761 | local vCategoryID = pGetItemCategoryFunction(vItem); |
||
2762 | |||
2763 | if vCategoryID then |
||
2764 | if vCategoryID ~= "NO" then |
||
2765 | vTotalAttendees = vTotalAttendees + 1; |
||
2766 | end |
||
2767 | |||
2768 | CalendarAttendanceList_AddItem(pAttendanceList, pGetItemCategoryFunction(vItem), vItem); |
||
2769 | end |
||
2770 | end |
||
2771 | |||
2772 | pAttendanceList.NumAttendees = vTotalAttendees; |
||
2773 | end |
||
2774 | |||
2775 | function CalendarAttendanceList_GetRSVPStatusCategory(pItem) |
||
2776 | -- Skip RSVPs which are supposed to be ignored |
||
2777 | |||
2778 | if pItem.mStatus == "-" |
||
2779 | or pItem.mStatus == "C" then |
||
2780 | return nil; |
||
2781 | end |
||
2782 | |||
2783 | if pItem.mStatus == "N" then |
||
2784 | return "NO"; |
||
2785 | elseif pItem.mStatus == "S" then |
||
2786 | return "STANDBY"; |
||
2787 | elseif pItem.mStatus == "Q" then |
||
2788 | return "QUEUED"; |
||
2789 | else |
||
2790 | return "YES"; |
||
2791 | end |
||
2792 | end |
||
2793 | |||
2794 | function CalendarAttendanceList_GetRSVPClassCategory(pItem) |
||
2795 | local vCategoryID = CalendarAttendanceList_GetRSVPStatusCategory(pItem); |
||
2796 | |||
2797 | if not vCategoryID then |
||
2798 | return nil; |
||
2799 | end |
||
2800 | |||
2801 | if vCategoryID ~= "YES" then |
||
2802 | return vCategoryID; |
||
2803 | end |
||
2804 | |||
2805 | if pItem.mClassCode then |
||
2806 | return pItem.mClassCode; |
||
2807 | end |
||
2808 | |||
2809 | return "?"; |
||
2810 | end |
||
2811 | |||
2812 | function CalendarAttendanceList_GetRSVPRankCategory(pItem) |
||
2813 | local vCategoryID = CalendarAttendanceList_GetRSVPStatusCategory(pItem); |
||
2814 | |||
2815 | if not vCategoryID then |
||
2816 | return nil; |
||
2817 | end |
||
2818 | |||
2819 | if vCategoryID ~= "YES" then |
||
2820 | return vCategoryID; |
||
2821 | end |
||
2822 | |||
2823 | vCategoryID = EventDatabase_MapGuildRank(pItem.mGuild, pItem.mGuildRank); |
||
2824 | |||
2825 | if vCategoryID then |
||
2826 | return vCategoryID; |
||
2827 | end |
||
2828 | |||
2829 | return "?"; |
||
2830 | end |
||
2831 | |||
2832 | function CalendarEvent_GetAttendanceCounts(pDatabase, pEvent, pUseClassCategories) |
||
2833 | local vAttendanceList = CalendarAttendanceList_New(); |
||
2834 | |||
2835 | -- Fill in the items list |
||
2836 | |||
2837 | CalendarAttendanceList_AddEventAttendanceItems(vAttendanceList, pDatabase, pEvent); |
||
2838 | |||
2839 | -- Sort into categories |
||
2840 | |||
2841 | local vGetItemCategoryFunction; |
||
2842 | |||
2843 | if pUseClassCategories then |
||
2844 | vGetItemCategoryFunction = CalendarAttendanceList_GetRSVPClassCategory; |
||
2845 | else |
||
2846 | vGetItemCategoryFunction = CalendarAttendanceList_GetRSVPStatusCategory; |
||
2847 | end |
||
2848 | |||
2849 | CalendarAttendanceList_SortIntoCategories(vAttendanceList, vGetItemCategoryFunction); |
||
2850 | |||
2851 | -- Add pending requests |
||
2852 | |||
2853 | CalendarAttendanceList_AddPendingRequests(vAttendanceList, pDatabase, pEvent); |
||
2854 | |||
2855 | -- Calculate class totals |
||
2856 | |||
2857 | CalendarAttendanceList_CalculateClassTotals(vAttendanceList, CalendarAttendanceList_RSVPIsAttending); |
||
2858 | |||
2859 | -- Done |
||
2860 | |||
2861 | return vAttendanceList; |
||
2862 | end |
||
2863 | |||
2864 | function CalendarEvent_SortAttendanceCounts(pAttendanceCounts, pSortBy) |
||
2865 | local vSortByClass, vSortByRank, vSortByName; |
||
2866 | |||
2867 | if pSortBy then |
||
2868 | local vSortByFlags = GroupCalendar_cSortByFlags[pSortBy]; |
||
2869 | |||
2870 | if not vSortByFlags then |
||
2871 | Calendar_ErrorMessage("CalendarEvent_SortAttendanceCounts: Unknown sort "..pSortBy); |
||
2872 | return; |
||
2873 | end |
||
2874 | |||
2875 | vSortByClass = vSortByFlags.Class; |
||
2876 | vSortByRank = vSortByFlags.Rank; |
||
2877 | vSortByName = vSortByFlags.Name; |
||
2878 | else |
||
2879 | vSortByClass = EventDatabase_IsQuestingEventType(pEvent.mType); |
||
2880 | vSortByRank = false; |
||
2881 | vSortByName = false; |
||
2882 | end |
||
2883 | |||
2884 | -- Sort the categories |
||
2885 | |||
2886 | if vSortByClass then |
||
2887 | table.sort(pAttendanceCounts.SortedCategories, EventDatabase_CompareClassCodes); |
||
2888 | else |
||
2889 | table.sort(pAttendanceCounts.SortedCategories, EventDatabase_CompareRankCodes); |
||
2890 | end |
||
2891 | |||
2892 | -- Sort the attendance within each category |
||
2893 | |||
2894 | local vCompareFunction; |
||
2895 | |||
2896 | if vSortByName then |
||
2897 | vCompareFunction = EventDatabase_CompareRSVPsByName; |
||
2898 | elseif vSortByClass and vSortByRank then |
||
2899 | vCompareFunction = EventDatabase_CompareRSVPsByRankAndDate; |
||
2900 | else |
||
2901 | vCompareFunction = EventDatabase_CompareRSVPsByDate; |
||
2902 | end |
||
2903 | |||
2904 | if vSortByClass and vSortByRank then |
||
2905 | end |
||
2906 | |||
2907 | for vCategory, vClassInfo in pAttendanceCounts.Categories do |
||
2908 | table.sort(vClassInfo.mAttendees, vCompareFunction); |
||
2909 | end |
||
2910 | end |
||
2911 | |||
2912 | function EventAvailableSlots_InitializeFromLimits(pLimits) |
||
2913 | local vAvailableSlots = {ClassInfo = {}}; |
||
2914 | local vMinTotal = 0; |
||
2915 | |||
2916 | for vClassCode, vClassCodeInfo in gGroupCalendar_ClassInfoByClassCode do |
||
2917 | local vClassAvailable = nil; |
||
2918 | local vClassExtrasAvailable = nil; |
||
2919 | |||
2920 | if pLimits |
||
2921 | and pLimits.mClassLimits then |
||
2922 | local vClassLimits = pLimits.mClassLimits[vClassCode]; |
||
2923 | |||
2924 | if vClassLimits then |
||
2925 | if vClassLimits.mMin then |
||
2926 | vClassAvailable = vClassLimits.mMin; |
||
2927 | |||
2928 | if vClassAvailable < 0 then |
||
2929 | vClassAvailable = 0; |
||
2930 | end |
||
2931 | |||
2932 | vMinTotal = vMinTotal + vClassLimits.mMin; |
||
2933 | end |
||
2934 | |||
2935 | if vClassLimits.mMax then |
||
2936 | vClassExtrasAvailable = vClassLimits.mMax; |
||
2937 | |||
2938 | if vClassAvailable then |
||
2939 | vClassExtrasAvailable = vClassExtrasAvailable - vClassAvailable; |
||
2940 | end |
||
2941 | |||
2942 | if vClassExtrasAvailable < 0 then |
||
2943 | vClassExtrasAvailable = 0; |
||
2944 | end |
||
2945 | end |
||
2946 | |||
2947 | vClassMax = vClassLimits.mMax; |
||
2948 | end |
||
2949 | end |
||
2950 | |||
2951 | if vClassAvailable |
||
2952 | or vClassExtrasAvailable then |
||
2953 | vAvailableSlots.ClassInfo[vClassCode] = {}; |
||
2954 | vAvailableSlots.ClassInfo[vClassCode].Available = vClassAvailable; |
||
2955 | vAvailableSlots.ClassInfo[vClassCode].ExtrasAvailable = vClassExtrasAvailable; |
||
2956 | end |
||
2957 | end |
||
2958 | |||
2959 | if pLimits |
||
2960 | and pLimits.mMaxAttendance then |
||
2961 | vAvailableSlots.TotalExtras = pLimits.mMaxAttendance - vMinTotal; |
||
2962 | if vAvailableSlots.TotalExtras < 0 then |
||
2963 | vAvailableSlots.TotalExtras = 0; |
||
2964 | end |
||
2965 | else |
||
2966 | vAvailableSlots.TotalExtras = nil; |
||
2967 | end |
||
2968 | |||
2969 | return vAvailableSlots; |
||
2970 | end |
||
2971 | |||
2972 | function CalendarEvent_PlayerClassAdded(pAvailableSlots, pClassCode) |
||
2973 | CalendarEvent_PlayerClassMultiAdded(pAvailableSlots, pClassCode, 1); |
||
2974 | end |
||
2975 | |||
2976 | function CalendarEvent_PlayerClassMultiAdded(pAvailableSlots, pClassCode, pNumAdded) |
||
2977 | local vNumAdded = pNumAdded; |
||
2978 | local vClassInfo = pAvailableSlots.ClassInfo[pClassCode]; |
||
2979 | |||
2980 | if vNumAdded == 0 then |
||
2981 | return; |
||
2982 | end |
||
2983 | |||
2984 | -- If the class hasn't reached its minimum yet then accept the request |
||
2985 | |||
2986 | if vClassInfo |
||
2987 | and vClassInfo.Available |
||
2988 | and vClassInfo.Available > 0 then |
||
2989 | local vAvailableUsed = vNumAdded; |
||
2990 | |||
2991 | if vAvailableUsed > vClassInfo.Available then |
||
2992 | vAvailableUsed = vClassInfo.Available; |
||
2993 | end |
||
2994 | |||
2995 | vClassInfo.Available = vClassInfo.Available - vAvailableUsed; |
||
2996 | vNumAdded = vNumAdded - vAvailableUsed; |
||
2997 | |||
2998 | if vNumAdded == 0 then |
||
2999 | return; |
||
3000 | end |
||
3001 | end |
||
3002 | |||
3003 | -- Nothing to do if there are no limits |
||
3004 | |||
3005 | if not pAvailableSlots.TotalExtras then |
||
3006 | return; |
||
3007 | end |
||
3008 | |||
3009 | -- Have to bail if total extras is now zero |
||
3010 | |||
3011 | if pAvailableSlots.TotalExtras == 0 then |
||
3012 | return; |
||
3013 | end |
||
3014 | |||
3015 | -- Decrease the space for the class |
||
3016 | |||
3017 | if vClassInfo |
||
3018 | and vClassInfo.ExtrasAvailable |
||
3019 | and vClassInfo.ExtrasAvailable > 0 then |
||
3020 | if vNumAdded > vClassInfo.ExtrasAvailable then |
||
3021 | vNumAdded = vClassInfo.ExtrasAvailable; |
||
3022 | end |
||
3023 | |||
3024 | vClassInfo.ExtrasAvailable = vClassInfo.ExtrasAvailable - vNumAdded; |
||
3025 | end |
||
3026 | |||
3027 | -- Decrease the total available extras |
||
3028 | |||
3029 | pAvailableSlots.TotalExtras = pAvailableSlots.TotalExtras - vNumAdded; |
||
3030 | end |
||
3031 | |||
3032 | function EventAvailableSlots_AcceptPlayer(pAvailableSlots, pClassCode) |
||
3033 | local vClassInfo = pAvailableSlots.ClassInfo[pClassCode]; |
||
3034 | |||
3035 | -- If the class hasn't reached its minimum yet then accept the request |
||
3036 | |||
3037 | if vClassInfo |
||
3038 | and vClassInfo.Available |
||
3039 | and vClassInfo.Available > 0 then |
||
3040 | vClassInfo.Available = vClassInfo.Available - 1; |
||
3041 | return true; |
||
3042 | end |
||
3043 | |||
3044 | -- If the minimum has been reached and the extra slots haven't all |
||
3045 | -- been filled then accept the request |
||
3046 | |||
3047 | if pAvailableSlots.TotalExtras then |
||
3048 | -- Put them on standby if the extras slots have all been filled |
||
3049 | |||
3050 | if pAvailableSlots.TotalExtras == 0 then |
||
3051 | return false; |
||
3052 | end |
||
3053 | |||
3054 | -- If the class has a max and it's been reached then put them |
||
3055 | -- on standby |
||
3056 | |||
3057 | if vClassInfo |
||
3058 | and vClassInfo.ExtrasAvailable then |
||
3059 | if vClassInfo.ExtrasAvailable == 0 then |
||
3060 | return false; |
||
3061 | end |
||
3062 | |||
3063 | vClassInfo.ExtrasAvailable = vClassInfo.ExtrasAvailable - 1; |
||
3064 | end |
||
3065 | |||
3066 | pAvailableSlots.TotalExtras = pAvailableSlots.TotalExtras - 1; |
||
3067 | return true; |
||
3068 | end |
||
3069 | |||
3070 | -- No limits at all, just accept them |
||
3071 | |||
3072 | return true; |
||
3073 | end |
||
3074 | |||
3075 | function EventAvailableSlots_CountSlots(pDatabase, pEvent) |
||
3076 | local vAvailableSlots = EventAvailableSlots_InitializeFromLimits(pEvent.mLimits); |
||
3077 | local vAttendanceCounts = CalendarEvent_GetAttendanceCounts(pDatabase, pEvent, true); |
||
3078 | |||
3079 | for vCategory, vClassInfo in vAttendanceCounts.Categories do |
||
3080 | if vCategory ~= "NO" |
||
3081 | and vCategory ~= "STANDBY" then |
||
3082 | CalendarEvent_PlayerClassMultiAdded(vAvailableSlots, vCategory, table.getn(vClassInfo.mAttendees)); |
||
3083 | end |
||
3084 | end |
||
3085 | |||
3086 | return vAvailableSlots; |
||
3087 | end |
||
3088 | |||
3089 | function EventDatabase_CompareRSVPsByDate(pRSVP1, pRSVP2) |
||
3090 | local vRSVP1Date, vRSVP1Time = EventDatabase_GetRSVPOriginalDateTime(pRSVP1); |
||
3091 | local vRSVP2Date, vRSVP2Time = EventDatabase_GetRSVPOriginalDateTime(pRSVP2); |
||
3092 | |||
3093 | if not vRSVP1Date then |
||
3094 | return false; |
||
3095 | elseif not vRSVP2Date then |
||
3096 | return true; |
||
3097 | end |
||
3098 | |||
3099 | if vRSVP1Date < vRSVP2Date then |
||
3100 | return true; |
||
3101 | elseif vRSVP1Date > vRSVP2Date then |
||
3102 | return false; |
||
3103 | elseif vRSVP1Time ~= vRSVP2Time then |
||
3104 | return vRSVP1Time < vRSVP2Time; |
||
3105 | else |
||
3106 | return EventDatabase_CompareRSVPsByName(pRSVP1, pRSVP2); |
||
3107 | end |
||
3108 | end |
||
3109 | |||
3110 | function EventDatabase_CompareRSVPsByName(pRSVP1, pRSVP2) |
||
3111 | return pRSVP1.mName < pRSVP2.mName; |
||
3112 | end |
||
3113 | |||
3114 | function EventDatabase_CompareRSVPsByRankAndDate(pRSVP1, pRSVP2) |
||
3115 | local vRank1 = EventDatabase_MapGuildRank(pRSVP1.mGuild, pRSVP1.mGuildRank); |
||
3116 | local vRank2 = EventDatabase_MapGuildRank(pRSVP2.mGuild, pRSVP2.mGuildRank); |
||
3117 | |||
3118 | if not vRank1 then |
||
3119 | if not vRank2 then |
||
3120 | return EventDatabase_CompareRSVPsByDate(pRSVP1, pRSVP2); |
||
3121 | else |
||
3122 | return false; |
||
3123 | end |
||
3124 | elseif not vRank2 then |
||
3125 | return true; |
||
3126 | end |
||
3127 | |||
3128 | if vRank1 == vRank2 then |
||
3129 | return EventDatabase_CompareRSVPsByDate(pRSVP1, pRSVP2); |
||
3130 | else |
||
3131 | return vRank1 < vRank2; |
||
3132 | end |
||
3133 | end |
||
3134 | |||
3135 | Calendar_cClassCodeSortOrder = |
||
3136 | { |
||
3137 | WHISPERS = 4, |
||
3138 | PENDING = 3, |
||
3139 | QUEUED = 2, |
||
3140 | YES = 1, |
||
3141 | STANDBY = -1, |
||
3142 | NO = -2, |
||
3143 | }; |
||
3144 | |||
3145 | function EventDatabase_CompareClassCodes(pClassCode1, pClassCode2) |
||
3146 | local vSortPriority1 = Calendar_cClassCodeSortOrder[pClassCode1]; |
||
3147 | local vSortPriority2 = Calendar_cClassCodeSortOrder[pClassCode2]; |
||
3148 | |||
3149 | if not vSortPriority1 then |
||
3150 | if not vSortPriority2 then |
||
3151 | return EventDatabase_GetClassByClassCode(pClassCode1) < EventDatabase_GetClassByClassCode(pClassCode2); |
||
3152 | else |
||
3153 | return vSortPriority2 < 0; |
||
3154 | end |
||
3155 | elseif not vSortPriority2 then |
||
3156 | return vSortPriority1 > 0; |
||
3157 | else |
||
3158 | return vSortPriority1 > vSortPriority2; |
||
3159 | end |
||
3160 | end |
||
3161 | |||
3162 | function EventDatabase_CompareRankCodes(pRank1, pRank2) |
||
3163 | local vIsRank1 = type(pRank1) == "number"; |
||
3164 | local vIsRank2 = type(pRank2) == "number"; |
||
3165 | |||
3166 | if vIsRank1 and vIsRank2 then |
||
3167 | return pRank1 < pRank2; |
||
3168 | end |
||
3169 | |||
3170 | if not vIsRank1 then |
||
3171 | if not vIsRank2 then |
||
3172 | return EventDatabase_CompareClassCodes(pRank1, pRank2); |
||
3173 | else |
||
3174 | return false; |
||
3175 | end |
||
3176 | end |
||
3177 | |||
3178 | return true; |
||
3179 | end |
||
3180 | |||
3181 | function EventDatabase_CreatePlayerRSVP( |
||
3182 | pDatabase, pEvent, |
||
3183 | pPlayerName, |
||
3184 | pPlayerRace, pPlayerClass, pPlayeLevel, |
||
3185 | pStatus, |
||
3186 | pComment, |
||
3187 | pGuild, |
||
3188 | pGuildRank, |
||
3189 | pAlts) |
||
3190 | local vDate, vTime60 = EventDatabase_GetServerDateTime60Stamp(); |
||
3191 | local vAlts = nil; |
||
3192 | |||
3193 | if pAlts then |
||
3194 | for vPlayerName, _ in pAlts do |
||
3195 | if vPlayerName ~= pPlayerName then |
||
3196 | if not vAlts then |
||
3197 | vAlts = {}; |
||
3198 | end |
||
3199 | |||
3200 | vAlts[vPlayerName] = true; |
||
3201 | end |
||
3202 | end |
||
3203 | end |
||
3204 | |||
3205 | return |
||
3206 | { |
||
3207 | mName = pPlayerName, |
||
3208 | mOrganizerName = pDatabase.UserName, |
||
3209 | mEventID = pEvent.mID, |
||
3210 | mDate = vDate, |
||
3211 | mTime = vTime60, |
||
3212 | mStatus = pStatus, |
||
3213 | mComment = pComment, |
||
3214 | mRaceCode = pPlayerRace, |
||
3215 | mClassCode = pPlayerClass, |
||
3216 | mLevel = pPlayeLevel, |
||
3217 | mGuild = pGuild, |
||
3218 | mGuildRank = pGuildRank, |
||
3219 | mAlts = vAlts, |
||
3220 | }; |
||
3221 | end |
||
3222 | |||
3223 | function EventDatabase_PlayerLevelChanged(pPlayerLevel) |
||
3224 | if not gGroupCalendar_UserDatabase then |
||
3225 | return; |
||
3226 | end |
||
3227 | |||
3228 | gGroupCalendar_UserDatabase.PlayerLevel = pPlayerLevel; |
||
3229 | end |
||
3230 | |||
3231 | function EventDatabase_PlayerIsQualifiedForEvent(pEvent, pPlayerLevel) |
||
3232 | if not pPlayerLevel then |
||
3233 | return false; |
||
3234 | end |
||
3235 | |||
3236 | if pEvent.mMinLevel and |
||
3237 | pPlayerLevel < pEvent.mMinLevel then |
||
3238 | return false; |
||
3239 | end |
||
3240 | |||
3241 | if pEvent.mMaxLevel and |
||
3242 | pPlayerLevel > pEvent.mMaxLevel then |
||
3243 | return false; |
||
3244 | end |
||
3245 | |||
3246 | return true; |
||
3247 | end |
||
3248 | |||
3249 | function EventDatabase_RescheduleEvent(pDatabase, pEvent, pNewDate) |
||
3250 | local vNewEvent = EventDatabase_NewEvent(pDatabase, pNewDate); |
||
3251 | |||
3252 | vNewEvent.mType = pEvent.mType; |
||
3253 | vNewEvent.mTitle = pEvent.mTitle; |
||
3254 | |||
3255 | vNewEvent.mTime = pEvent.mTime; |
||
3256 | vNewEvent.mDuration = pEvent.mDuration; |
||
3257 | |||
3258 | vNewEvent.mDescription = pEvent.mDescription; |
||
3259 | |||
3260 | vNewEvent.mMinLevel = pEvent.mMinLevel; |
||
3261 | vNewEvent.mAttendance = pEvent.mAttendance; |
||
3262 | |||
3263 | EventDatabase_AddEvent(pDatabase, vNewEvent); |
||
3264 | |||
3265 | return EventDatabase_DeleteEvent(pDatabase, pEvent); |
||
3266 | end |
||
3267 | |||
3268 | function EventDatabase_DeleteOldEvents(pDatabase) |
||
3269 | if not pDatabase.Events then |
||
3270 | return; |
||
3271 | end |
||
3272 | |||
3273 | for vDate, vEvents in pDatabase.Events do |
||
3274 | if vDate < gGroupCalendar_MinimumEventDate then |
||
3275 | -- Remove or reschedule the events for this date |
||
3276 | |||
3277 | local vNumEvents = table.getn(vEvents); |
||
3278 | local vEventIndex = 1; |
||
3279 | |||
3280 | for vIndex = 1, vNumEvents do |
||
3281 | local vEvent = vEvents[vEventIndex]; |
||
3282 | |||
3283 | if pDatabase.IsPlayerOwned and vEvent.mType == "Birth" then |
||
3284 | Calendar_DebugMessage("GroupCalendar: Rescheduling birthday event "..vEvent.mID.." for "..pDatabase.UserName); |
||
3285 | |||
3286 | local vMonth, vDay, vYear = Calendar_ConvertDateToMDY(vDate); |
||
3287 | vYear = vYear + 1; |
||
3288 | local vNewDate = Calendar_ConvertMDYToDate(vMonth, vDay, vYear); |
||
3289 | |||
3290 | if not EventDatabase_RescheduleEvent(pDatabase, vEvent, vNewDate) then |
||
3291 | Calendar_DebugMessage("GroupCalendar: Can't reschedule event "..vEvent.mID.." for "..pDatabase.UserName..": Unknown error"); |
||
3292 | vEventIndex = vEventIndex + 1; |
||
3293 | end |
||
3294 | elseif not EventDatabase_DeleteEvent(pDatabase, vEvent) then |
||
3295 | Calendar_DebugMessage("GroupCalendar: Can't delete old event "..vEvent.mID.." for "..pDatabase.UserName..": Unknown error"); |
||
3296 | vEventIndex = vEventIndex + 1; |
||
3297 | end |
||
3298 | end |
||
3299 | end |
||
3300 | end |
||
3301 | end |
||
3302 | |||
3303 | function EventDatabase_PlayerIsAttendingEvent(pEventOwner, pEvent) |
||
3304 | for vPlayerName, vPlayerValue in gGroupCalendar_PlayerCharacters do |
||
3305 | local vPlayerDatabase = EventDatabase_GetDatabase(vPlayerName, false); |
||
3306 | local vRSVP = nil; |
||
3307 | |||
3308 | if vPlayerDatabase then |
||
3309 | vRSVP = EventDatabase_FindRSVPRequestData(vPlayerDatabase, pEventOwner, pEvent.mID); |
||
3310 | end |
||
3311 | |||
3312 | if not vRSVP then |
||
3313 | vRSVP = EventDatabase_FindEventRSVP(pEventOwner, pEvent, vPlayerName); |
||
3314 | end |
||
3315 | |||
3316 | if vRSVP then |
||
3317 | local vStatus1 = string.sub(vRSVP.mStatus, 1, 1); |
||
3318 | |||
3319 | if vStatus1 == "Y" then |
||
3320 | return true; |
||
3321 | end |
||
3322 | end |
||
3323 | end |
||
3324 | |||
3325 | |||
3326 | return false; |
||
3327 | end |
||
3328 | |||
3329 | function EventDatabase_RemoveSavedInstanceEvents(pDatabase) |
||
3330 | for vDate, vSchedule in pDatabase.Events do |
||
3331 | local vEventIndex = 1; |
||
3332 | local vNumEvents = table.getn(vSchedule); |
||
3333 | |||
3334 | while vEventIndex <= vNumEvents do |
||
3335 | local vEvent = vSchedule[vEventIndex]; |
||
3336 | |||
3337 | if EventDatabase_IsDungeonResetEventType(vEvent.mType) then |
||
3338 | EventDatabase_DeleteEvent(pDatabase, vEvent); |
||
3339 | vNumEvents = vNumEvents - 1; |
||
3340 | else |
||
3341 | vEventIndex = vEventIndex + 1; |
||
3342 | end |
||
3343 | end |
||
3344 | end |
||
3345 | end |
||
3346 | |||
3347 | function EventDatabase_RemoveTradeskillEventByType(pDatabase, pEventType) |
||
3348 | for vDate, vSchedule in pDatabase.Events do |
||
3349 | local vEventIndex = 1; |
||
3350 | local vNumEvents = table.getn(vSchedule); |
||
3351 | |||
3352 | while vEventIndex <= vNumEvents do |
||
3353 | local vEvent = vSchedule[vEventIndex]; |
||
3354 | |||
3355 | if vEvent.mType == pEventType then |
||
3356 | EventDatabase_DeleteEvent(pDatabase, vEvent); |
||
3357 | vNumEvents = vNumEvents - 1; |
||
3358 | else |
||
3359 | vEventIndex = vEventIndex + 1; |
||
3360 | end |
||
3361 | end |
||
3362 | end |
||
3363 | end |
||
3364 | |||
3365 | function EventDatabase_ScheduleResetEvent(pDatabase, pType, pResetDate, pResetTime) |
||
3366 | local vEvent = EventDatabase_NewEvent(pDatabase, pResetDate); |
||
3367 | |||
3368 | vEvent.mType = pType; |
||
3369 | vEvent.mPrivate = true; |
||
3370 | vEvent.mTime = pResetTime; |
||
3371 | vEvent.mDuration = nil; |
||
3372 | |||
3373 | EventDatabase_AddEvent(pDatabase, vEvent); |
||
3374 | end |
||
3375 | |||
3376 | function EventDatabase_ScheduleSavedInstanceEvent(pDatabase, pName, pResetDate, pResetTime) |
||
3377 | local vType = EventDatabase_LookupDungeonResetEventTypeByName(pName); |
||
3378 | |||
3379 | if not vType then |
||
3380 | Calendar_DebugMessage("GroupCalendar: Can't schedule reset event for "..pName..": The instance name is not recognized"); |
||
3381 | return; |
||
3382 | end |
||
3383 | |||
3384 | EventDatabase_ScheduleResetEvent(pDatabase, vType, pResetDate, pResetTime); |
||
3385 | end |
||
3386 | |||
3387 | function EventDatabase_ScheduleTradeskillCooldownEvent(pDatabase, pTradeskillID, pCooldownSeconds) |
||
3388 | local vType = EventDatabase_LookupTradeskillEventTypeByID(pTradeskillID); |
||
3389 | local vResetDate, vResetTime = Calendar_GetServerDateTimeFromSecondsOffset(pCooldownSeconds); |
||
3390 | |||
3391 | EventDatabase_RemoveTradeskillEventByType(pDatabase, vType); |
||
3392 | EventDatabase_ScheduleResetEvent(pDatabase, vType, vResetDate, vResetTime); |
||
3393 | end |
||
3394 | |||
3395 | function EventDatabase_UpdateTradeskillCooldown(pDatabase, pTradeskillID) |
||
3396 | local vCooldown = Calendar_GetTradeskillCooldown(pTradeskillID); |
||
3397 | |||
3398 | if vCooldown then |
||
3399 | EventDatabase_ScheduleTradeskillCooldownEvent(pDatabase, pTradeskillID, vCooldown) |
||
3400 | end |
||
3401 | end |
||
3402 | |||
3403 | function EventDatabase_UpdateCurrentTradeskillCooldown() |
||
3404 | local vTradeskillName, vCurrentLevel, vMaxLevel = GetTradeSkillLine(); |
||
3405 | |||
3406 | if not vTradeskillName then |
||
3407 | return; |
||
3408 | end |
||
3409 | |||
3410 | local vTradeskillID = Calendar_LookupTradeskillIDByName(vTradeskillName); |
||
3411 | |||
3412 | if not vTradeskillID then |
||
3413 | return; |
||
3414 | end |
||
3415 | |||
3416 | EventDatabase_UpdateTradeskillCooldown(gGroupCalendar_UserDatabase, vTradeskillID); |
||
3417 | end |
||
3418 | |||
3419 | function EventDatabase_MapGuildRank(pFromGuild, pFromRank) |
||
3420 | if not pFromGuild |
||
3421 | or not pFromRank then |
||
3422 | return nil; |
||
3423 | end |
||
3424 | |||
3425 | -- If it's the same guild then just return the rank |
||
3426 | |||
3427 | if pFromGuild == gGroupCalendar_PlayerGuild then |
||
3428 | return pFromRank; |
||
3429 | end |
||
3430 | |||
3431 | -- Force to zero if not in any guild |
||
3432 | |||
3433 | if not IsInGuild() then |
||
3434 | return nil; |
||
3435 | end |
||
3436 | |||
3437 | -- Just cover our eyes if the roster isn't loaded yet |
||
3438 | |||
3439 | if GetNumGuildMembers() == 0 then |
||
3440 | CalendarNetwork_LoadGuildRoster(); |
||
3441 | return pFromRank; |
||
3442 | end |
||
3443 | |||
3444 | local vMaxGuildRank = GuildControlGetNumRanks() - 1; |
||
3445 | |||
3446 | -- Get the mapping |
||
3447 | |||
3448 | local vToRankMap; |
||
3449 | |||
3450 | if gGroupCalendar_RealmSettings.RankMap then |
||
3451 | vToRankMap = gGroupCalendar_RealmSettings.RankMap[gGroupCalendar_PlayerGuild]; |
||
3452 | end |
||
3453 | |||
3454 | local vRankMap; |
||
3455 | |||
3456 | if vToRankMap then |
||
3457 | vRankMap = vToRankMap[pFromGuild]; |
||
3458 | end |
||
3459 | |||
3460 | if vRankMap then |
||
3461 | local vToRank = vRankMap[pFromRank]; |
||
3462 | |||
3463 | if vToRank then |
||
3464 | return vToRank; |
||
3465 | end |
||
3466 | |||
3467 | -- If there's not a mapping for this rank, map it to the |
||
3468 | -- same value as the next highest rank |
||
3469 | |||
3470 | for vFromRank, vToRank in vRankMap do |
||
3471 | if vFromRank > pFromRank then |
||
3472 | return vToRank; |
||
3473 | end |
||
3474 | end |
||
3475 | end |
||
3476 | |||
3477 | -- Do a dumb mapping which simply ensures that the rank index |
||
3478 | -- is valid for the current guild |
||
3479 | |||
3480 | if pFromRank > vMaxGuildRank then |
||
3481 | return vMaxGuildRank; |
||
3482 | else |
||
3483 | return pFromRank; |
||
3484 | end |
||
3485 | end |
||
3486 | |||
3487 | function EventDatabase_SetGuildRankMapping(pFromGuild, pFromRank, pToRank) |
||
3488 | if not pFromGuild |
||
3489 | or pFromGuild == "" |
||
3490 | or not pFromRank then |
||
3491 | return; |
||
3492 | end |
||
3493 | |||
3494 | -- If it's the same guild then there's nothing to do |
||
3495 | |||
3496 | if pFromGuild == gGroupCalendar_PlayerGuild then |
||
3497 | return; |
||
3498 | end |
||
3499 | |||
3500 | -- Make sure the maps exist |
||
3501 | |||
3502 | if not gGroupCalendar_RealmSettings.RankMap then |
||
3503 | gGroupCalendar_RealmSettings.RankMap = {}; |
||
3504 | end |
||
3505 | |||
3506 | -- Make sure the to guild map exists |
||
3507 | |||
3508 | local vToGuildMap = gGroupCalendar_RealmSettings.RankMap[gGroupCalendar_PlayerGuild]; |
||
3509 | |||
3510 | if not vToGuildMap then |
||
3511 | vToGuildMap = {}; |
||
3512 | gGroupCalendar_RealmSettings.RankMap[gGroupCalendar_PlayerGuild] = vToGuildMap; |
||
3513 | end |
||
3514 | |||
3515 | -- Make sure the from guild map exists |
||
3516 | |||
3517 | local vGuildMap = vToGuildMap[pFromGuild]; |
||
3518 | |||
3519 | if not vGuildMap then |
||
3520 | vGuildMap = {}; |
||
3521 | vToGuildMap[pFromGuild] = vGuildMap; |
||
3522 | end |
||
3523 | |||
3524 | vGuildMap[pFromRank] = pToRank; |
||
3525 | end |
||
3526 | |||
3527 | function EventDatabase_UpdateGuildRankCache() |
||
3528 | if not gGroupCalendar_PlayerGuild |
||
3529 | or not gGroupCalendar_Initialized then |
||
3530 | return; |
||
3531 | end |
||
3532 | |||
3533 | if not gGroupCalendar_RealmSettings.GuildRanks then |
||
3534 | gGroupCalendar_RealmSettings.GuildRanks = {}; |
||
3535 | end |
||
3536 | |||
3537 | vGuildRanks = {}; |
||
3538 | |||
3539 | local vNumRanks = GuildControlGetNumRanks(); |
||
3540 | |||
3541 | for vIndex = 1, vNumRanks do |
||
3542 | vGuildRanks[vIndex - 1] = GuildControlGetRankName(vIndex); |
||
3543 | end |
||
3544 | |||
3545 | gGroupCalendar_RealmSettings.GuildRanks[gGroupCalendar_PlayerGuild] = vGuildRanks; |
||
3546 | end |