comparison Modules/Alerts.lua @ 176:26c750a10b14

Renamed Inventorium debug channel to IMDebug (so it?s easier to recognize only IM changes, not from other addons), write /im d to register this new channel. Implemented stock alerts. Added ?don?t alert at characters? option which allows you to track groups at characters without being bothered about low stock. You can change the speed of the stock alert at the extra config tab.
author Zerotorescue
date Sun, 30 Jan 2011 15:39:18 +0100
parents
children 679d3664849d
comparison
equal deleted inserted replaced
175:7aa0850952ef 176:26c750a10b14
1 local addon = select(2, ...);
2 local mod = addon:NewModule("Alerts", "AceEvent-3.0", "AceTimer-3.0");
3
4 local queue, cache = {}, {};
5
6 function mod:OnEnable()
7 addon:Debug("Alerts:OnEnable");
8
9 -- Register our alert slash command
10 -- /im alert
11 addon:RegisterSlash(function(this)
12 mod:Scan(true);
13 end, { "a", "alert" }, "|Hfunction:InventoriumCommandHandler:alert|h|cff00fff7/im alert|r|h (or /im a) - Rescan the items within all tracked groups and show item alerts for those items missing.");
14
15 self:RegisterEvent("PLAYER_LOGIN", function()
16 mod:Scan(false);
17 end);
18
19 --[[if addon.db.profile.defaults.scanInterval["00Login"] then
20 self:RegisterEvent("PLAYER_LOGIN", "Scan");
21 end
22
23 if addon.db.profile.defaults.scanInterval["01Repeat5"] then
24 self:ScheduleTimer("Scan", 5 * 60);
25 elseif addon.db.profile.defaults.scanInterval["01Repeat10"] then
26 self:ScheduleTimer("Scan", 10 * 60);
27 elseif addon.db.profile.defaults.scanInterval["01Repeat15"] then
28 self:ScheduleTimer("Scan", 15 * 60);
29 elseif addon.db.profile.defaults.scanInterval["01Repeat30"] then
30 self:ScheduleTimer("Scan", 30 * 60);
31 elseif addon.db.profile.defaults.scanInterval["01Repeat60"] then
32 self:ScheduleTimer("Scan", 60 * 60);
33 elseif addon.db.profile.defaults.scanInterval["01Repeat120"] then
34 self:ScheduleTimer("Scan", 120 * 60);
35 end]]
36 end
37
38 local scanTypes = {
39 Local = "local",
40 Global = "global",
41 };
42
43 function mod:Scan(verbal)
44 addon:Debug("Alerts:Scan");
45
46 if verbal then
47 addon:Print("Scanning items, the results will be presented to you in a moment. Please be patient.");
48 end
49
50 local playerName = UnitName("player");
51
52 table.wipe(queue);
53 table.wipe(cache);
54
55 -- Go through all groups
56 for groupName, values in pairs(addon.db.profile.groups) do
57 -- Settings
58 local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters");
59 local dontAlertAt = addon:GetOptionByKey(groupName, "dontAlertAtCharacters");
60
61 local alertBelowLocalMinimum = addon:GetOptionByKey(groupName, "alertBelowLocalMinimum");
62 local minLocalStock = alertBelowLocalMinimum and addon:GetOptionByKey(groupName, "minLocalStock");
63
64 local alertBelowGlobalMinimum = addon:GetOptionByKey(groupName, "alertBelowGlobalMinimum");
65 local minGlobalStock = alertBelowGlobalMinimum and addon:GetOptionByKey(groupName, "minGlobalStock");
66
67 local isTracked = (trackAt and trackAt[playerName] and (not dontAlertAt or not dontAlertAt[playerName])); -- Is this character interested in this data and does it want alerts?
68
69 if values.items and isTracked and (alertBelowLocalMinimum or alertBelowGlobalMinimum) then
70 addon:Debug("Scanning |cff00ff00%s|r", groupName);
71
72 local groupSettings = {
73 ["name"] = groupName,
74 ["minLocalStock"] = minLocalStock,
75 ["minGlobalStock"] = minGlobalStock,
76 };
77
78 for itemId, _ in pairs(values.items) do
79 if alertBelowLocalMinimum then
80 self:QeueueScan(groupSettings, itemId, scanTypes.Local);
81 end
82
83 if alertBelowGlobalMinimum then
84 self:QeueueScan(groupSettings, itemId, scanTypes.Global);
85 end
86 end
87 end
88 end
89
90 if self:HasQueue() then
91 addon:Debug("Alerts:HasQueue, processing");
92 --addon:Debug(queue);
93
94 self:ProcessScan(verbal);
95 end
96 end
97
98 function mod:QeueueScan(groupSettings, itemId, scanType)
99 table.insert(queue, {
100 ["group"] = groupSettings,
101 ["itemId"] = itemId,
102 ["type"] = scanType,
103 });
104 end
105
106 function mod:HasQueue()
107 return (#queue > 0);
108 end
109
110 function mod:ProcessScan(verbal)
111 local thisItem = table.remove(queue, 1);
112
113 if not thisItem then
114 self:ScanFinished();
115 return;
116 end
117
118 if thisItem.type == scanTypes.Global then
119 local globalCount = addon:GetItemCount(thisItem.itemId, thisItem.group.name);
120
121 if not cache[thisItem.itemId] then
122 cache[thisItem.itemId] = {
123 ["itemId"] = thisItem.itemId, -- needed later for displaying
124 ["group"] = thisItem.group,
125 ["globalCount"] = globalCount,
126 };
127 else
128 cache[thisItem.itemId].globalCount = globalCount;
129 end
130 elseif thisItem.type == scanTypes.Local then
131 local localCount = addon:GetLocalItemCount(thisItem.itemId, thisItem.group.name);
132
133 if not cache[thisItem.itemId] then
134 cache[thisItem.itemId] = {
135 ["itemId"] = thisItem.itemId, -- needed later for displaying
136 ["group"] = thisItem.group,
137 ["localCount"] = localCount,
138 };
139 else
140 cache[thisItem.itemId].globalCount = localCount;
141 end
142 end
143
144 local nextScanDelay = (tonumber(addon.db.profile.defaults.scanInterval) or .1);
145
146 if nextScanDelay == 0 then
147 mod:ProcessScan(verbal);
148 else
149 self:ScheduleTimer(function()
150 mod:ProcessScan(verbal);
151 end, nextScanDelay); -- scan next item in nextScanDelay seconds
152 end
153 end
154
155 local function OnProceed()
156 InventoriumCommandHandler("summary");
157
158 if InventoriumItemMover then
159 InventoriumItemMover:Hide();
160 end
161 end
162
163 local function OnCancel()
164 if InventoriumItemMover then
165 InventoriumItemMover:Hide();
166 end
167 end
168
169 local function UseScanST()
170 if not InventoriumItemMover then
171 addon:CreateMoverFrame();
172 end
173
174 local frame = InventoriumItemMover; -- both for speed as code-consistency
175
176 -- Scrolling table with a list of items to be moved
177 local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size
178 local headers = {
179 {
180 ["name"] = "Item",
181 ["width"] = (scrollTableWidth * .6),
182 ["defaultsort"] = "asc",
183 ["comparesort"] = function(this, aRow, bRow, column)
184 local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId);
185 local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId);
186 local template = "%d%s";
187 aName = template:format((10 - (aRarity or 10)), (aName or ""):lower());
188 bName = template:format((10 - (bRarity or 10)), (bName or ""):lower());
189
190 if this.cols[column].sort == "dsc" then
191 return aName > bName;
192 else
193 return aName < bName;
194 end
195 end,
196 ["sort"] = "asc", -- when the data is set, use this column so sort the default data
197 ["tooltipTitle"] = "Item",
198 ["tooltip"] = "Click to sort the list by item quality then item name.",
199 },
200 {
201 ["name"] = "Local",
202 ["width"] = (scrollTableWidth * .2),
203 ["align"] = "RIGHT",
204 ["defaultsort"] = "dsc",
205 ["sortnext"] = 1,
206 ["comparesort"] = function(this, aRow, bRow, column)
207 local aAvailablePercent = (this:GetRow(aRow).rowData.localCount / this:GetRow(aRow).rowData.group.minLocalStock);
208 local bAvailablePercent = (this:GetRow(bRow).rowData.localCount / this:GetRow(bRow).rowData.group.minLocalStock);
209
210 if this.cols[column].sort == "dsc" then
211 return aAvailablePercent > bAvailablePercent;
212 else
213 return aAvailablePercent < bAvailablePercent;
214 end
215 end,
216 ["tooltipTitle"] = "Local Stock",
217 ["tooltip"] = "Click to sort the list by the local stock percentage.",
218 },
219 {
220 ["name"] = "Global",
221 ["width"] = (scrollTableWidth * .2),
222 ["align"] = "RIGHT",
223 ["defaultsort"] = "dsc",
224 ["sortnext"] = 1,
225 ["comparesort"] = function(this, aRow, bRow, column)
226 local aAvailablePercent = (this:GetRow(aRow).rowData.globalCount / this:GetRow(aRow).rowData.group.minGlobalStock);
227 local bAvailablePercent = (this:GetRow(bRow).rowData.globalCount / this:GetRow(bRow).rowData.group.minGlobalStock);
228
229 if this.cols[column].sort == "dsc" then
230 return aAvailablePercent > bAvailablePercent;
231 else
232 return aAvailablePercent < bAvailablePercent;
233 end
234 end,
235 ["tooltipTitle"] = "Global Stock",
236 ["tooltip"] = "Click to sort the list by the global stock percentage.",
237 },
238 };
239
240 local proceedButton = {
241 text = "Show in summary",
242 tooltipTitle = "Show in Summary",
243 tooltip = "Show the summary giving a more detailed list of missing items.",
244 onClick = OnProceed,
245 };
246 local cancelButton = {
247 text = "Cancel",
248 tooltipTitle = "Cancel",
249 tooltip = "Close the window.",
250 onClick = OnCancel,
251 };
252
253 addon:SetMoverFrameSettings("Inventorium Stock Alert", "You have elected to receive an alert when the following items are under your minimum stock requirement:", proceedButton, cancelButton, headers);
254 end
255
256 function mod:ScanFinished()
257 table.wipe(queue);
258
259 --addon:Debug(cache);
260
261 -- This table is never copied, just referenced. It is the same for every row.
262 local missingRow = {
263 {
264 ["value"] = function(data, cols, realrow, column, table)
265 return IdToItemLink(data[realrow].rowData.itemId);
266 end,
267 }, -- item
268 {
269 ["value"] = function(data, cols, realrow, column, table)
270 return addon:DisplayItemCount(data[realrow].rowData.localCount or -4, data[realrow].rowData.group.minLocalStock);
271 end,
272 }, -- local
273 {
274 ["value"] = function(data, cols, realrow, column, table)
275 return addon:DisplayItemCount(data[realrow].rowData.globalCount or -4, data[realrow].rowData.group.minGlobalStock);
276 end,
277 }, -- global
278 };
279
280 -- Store the list with rows in this
281 local missingList = {};
282
283 for itemId, info in pairs(cache) do
284 if (info.globalCount and info.globalCount < info.group.minGlobalStock) or (info.localCount and info.localCount < info.group.minLocalStock) then
285 -- Not enough global or not enough local
286
287 tinsert(missingList, {
288 ["rowData"] = info, -- this is not a key usually found in a row item and ignored by the library
289 ["cols"] = missingRow,
290 });
291 end
292 end
293
294 table.wipe(cache); -- no longer needed, all missing items are now stored in the missingList
295
296 if #missingList > 0 then
297 UseScanST();
298
299 addon:SetMoverFrameData(missingList);
300
301 if verbal then
302 addon:Print("Presenting the data...");
303 end
304 elseif verbal then
305 addon:Print("No items that you elected to be alerted about are below the selected stock thresholds.");
306 end
307 end