annotate Modules/Alerts.lua @ 184:679d3664849d

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