Asa@63
|
1 local ItemAuditor = select(2, ...)
|
Asa@63
|
2 local QuickAuctions= ItemAuditor:NewModule("QuickAuctions")
|
Asa@64
|
3 local Crafting = ItemAuditor:GetModule("Crafting")
|
Asa@18
|
4
|
Asa@62
|
5 --[[
|
Asa@62
|
6 This is simply for compatibility while I change the QA API. Once
|
Asa@62
|
7 my changes get merged into the main project, this can go away.
|
Asa@62
|
8 ]]
|
Asa@62
|
9 if QAAPI ~= nil and QAAPI.GetGroupThreshold ~= nil and QAAPI.GetGroupConfig == nil then
|
Asa@62
|
10 function QAAPI:GetGroupConfig(groupName)
|
Asa@62
|
11 return QAAPI:GetGroupThreshold(groupName),
|
Asa@62
|
12 QAAPI:GetGroupPostCap(groupName),
|
Asa@62
|
13 QAAPI:GetGroupPerAuction(groupName)
|
Asa@62
|
14 end
|
Asa@62
|
15
|
Asa@62
|
16 function QAAPI:SetGroupConfig(groupName, key, value)
|
Asa@62
|
17 if key == 'threshold' then
|
Asa@62
|
18 return QAAPI:SetGroupThreshold(groupName, value)
|
Asa@62
|
19 end
|
Asa@62
|
20 end
|
Asa@62
|
21 end
|
Asa@62
|
22
|
Asa@62
|
23
|
Asa@62
|
24
|
Asa@63
|
25 function ItemAuditor:IsQACompatible()
|
Asa@62
|
26 return (QAAPI ~= nil and QAAPI.GetGroupConfig ~= nil)
|
Asa@18
|
27 end
|
Asa@18
|
28
|
Asa@63
|
29 function ItemAuditor:IsQAEnabled()
|
Asa@63
|
30 return ItemAuditor:IsQACompatible() and ItemAuditor.db.char.use_quick_auctions
|
Asa@18
|
31 end
|
Asa@18
|
32
|
Asa@63
|
33 function ItemAuditor:IsQADisabled()
|
Asa@18
|
34 return not self:IsQAEnabled()
|
Asa@18
|
35 end
|
Asa@18
|
36
|
Asa@63
|
37 function ItemAuditor:SetQAEnabled(info, value)
|
Asa@18
|
38 ItemAuditor.db.char.use_quick_auctions = value
|
Asa@18
|
39 end
|
Asa@18
|
40
|
Asa@63
|
41 function ItemAuditor:RefreshQAGroups()
|
Asa@63
|
42 if not ItemAuditor.IsQAEnabled() then
|
Asa@18
|
43 return
|
Asa@18
|
44 end
|
Asa@18
|
45 for groupName in pairs(QAAPI:GetGroups()) do
|
Asa@18
|
46 self:UpdateQAGroup(groupName)
|
Asa@18
|
47 end
|
Asa@18
|
48 end
|
Asa@18
|
49
|
Asa@63
|
50 function ItemAuditor:UpdateQAThreshold(link)
|
Asa@63
|
51 if not ItemAuditor.IsQAEnabled() then
|
Asa@18
|
52 return
|
Asa@18
|
53 end
|
Asa@18
|
54 _, link= GetItemInfo(link)
|
Asa@18
|
55
|
Asa@18
|
56 self:UpdateQAGroup(QAAPI:GetItemGroup(link))
|
Asa@18
|
57 end
|
Asa@18
|
58
|
Asa@19
|
59 local function calculateQAThreshold(copper)
|
Asa@19
|
60 if copper == 0 then
|
Asa@19
|
61 copper = 1
|
Asa@19
|
62 end
|
Asa@19
|
63
|
Asa@19
|
64 -- add my minimum profit margin
|
Asa@20
|
65 -- GetAuctionThreshold returns a percent as a whole number. This will convert 25 to 1.25
|
Asa@63
|
66 copper = copper * (1+ItemAuditor:GetAuctionThreshold())
|
Asa@19
|
67
|
Asa@19
|
68 -- add AH Cut
|
Asa@63
|
69 local keep = 1 - ItemAuditor:GetAHCut()
|
Asa@19
|
70 return copper/keep
|
Asa@19
|
71 end
|
Asa@19
|
72
|
Asa@63
|
73 function ItemAuditor:UpdateQAGroup(groupName)
|
Asa@63
|
74 if not ItemAuditor.IsQAEnabled() then
|
Asa@18
|
75 return
|
Asa@18
|
76 end
|
Asa@18
|
77 if groupName then
|
Asa@18
|
78 local threshold = 0
|
Asa@18
|
79
|
Asa@18
|
80 for link in pairs(QAAPI:GetItemsInGroup(groupName)) do
|
Asa@18
|
81 local _, itemCost= ItemAuditor:GetItemCost(link, 0)
|
Asa@18
|
82
|
Asa@18
|
83 threshold = max(threshold, itemCost)
|
Asa@18
|
84 end
|
Asa@18
|
85
|
Asa@19
|
86 threshold = calculateQAThreshold(threshold)
|
Asa@18
|
87
|
Asa@62
|
88 QAAPI:SetGroupConfig(groupName, 'threshold', ceil(threshold))
|
Asa@18
|
89 end
|
Asa@18
|
90 end
|
Asa@18
|
91
|
Asa@59
|
92 local function isProfitable(data)
|
Asa@63
|
93 if ItemAuditor.IsQAEnabled() then
|
Asa@59
|
94 local QAGroup = QAAPI:GetItemGroup(data.link)
|
Asa@59
|
95 if QAGroup ~= nil then
|
Asa@63
|
96 local currentInvested, _, currentCount = ItemAuditor:GetItemCost(data.link)
|
Asa@62
|
97 local threshold, postCap, perAuction = QAAPI:GetGroupConfig(QAGroup)
|
Asa@62
|
98 local stackSize = postCap * perAuction
|
Asa@59
|
99
|
Asa@59
|
100 stackSize = stackSize / GetTradeSkillNumMade(data.tradeSkillIndex)
|
Asa@59
|
101
|
Asa@59
|
102 -- bonus
|
Asa@59
|
103 stackSize = ceil(stackSize *1.25)
|
Asa@59
|
104
|
Asa@59
|
105 local newThreshold = ((data.cost*stackSize) + currentInvested) / (currentCount + stackSize)
|
Asa@59
|
106 newThreshold = calculateQAThreshold(newThreshold)
|
Asa@59
|
107
|
Asa@59
|
108 if newThreshold < data.price then
|
Asa@59
|
109 return stackSize
|
Asa@59
|
110 end
|
Asa@59
|
111
|
Asa@59
|
112 return -1
|
Asa@59
|
113 end
|
Asa@59
|
114 end
|
Asa@59
|
115 return 0
|
Asa@59
|
116 end
|
Asa@64
|
117 Crafting.RegisterCraftingDecider('IA QuickAuctions', isProfitable)
|
Asa@59
|
118
|
Asa@18
|
119 --[[
|
Asa@18
|
120 This is based on KTQ
|
Asa@18
|
121 ]]
|
Asa@63
|
122 function ItemAuditor:Queue()
|
Asa@18
|
123 if LSW == nil then
|
Asa@18
|
124 self:Print("This feature requires LilSparky's Workshop.")
|
Asa@18
|
125 return
|
Asa@18
|
126 end
|
Asa@21
|
127 if Skillet == nil then
|
Asa@21
|
128 self:Print("This feature requires Skillet.")
|
Asa@21
|
129 return
|
Asa@21
|
130 end
|
Asa@21
|
131 if GetAuctionBuyout ~= nil then
|
Asa@21
|
132 elseif AucAdvanced and AucAdvanced.Version then
|
Asa@21
|
133 else
|
Asa@21
|
134 self:Print("This feature requires Auctionator, Auctioneer, AuctionLite, or AuctionMaster.")
|
Asa@21
|
135 return
|
Asa@21
|
136 end
|
Asa@21
|
137
|
Asa@21
|
138
|
Asa@63
|
139 if ItemAuditor.IsQAEnabled() then
|
Asa@24
|
140 self:Debug("Auction Threshold: %d%%", self:GetAuctionThreshold()*100 )
|
Asa@21
|
141 end
|
Asa@20
|
142 self:Debug(format("Crafting Threshold: %s", self:FormatMoney(self:GetCraftingThreshold())))
|
Asa@21
|
143 local profitableItems = {}
|
Asa@21
|
144 local profitableIndex = 1
|
Asa@21
|
145 local numChecked = 0
|
Asa@18
|
146
|
Asa@18
|
147 for i = 1, GetNumTradeSkills() do
|
Asa@18
|
148 local itemLink = GetTradeSkillItemLink(i)
|
Asa@18
|
149 local itemId = Skillet:GetItemIDFromLink(itemLink)
|
Asa@18
|
150
|
Asa@18
|
151 --Figure out if its an enchant or not
|
Asa@18
|
152 _, _, _, _, altVerb = GetTradeSkillInfo(i)
|
Asa@18
|
153 if LSW.scrollData[itemId] ~= nil and altVerb == 'Enchant' then
|
Asa@18
|
154 -- Ask LSW for the correct scroll
|
Asa@18
|
155 itemId = LSW.scrollData[itemId]["scrollID"]
|
Asa@18
|
156 end
|
Asa@18
|
157
|
Asa@18
|
158 local skillName, skillType, numAvailable, isExpanded, altVerb = GetTradeSkillInfo(i)
|
Asa@18
|
159 local recipeLink = GetTradeSkillRecipeLink(i)
|
Asa@19
|
160 local stackSize = 1
|
Asa@18
|
161 if recipeLink ~= nil then
|
Asa@18
|
162 _, itemLink= GetItemInfo(itemId)
|
Asa@21
|
163
|
Asa@21
|
164
|
Asa@21
|
165 -- if QA isn't enabled, this will just return nil
|
Asa@21
|
166 local QAGroup = nil
|
Asa@63
|
167 if ItemAuditor.IsQAEnabled() then
|
Asa@21
|
168 QAGroup = QAAPI:GetItemGroup(itemLink)
|
Asa@21
|
169 if QAGroup ~= nil then
|
Asa@62
|
170 local threshold, postCap, perAuction = QAAPI:GetGroupConfig(QAGroup)
|
Asa@62
|
171 stackSize = postCap * perAuction
|
Asa@21
|
172 stackSize = stackSize / GetTradeSkillNumMade(i)
|
Asa@21
|
173
|
Asa@21
|
174 -- bonus
|
Asa@21
|
175 stackSize = ceil(stackSize *1.25)
|
Asa@21
|
176 end
|
Asa@18
|
177 end
|
Asa@21
|
178
|
Asa@18
|
179 local count = Altoholic:GetItemCount(itemId)
|
Asa@18
|
180
|
Asa@19
|
181 if count < stackSize and itemLink ~= nil then
|
Asa@18
|
182 local found, _, skillString = string.find(recipeLink, "^|%x+|H(.+)|h%[.+%]")
|
Asa@18
|
183 local _, skillId = strsplit(":", skillString )
|
Asa@18
|
184
|
Asa@19
|
185 local toQueue = stackSize - count
|
Asa@19
|
186 local newCost = 0
|
Asa@18
|
187 for reagentId = 1, GetTradeSkillNumReagents(i) do
|
Asa@18
|
188 _, _, reagentCount = GetTradeSkillReagentInfo(i, reagentId);
|
Asa@18
|
189 reagentLink = GetTradeSkillReagentItemLink(i, reagentId)
|
Asa@63
|
190 newCost = newCost + ItemAuditor:GetReagentCost(reagentLink, reagentCount)
|
Asa@18
|
191 end
|
Asa@18
|
192
|
Asa@63
|
193 local currentInvested, _, currentCount = ItemAuditor:GetItemCost(itemLink)
|
Asa@19
|
194 local newThreshold = (newCost + currentInvested) / (currentCount + toQueue)
|
Asa@19
|
195
|
Asa@63
|
196 if ItemAuditor.IsQAEnabled() then
|
Asa@21
|
197 newThreshold = calculateQAThreshold(newThreshold)
|
Asa@21
|
198 else
|
Asa@21
|
199 -- if quick auctions isn't enabled, this will cause the decision to rely
|
Asa@21
|
200 -- completly on the crafting threshold
|
Asa@21
|
201 newThreshold = 0
|
Asa@21
|
202 end
|
Asa@63
|
203 local currentPrice = ItemAuditor:GetAuctionPrice(itemLink) or 0
|
Asa@21
|
204 numChecked = numChecked + 1
|
Asa@18
|
205
|
Asa@20
|
206 if newThreshold < currentPrice and (currentPrice - newCost) > self:GetCraftingThreshold() then
|
Asa@21
|
207
|
Asa@21
|
208 profitableItems[profitableIndex] = {
|
Asa@21
|
209 itemLink = itemLink,
|
Asa@21
|
210 SkillID = skillId,
|
Asa@21
|
211 Index = i,
|
Asa@21
|
212 toQueue = toQueue,
|
Asa@21
|
213 profit = (currentPrice - newCost) * toQueue
|
Asa@21
|
214 }
|
Asa@21
|
215 profitableIndex = profitableIndex + 1
|
Asa@23
|
216 else
|
Asa@63
|
217 local skipMessage = format("Skipping %s x%s. Profit: %s ", itemLink, toQueue, ItemAuditor:FormatMoney(currentPrice - newCost))
|
Asa@23
|
218 if ItemAuditor.db.profile.messages.queue_skip then
|
Asa@23
|
219 self:Print(skipMessage)
|
Asa@23
|
220 else
|
Asa@63
|
221 self:Debug(format("Skipping %s x%s. Profit: %s ", itemLink, toQueue, ItemAuditor:FormatMoney(currentPrice - newCost)))
|
Asa@23
|
222 end
|
Asa@18
|
223 end
|
Asa@18
|
224 end
|
Asa@21
|
225 end
|
Asa@18
|
226 end
|
Asa@21
|
227 local numAdded = 0
|
Asa@21
|
228 table.sort(profitableItems, function(a, b) return a.profit > b.profit end)
|
Asa@21
|
229 for key, data in pairs(profitableItems) do
|
Asa@21
|
230 self:Print(format("Adding %s x%s to skillet queue. Profit: %s",
|
Asa@21
|
231 data.itemLink,
|
Asa@21
|
232 data.toQueue,
|
Asa@21
|
233 self:FormatMoney(data.profit)
|
Asa@21
|
234 ))
|
Asa@21
|
235 self:AddToQueue(data.SkillID, data.Index, data.toQueue)
|
Asa@21
|
236 numAdded = numAdded +1
|
Asa@21
|
237 end
|
Asa@21
|
238 self:Print(format("%d items checked", numChecked))
|
Asa@21
|
239 self:Print(format("%d queued", numAdded))
|
Asa@18
|
240 end
|
Asa@18
|
241
|
Asa@63
|
242 function ItemAuditor:GetReagentCost(link, total)
|
Asa@18
|
243 local totalCost = 0
|
Asa@19
|
244
|
Asa@19
|
245 if Skillet:VendorSellsReagent(link) then
|
Asa@19
|
246 local _, _, _, _, _, _, _, _, _, _, itemVendorPrice = GetItemInfo (link);
|
Asa@19
|
247 totalCost = itemVendorPrice * total
|
Asa@19
|
248 total = 0
|
Asa@19
|
249 end
|
Asa@19
|
250
|
Asa@19
|
251
|
Asa@63
|
252 local investedTotal, investedPerItem, count = ItemAuditor:GetItemCost(link)
|
Asa@18
|
253
|
Asa@18
|
254 if count > 0 then
|
Asa@18
|
255 if total <= count then
|
Asa@18
|
256 totalCost = investedPerItem * total
|
Asa@18
|
257 total = 0
|
Asa@18
|
258 else
|
Asa@18
|
259 totalCost = investedTotal
|
Asa@18
|
260 total = total - count
|
Asa@18
|
261 end
|
Asa@18
|
262 end
|
Asa@18
|
263
|
Asa@18
|
264 -- If there is none on the auction house, this uses a large enough number
|
Asa@18
|
265 -- to prevent us from trying to make the item.
|
Asa@21
|
266 local ahPrice = (self:GetAuctionPrice(link) or 99990000)
|
Asa@21
|
267 -- local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, _, _, _, _, itemVendorPrice = GetItemInfo (link);
|
Asa@18
|
268
|
Asa@18
|
269 return totalCost + (ahPrice * total)
|
Asa@18
|
270 end
|
Asa@18
|
271
|
Asa@63
|
272 function ItemAuditor:GetAuctionPrice(itemLink)
|
Asa@21
|
273 if GetAuctionBuyout ~= nil then
|
Asa@21
|
274 return GetAuctionBuyout(itemLink)
|
Asa@21
|
275 elseif AucAdvanced and AucAdvanced.Version then
|
Asa@21
|
276 local _, _, _, _, _, lowBuy= AucAdvanced.Modules.Util.SimpleAuction.Private.GetItems(itemLink)
|
Asa@21
|
277 return lowBuy
|
Asa@21
|
278 end
|
Asa@21
|
279 return nil
|
Asa@21
|
280 end
|
Asa@21
|
281
|
Asa@63
|
282 function ItemAuditor:AddToQueue(skillId,skillIndex, toQueue)
|
Asa@18
|
283 if Skillet == nil then
|
Asa@18
|
284 self:Print("Skillet not loaded")
|
Asa@21
|
285 return
|
Asa@18
|
286 end
|
Asa@18
|
287 if Skillet.QueueCommandIterate ~= nil then
|
Asa@18
|
288 local queueCommand = Skillet:QueueCommandIterate(tonumber(skillId), toQueue)
|
Asa@18
|
289 Skillet:AddToQueue(queueCommand)
|
Asa@18
|
290 else
|
Asa@18
|
291 Skillet.stitch:AddToQueue(skillIndex, toQueue)
|
Asa@18
|
292 end
|
Asa@18
|
293 end
|
Asa@67
|
294
|
Asa@67
|
295 ItemAuditor.Options.args.qa_options = {
|
Asa@67
|
296 name = "QA Options",
|
Asa@67
|
297 desc = "Control how ItemAuditor integrates with QuickAuctions",
|
Asa@67
|
298 type = 'group',
|
Asa@67
|
299 disabled = function() return not ItemAuditor:IsQACompatible() end,
|
Asa@67
|
300 args = {
|
Asa@67
|
301 toggle_qa = {
|
Asa@67
|
302 type = "toggle",
|
Asa@67
|
303 name = "Enable Quick Auctions",
|
Asa@67
|
304 desc = "This will enable or disable Quick Auctions integration",
|
Asa@67
|
305 get = "IsQAEnabled",
|
Asa@67
|
306 set = "SetQAEnabled",
|
Asa@67
|
307 order = 0,
|
Asa@67
|
308 },
|
Asa@67
|
309 auction_threshold = {
|
Asa@67
|
310 type = "range",
|
Asa@67
|
311 name = "Auction Threshold",
|
Asa@67
|
312 desc = "Don't create items that will make less than this amount of profit",
|
Asa@67
|
313 min = 0.0,
|
Asa@67
|
314 max = 1.0,
|
Asa@67
|
315 isPercent = true,
|
Asa@67
|
316 get = function() return ItemAuditor.db.char.auction_threshold end,
|
Asa@67
|
317 set = function(info, value)
|
Asa@67
|
318 ItemAuditor.db.char.auction_threshold = value
|
Asa@67
|
319 ItemAuditor:RefreshQAGroups()
|
Asa@67
|
320 end,
|
Asa@67
|
321 disabled = 'IsQADisabled',
|
Asa@67
|
322 order = 1,
|
Asa@67
|
323 },
|
Asa@67
|
324 refresh_qa = {
|
Asa@67
|
325 type = "execute",
|
Asa@67
|
326 name = "Refresh QA Thresholds",
|
Asa@67
|
327 desc = "Resets all Quick Auctions thresholds",
|
Asa@67
|
328 func = "RefreshQAGroups",
|
Asa@67
|
329 disabled = 'IsQADisabled',
|
Asa@67
|
330 order = 9,
|
Asa@67
|
331 },
|
Asa@67
|
332 }
|
Asa@67
|
333 }
|
Asa@67
|
334
|
Asa@67
|
335 ItemAuditor.Options.args.queue = {
|
Asa@67
|
336 type = "execute",
|
Asa@67
|
337 name = "queue",
|
Asa@67
|
338 desc = "Queue",
|
Asa@67
|
339 func = "Queue",
|
Asa@67
|
340 guiHidden = true,
|
Asa@67
|
341 } |