farmbuyer@6: local nametag = ... farmbuyer@6: local addon = CreateFrame("Frame") farmbuyer@6: local L = LibStub("AceLocale-3.0"):GetLocale(nametag) farmbuyer@9: local SV, SVc farmbuyer@1: farmbuyer@1: local DEFAULT_CHAT = 2 -- combat log (no constant predefined for that) farmbuyer@1: farmbuyer@1: local guild_selection, log_ever_shown farmbuyer@1: addon.options = { farmbuyer@6: --name = filled in during OnInit farmbuyer@1: type = 'group', farmbuyer@3: childGroups = 'tab', farmbuyer@1: handler = addon, -- functions listed as strings called as addon:func farmbuyer@1: args = { farmbuyer@1: version = { farmbuyer@1: --name = filled in during OnEnable farmbuyer@1: type = 'description', farmbuyer@1: fontSize = "large", farmbuyer@1: --image = "Interface\\AddOns\\GuildDelta\\test2", farmbuyer@1: cmdHidden = true, farmbuyer@1: order = 1, farmbuyer@1: }, farmbuyer@1: note = { farmbuyer@1: --name = filled in locals section farmbuyer@1: type = 'description', farmbuyer@1: cmdHidden = true, farmbuyer@1: width = 'full', farmbuyer@1: order = 2, farmbuyer@1: }, farmbuyer@3: general = { farmbuyer@6: name = GENERAL, farmbuyer@6: desc = L["Tracking options"], farmbuyer@3: type = 'group', farmbuyer@3: order = 10, farmbuyer@3: args = { farmbuyer@3: fields = { farmbuyer@6: name = L["Attributes"], farmbuyer@6: desc = L["Track changes to these player attributes"], farmbuyer@3: type = 'multiselect', farmbuyer@3: order = 10, farmbuyer@3: -- these need to be of function type rather than string keys of members farmbuyer@3: values = function(info) return addon:MakeFieldList() end, farmbuyer@3: get = function(info,x) return SV.fields[x] end, farmbuyer@3: set = function(info,x,val) SV.fields[x] = val end, farmbuyer@3: }, farmbuyer@3: nochange = { farmbuyer@7: name = L["No Change"], farmbuyer@6: desc = L["Print a message even when no changes are detected"], farmbuyer@3: type = 'toggle', farmbuyer@3: order = 15, farmbuyer@3: get = function() return not not SV.notify_nochange end, farmbuyer@3: set = function(info,val) SV.notify_nochange = val end, farmbuyer@3: }, farmbuyer@4: color = { farmbuyer@6: name = L["Color of output text"], farmbuyer@4: type = 'color', farmbuyer@4: order = 17, farmbuyer@4: get = function() return SV.red, SV.green, SV.blue, 1 end, farmbuyer@4: set = function(info,...) SV.red, SV.green, SV.blue = ... end, farmbuyer@4: }, farmbuyer@3: spacer2 = { farmbuyer@3: name = '', farmbuyer@3: type = 'description', farmbuyer@3: cmdHidden = true, farmbuyer@3: width = 'full', farmbuyer@3: order = 19, farmbuyer@3: }, farmbuyer@3: guilds = { farmbuyer@6: name = L["Guilds"], farmbuyer@6: desc = L["Guilds for which a roster is known"], farmbuyer@3: type = 'select', farmbuyer@3: order = 20, farmbuyer@3: width = 'double', farmbuyer@3: values = function(info) return addon:MakeGuildList() end, farmbuyer@3: get = function(info) return guild_selection end, farmbuyer@3: set = function(info,val) guild_selection = val end, farmbuyer@3: }, farmbuyer@3: clearguild = { farmbuyer@6: name = L["Reset Guild"], farmbuyer@7: desc = L["Erase stored data for selected guild; information will be scanned from scratch on next login."], farmbuyer@3: type = 'execute', farmbuyer@3: order = 22, farmbuyer@3: disabled = function() return not guild_selection end, farmbuyer@3: func = function() farmbuyer@3: assert(type(guild_selection)=='string') farmbuyer@3: local g,r = guild_selection:match("<([^>]+)> %- (.*)") farmbuyer@3: local m = SV.members[r] farmbuyer@3: if m then farmbuyer@3: m[g] = nil farmbuyer@3: else farmbuyer@6: addon:Printf(L["Error: %s cannot be matched as a realm name. Please report this as a bug, including the name of the realm and guild."], r) farmbuyer@3: end farmbuyer@3: end, farmbuyer@3: }, farmbuyer@3: }, farmbuyer@1: }, farmbuyer@3: output = { farmbuyer@6: name = L["Output"], farmbuyer@6: desc = L["What and where to print"], farmbuyer@3: type = 'group', farmbuyer@1: order = 20, farmbuyer@3: args = { farmbuyer@3: reset = { farmbuyer@6: name = L["Reset Output"], farmbuyer@6: desc = L["Restores default output settings"], farmbuyer@3: type = 'execute', farmbuyer@3: order = 10, farmbuyer@3: func = "SetChat", farmbuyer@3: arg = DEFAULT_CHAT, farmbuyer@3: }, farmbuyer@3: spacer1 = { farmbuyer@3: name = '', farmbuyer@3: type = 'description', farmbuyer@3: cmdHidden = true, farmbuyer@3: width = 'full', farmbuyer@3: order = 11, farmbuyer@3: }, farmbuyer@3: print_chatframes = { farmbuyer@6: name = L["Print Chatframe Numbers"], farmbuyer@6: desc = L["Print each chat window number in its frame, for easy reference in the next slider option"], farmbuyer@3: type = 'execute', farmbuyer@3: --func = print_chatframes filled in below farmbuyer@3: order = 20, farmbuyer@3: }, farmbuyer@3: chatframe_num = { farmbuyer@6: name = L["Output Chatframe"], farmbuyer@6: desc = L["Which chat window to prefer for printing all the output during login"], farmbuyer@3: type = 'range', farmbuyer@3: min = 1, farmbuyer@3: max = NUM_CHAT_WINDOWS, farmbuyer@3: step = 1, farmbuyer@3: get = function() return tonumber(SV.chatframe) or --[[in case of custom name]]DEFAULT_CHAT end, farmbuyer@3: set = "SetChat", farmbuyer@3: order = 25, farmbuyer@3: }, farmbuyer@3: chatframe_name = { farmbuyer@6: name = L["Chatframe Override"], farmbuyer@7: desc = L[" If blank, uses the numerical slider. If set, it is the Lua variable name of a frame with AddMessage capability to use for output."], farmbuyer@3: type = 'input', farmbuyer@3: get = function() farmbuyer@3: return type(SV.chatframe) == 'string' and SV.chatframe or nil farmbuyer@3: end, farmbuyer@3: set = "SetChat", farmbuyer@3: order = 26, farmbuyer@3: }, farmbuyer@9: header = { farmbuyer@9: name = '', farmbuyer@9: type = 'header', farmbuyer@9: order = 30, farmbuyer@9: }, farmbuyer@9: snapshot = { farmbuyer@9: name = L["Snapshot"], farmbuyer@9: desc = L["Show a text window with the current guild roster."], farmbuyer@9: type = 'execute', farmbuyer@9: order = 31, farmbuyer@9: func = "Snapshot", farmbuyer@9: }, farmbuyer@3: }, farmbuyer@1: }, farmbuyer@1: persist = { farmbuyer@6: name = L["Logging"], farmbuyer@6: desc = L["Storing changes for later review"], farmbuyer@1: type = 'group', farmbuyer@3: order = 30, farmbuyer@1: args = { farmbuyer@1: note = { farmbuyer@1: --name = filled in locals section farmbuyer@1: type = 'description', farmbuyer@1: cmdHidden = true, farmbuyer@1: width = 'full', farmbuyer@3: order = 10, farmbuyer@1: }, farmbuyer@1: enable = { farmbuyer@6: name = L["Enable Logging"], farmbuyer@6: desc = L["Accumulate all deltas, including a timestamp. |cffFF0000WARNING|r: if logging was enabled and you turn it off, the log itself will not be saved when exiting the game."], farmbuyer@1: type = 'toggle', farmbuyer@3: order = 15, farmbuyer@1: get = function() return SV.logging end, farmbuyer@1: set = function(i,v) farmbuyer@1: SV.logging = v farmbuyer@1: log_ever_shown = SV.logging or log_ever_shown farmbuyer@1: end, farmbuyer@1: }, farmbuyer@1: clearlog = { farmbuyer@6: name = L["Reset Log"], farmbuyer@6: desc = L["Erase accumulated deltas"], farmbuyer@1: type = 'execute', farmbuyer@3: order = 20, farmbuyer@1: hidden = function() return not (SV.logging or log_ever_shown) end, farmbuyer@1: disabled = function() return not SV.logging end, farmbuyer@1: func = function() farmbuyer@1: SV.logtext = nil farmbuyer@1: end, farmbuyer@1: }, farmbuyer@1: log = { farmbuyer@6: name = L["Log"], farmbuyer@6: desc = L["If you make changes, don't forget to click 'Accept' to save them. Scroll down if needed."], farmbuyer@1: type = 'input', farmbuyer@3: order = 25, farmbuyer@1: multiline = 15, farmbuyer@1: width = 'full', farmbuyer@1: hidden = function() return not (SV.logging or log_ever_shown) end, farmbuyer@1: disabled = function() return not SV.logging end, farmbuyer@1: get = function() return SV.logtext end, farmbuyer@1: set = function(i,t) SV.logtext = t end, farmbuyer@1: }, farmbuyer@1: }, farmbuyer@1: }, farmbuyer@1: } farmbuyer@1: } farmbuyer@1: farmbuyer@1: farmbuyer@1: ----------------------------------------------------------------------------- farmbuyer@1: -- other locals farmbuyer@1: local tinsert, GetGuildRosterInfo = _G.table.insert, _G.GetGuildRosterInfo farmbuyer@1: local chatframe, fieldlist farmbuyer@1: local function prt (...) farmbuyer@1: return chatframe:AddMessage(...) farmbuyer@1: end farmbuyer@1: local function cprt (txt) farmbuyer@1: if SV.logging then addon:AddLogNote(txt) end farmbuyer@4: return prt(txt, SV.red, SV.green, SV.blue) farmbuyer@1: end farmbuyer@1: farmbuyer@1: function addon:current_guild_info (N) farmbuyer@1: local ret = {} farmbuyer@11: local swearing = GetCVar("profanityFilter") farmbuyer@11: SetCVar ("profanityFilter", "0") farmbuyer@1: for i = 1, N do farmbuyer@1: local name,rank_as_string,_,level,_,_,publicnote,officernote = GetGuildRosterInfo(i) farmbuyer@1: -- This technically does not work out to the same as A?B:C, combined farmbuyer@1: -- with the logic below. It does, however, still result in the entry farmbuyer@1: -- not appearing in the returned table. farmbuyer@1: publicnote = publicnote ~= "" and publicnote or nil farmbuyer@1: officernote = officernote ~= "" and officernote or nil farmbuyer@1: if name then -- redundant, but apparently happens on extreme lag farmbuyer@1: tinsert(ret, farmbuyer@1: {name = name, farmbuyer@1: rank = SV.fields.rank and rank_as_string or nil, farmbuyer@1: level = SV.fields.level and level or nil, farmbuyer@1: pnote = SV.fields.notes and publicnote or nil, farmbuyer@20: onote = SV.fields.onotes and officernote or nil, farmbuyer@1: }) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: table.sort(ret, function (l,r) return l.name < r.name end) farmbuyer@11: SetCVar ("profanityFilter", swearing) farmbuyer@1: return ret farmbuyer@1: end farmbuyer@1: farmbuyer@3: function addon.options.args.output.args.print_chatframes.func() farmbuyer@1: for i = 1, NUM_CHAT_WINDOWS do farmbuyer@2: local cf = _G['ChatFrame'..i] farmbuyer@1: if not cf then break end farmbuyer@6: addon:Printf(cf, L["This is frame number %d."], i) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@6: -- Localize these? farmbuyer@1: addon.options.args.note.name = farmbuyer@1: "You can use the '/guilddelta' command to open the options window.\n\n".. farmbuyer@1: "The guild roster has already been scanned by the time you see this. Therefore, ".. farmbuyer@1: "if you make any changes to the Fields section below, you should probably relog ".. farmbuyer@1: "immediately to begin tracking the changed fields. Changes to the contents *OF* ".. farmbuyer@3: "those fields will not be noticed until the first login after *that*.\n" farmbuyer@1: farmbuyer@1: addon.options.args.persist.args.note.name = farmbuyer@1: "Enabling logging will accumulate the text of the 'deltas' as you see them. ".. farmbuyer@1: "This can grow large over time, depending on the activity of your guilds, so you ".. farmbuyer@1: "should use the Reset Log button below from time to time.\n\n".. farmbuyer@1: "If you click inside the text area below, you can use Control-A to select all ".. farmbuyer@1: "the text, and Control-C to copy it to your computer's clipboard. If you make ".. farmbuyer@2: "any changes to the text, the changes will be preserved. (You can remove uninteresting ".. farmbuyer@1: "changes, add reminders to yourself, and so forth.)\n\n" farmbuyer@1: farmbuyer@1: farmbuyer@1: ----------------------------------------------------------------------------- farmbuyer@6: addon = LibStub("AceAddon-3.0"):NewAddon(addon, nametag, farmbuyer@3: "AceConsole-3.0") farmbuyer@1: farmbuyer@1: function addon:OnInitialize() farmbuyer@1: if _G.GuildDeltaSV == nil then farmbuyer@1: -- Defaults need to transition from potential older savedvars farmbuyer@1: _G.GuildDeltaSV = { farmbuyer@1: chatframe = _G.GuildDelta_chatframe or DEFAULT_CHAT, farmbuyer@20: fields = _G.GuildDelta_fields or farmbuyer@20: { rank = true, level = false, notes = true }, farmbuyer@3: members = _G.GuildDelta_memberdata or {}, farmbuyer@3: --notify_nochange = nil by default farmbuyer@3: --logging = nil by default farmbuyer@1: } farmbuyer@1: end farmbuyer@1: SV = _G.GuildDeltaSV farmbuyer@4: -- upgrade path farmbuyer@4: if SV.red == nil then farmbuyer@4: SV.red = 255/255 farmbuyer@4: SV.green = 26/255 farmbuyer@4: SV.blue = 160/255 farmbuyer@4: end farmbuyer@20: if SV.fields.onotes == nil then farmbuyer@20: SV.fields.onotes = SV.fields.notes farmbuyer@20: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- Remove anything that normal operation doesn't need after finishing its work. farmbuyer@1: function addon:cleanup() farmbuyer@1: prt = nil; cprt = nil farmbuyer@1: self.current_guild_info = nil farmbuyer@1: self.cleanup = nil farmbuyer@1: self.unload = nil farmbuyer@1: self.logquay = nil farmbuyer@1: self.AddLogNote = nil farmbuyer@1: self.FinishLog = nil farmbuyer@1: end farmbuyer@2: -- Remove everything. farmbuyer@1: function addon:unload() farmbuyer@1: self:cleanup() farmbuyer@6: LibStub("AceAddon-3.0").addons[nametag] = nil farmbuyer@3: addon = nil; farmbuyer@1: -- put the userdata back so it counts as a Frame object again farmbuyer@1: local ud = self[0] farmbuyer@1: table.wipe(self) farmbuyer@1: self[0] = ud farmbuyer@1: end farmbuyer@1: farmbuyer@1: function addon:OnEnable() farmbuyer@1: if not IsInGuild() then farmbuyer@1: self:Print("You are not in a guild, not loading.") farmbuyer@1: return self:unload() farmbuyer@1: end farmbuyer@1: farmbuyer@3: self:RegisterEvent("GUILD_ROSTER_UPDATE") farmbuyer@1: self:SetScript("OnEvent", self.GuildUpdate) farmbuyer@1: farmbuyer@1: self.options.args.version.name = farmbuyer@6: "|cff30adffVersion " .. (GetAddOnMetadata(nametag, "Version") or "?") .. "|r" farmbuyer@6: LibStub("AceConfig-3.0"):RegisterOptionsTable(nametag, self.options) farmbuyer@9: self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions(nametag, "Guild Delta") farmbuyer@1: self:RegisterChatCommand("guilddelta", "OnChatCommand") farmbuyer@2: self:SetChat(self) farmbuyer@1: log_ever_shown = SV.logging farmbuyer@1: self.OnEnable = nil farmbuyer@1: end farmbuyer@1: farmbuyer@1: farmbuyer@1: function addon:OnChatCommand (input) farmbuyer@1: if not input or input:trim() == "" then farmbuyer@6: LibStub("AceConfigDialog-3.0"):Open(nametag) farmbuyer@1: else farmbuyer@6: LibStub("AceConfigCmd-3.0").HandleCommand(self, "guilddelta", nametag, input) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: farmbuyer@2: -- 1 arg: (self) called during startup to initialize farmbuyer@2: -- (other) resetting via menus to defaults (see arg field) farmbuyer@2: -- 2 args: setting via menus to new value, number or custom name (see value) farmbuyer@1: function addon:SetChat (info, value) farmbuyer@1: local n, nframe farmbuyer@2: local isauto = info == self farmbuyer@2: if isauto then farmbuyer@2: n = SV.chatframe farmbuyer@2: else -- coming via menu farmbuyer@1: n = info.arg or value farmbuyer@1: end farmbuyer@1: if type(n) == 'number' then farmbuyer@2: if isauto then farmbuyer@2: -- start at the preferred number and find a non-minimized and farmbuyer@2: -- potentially visible frame farmbuyer@2: n = math.min(n,NUM_CHAT_WINDOWS) farmbuyer@2: local cf,cft farmbuyer@2: for i = n, 1, -1 do farmbuyer@2: cf = _G['ChatFrame'..i] farmbuyer@2: cft = _G[cf:GetName()..'Tab'] farmbuyer@2: if cft:IsVisible() then farmbuyer@2: n = i farmbuyer@2: break farmbuyer@2: end farmbuyer@2: end farmbuyer@2: end farmbuyer@2: nframe = _G['ChatFrame'..n] farmbuyer@1: else farmbuyer@2: nframe = _G[n] -- advanced name farmbuyer@1: end farmbuyer@1: if type(nframe) == 'table' and type(nframe.AddMessage) == 'function' then farmbuyer@2: if not isauto then farmbuyer@2: SV.chatframe = n farmbuyer@6: self:Print(L["Now printing to chat frame"], n, farmbuyer@1: (type(nframe.name)=='string' and ("(".. nframe.name .. ")") or "")) farmbuyer@1: end farmbuyer@1: chatframe = nframe farmbuyer@1: else farmbuyer@6: self:Printf(L["'%s' was not a valid chat frame number/name, no change has been made."], n) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: farmbuyer@9: function addon:Snapshot() farmbuyer@9: if self.optionsFrame:IsVisible() then farmbuyer@9: InterfaceOptionsFrameCancel:Click() farmbuyer@9: HideUIPanel(GameMenuFrame) farmbuyer@9: else farmbuyer@9: LibStub("AceConfigDialog-3.0"):Close(nametag) farmbuyer@9: end farmbuyer@9: GameTooltip:Hide() farmbuyer@9: farmbuyer@9: local tinsert = table.insert farmbuyer@9: local fmt = "%-20s%-16s%-20s%-20s" farmbuyer@9: local results = { farmbuyer@9: fmt:format(CALENDAR_PLAYER_NAME, L["FIELD_rank"], LABEL_NOTE, OFFICER_NOTE_COLON), farmbuyer@9: ('-'):rep(80), farmbuyer@9: } farmbuyer@9: farmbuyer@9: for _,x in ipairs(SVc) do farmbuyer@9: tinsert (results, fmt:format(x.name, x.rank or '--', x.pnote or '--', x.onote or '')) farmbuyer@9: end farmbuyer@9: farmbuyer@9: results = table.concat (results, '\n') farmbuyer@9: farmbuyer@9: local GUI = LibStub("AceGUI-3.0") farmbuyer@9: local f = GUI:Create("Frame") farmbuyer@9: f:SetTitle(nametag) farmbuyer@9: f:SetStatusText("Use Ctrl-A and Ctrl-C to copy this text to your system clipboard.") farmbuyer@9: f:SetLayout("Fill") farmbuyer@9: f:SetStatusTable{width=700} farmbuyer@9: farmbuyer@9: local eb = GUI:Create("MultiLineEditBox") farmbuyer@9: eb:SetFullWidth(true) farmbuyer@9: eb:SetFullHeight(true) farmbuyer@9: eb:SetLabel("Pressing the Escape key while typing will return keystroke control to the usual chat window.") farmbuyer@9: eb:DisableButton(true) farmbuyer@9: eb:SetText(results) farmbuyer@9: farmbuyer@9: f:SetCallback("OnClose", function(_f) farmbuyer@9: eb:SetText'' -- hmmmm farmbuyer@9: GUI:Release(_f) farmbuyer@9: end) farmbuyer@9: f:AddChild(eb) farmbuyer@9: eb:SetFocus() farmbuyer@9: f:ApplyStatus() farmbuyer@9: f:Show() farmbuyer@9: end farmbuyer@9: farmbuyer@9: farmbuyer@1: -- Not a "normal" PLAYER_LOGOUT handler; this only fires if the player is in farmbuyer@1: -- a guild and the update has already run. farmbuyer@1: function addon:PLAYER_LOGOUT() farmbuyer@1: if not SV.logging then farmbuyer@1: SV.logtext = nil farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: farmbuyer@1: function addon:GuildUpdate() farmbuyer@1: local current_n = GetNumGuildMembers(true) farmbuyer@5: if (current_n <= 0) or (not GetGuildInfo("player")) then farmbuyer@1: -- catch the hell up, servers... farmbuyer@1: return GuildRoster() farmbuyer@1: end farmbuyer@1: self:UnregisterEvent("GUILD_ROSTER_UPDATE") farmbuyer@1: self:SetScript("OnEvent", self.PLAYER_LOGOUT) -- keepin' it real^H^H^H^Hsmall and kludgey farmbuyer@1: self:RegisterEvent("PLAYER_LOGOUT") farmbuyer@1: self.GuildUpdate = nil farmbuyer@1: farmbuyer@2: if SV.logtext and #SV.logtext > 20000 then farmbuyer@6: self:Print(L["Your accumulated logfile has grown rather large; you should consider copying it out and clearing it."]) farmbuyer@2: end farmbuyer@2: farmbuyer@5: local guild = assert((GetGuildInfo("player")), "GetGuildInfo returns nil?") farmbuyer@5: local realm = assert(GetRealmName(), "GetRealmName returns nil?") farmbuyer@1: local members = SV.members farmbuyer@1: if members[realm] farmbuyer@1: and members[realm][guild] farmbuyer@1: and #(members[realm][guild]) > 0 farmbuyer@1: then farmbuyer@1: -- moved the normal case below farmbuyer@1: else farmbuyer@1: -- new user, or new guild, or any number of things farmbuyer@6: self:Print(L["GuildDelta initializing roster..."]) farmbuyer@1: members[realm] = members[realm] or {} farmbuyer@1: members[realm][guild] = self:current_guild_info(current_n) farmbuyer@2: return self:cleanup() farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- table.insert with notes if available farmbuyer@3: -- concatentation of string-only args faster than string.format of same farmbuyer@1: local function tins (t, x) farmbuyer@1: local s = x.name farmbuyer@1: if x.onote and (x.onote ~= "") then farmbuyer@6: s = s .. "(" .. L["Oabbrev"] .. ": " .. x.onote .. ")" farmbuyer@1: end farmbuyer@1: if x.pnote and (x.pnote ~= "") then farmbuyer@1: s = s .. "(" .. x.pnote .. ")" farmbuyer@1: end farmbuyer@1: tinsert(t, s) farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- build the current list farmbuyer@1: local previous, current = members[realm][guild], farmbuyer@1: self:current_guild_info(current_n) farmbuyer@1: local previous_n = #previous farmbuyer@1: farmbuyer@1: -- walk both and do equivalence comparison farmbuyer@1: local joined, left, rank, level, notes = {}, {}, {}, {}, {} farmbuyer@1: local p, c = 1, 1 farmbuyer@1: while p <= previous_n and c <= current_n do farmbuyer@1: local P, C = previous[p], current[c] farmbuyer@1: farmbuyer@1: if P.name == C.name then farmbuyer@1: -- normal case farmbuyer@1: p = p + 1 farmbuyer@1: c = c + 1 farmbuyer@1: -- but can now compare details farmbuyer@1: if C.rank and P.rank and (P.rank ~= C.rank) then farmbuyer@1: tinsert(rank, {C.name, P.rank.." --> "..C.rank}) farmbuyer@1: end farmbuyer@1: if C.level and P.level and (P.level ~= C.level) then farmbuyer@1: tinsert(level, {C.name, P.level.." --> "..C.level}) farmbuyer@1: end farmbuyer@1: if C.pnote and (P.pnote ~= C.pnote) then farmbuyer@1: tinsert(notes, {C.name, C.pnote}) farmbuyer@1: end farmbuyer@1: if C.onote and (P.onote ~= C.onote) then farmbuyer@6: tinsert(notes, {C.name, "["..L["Oabbrev"].."]: "..C.onote}) farmbuyer@1: end farmbuyer@1: farmbuyer@1: elseif P.name < C.name then farmbuyer@1: -- entry at index p not at c -> somebody has left farmbuyer@1: tins (left, P) farmbuyer@1: p = p + 1 farmbuyer@1: farmbuyer@1: else farmbuyer@1: -- entry at index c not at p -> somebody has joined farmbuyer@1: tins (joined, C) farmbuyer@1: c = c + 1 farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- leftovers farmbuyer@1: for i = p, previous_n do farmbuyer@1: tins (left, previous[i]) farmbuyer@1: end farmbuyer@1: for i = c, current_n do farmbuyer@1: tins (joined, current[i]) farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- show results farmbuyer@1: if SV.logging then self.logquay = {} end farmbuyer@3: local m, changes farmbuyer@1: if #left > 0 then farmbuyer@3: changes = true farmbuyer@6: m = L["LEFT"] .. table.concat(left, ", ") farmbuyer@1: cprt(m) farmbuyer@1: end farmbuyer@1: farmbuyer@1: if #joined > 0 then farmbuyer@3: changes = true farmbuyer@6: m = L["JOINED"] .. table.concat(joined, ", ") farmbuyer@1: cprt(m) farmbuyer@1: end farmbuyer@1: farmbuyer@1: if #rank > 0 then farmbuyer@3: changes = true farmbuyer@6: cprt(L["RANK"]) farmbuyer@1: for i = 1, #rank do farmbuyer@1: cprt(rank[i][1]..': '..rank[i][2]) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: if #level > 0 then farmbuyer@3: changes = true farmbuyer@6: cprt(L["LEVEL"]) farmbuyer@1: for i = 1, #level do farmbuyer@1: cprt(level[i][1]..': '..level[i][2]) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: if #notes > 0 then farmbuyer@3: changes = true farmbuyer@6: cprt(L["NOTES"]) farmbuyer@1: for i = 1, #notes do farmbuyer@1: cprt(notes[i][1]..': "'..notes[i][2]..'"') farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: if SV.logging then self:FinishLog(guild,realm) end farmbuyer@6: if SV.notify_nochange and (not changes) then cprt(L["NOCHANGE"]) end farmbuyer@1: members[realm][guild] = current farmbuyer@9: SVc = current farmbuyer@2: self:cleanup() farmbuyer@1: end farmbuyer@1: farmbuyer@1: farmbuyer@1: function addon:MakeFieldList() farmbuyer@1: if not fieldlist then farmbuyer@1: fieldlist = {} farmbuyer@1: for name in pairs(SV.fields) do farmbuyer@6: fieldlist[name] = L["FIELD_"..name] farmbuyer@1: end farmbuyer@1: end farmbuyer@1: return fieldlist farmbuyer@1: end farmbuyer@1: farmbuyer@1: function addon:MakeGuildList() farmbuyer@1: local list = {} farmbuyer@1: local K farmbuyer@1: for rname,rdata in pairs(SV.members) do farmbuyer@1: for g in pairs(rdata) do farmbuyer@1: K = ("<%s> - %s"):format(g,rname) farmbuyer@1: list[K] = K farmbuyer@1: end farmbuyer@1: end farmbuyer@1: return list farmbuyer@1: end farmbuyer@1: farmbuyer@1: function addon:AddLogNote (txt) farmbuyer@1: tinsert(self.logquay,txt) farmbuyer@1: end farmbuyer@1: farmbuyer@1: function addon:FinishLog(g,r) farmbuyer@1: if #self.logquay > 0 then farmbuyer@1: Calendar_LoadUI() farmbuyer@1: local _,M,D,Y = CalendarGetDate() farmbuyer@1: local h,m = GetGameTime() farmbuyer@1: local timestamp = ("%.4d/%.2d/%.2d %.2d:%.2d <%s> - %s\n"):format(Y,M,D,h,m,g,r) farmbuyer@1: SV.logtext = timestamp farmbuyer@1: .. table.concat(self.logquay, '\n') farmbuyer@1: .. (SV.logtext and ('\n\n'..SV.logtext) or '') farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- vim:noet