view Core.lua @ 49:9ff6a3b02332 ticket7

I have changed my mind, price distribution will always be based on the AH price, unless none is available, then all items have the same weight which is what was being done before.
author Asa Ayers <Asa.Ayers@Gmail.com>
date Wed, 21 Jul 2010 01:00:14 -0700
parents a66f6fc57cfb
children 234896be4087
line wrap: on
line source
local addonName, addonTable = ...; 
_G[addonName] = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceEvent-3.0", "AceBucket-3.0")
local addon = _G[addonName]
addonTable.ItemAuditor = addon

local WHITE		= "|cFFFFFFFF"
local RED		= "|cFFFF0000"
local GREEN		= "|cFF00FF00"
local YELLOW	= "|cFFFFFF00"
local ORANGE	= "|cFFFF7F00"
local TEAL		= "|cFF00FF9A"
local GOLD		= "|cFFFFD700"

function addon:OnInitialize()
	local DB_defaults = {
		char = {
			ah = 1,
			use_quick_auctions = false,
			crafting_threshold = 1,
			auction_threshold = 0.15,
		},
		profile = {
			messages = {
				cost_updates = true,
				queue_skip = false,
			},
			addon_enabled = true,
			-- This is for development, so I have no plans to turn it into an option.
			show_debug_frame_on_startup = false,
		},
		factionrealm = {
			item_account = {},
			items = {},
			outbound_cod = {},
		},
	}
	self.db = LibStub("AceDB-3.0"):New("ItemAuditorDB", DB_defaults, true)
	addonTable.db= self.db
	self.items = self.db.factionrealm.items
	
	self:RegisterOptions()
	ItemAuditor:RegisterFrame(ItemAuditor_DebugFrame)
	
	-- /run ItemAuditor.db.profile.show_debug_frame_on_startup = true
	if self.db.profile.show_debug_frame_on_startup then
		ItemAuditor_DebugFrame:Show()
		self:CreateFrames()
	end
end

local registeredEvents = {}
local originalRegisterEvent = addon.RegisterEvent 
function addon:RegisterEvent(event, callback, arg)
	registeredEvents[event] = true
	if arg ~= nil then
		return originalRegisterEvent(self, event, callback, arg)
	elseif callback ~= nil then
		return originalRegisterEvent(self, event, callback)
	else
		return originalRegisterEvent(self, event)
	end
end

local originalUnregisterEvent = addon.UnregisterEvent
function addon:UnregisterEvent(event)
	registeredEvents[event] = nil
        return originalUnregisterEvent(self, event)
end

function addon:UnregisterAllEvents()
	for event in pairs(registeredEvents) do
		self:UnregisterEvent(event)
	end
end

local registeredFrames = {}
function addon:RegisterFrame(frame)
	tinsert(registeredFrames, frame)
end

function addon:HideAllFrames()
	for key, frame in pairs(registeredFrames) do
		if frame then
			frame:Hide()
		end
	end
end

function addon:ConvertItems()
	for itemName, value in pairs(self.db.factionrealm.item_account) do
		local itemID = self:GetItemID(itemName)
		if itemID ~= nil then
			self:GetItem('item:' .. itemID)
		end
		if value == 0 then
			self.db.factionrealm.item_account[itemName] = nil
		end
	end
	
	for link, data in pairs(self.db.factionrealm.items) do
		if self:GetItem(link).count == 0 or self:GetItem(link).invested == 0 then
			self:RemoveItem(link)
		end
	end
	
	self:RefreshQAGroups()
end

local printPrefix = "|cFFA3CEFFItemAuditor|r: "
function addon:Print(message, ...)
	message = format(message, ...)
	DEFAULT_CHAT_FRAME:AddMessage( printPrefix .. tostring(message))
	self:Log(message)
end

