annotate Modules/Crafting.lua @ 61:b24dbfbe2aef

Fixed an infinite loop when when adding items to the Skillet queue from the crafting interface.
author Asa Ayers <Asa.Ayers@Gmail.com>
date Tue, 27 Jul 2010 11:56:00 -0700
parents 069f39f62104
children e7d287cc3b02
rev   line source
Asa@59 1 local addonName, addonTable = ...;
Asa@59 2 local ItemAuditor = _G[addonName]
Asa@59 3
Asa@59 4 local AceGUI = LibStub("AceGUI-3.0")
Asa@59 5 local ScrollingTable = LibStub("ScrollingTable")
Asa@59 6
Asa@59 7 local validateMoney = ItemAuditor.validateMoney
Asa@59 8 local parseMoney = ItemAuditor.parseMoney
Asa@59 9
Asa@59 10 local realData = {}
Asa@59 11
Asa@59 12 local function displayMoney(rowFrame, cellFrame, data, cols, row, realrow, column, fShow, table, ...)
Asa@59 13 if fShow == true then
Asa@59 14 local money = data[realrow][column]
Asa@59 15 if money then
Asa@59 16 cellFrame.text:SetText(ItemAuditor:FormatMoney(tonumber(money)))
Asa@59 17 else
Asa@59 18 cellFrame.text:SetText("")
Asa@59 19 end
Asa@59 20
Asa@59 21 end
Asa@59 22 end
Asa@59 23
Asa@59 24 local craftingCols = {
Asa@59 25 { name= "Item", width = 200, defaultsort = "desc",
Asa@59 26 ['DoCellUpdate'] = function(rowFrame, cellFrame, data, cols, row, realrow, column, fShow, table, ...)
Asa@59 27 if fShow == true then
Asa@59 28 local data = realData[realrow]
Asa@59 29 cellFrame.text:SetText(data.link)
Asa@59 30 end
Asa@59 31 end,
Asa@59 32 },
Asa@59 33 { name= "Cost Each", width = 100, align = "RIGHT",
Asa@59 34 ['DoCellUpdate'] = displayMoney,
Asa@59 35 },
Asa@59 36 { name= "Est Sale Each", width = 100, align = "RIGHT",
Asa@59 37 ['DoCellUpdate'] = displayMoney,
Asa@59 38 },
Asa@59 39 { name= "Decided By", width = 100, align = "RIGHT",
Asa@59 40
Asa@59 41 },
Asa@59 42 { name= "craft", width = 50, align = "RIGHT",
Asa@59 43
Asa@59 44 },
Asa@59 45 { name= "Total Profit", width = 100, align = "RIGHT",
Asa@59 46 ['DoCellUpdate'] = displayMoney,
Asa@59 47 },
Asa@59 48 }
Asa@59 49
Asa@59 50 local function ExportToSkillet()
Asa@59 51 local index = 1
Asa@59 52 local data = ItemAuditor:GetCraftingRow(index)
Asa@59 53 while data do
Asa@59 54 local skillString = select(3, string.find(data.recipeLink, "^|%x+|H(.+)|h%[.+%]"))
Asa@59 55 local _, skillId = strsplit(":", skillString)
Asa@59 56
Asa@59 57 ItemAuditor:AddToQueue(skillId,tradeSkillIndex, data.queue)
Asa@61 58 index = index + 1
Asa@61 59 data = ItemAuditor:GetCraftingRow(index)
Asa@59 60
Asa@59 61 end
Asa@59 62 end
Asa@59 63
Asa@59 64 local craftingContent = false
Asa@59 65 local craftingTable = false
Asa@60 66 local btnProcess = false
Asa@59 67 local function ShowCrafting(container)
Asa@59 68 if craftingContent == false then
Asa@59 69 local window = container.frame
Asa@59 70 craftingContent = CreateFrame("Frame",nil,window)
Asa@59 71 craftingContent:SetBackdropColor(0, 0, 1, 0.5)
Asa@59 72 craftingContent:SetBackdropBorderColor(1, 0, 0, 1)
Asa@59 73
Asa@59 74 craftingContent:SetPoint("TOPLEFT", window, 10, -50)
Asa@59 75 craftingContent:SetPoint("BOTTOMRIGHT",window, -10, 10)
Asa@59 76
Asa@59 77 craftingTable = ScrollingTable:CreateST(craftingCols, 22, nil, nil, craftingContent )
Asa@59 78
Asa@59 79 IAcc = craftingContent
Asa@59 80 IAccWindow = window
Asa@59 81 craftingTable.frame:SetPoint("TOPLEFT",craftingContent, 0,0)
Asa@59 82 craftingTable.frame:SetPoint("BOTTOMRIGHT", craftingContent, 0, 30)
Asa@59 83
Asa@59 84 craftingTable:RegisterEvents({
Asa@59 85 ["OnEnter"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
Asa@59 86 if realrow then
Asa@59 87 local data = realData[realrow]
Asa@59 88
Asa@59 89 GameTooltip:SetOwner(rowFrame, "ANCHOR_CURSOR")
Asa@59 90 GameTooltip:SetHyperlink(data.link)
Asa@59 91 GameTooltip:Show()
Asa@59 92 end
Asa@59 93 end,
Asa@59 94 ["OnLeave"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
Asa@59 95 GameTooltip:Hide()
Asa@59 96 end,
Asa@59 97 });
Asa@59 98
Asa@59 99
Asa@59 100 btnProcess = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
Asa@59 101 btnProcess:SetText("Process")
Asa@59 102 btnProcess:SetSize(100, 25)
Asa@59 103 btnProcess:SetPoint("BOTTOMRIGHT", craftingContent, 0, 0)
Asa@59 104 btnProcess:RegisterForClicks("LeftButtonUp");
Asa@59 105
Asa@60 106 local function UpdateProcessTooltip(btn)
Asa@59 107 local data = ItemAuditor:GetCraftingRow(1)
Asa@59 108 if data then
Asa@59 109 GameTooltip:SetOwner(this, "ANCHOR_CURSOR")
Asa@59 110 GameTooltip:SetText(format('Create %sx%s', data.link, data.queue))
Asa@59 111 GameTooltip:Show()
Asa@59 112 end
Asa@60 113 end
Asa@60 114 btnProcess:SetScript("OnClick", function (self, button, down)
Asa@60 115 local data = ItemAuditor:GetCraftingRow(1)
Asa@60 116 if data then
Asa@60 117 ItemAuditor:Print('Crafting %sx%s', data.link, data.queue)
Asa@60 118 DoTradeSkill(data.tradeSkillIndex, data.queue)
Asa@60 119 data.queue = 0
Asa@60 120 ItemAuditor:RefreshCraftingTable()
Asa@60 121 UpdateProcessTooltip()
Asa@60 122 end
Asa@59 123 end)
Asa@59 124
Asa@60 125 btnProcess:SetScript("OnEnter", UpdateProcessTooltip)
Asa@60 126
Asa@59 127 btnProcess:SetScript("OnLeave", function()
Asa@59 128 GameTooltip:Hide()
Asa@59 129 end)
Asa@59 130
Asa@59 131 btnSkillet = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
Asa@59 132 btnSkillet:SetText("Queue in Skillet")
Asa@59 133 btnSkillet:SetSize(125, 25)
Asa@59 134 btnSkillet:SetPoint("BOTTOMRIGHT", btnProcess, 'BOTTOMLEFT', 0, 0)
Asa@59 135 btnSkillet:RegisterForClicks("LeftButtonUp");
Asa@59 136 btnSkillet:SetScript("OnClick", function (self, button, down)
Asa@59 137 ExportToSkillet()
Asa@59 138 end)
Asa@59 139
Asa@59 140 end
Asa@59 141 craftingContent:Show()
Asa@59 142
Asa@59 143 if container.parent then
Asa@59 144 local width = 80
Asa@59 145 for i, data in pairs(craftingCols) do
Asa@59 146 width = width + data.width
Asa@59 147 end
Asa@59 148 container.parent:SetWidth(width);
Asa@59 149 end
Asa@59 150
Asa@59 151 ItemAuditor:RegisterEvent("TRADE_SKILL_SHOW", function()
Asa@59 152 if craftingContent and craftingContent:IsVisible() then
Asa@59 153 ItemAuditor:UpdateCraftingTable()
Asa@59 154 end
Asa@59 155 end)
Asa@59 156 ItemAuditor:UpdateCraftingTable()
Asa@59 157
Asa@59 158 return craftingContent
Asa@59 159 end
Asa@59 160
Asa@59 161
Asa@59 162
Asa@59 163 ItemAuditor:RegisterTab('Crafting', 'tab_crafting', ShowCrafting)
Asa@59 164 function ItemAuditor:DisplayCrafting()
Asa@59 165 self:CreateFrame('tab_crafting')
Asa@59 166 end
Asa@59 167
Asa@59 168 local craftingDeciders = {}
Asa@59 169
Asa@59 170 function ItemAuditor:RegisterCraftingDecider(name, decider)
Asa@59 171 craftingDeciders[name] = decider
Asa@59 172 end
Asa@59 173
Asa@59 174 local lastWinnder = ""
Asa@59 175 local function Decide(data)
Asa@59 176 local newDecision = 0
Asa@59 177 for name, decider in pairs(craftingDeciders) do
Asa@59 178 if name ~= lastWinner then
Asa@59 179 newDecision = decider(data)
Asa@59 180 if newDecision > data.queue then
Asa@59 181 data.queue = newDecision
Asa@59 182 lastWinner = name
Asa@59 183 return Decide(data)
Asa@59 184 elseif newDecision < 0 then
Asa@59 185 lastWinner = ""
Asa@59 186 return 'VETO: '..name, 0
Asa@59 187 end
Asa@59 188 end
Asa@59 189 end
Asa@59 190
Asa@59 191 winner = lastWinner
Asa@59 192 lastWinner = ""
Asa@59 193
Asa@59 194 return winner, data.queue
Asa@59 195 end
Asa@59 196
Asa@59 197 local function isProfitable(data)
Asa@59 198 if data.profit > 0 and data.profit > ItemAuditor:GetCraftingThreshold() then
Asa@59 199 return 1
Asa@59 200 end
Asa@59 201 return -1
Asa@59 202 end
Asa@59 203 ItemAuditor:RegisterCraftingDecider('Is Profitable', isProfitable)
Asa@59 204
Asa@59 205 local function tableFilter(self, row, ...)
Asa@59 206 -- column 5 is how many should be crafted
Asa@59 207 return row[5] > 0
Asa@59 208 end
Asa@59 209
Asa@59 210 local tableData = {}
Asa@59 211 function ItemAuditor:UpdateCraftingTable()
Asa@59 212 if LSW == nil then
Asa@59 213 self:Print("This feature requires LilSparky's Workshop.")
Asa@59 214 return
Asa@59 215 end
Asa@59 216 if Skillet == nil then
Asa@59 217 self:Print("This feature requires Skillet.")
Asa@59 218 return
Asa@59 219 end
Asa@59 220 if GetAuctionBuyout ~= nil then
Asa@59 221 elseif AucAdvanced and AucAdvanced.Version then
Asa@59 222 else
Asa@59 223 self:Print("This feature requires Auctionator, Auctioneer, AuctionLite, or AuctionMaster.")
Asa@59 224 return
Asa@59 225 end
Asa@59 226 wipe(realData)
Asa@59 227 wipe(tableData)
Asa@59 228
Asa@59 229 local profitableItems = {}
Asa@59 230 local profitableIndex = 1
Asa@59 231 local numChecked = 0
Asa@59 232 local row = 1
Asa@59 233
Asa@59 234 for i = 1, GetNumTradeSkills() do
Asa@59 235 local itemLink = GetTradeSkillItemLink(i)
Asa@59 236 local itemId = Skillet:GetItemIDFromLink(itemLink)
Asa@59 237
Asa@59 238 --Figure out if its an enchant or not
Asa@59 239 _, _, _, _, altVerb = GetTradeSkillInfo(i)
Asa@59 240 if LSW.scrollData[itemId] ~= nil and altVerb == 'Enchant' then
Asa@59 241 -- Ask LSW for the correct scroll
Asa@59 242 itemId = LSW.scrollData[itemId]["scrollID"]
Asa@59 243 end
Asa@59 244
Asa@59 245 local recipeLink = GetTradeSkillRecipeLink(i)
Asa@59 246 local stackSize = 1
Asa@59 247 if recipeLink ~= nil and itemId ~= nil then
Asa@59 248 local skillName, skillType, numAvailable, isExpanded, altVerb = GetTradeSkillInfo(i)
Asa@59 249 local itemName, itemLink= GetItemInfo(itemId)
Asa@59 250
Asa@59 251 local count = Altoholic:GetItemCount(itemId)
Asa@59 252 local reagents = {}
Asa@59 253 local totalCost = 0
Asa@59 254 for reagentId = 1, GetTradeSkillNumReagents(i) do
Asa@59 255 local reagentName, _, reagentCount = GetTradeSkillReagentInfo(i, reagentId);
Asa@59 256 local reagentLink = GetTradeSkillReagentItemLink(i, reagentId)
Asa@59 257
Asa@59 258 reagents[reagentId] = {
Asa@59 259 name = reagentName,
Asa@59 260 count = reagentCount,
Asa@59 261 price = self:GetReagentCost(reagentLink, reagentCount),
Asa@59 262 }
Asa@59 263 totalCost = totalCost + self:GetReagentCost(reagentLink, reagentCount)
Asa@59 264 end
Asa@59 265
Asa@59 266 local data = {
Asa@59 267 recipeLink = recipeLink,
Asa@59 268 link = itemLink,
Asa@59 269 name = itemName,
Asa@59 270 count = count,
Asa@59 271 price = (self:GetAuctionPrice(itemLink) or 0),
Asa@59 272 cost = totalCost,
Asa@59 273 profit = (self:GetAuctionPrice(itemLink) or 0) - totalCost,
Asa@59 274 reagents = reagents,
Asa@59 275 count = count,
Asa@59 276 tradeSkillIndex = i,
Asa@59 277 queue = 0,
Asa@59 278 winner = "",
Asa@59 279 }
Asa@59 280
Asa@59 281 data.winner, data.queue = Decide(data)
Asa@59 282 data.queue = data.queue - count
Asa@59 283
Asa@59 284 -- If a tradeskill makes 5 at a time and something asks for 9, we should only
Asa@59 285 -- craft twice to get 10.
Asa@59 286 data.queue = ceil(data.queue / GetTradeSkillNumMade(i))
Asa@59 287
Asa@59 288 realData[row] = data
Asa@59 289 row = row + 1
Asa@59 290 end
Asa@59 291 end
Asa@59 292 table.sort(realData, function(a, b) return a.profit*a.queue > b.profit*b.queue end)
Asa@60 293 craftingTable:SetFilter(tableFilter)
Asa@60 294 self:RefreshCraftingTable()
Asa@60 295 end
Asa@60 296
Asa@60 297 function ItemAuditor:RefreshCraftingTable()
Asa@59 298 for key, data in pairs(realData) do
Asa@59 299 tableData[key] = {
Asa@59 300 data.name,
Asa@59 301 data.cost,
Asa@59 302 data.price,
Asa@59 303 data.winner,
Asa@59 304 data.queue,
Asa@59 305 data.profit*data.queue,
Asa@59 306 }
Asa@59 307 end
Asa@60 308 craftingTable:SetData(tableData, true)
Asa@59 309
Asa@60 310 if self:GetCraftingRow(1) then
Asa@60 311 btnProcess:Enable()
Asa@60 312 else
Asa@60 313 btnProcess:Disable()
Asa@60 314 end
Asa@59 315 end
Asa@59 316
Asa@59 317 function ItemAuditor:GetCraftingRow(row)
Asa@59 318 if craftingTable then
Asa@59 319 for _, index in pairs(craftingTable.sorttable) do
Asa@59 320 local tableRow = tableData[index]
Asa@59 321 if tableFilter(nil, tableRow) then
Asa@59 322 row = row - 1
Asa@59 323 if row == 0 then
Asa@59 324 return realData[index]
Asa@59 325 end
Asa@59 326 end
Asa@59 327 end
Asa@59 328 elseif realData then
Asa@59 329 return realData[row]
Asa@59 330 end
Asa@59 331 return nil
Asa@59 332 end