annotate Modules/Crafting.lua @ 69:4ae431c98059

Added integration with ArkInventory. You can set up rules that use "itemauditor('profitable')" or "itemauditor('qa')" to find items managed by QuickAuctions
author Asa Ayers <Asa.Ayers@Gmail.com>
date Wed, 28 Jul 2010 21:27:39 -0700
parents 2d65db19d3ce
children 3930518cb8d9
rev   line source
Asa@63 1 local ItemAuditor = select(2, ...)
Asa@63 2 local Crafting = ItemAuditor:NewModule("Crafting")
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@67 12
Asa@68 13 local queueDestinations = {}
Asa@68 14
Asa@68 15 function Crafting.RegisterQueueDestination(name, destination)
Asa@68 16 queueDestinations[name] = destination
Asa@68 17 end
Asa@68 18
Asa@67 19 -- TODO: Convert this to a text field.
Asa@67 20 local craftingThresholds = {5000, 10000, 50000}
Asa@67 21 local craftingThresholdsDisplay = {}
Asa@67 22
Asa@67 23 for key, value in pairs(craftingThresholds) do
Asa@67 24 craftingThresholdsDisplay[key] = ItemAuditor:FormatMoney(value, '', true)
Asa@67 25 -- craftingThresholdsDisplay[key] = value
Asa@67 26 end
Asa@67 27
Asa@68 28 function ItemAuditor:GetCraftingThreshold()
Asa@68 29 local key = ItemAuditor.db.char.crafting_threshold
Asa@68 30 return craftingThresholds[key]
Asa@68 31 end
Asa@68 32
Asa@67 33 ItemAuditor.Options.args.crafting_options = {
Asa@67 34 name = "Crafting with Skillet",
Asa@67 35 desc = "/ia queue",
Asa@67 36 type = 'group',
Asa@67 37 disabled = function() return Skillet == nil end,
Asa@67 38 args = {
Asa@67 39 crafting_threshold = {
Asa@67 40 type = "select",
Asa@67 41 name = "Crafting Threshold",
Asa@67 42 desc = "Don't create items that will make less than this amount of profit",
Asa@67 43 values = craftingThresholdsDisplay,
Asa@67 44 get = function() return ItemAuditor.db.char.crafting_threshold end,
Asa@67 45 set = function(info, value) ItemAuditor.db.char.crafting_threshold = value end,
Asa@67 46 order = 11,
Asa@67 47 },
Asa@67 48 },
Asa@67 49 }
Asa@67 50
Asa@59 51 local function displayMoney(rowFrame, cellFrame, data, cols, row, realrow, column, fShow, table, ...)
Asa@59 52 if fShow == true then
Asa@59 53 local money = data[realrow][column]
Asa@59 54 if money then
Asa@59 55 cellFrame.text:SetText(ItemAuditor:FormatMoney(tonumber(money)))
Asa@59 56 else
Asa@59 57 cellFrame.text:SetText("")
Asa@59 58 end
Asa@59 59
Asa@59 60 end
Asa@59 61 end
Asa@59 62
Asa@59 63 local craftingCols = {
Asa@59 64 { name= "Item", width = 200, defaultsort = "desc",
Asa@59 65 ['DoCellUpdate'] = function(rowFrame, cellFrame, data, cols, row, realrow, column, fShow, table, ...)
Asa@59 66 if fShow == true then
Asa@59 67 local data = realData[realrow]
Asa@59 68 cellFrame.text:SetText(data.link)
Asa@59 69 end
Asa@59 70 end,
Asa@59 71 },
Asa@59 72 { name= "Cost Each", width = 100, align = "RIGHT",
Asa@59 73 ['DoCellUpdate'] = displayMoney,
Asa@59 74 },
Asa@59 75 { name= "Est Sale Each", width = 100, align = "RIGHT",
Asa@59 76 ['DoCellUpdate'] = displayMoney,
Asa@59 77 },
Asa@59 78 { name= "Decided By", width = 100, align = "RIGHT",
Asa@59 79
Asa@59 80 },
Asa@59 81 { name= "craft", width = 50, align = "RIGHT",
Asa@59 82
Asa@59 83 },
Asa@59 84 { name= "Total Profit", width = 100, align = "RIGHT",
Asa@59 85 ['DoCellUpdate'] = displayMoney,
Asa@59 86 },
Asa@59 87 }
Asa@59 88
Asa@68 89 function Crafting.ExportToSkillet(data)
Asa@68 90 local skillString = select(3, string.find(data.recipeLink, "^|%x+|H(.+)|h%[.+%]"))
Asa@68 91 local _, skillId = strsplit(":", skillString)
Asa@68 92
Asa@68 93 ItemAuditor:AddToQueue(skillId,tradeSkillIndex, data.queue)
Asa@68 94 end
Asa@68 95
Asa@68 96 Crafting.RegisterQueueDestination('Skillet', Crafting.ExportToSkillet)
Asa@68 97
Asa@68 98
Asa@68 99
Asa@68 100 function Crafting.Export(destination)
Asa@68 101 if type(destination) == 'function' then
Asa@68 102 -- do nothing
Asa@68 103 elseif destination == nil then
Asa@68 104 destination = queueDestinations['Skillet']
Asa@68 105 elseif type(destination) == 'string' then
Asa@68 106 destination = queueDestinations[destination]
Asa@68 107 else
Asa@68 108 error('destination must be a function or a string')
Asa@68 109 end
Asa@68 110
Asa@59 111 local index = 1
Asa@59 112 local data = ItemAuditor:GetCraftingRow(index)
Asa@59 113 while data do
Asa@68 114 if data.queue > 0 then
Asa@68 115 destination(data)
Asa@68 116 end
Asa@61 117 index = index + 1
Asa@61 118 data = ItemAuditor:GetCraftingRow(index)
Asa@59 119
Asa@59 120 end
Asa@59 121 end
Asa@59 122
Asa@59 123 local craftingContent = false
Asa@59 124 local craftingTable = false
Asa@60 125 local btnProcess = false
Asa@59 126 local function ShowCrafting(container)
Asa@59 127 if craftingContent == false then
Asa@59 128 local window = container.frame
Asa@59 129 craftingContent = CreateFrame("Frame",nil,window)
Asa@59 130 craftingContent:SetBackdropColor(0, 0, 1, 0.5)
Asa@59 131 craftingContent:SetBackdropBorderColor(1, 0, 0, 1)
Asa@59 132
Asa@59 133 craftingContent:SetPoint("TOPLEFT", window, 10, -50)
Asa@59 134 craftingContent:SetPoint("BOTTOMRIGHT",window, -10, 10)
Asa@59 135
Asa@59 136 craftingTable = ScrollingTable:CreateST(craftingCols, 22, nil, nil, craftingContent )
Asa@59 137
Asa@59 138 IAcc = craftingContent
Asa@59 139 IAccWindow = window
Asa@59 140 craftingTable.frame:SetPoint("TOPLEFT",craftingContent, 0,0)
Asa@59 141 craftingTable.frame:SetPoint("BOTTOMRIGHT", craftingContent, 0, 30)
Asa@59 142
Asa@59 143 craftingTable:RegisterEvents({
Asa@59 144 ["OnEnter"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
Asa@59 145 if realrow then
Asa@59 146 local data = realData[realrow]
Asa@59 147
Asa@59 148 GameTooltip:SetOwner(rowFrame, "ANCHOR_CURSOR")
Asa@59 149 GameTooltip:SetHyperlink(data.link)
Asa@59 150 GameTooltip:Show()
Asa@59 151 end
Asa@59 152 end,
Asa@59 153 ["OnLeave"] = function (rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
Asa@59 154 GameTooltip:Hide()
Asa@59 155 end,
Asa@59 156 });
Asa@59 157
Asa@59 158
Asa@59 159 btnProcess = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
Asa@59 160 btnProcess:SetText("Process")
Asa@59 161 btnProcess:SetSize(100, 25)
Asa@59 162 btnProcess:SetPoint("BOTTOMRIGHT", craftingContent, 0, 0)
Asa@59 163 btnProcess:RegisterForClicks("LeftButtonUp");
Asa@59 164
Asa@60 165 local function UpdateProcessTooltip(btn)
Asa@59 166 local data = ItemAuditor:GetCraftingRow(1)
Asa@59 167 if data then
Asa@59 168 GameTooltip:SetOwner(this, "ANCHOR_CURSOR")
Asa@59 169 GameTooltip:SetText(format('Create %sx%s', data.link, data.queue))
Asa@59 170 GameTooltip:Show()
Asa@59 171 end
Asa@60 172 end
Asa@60 173 btnProcess:SetScript("OnClick", function (self, button, down)
Asa@60 174 local data = ItemAuditor:GetCraftingRow(1)
Asa@60 175 if data then
Asa@60 176 ItemAuditor:Print('Crafting %sx%s', data.link, data.queue)
Asa@60 177 DoTradeSkill(data.tradeSkillIndex, data.queue)
Asa@60 178 data.queue = 0
Asa@60 179 ItemAuditor:RefreshCraftingTable()
Asa@60 180 UpdateProcessTooltip()
Asa@60 181 end
Asa@59 182 end)
Asa@59 183
Asa@60 184 btnProcess:SetScript("OnEnter", UpdateProcessTooltip)
Asa@60 185
Asa@59 186 btnProcess:SetScript("OnLeave", function()
Asa@59 187 GameTooltip:Hide()
Asa@59 188 end)
Asa@59 189
Asa@59 190 btnSkillet = CreateFrame("Button", nil, craftingContent, "UIPanelButtonTemplate")
Asa@59 191 btnSkillet:SetText("Queue in Skillet")
Asa@59 192 btnSkillet:SetSize(125, 25)
Asa@59 193 btnSkillet:SetPoint("BOTTOMRIGHT", btnProcess, 'BOTTOMLEFT', 0, 0)
Asa@59 194 btnSkillet:RegisterForClicks("LeftButtonUp");
Asa@59 195 btnSkillet:SetScript("OnClick", function (self, button, down)
Asa@59 196 ExportToSkillet()
Asa@59 197 end)
Asa@59 198
Asa@59 199 end
Asa@59 200 craftingContent:Show()
Asa@59 201
Asa@59 202 if container.parent then
Asa@59 203 local width = 80
Asa@59 204 for i, data in pairs(craftingCols) do
Asa@59 205 width = width + data.width
Asa@59 206 end
Asa@59 207 container.parent:SetWidth(width);
Asa@59 208 end
Asa@59 209
Asa@59 210 ItemAuditor:RegisterEvent("TRADE_SKILL_SHOW", function()
Asa@59 211 if craftingContent and craftingContent:IsVisible() then
Asa@59 212 ItemAuditor:UpdateCraftingTable()
Asa@59 213 end
Asa@59 214 end)
Asa@59 215 ItemAuditor:UpdateCraftingTable()
Asa@59 216
Asa@59 217 return craftingContent
Asa@59 218 end
Asa@59 219
Asa@59 220
Asa@59 221
Asa@59 222 ItemAuditor:RegisterTab('Crafting', 'tab_crafting', ShowCrafting)
Asa@59 223 function ItemAuditor:DisplayCrafting()
Asa@59 224 self:CreateFrame('tab_crafting')
Asa@59 225 end
Asa@59 226
Asa@59 227 local craftingDeciders = {}
Asa@59 228
Asa@64 229 function Crafting.RegisterCraftingDecider(name, decider)
Asa@59 230 craftingDeciders[name] = decider
Asa@59 231 end
Asa@59 232
Asa@59 233 local lastWinnder = ""
Asa@59 234 local function Decide(data)
Asa@59 235 local newDecision = 0
Asa@59 236 for name, decider in pairs(craftingDeciders) do
Asa@59 237 if name ~= lastWinner then
Asa@59 238 newDecision = decider(data)
Asa@59 239 if newDecision > data.queue then
Asa@59 240 data.queue = newDecision
Asa@59 241 lastWinner = name
Asa@59 242 return Decide(data)
Asa@59 243 elseif newDecision < 0 then
Asa@59 244 lastWinner = ""
Asa@59 245 return 'VETO: '..name, 0
Asa@59 246 end
Asa@59 247 end
Asa@59 248 end
Asa@59 249
Asa@59 250 winner = lastWinner
Asa@59 251 lastWinner = ""
Asa@59 252
Asa@59 253 return winner, data.queue
Asa@59 254 end
Asa@59 255
Asa@59 256 local function isProfitable(data)
Asa@59 257 if data.profit > 0 and data.profit > ItemAuditor:GetCraftingThreshold() then
Asa@59 258 return 1
Asa@59 259 end
Asa@59 260 return -1
Asa@59 261 end
Asa@64 262 Crafting.RegisterCraftingDecider('Is Profitable', isProfitable)
Asa@59 263
Asa@59 264 local function tableFilter(self, row, ...)
Asa@59 265 -- column 5 is how many should be crafted
Asa@59 266 return row[5] > 0
Asa@59 267 end
Asa@59 268
Asa@59 269 local tableData = {}
Asa@59 270 function ItemAuditor:UpdateCraftingTable()
Asa@59 271 if LSW == nil then
Asa@59 272 self:Print("This feature requires LilSparky's Workshop.")
Asa@59 273 return
Asa@59 274 end
Asa@59 275 if Skillet == nil then
Asa@59 276 self:Print("This feature requires Skillet.")
Asa@59 277 return
Asa@59 278 end
Asa@59 279 if GetAuctionBuyout ~= nil then
Asa@59 280 elseif AucAdvanced and AucAdvanced.Version then
Asa@59 281 else
Asa@59 282 self:Print("This feature requires Auctionator, Auctioneer, AuctionLite, or AuctionMaster.")
Asa@59 283 return
Asa@59 284 end
Asa@59 285 wipe(realData)
Asa@59 286 wipe(tableData)
Asa@59 287
Asa@59 288 local profitableItems = {}
Asa@59 289 local profitableIndex = 1
Asa@59 290 local numChecked = 0
Asa@59 291 local row = 1
Asa@59 292
Asa@59 293 for i = 1, GetNumTradeSkills() do
Asa@59 294 local itemLink = GetTradeSkillItemLink(i)
Asa@59 295 local itemId = Skillet:GetItemIDFromLink(itemLink)
Asa@59 296
Asa@59 297 --Figure out if its an enchant or not
Asa@59 298 _, _, _, _, altVerb = GetTradeSkillInfo(i)
Asa@59 299 if LSW.scrollData[itemId] ~= nil and altVerb == 'Enchant' then
Asa@59 300 -- Ask LSW for the correct scroll
Asa@59 301 itemId = LSW.scrollData[itemId]["scrollID"]
Asa@59 302 end
Asa@59 303
Asa@59 304 local recipeLink = GetTradeSkillRecipeLink(i)
Asa@59 305 local stackSize = 1
Asa@59 306 if recipeLink ~= nil and itemId ~= nil then
Asa@59 307 local skillName, skillType, numAvailable, isExpanded, altVerb = GetTradeSkillInfo(i)
Asa@59 308 local itemName, itemLink= GetItemInfo(itemId)
Asa@59 309
Asa@59 310 local count = Altoholic:GetItemCount(itemId)
Asa@59 311 local reagents = {}
Asa@59 312 local totalCost = 0
Asa@59 313 for reagentId = 1, GetTradeSkillNumReagents(i) do
Asa@59 314 local reagentName, _, reagentCount = GetTradeSkillReagentInfo(i, reagentId);
Asa@59 315 local reagentLink = GetTradeSkillReagentItemLink(i, reagentId)
Asa@59 316
Asa@59 317 reagents[reagentId] = {
Asa@59 318 name = reagentName,
Asa@59 319 count = reagentCount,
Asa@59 320 price = self:GetReagentCost(reagentLink, reagentCount),
Asa@59 321 }
Asa@59 322 totalCost = totalCost + self:GetReagentCost(reagentLink, reagentCount)
Asa@59 323 end
Asa@59 324
Asa@59 325 local data = {
Asa@59 326 recipeLink = recipeLink,
Asa@59 327 link = itemLink,
Asa@59 328 name = itemName,
Asa@59 329 count = count,
Asa@59 330 price = (self:GetAuctionPrice(itemLink) or 0),
Asa@59 331 cost = totalCost,
Asa@59 332 profit = (self:GetAuctionPrice(itemLink) or 0) - totalCost,
Asa@59 333 reagents = reagents,
Asa@59 334 count = count,
Asa@59 335 tradeSkillIndex = i,
Asa@59 336 queue = 0,
Asa@59 337 winner = "",
Asa@59 338 }
Asa@59 339
Asa@59 340 data.winner, data.queue = Decide(data)
Asa@59 341 data.queue = data.queue - count
Asa@59 342
Asa@59 343 -- If a tradeskill makes 5 at a time and something asks for 9, we should only
Asa@59 344 -- craft twice to get 10.
Asa@59 345 data.queue = ceil(data.queue / GetTradeSkillNumMade(i))
Asa@59 346
Asa@59 347 realData[row] = data
Asa@59 348 row = row + 1
Asa@59 349 end
Asa@59 350 end
Asa@59 351 table.sort(realData, function(a, b) return a.profit*a.queue > b.profit*b.queue end)
Asa@68 352 if craftingTable then
Asa@68 353 craftingTable:SetFilter(tableFilter)
Asa@68 354 self:RefreshCraftingTable()
Asa@68 355 end
Asa@60 356 end
Asa@60 357
Asa@60 358 function ItemAuditor:RefreshCraftingTable()
Asa@59 359 for key, data in pairs(realData) do
Asa@59 360 tableData[key] = {
Asa@59 361 data.name,
Asa@59 362 data.cost,
Asa@59 363 data.price,
Asa@59 364 data.winner,
Asa@59 365 data.queue,
Asa@59 366 data.profit*data.queue,
Asa@59 367 }
Asa@59 368 end
Asa@60 369 craftingTable:SetData(tableData, true)
Asa@59 370
Asa@60 371 if self:GetCraftingRow(1) then
Asa@60 372 btnProcess:Enable()
Asa@60 373 else
Asa@60 374 btnProcess:Disable()
Asa@60 375 end
Asa@59 376 end
Asa@59 377
Asa@59 378 function ItemAuditor:GetCraftingRow(row)
Asa@59 379 if craftingTable then
Asa@59 380 for _, index in pairs(craftingTable.sorttable) do
Asa@59 381 local tableRow = tableData[index]
Asa@59 382 if tableFilter(nil, tableRow) then
Asa@59 383 row = row - 1
Asa@59 384 if row == 0 then
Asa@59 385 return realData[index]
Asa@59 386 end
Asa@59 387 end
Asa@59 388 end
Asa@59 389 elseif realData then
Asa@59 390 return realData[row]
Asa@59 391 end
Asa@59 392 return nil
Asa@59 393 end
Asa@67 394 ItemAuditor.Options.args.crafting = {
Asa@67 395 type = "execute",
Asa@67 396 name = "crafting",
Asa@67 397 desc = "This opens a window to configure a crafting queue.",
Asa@67 398 func = "DisplayCrafting",
Asa@67 399 guiHidden = false,
Asa@67 400 }