function addon:GetCurrentInventory()
	local i = {}
	local bagID
	local slotID
	
	for bagID = 0, NUM_BAG_SLOTS do
		bagSize=GetContainerNumSlots(bagID)
		for slotID = 0, bagSize do
			local link= GetContainerItemLink(bagID, slotID);
			link = link and self:GetSafeLink(link)

			if link ~= nil and i[link] == nil then
				i[link] = GetItemCount(link);
			end
		end

	end
	return {items = i, money = GetMoney()}
end

function addon:GetInventoryDiff(pastInventory, current)
	if current == nil then
		current = self:GetCurrentInventory()
	end
	local diff = {}

	for link, count in pairs(current.items) do
		if pastInventory.items[link] == nil then
			diff[link] = count
			self:Debug("1 diff[" .. link .. "]=" .. diff[link])
		elseif count - pastInventory.items[link] ~= 0 then
			diff[link] = count - pastInventory.items[link]
			self:Debug("2 diff[" .. link .. "]=" .. diff[link])        
		end    
	end

	for link, count in pairs(pastInventory.items) do
		if current.items[link] == nil then
			diff[link] = -count
			self:Debug("3 diff[" .. link .. "]=" .. diff[link])                
		elseif current.items[link] - count ~= 0 then
			diff[link] = current.items[link] - pastInventory.items[link]
			self:Debug("4 diff[" .. link .. "]=" .. diff[link])        
		end
	end

	local moneyDiff = current.money - pastInventory.money
	if abs(moneyDiff) > 0 then
		self:Debug("moneyDiff: " .. moneyDiff)
	end

	return {items = diff, money = moneyDiff}
end

local inboundCOD = {}
local skipMail = {}
function addon:ScanMail()
	local results = {}
	local CODPaymentRegex = gsub(COD_PAYMENT, "%%s", "(.*)")
	
	for mailIndex = 1, GetInboxNumItems() or 0 do
		local sender, msgSubject, msgMoney, msgCOD, daysLeft, msgItem, _, _, msgText, _, isGM = select(3, GetInboxHeaderInfo(mailIndex))
		local mailType = self:GetMailType(msgSubject)
		
		local mailSignature = msgSubject .. '-' .. msgMoney .. '-' .. msgCOD .. '-' .. daysLeft
		
		results[mailType] = (results[mailType] or {})
		
		if skipMail[mailSignature] ~= nil then
			-- do nothing
		elseif mailType == "NonAHMail" and msgCOD > 0 then
			mailType = 'COD'
			results[mailType] = (results[mailType] or {})
			
			local itemTypes = {}
			for itemIndex = 1, ATTACHMENTS_MAX_RECEIVE do
				local itemName, _, count, _, _= GetInboxItem(mailIndex, itemIndex)
				if itemName ~= nil then
					itemTypes[itemName] = (itemTypes[itemName] or 0) + count
				end
			end
			
			if self:tcount(itemTypes) == 1 then
				for itemName, count in pairs(itemTypes) do
					results[mailType][itemName] = (results[mailType][itemName] or {total=0,count=0})
					results[mailType][itemName].total = results[mailType][itemName].total + msgCOD
					
					if inboundCOD[mailSignature] == nil then
						results[mailType][itemName].count = results[mailType][itemName].count + count
						inboundCOD[mailSignature] = (inboundCOD[mailSignature] or 0) + count
					else
						results[mailType][itemName].count = inboundCOD[mailSignature]
					end
					
					
				end
			else
				self:Debug("Don't know what to do with more than one item type on COD mail.")
			end
		elseif mailType == "CODPayment" then	
			-- /dump ItemAuditor.db.factionrealm.outbound_cod
			self:Debug(msgSubject)
			self:Debug(CODPaymentRegex)
			local outboundSubject = select(3, msgSubject:find(CODPaymentRegex))
			local trackID
			if outboundSubject ~= nil then
				self:Debug(outboundSubject)
				trackID = select(3, outboundSubject:find('[[]IA: (%d*)[]]'))
				
				if trackID ~= nil then
					trackID = tonumber(trackID)
					self:Debug('COD ID: %s', trackID)
					local cod = self.db.factionrealm.outbound_cod[trackID]
					if cod == nil then
						skipMail[mailSignature] = true
						self:Print("WARNING: {%s} has an invalid ItemAuditor tracking number.", msgSubject)
					else
						itemName = trackID .. "|" .. cod['link']
						
						
						results[mailType][itemName] = (results[mailType][itemName] or {total=0,count=0})
						results[mailType][itemName].total = results[mailType][itemName].total - msgMoney
						results[mailType][itemName].count = results[mailType][itemName].count - cod.count
					end
				end
			end
			
			if trackID == nil then
				skipMail[mailSignature] = true
				self:Print("WARNING: {%s} is a COD payment but doesn't have an ItemAuditor tracking number.", msgSubject)
			end
			
		elseif mailType == "AHSuccess" then
			local invoiceType, itemName, playerName, bid, buyout, deposit, consignment = GetInboxInvoiceInfo(mailIndex);
			results[mailType][itemName] = (results[mailType][itemName] or {total=0,count=0})
			results[mailType][itemName].total = results[mailType][itemName].total - deposit - buyout + consignment
			

		elseif mailType == "AHWon" then
			local invoiceType, itemName, playerName, bid, buyout, deposit, consignment = GetInboxInvoiceInfo(mailIndex);
			results[mailType][itemName] = (results[mailType][itemName] or {total=0,count=0})
			results[mailType][itemName].total = results[mailType][itemName].total + bid
			
			local count = select(3, GetInboxItem(1,1))
			results[mailType][itemName].count = results[mailType][itemName].count + count
		elseif mailType == "AHExpired" or mailType == "AHCancelled" or mailType == "AHOutbid" then
			-- These should be handled when you pay the deposit at the AH
		else
			-- self:Debug("Unhandled mail type: " .. mailType)
			-- self:Debug(msgSubject)
		end

	end
	
	for mailType, collection in pairs(results) do
		for item, data in pairs(collection) do
			self:Debug(format("|cFF00FF00MailScan|r: %s - %s - %s x %s", mailType, item, data.total, data.count))
		end
	end
	
	return results   
