view Modules/Alerts.lua @ 179:a44a4147b34f

No need to keep the loading times debug info.
author Zerotorescue
date Sun, 30 Jan 2011 15:40:53 +0100
parents 26c750a10b14
children 679d3664849d
line wrap: on
line source
local addon = select(2, ...);
local mod = addon:NewModule("Alerts", "AceEvent-3.0", "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.");
	
	self:RegisterEvent("PLAYER_LOGIN", function()
		mod:Scan(false);
	end);
	
	--[[if addon.db.profile.defaults.scanInterval["00Login"] then
		self:RegisterEvent("PLAYER_LOGIN", "Scan");
	end
	
	if addon.db.profile.defaults.scanInterval["01Repeat5"] then
		self:ScheduleTimer("Scan", 5 * 60);
	elseif addon.db.profile.defaults.scanInterval["01Repeat10"] then
		self:ScheduleTimer("Scan", 10 * 60);
	elseif addon.db.profile.defaults.scanInterval["01Repeat15"] then
		self:ScheduleTimer("Scan", 15 * 60);
	elseif addon.db.profile.defaults.scanInterval["01Repeat30"] then
		self:ScheduleTimer("Scan", 30 * 60);
	elseif addon.db.profile.defaults.scanInterval["01Repeat60"] then
		self:ScheduleTimer("Scan", 60 * 60);
	elseif addon.db.profile.defaults.scanInterval["01Repeat120"] then
		self:ScheduleTimer("Scan", 120 * 60);
	end]]
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 thisItem = table.remove(queue, 1);
	
	if not thisItem then
		self:ScanFinished();
		return;
	end
	
	if thisItem.type == scanTypes.Global then
		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 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
	
	local nextScanDelay = (tonumber(addon.db.profile.defaults.scanInterval) or .1);
	
	if nextScanDelay == 0 then
		mod:ProcessScan(verbal);
	else
		self:ScheduleTimer(function()
			mod:ProcessScan(verbal);
		end, nextScanDelay); -- scan next item in nextScanDelay seconds
	end
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 -4, data[realrow].rowData.group.minLocalStock);
			end,
		}, -- local
		{
			["value"] = function(data, cols, realrow, column, table)
				return addon:DisplayItemCount(data[realrow].rowData.globalCount or -4, 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