view Modules/Alerts.lua @ 202:15f22a466596

Cleaning up.
author Zerotorescue
date Sat, 05 Feb 2011 17:36:08 +0100
parents 5cee31b1418a
children 4f5e114fe15f
line wrap: on
line source
local addon = select(2, ...);
local mod = addon:NewModule("Alerts", "AceTimer-3.0");

local queue, cache = {}, {};

function mod:OnEnable()
	addon:Debug("Alerts:OnEnable");
	
	-- Register our alert slash command
	-- /im alert
	addon:RegisterSlash(function(this)
		mod:Scan(true);
	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.");
	
	mod:Scan(false);
end

local scanTypes = {
	Local = "local",
	Global = "global",
};

function mod:Scan(verbal)
	addon:Debug("Alerts:Scan");
	
	if verbal then
		addon:Print("Scanning items, the results will be presented to you in a moment. Please be patient.");
	end
	
	local playerName = UnitName("player");
	
	table.wipe(queue);
	table.wipe(cache);
	
	-- Go through all groups
	for groupName, values in pairs(addon.db.profile.groups) do
		-- Settings
		local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters");
		local dontAlertAt = addon:GetOptionByKey(groupName, "dontAlertAtCharacters");
		
		local alertBelowLocalMinimum = addon:GetOptionByKey(groupName, "alertBelowLocalMinimum");
		local minLocalStock = alertBelowLocalMinimum and addon:GetOptionByKey(groupName, "minLocalStock");
		
		local alertBelowGlobalMinimum = addon:GetOptionByKey(groupName, "alertBelowGlobalMinimum");
		local minGlobalStock = alertBelowGlobalMinimum and addon:GetOptionByKey(groupName, "minGlobalStock");
		
		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?
		
		if values.items and isTracked and (alertBelowLocalMinimum or alertBelowGlobalMinimum) then
			addon:Debug("Scanning |cff00ff00%s|r", groupName);
			
			local groupSettings = {
				["name"] = groupName,
				["minLocalStock"] = minLocalStock,
				["minGlobalStock"] = minGlobalStock,
			};
			
			for itemId, _ in pairs(values.items) do
				if alertBelowLocalMinimum then
					self:QeueueScan(groupSettings, itemId, scanTypes.Local);
				end
				
				if alertBelowGlobalMinimum then
					self:QeueueScan(groupSettings, itemId, scanTypes.Global);
				end
			end
		end
	end
	
	if self:HasQueue() then
		addon:Debug("Alerts:HasQueue, processing");
		--addon:Debug(queue);
		
		self:ProcessScan(verbal);
	end
end

function mod:QeueueScan(groupSettings, itemId, scanType)
	table.insert(queue, {
		["group"] = groupSettings,
		["itemId"] = itemId,
		["type"] = scanType,
	});
end

function mod:HasQueue()
	return (#queue > 0);
end

function mod:ProcessScan(verbal)
	local nextScanDelay = (tonumber(addon.db.profile.defaults.scanInterval) or .1);
	local runs = (0.1 / nextScanDelay); -- 0.01 = 10, 0.05 = 2, 0.1 and smaller = 1
	runs = (runs < 1 and 1) or runs;
	runs = (nextScanDelay == 0 and 100) or runs;
	
	for no = 1, runs do
		-- Get the last item added to the queue
		local thisItem = table.remove(queue, 1);
		
		if not thisItem then
			-- If no item exists then we processed everything, show summary
			self:ScanFinished();
			return;
		end
		
		if thisItem.type == scanTypes.Global then
			-- Global scan
			local globalCount = addon:GetItemCount(thisItem.itemId, thisItem.group.name);
			
			if not cache[thisItem.itemId] then
				cache[thisItem.itemId] = {
					["itemId"] = thisItem.itemId, -- needed later for displaying
					["group"] = thisItem.group,
					["globalCount"] = globalCount,
				};
			else
				cache[thisItem.itemId].globalCount = globalCount;
			end
		elseif thisItem.type == scanTypes.Local then
			-- Local scan
			local localCount = addon:GetLocalItemCount(thisItem.itemId, thisItem.group.name);
			
			if not cache[thisItem.itemId] then
				cache[thisItem.itemId] = {
					["itemId"] = thisItem.itemId, -- needed later for displaying
					["group"] = thisItem.group,
					["localCount"] = localCount,
				};
			else
				cache[thisItem.itemId].globalCount = localCount;
			end
		end
	end
	
	self:ScheduleTimer(function()
		mod:ProcessScan(verbal);
	end, nextScanDelay); -- scan next item in nextScanDelay seconds
end

local function OnProceed()
	InventoriumCommandHandler("summary");
	
	if InventoriumItemMover then
		InventoriumItemMover:Hide();
	end
end

local function OnCancel()
	if InventoriumItemMover then
		InventoriumItemMover:Hide();
	end
end

local function UseScanST()
	if not InventoriumItemMover then
		addon:CreateMoverFrame();
	end
	
	local frame = InventoriumItemMover; -- both for speed as code-consistency
	
	-- Scrolling table with a list of items to be moved
	local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size
	local headers = {
		{
			["name"] = "Item",
			["width"] = (scrollTableWidth * .6),
			["defaultsort"] = "asc",
			["comparesort"] = function(this, aRow, bRow, column)
				local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId);
				local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId);
				local template = "%d%s";
				aName = template:format((10 - (aRarity or 10)), (aName or ""):lower());
				bName = template:format((10 - (bRarity or 10)), (bName or ""):lower());
				
				if this.cols[column].sort == "dsc" then
					return aName > bName;
				else
					return aName < bName;
				end
			end,
			["sort"] = "asc", -- when the data is set, use this column so sort the default data
			["tooltipTitle"] = "Item",
			["tooltip"] = "Click to sort the list by item quality then item name.",
		},
		{
			["name"] = "Local",
			["width"] = (scrollTableWidth * .2),
			["align"] = "RIGHT",
			["defaultsort"] = "dsc",
			["sortnext"] = 1,
			["comparesort"] = function(this, aRow, bRow, column)
				local aAvailablePercent = (this:GetRow(aRow).rowData.localCount / this:GetRow(aRow).rowData.group.minLocalStock);
				local bAvailablePercent = (this:GetRow(bRow).rowData.localCount / this:GetRow(bRow).rowData.group.minLocalStock);
				
				if this.cols[column].sort == "dsc" then
					return aAvailablePercent > bAvailablePercent;
				else
					return aAvailablePercent < bAvailablePercent;
				end
			end,
			["tooltipTitle"] = "Local Stock",
			["tooltip"] = "Click to sort the list by the local stock percentage.",
		},
		{
			["name"] = "Global",
			["width"] = (scrollTableWidth * .2),
			["align"] = "RIGHT",
			["defaultsort"] = "dsc",
			["sortnext"] = 1,
			["comparesort"] = function(this, aRow, bRow, column)
				local aAvailablePercent = (this:GetRow(aRow).rowData.globalCount / this:GetRow(aRow).rowData.group.minGlobalStock);
				local bAvailablePercent = (this:GetRow(bRow).rowData.globalCount / this:GetRow(bRow).rowData.group.minGlobalStock);
				
				if this.cols[column].sort == "dsc" then
					return aAvailablePercent > bAvailablePercent;
				else
					return aAvailablePercent < bAvailablePercent;
				end
			end,
			["tooltipTitle"] = "Global Stock",
			["tooltip"] = "Click to sort the list by the global stock percentage.",
		},
	};
	
	local proceedButton = {
		text = "Show in summary",
		tooltipTitle = "Show in Summary",
		tooltip = "Show the summary giving a more detailed list of missing items.",
		onClick = OnProceed,
	};
	local cancelButton = {
		text = "Cancel",
		tooltipTitle = "Cancel",
		tooltip = "Close the window.",
		onClick = OnCancel,
	};
	
	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);