end

function addon:GetItem(link, viewOnly)
	if viewOnly == nil then
		viewOnly = false
	end
	
	local itemName = nil
	if self:GetSafeLink(link) == nil then
		itemName = link
	else
		link = self:GetSafeLink(link)
		itemName = GetItemInfo(link)
	end
	
	
	if self.db.factionrealm.item_account[itemName] ~= nil then
		self.items[link] = {
			count = Altoholic:GetItemCount(self:GetIDFromLink(link)),
			invested = abs(self.db.factionrealm.item_account[itemName] or 0),
		}
		self.db.factionrealm.item_account[itemName] = nil
	end
	
	if viewOnly == false and self.items[link] == nil then
		
		self.items[link] = {
			count =  Altoholic:GetItemCount(self:GetIDFromLink(link)),
			invested = abs(self.db.factionrealm.item_account[itemName] or 0),
		}
		
	end
	
	if self.items[link] ~= nil then
		self.items[link].count =  Altoholic:GetItemCount(self:GetIDFromLink(link))
		
		if self.items[link].invested == nil then
			self.items[link].invested = 0
		end
	end
	
	if viewOnly == true and self.items[link] == nil then
		return {count = 0, invested = 0}
	elseif viewOnly == true then
		
		return {count = self.items[link].count, invested = self.items[link].invested}
	end
	
	
	
	return self.items[link]
end

function addon:RemoveItem(link)
	self.db.factionrealm.item_account[link] = nil
	link = self:GetSafeLink(link)
	if link ~= nil then
		local item = addon:GetItem(link)
		item.invested = 0
	else
		self:Debug('Failed to convert link' .. tostring(link))
	end
