annotate Modules/Events.lua @ 82:e9f7bc9199ca release 2010-08-05

Fixed Bug 23 - When you purchase multiple stacks of the same item and it is one you have not invested in yet, ItemAuditor mistakenly counted items you have not yet pulled from the mail as items you already owned. This resulted in those items being counted twice.
author Asa Ayers <Asa.Ayers@Gmail.com>
date Thu, 05 Aug 2010 22:20:44 -0700
parents 64166ba5209a
children e2dab8e34b32
rev   line source
Asa@63 1 local ItemAuditor = select(2, ...)
Asa@63 2 local Events = ItemAuditor:NewModule("Events", "AceEvent-3.0")
Asa@3 3
Asa@63 4 function ItemAuditor:OnEnable()
Asa@3 5 self:RegisterEvent("MAIL_SHOW")
Asa@4 6 self:RegisterEvent("UNIT_SPELLCAST_START")
Asa@81 7
Asa@81 8 self:RegisterEvent("BANKFRAME_OPENED", 'BankFrameChanged')
Asa@81 9 self:RegisterEvent("BANKFRAME_CLOSED", 'BankFrameChanged')
Asa@81 10
Asa@63 11 ItemAuditor:UpdateCurrentInventory()
Asa@3 12 self:WatchBags()
Asa@9 13
Asa@63 14 self:SetEnabled(nil, self.db.profile.ItemAuditor_enabled)
Asa@38 15 end
Asa@38 16
Asa@63 17 function ItemAuditor:OnDisable()
Asa@38 18 self:UnwatchBags()
Asa@38 19 self:UnregisterAllEvents()
Asa@63 20 ItemAuditor:HideAllFrames()
Asa@3 21 end
Asa@3 22
Asa@63 23 function ItemAuditor:MAIL_SHOW()
Asa@3 24 self:Debug("MAIL_SHOW")
Asa@39 25 self:UnwatchBags()
Asa@63 26 ItemAuditor:UpdateCurrentInventory()
Asa@3 27 self.lastMailScan = self:ScanMail()
Asa@7 28
Asa@3 29 self:UnregisterEvent("MAIL_SHOW")
Asa@3 30 self:RegisterEvent("MAIL_CLOSED")
Asa@3 31 self:RegisterEvent("MAIL_INBOX_UPDATE")
Asa@39 32
Asa@39 33 self:GenerateBlankOutbox()
Asa@39 34
Asa@39 35 self:RegisterEvent("MAIL_SUCCESS")
Asa@39 36 end
Asa@39 37
Asa@63 38 function ItemAuditor:GenerateBlankOutbox()
Asa@39 39 self.mailOutbox = {
Asa@39 40 from = UnitName("player"),
Asa@39 41 to = "",
Asa@39 42 subject = "",
Asa@39 43 link = '',
Asa@39 44 count = 0,
Asa@39 45 COD = 0,
Asa@39 46 key = random(10000),
Asa@39 47 sent = 0,
Asa@39 48 }
Asa@39 49
Asa@39 50 if self.db.factionrealm.outbound_cod[self.mailOutbox.key] ~= nil then
Asa@39 51 return self:GenerateBlankOutbox()
Asa@39 52 end
Asa@39 53 end
Asa@39 54
Asa@40 55 local attachedItems = {}
Asa@39 56 local Orig_SendMail = SendMail
Asa@42 57 local skipCODTracking = false
Asa@42 58
Asa@42 59 StaticPopupDialogs["ItemAuditor_Send_COD_without_tracking_number"] = {
Asa@42 60 text = "ItemAuditor cannot track COD mail with multiple item types attached. Do you want to send this mail without tracking?",
Asa@42 61 button1 = "Yes",
Asa@42 62 button2 = "No",
Asa@42 63 OnAccept = function()
Asa@42 64 skipCODTracking = true
Asa@42 65 end,
Asa@42 66 timeout = 0,
Asa@42 67 whileDead = true,
Asa@42 68 hideOnEscape = true,
Asa@42 69 }
Asa@39 70
Asa@39 71 function SendMail(recipient, subject, body, ...)
Asa@39 72 local self = ItemAuditor
Asa@39 73 self:GenerateBlankOutbox()
Asa@39 74
Asa@39 75 self:Debug(format("[To: %s] [Subject: %s]", recipient, subject))
Asa@39 76
Asa@39 77 self.mailOutbox.COD = GetSendMailCOD()
Asa@39 78
Asa@40 79 attachedItems = {}
Asa@40 80 local totalStacks = 0
Asa@39 81 local link
Asa@40 82 for index = 1, ATTACHMENTS_MAX_SEND do
Asa@39 83 local itemName, _, itemCount = GetSendMailItem(index)
Asa@39 84 local newLink = GetSendMailItemLink(index)
Asa@39 85
Asa@40 86 if newLink ~= nil then
Asa@40 87 newLink = self:GetSafeLink(newLink)
Asa@40 88 totalStacks = totalStacks + 1
Asa@40 89 attachedItems[newLink] = (attachedItems[newLink] or {stacks = 0, count = 0})
Asa@40 90 attachedItems[newLink].stacks = attachedItems[newLink].stacks + 1
Asa@40 91 attachedItems[newLink].count = attachedItems[newLink].count + itemCount
Asa@40 92 attachedItems[newLink].price = 0 -- This is a placeholder for below.
Asa@39 93 end
Asa@40 94 end
Asa@40 95 for link, data in pairs(attachedItems) do
Asa@53 96 data.price = 30 * data.stacks
Asa@40 97 end
Asa@40 98
Asa@42 99 if self.mailOutbox.COD > 0 and skipCODTracking then
Asa@42 100
Asa@42 101 elseif self.mailOutbox.COD > 0 then
Asa@40 102 if self:tcount(attachedItems) > 1 then
Asa@39 103 self:GenerateBlankOutbox()
Asa@42 104 local vararg = ...
Asa@42 105 StaticPopupDialogs["ItemAuditor_Send_COD_without_tracking_number"].OnAccept = function()
Asa@42 106 skipCODTracking = true
Asa@42 107 SendMail(recipient, subject, body, vararg)
Asa@42 108 skipCODTracking = false
Asa@42 109 end
Asa@42 110 StaticPopup_Show ("ItemAuditor_Send_COD_without_tracking_number");
Asa@39 111 return
Asa@39 112 end
Asa@40 113 self:Debug("COD mail")
Asa@39 114
Asa@40 115 subject = format("[IA: %s] %s", self.mailOutbox.key, subject)
Asa@40 116 self.mailOutbox.subject = subject
Asa@40 117 self.mailOutbox.to = recipient
Asa@40 118
Asa@40 119 -- At this point we know there is only one item
Asa@40 120 for link, data in pairs(attachedItems) do
Asa@40 121 self.mailOutbox.link = link
Asa@40 122 self.mailOutbox.count = data.count
Asa@40 123 end
Asa@40 124 else
Asa@40 125 self:Debug("Non-COD mail")
Asa@39 126 end
Asa@40 127
Asa@39 128 return Orig_SendMail(recipient, subject, body, ...)
Asa@39 129 end
Asa@39 130
Asa@63 131 function ItemAuditor:MAIL_SUCCESS(event)
Asa@42 132 skipCODTracking = false
Asa@40 133 for link, data in pairs(attachedItems) do
Asa@40 134 self:SaveValue(link, data.price, data.count)
Asa@40 135 end
Asa@39 136 if self.mailOutbox.COD > 0 then
Asa@39 137 self:Debug(format("MAIL_SUCCESS %d [To: %s] [Subject: %s] [COD: %s]", self.mailOutbox.key, self.mailOutbox.to, self.mailOutbox.subject, self.mailOutbox.COD))
Asa@39 138
Asa@39 139 self.mailOutbox.sent = time()
Asa@39 140 self.db.factionrealm.outbound_cod[self.mailOutbox.key] = self.mailOutbox
Asa@39 141 end
Asa@39 142
Asa@40 143
Asa@40 144 self:GenerateBlankOutbox()
Asa@3 145 end
Asa@3 146
Asa@63 147 function ItemAuditor:MAIL_CLOSED()
Asa@23 148 self:Debug("MAIL_CLOSED")
Asa@63 149 ItemAuditor:UnregisterEvent("MAIL_CLOSED")
Asa@7 150 self:MAIL_INBOX_UPDATE()
Asa@3 151 self:UnregisterEvent("MAIL_INBOX_UPDATE")
Asa@3 152 self:RegisterEvent("MAIL_SHOW")
Asa@39 153 self:WatchBags()
Asa@3 154 end
Asa@3 155
Asa@26 156 local storedCountDiff
Asa@63 157 function ItemAuditor:MAIL_INBOX_UPDATE()
Asa@23 158 self:Debug("MAIL_INBOX_UPDATE")
Asa@63 159 local newScan = ItemAuditor:ScanMail()
Asa@3 160 local diff
Asa@39 161
Asa@6 162 for mailType, collection in pairs(self.lastMailScan) do
Asa@7 163 newScan[mailType] = (newScan[mailType] or {})
Asa@26 164 for itemName, data in pairs(collection) do
Asa@26 165 newScan[mailType][itemName] = (newScan[mailType][itemName] or {total=0,count=0})
Asa@26 166 local totalDiff = data.total - newScan[mailType][itemName].total
Asa@26 167 local countDiff = data.count - newScan[mailType][itemName].count
Asa@26 168 --[[
Asa@26 169 In one update the item will be taken and in the following update the invoice
Asa@26 170 will be gone. I need to store the item difference in order ot pass it into
Asa@26 171 SaveValue.
Asa@26 172 ]]
Asa@26 173 if countDiff ~= 0 then
Asa@26 174 storedCountDiff = countDiff
Asa@26 175 end
Asa@26 176
Asa@26 177 if totalDiff ~= 0 then
Asa@39 178 if mailType == "CODPayment" then
Asa@39 179 local trackID
Asa@39 180 trackID, itemName= strsplit("|", itemName, 2)
Asa@39 181 self.db.factionrealm.outbound_cod[tonumber(trackID)] = nil
Asa@39 182 self:Debug("Removing COD Tracker: " .. trackID)
Asa@39 183 end
Asa@26 184 self:SaveValue(itemName, totalDiff, storedCountDiff)
Asa@26 185 storedCountDiff = 0
Asa@6 186 end
Asa@6 187
Asa@3 188 end
Asa@3 189 end
Asa@3 190
Asa@3 191 self.lastMailScan = newScan
Asa@3 192 end
Asa@3 193
Asa@63 194 function ItemAuditor:UNIT_SPELLCAST_START(event, target, spell)
Asa@5 195 if target == "player" and spell == "Milling" or spell == "Prospecting" or spell == "Disenchanting" then
Asa@23 196 self:Debug(event .. " " .. spell)
Asa@4 197 self:UnwatchBags()
Asa@4 198 self:UpdateCurrentInventory()
Asa@4 199 self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
Asa@4 200 self:RegisterEvent("LOOT_CLOSED")
Asa@3 201 end
Asa@3 202 end
Asa@3 203
Asa@4 204 --[[
Asa@4 205 The item should be destroyed before this point, so the last inventory check
Asa@4 206 needs to be kept so it can be combined with the up coming loot.
Asa@4 207 ]]
Asa@63 208 function ItemAuditor:LOOT_CLOSED()
Asa@23 209 self:Debug("LOOT_CLOSED")
Asa@4 210 self:UnregisterEvent("LOOT_CLOSED")
Asa@4 211 self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED")
Asa@4 212 local inventory = self.lastInventory
Asa@4 213 self:WatchBags()
Asa@4 214 self.lastInventory = inventory
Asa@4 215 end
Asa@3 216
Asa@63 217 function ItemAuditor:UNIT_SPELLCAST_INTERRUPTED(event, target, spell)
Asa@5 218 if target == "player" and spell == "Milling" or spell == "Prospecting" or spell == "Disenchanting" then
Asa@23 219 self:Debug(event .. " " .. spell)
Asa@4 220 self:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED")
Asa@4 221 self:UnregisterEvent("LOOT_CLOSED")
Asa@4 222 self:WatchBags()
Asa@4 223 end
Asa@4 224 end
Asa@4 225
Asa@63 226 function ItemAuditor:UpdateCurrentInventory()
Asa@4 227 self.lastInventory = self:GetCurrentInventory()
Asa@3 228 end
Asa@3 229
Asa@49 230 local function distributeValue(self, totalValue, targetItems)
Asa@46 231
Asa@46 232 local weights = {}
Asa@46 233 local totalWeight = 0
Asa@46 234 for link, change in pairs(targetItems) do
Asa@46 235 --[[
Asa@46 236 If something has never been seen on the AH, it must not be very valuable.
Asa@46 237 I'm using 1c so it doesn't have much weight and I can't get a devided by zero error.
Asa@46 238 The only time I know that this is a problem is when crafting a BOP item, and it
Asa@46 239 is always crafted 1 at a time, so a weight of 1 will work.
Asa@46 240 ]]
Asa@63 241 local ap = (ItemAuditor:GetAuctionPrice(link) or 1) * change
Asa@46 242 totalWeight = totalWeight + ap
Asa@46 243 weights[link] = ap
Asa@46 244 end
Asa@46 245
Asa@46 246 for link, change in pairs(targetItems) do
Asa@52 247 local value = totalValue * (weights[link]/totalWeight)
Asa@52 248 self:SaveValue(link, value, change)
Asa@46 249 end
Asa@46 250 end
Asa@46 251
Asa@63 252 function ItemAuditor:UpdateAudit()
Asa@23 253 -- self:Debug("UpdateAudit " .. event)
Asa@3 254 local currentInventory = self:GetCurrentInventory()
Asa@63 255 local diff = ItemAuditor:GetInventoryDiff(self.lastInventory, currentInventory)
Asa@3 256
Asa@5 257 local positive, negative = {}, {}
Asa@5 258 local positiveCount, negativeCount = 0, 0
Asa@5 259 for item, count in pairs(diff.items) do
Asa@5 260 if count > 0 then
Asa@5 261 positive[item] = count
Asa@5 262 positiveCount = positiveCount + count
Asa@5 263 elseif count < 0 then
Asa@5 264 negative[item] = count
Asa@5 265 negativeCount = negativeCount + abs(count)
Asa@5 266 end
Asa@5 267 end
Asa@5 268
Asa@23 269 if positiveCount + negativeCount == 0 then
Asa@33 270 --[[
Asa@33 271 Nothing needs to be done, but this will prevent mistakenly attributing
Asa@33 272 the cost of flights to the first item you pick up.
Asa@33 273 ]]
Asa@33 274 elseif diff.money > 0 and self:tcount(positive) > 0 and self:tcount(negative) == 0 then
Asa@15 275 self:Debug("loot")
Asa@20 276 elseif abs(diff.money) > 0 and self:tcount(diff.items) == 1 then
Asa@15 277 self:Debug("purchase or sale")
Asa@3 278
Asa@9 279 for link, count in pairs(diff.items) do
Asa@26 280 self:SaveValue(link, 0 - diff.money, count)
Asa@3 281 end
Asa@23 282 elseif self:tcount(diff.items) > 1 and self:tcount(positive) > 0 and self:tcount(negative) > 0 then
Asa@23 283 -- we must have created/converted something
Asa@23 284 self:Debug("conversion")
Asa@3 285
Asa@23 286 local totalChange = 0
Asa@23 287 for link, change in pairs(negative) do
Asa@23 288 local _, itemCost, count = self:GetItemCost(link, change)
Asa@26 289 self:SaveValue(link, itemCost * change, change)
Asa@10 290
Asa@23 291 totalChange = totalChange + (itemCost * abs(change))
Asa@3 292 end
Asa@23 293
Asa@46 294 distributeValue(self, totalChange, positive)
Asa@23 295 else
Asa@23 296 self:Debug("No match in UpdateAudit.")
Asa@3 297 end
Asa@3 298
Asa@3 299 self.lastInventory = currentInventory
Asa@63 300 ItemAuditor:WatchBags()
Asa@3 301 end