end

function mod:ScanFinished()
	table.wipe(queue);
	
	--addon:Debug(cache);
	
	-- This table is never copied, just referenced. It is the same for every row.
	local missingRow = {
		{
			["value"] = function(data, cols, realrow, column, table)
				return IdToItemLink(data[realrow].rowData.itemId);
			end,
		}, -- item
		{
			["value"] = function(data, cols, realrow, column, table)
				return addon:DisplayItemCount(data[realrow].rowData.localCount or -2, data[realrow].rowData.group.minLocalStock);
			end,
		}, -- local
		{
			["value"] = function(data, cols, realrow, column, table)
				return addon:DisplayItemCount(data[realrow].rowData.globalCount or -2, data[realrow].rowData.group.minGlobalStock);
			end,
		}, -- global
	};
	
	-- Store the list with rows in this
	local missingList = {};
	
	for itemId, info in pairs(cache) do
		if (info.globalCount and info.globalCount < info.group.minGlobalStock) or (info.localCount and info.localCount < info.group.minLocalStock) then
			-- Not enough global or not enough local
			
			tinsert(missingList, {
				["rowData"] = info, -- this is not a key usually found in a row item and ignored by the library
				["cols"] = missingRow,
			});
		end
	end
	
	table.wipe(cache); -- no longer needed, all missing items are now stored in the missingList
	
	if #missingList > 0 then
		UseScanST();
		
		addon:SetMoverFrameData(missingList);
		
		if verbal then
			addon:Print("Presenting the data...");
		end
	elseif verbal then
		addon:Print("No items that you elected to be alerted about are below the selected stock thresholds.");
	end
end