end

function addon:SaveValue(link, value, countChange)
	self:Debug("SaveValue(%s, %s, %s)", tostring(link), value, (countChange or 'default'))
	countChange = countChange or 0
	local item = nil
	local realLink = self:GetSafeLink(link)
	local itemName = nil
	if realLink == nil then
		itemName = link
		self:Debug('SaveValue: GetSafeLink failed, falling back to storing by name: ' .. tostring(itemName))
		self.db.factionrealm.item_account[itemName] = (self.db.factionrealm.item_account[itemName] or 0) + value
		item = {invested = self.db.factionrealm.item_account[itemName], count = 1}
	else
		
		item = self:GetItem(realLink)
		item.invested = item.invested + value
		itemName = GetItemInfo(realLink)
	end
	
	if value > 0 and countChange > 0 and item.invested == value and item.count ~= countChange then
		local costPerItem = value / countChange
		value = costPerItem * item.count
		item.invested = value
		self:Print("You already owned %s %s with an unknown price, so they have also been updated to %s each", (item.count - countChange), itemName, self:FormatMoney(costPerItem))
	end
	
	if abs(value) > 0 then
		if  item.invested < 0 then
			if self.db.profile.messages.cost_updates then
				self:Print(format("Updated price of %s from %s to %s. %sYou just made a profit of %s.", itemName, self:FormatMoney(item.invested - value), self:FormatMoney(0), GREEN, self:FormatMoney(abs(item.invested))))
			end
			self:RemoveItem(link)
		-- This doesn't work when you mail the only copy of an item you have to another character.
		--[[
		elseif item.count == 0 and realLink and Altoholic:GetItemCount(self:GetIDFromLink(realLink)) then 
			self:Print("You ran out of " .. itemName .. " and never recovered " .. self:FormatMoney(item.invested))
			self:RemoveItem(link)
		]]
		else
			if self.db.profile.messages.cost_updates then
				self:Print(format("Updated price of %s from %s to %s. (total change:%s)", itemName, self:FormatMoney(item.invested - value), self:FormatMoney(item.invested), self:FormatMoney(value)))
			end
		end
	end
	
	if realLink ~= nil then
		addon:UpdateQAThreshold(realLink)
	end
	UpdateInvestedData()
end


function addon:WatchBags()
	if self.watch_handle == nil then
		addon:UpdateCurrentInventory()
		self.watch_handle = self:RegisterBucketEvent({"BAG_UPDATE", "PLAYER_MONEY"}, 0.3, "UpdateAudit")
	end
end

function addon:UnwatchBags()
	if self.watch_handle ~= nil then
		self:UnregisterBucket(self.watch_handle)
		self.watch_handle = nil
	end
end


function addon:GetSafeLink(link)
	local newLink = nil

	if link and link == string.match(link, '.-:[-0-9]+[:0-9]*') then
		newLink = link
	elseif link then
		newLink = link and string.match(link, "|H(.-):([-0-9]+):([0-9]+)|h")
	end
	if newLink == nil then
		local itemID = self:GetItemID(link)
		if itemID ~= nil then
			_, newLink = GetItemInfo(itemID)
			return self:GetSafeLink(newLink)
		end
	end
	return newLink and string.gsub(newLink, ":0:0:0:0:0:0", "")
end

function addon:GetIDFromLink(link)
	local _, _, _, _, Id = string.find(link, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?")
	return tonumber(Id)
end

function addon:GetItemCost(link, countModifier)
	local item = self:GetItem(link, true)

	if item.invested > 0 then
		local count = item.count
		
		if countModifier ~= nil then
			count = count - countModifier
		end
		if count > 0 then 
			return ceil(item.invested), ceil(item.invested/count), count
		end
		
	end
	return 0, 0, Altoholic:GetItemCount(ItemAuditor:GetIDFromLink(link))
end