You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
9.0 KiB
250 lines
9.0 KiB
local TSM = select(2, ...) |
|
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Shopping") -- loads the localization table |
|
|
|
local private = {itemOperations={}, purchasedCounts={}, itemQuantities={}, operationSettings={}, itemOperationSettings={}, itemOperationMaxPrices={}} |
|
|
|
local function GetCachedItemQuantity(itemString) |
|
local quantity = private.itemQuantities[itemString] |
|
if quantity == nil then |
|
local totalQty = TSM:GetTotalQuantity(itemString) or 0 |
|
totalQty = totalQty + (private.purchasedCounts[itemString] or 0) |
|
private.itemQuantities[itemString] = totalQty |
|
quantity = totalQty |
|
end |
|
return quantity |
|
end |
|
|
|
local function GetOperationSettings(opName) |
|
local settings = private.operationSettings[opName] |
|
if settings == nil then |
|
TSMAPI:UpdateOperation("Shopping", opName) |
|
settings = TSM.operations[opName] |
|
private.operationSettings[opName] = settings or false |
|
end |
|
return settings ~= false and settings or nil |
|
end |
|
|
|
local function GetOperationMaxPrice(itemString, opName, opSettings) |
|
private.itemOperationMaxPrices[itemString] = private.itemOperationMaxPrices[itemString] or {} |
|
local cached = private.itemOperationMaxPrices[itemString][opName] |
|
if cached ~= nil then |
|
return cached ~= false and cached or nil |
|
end |
|
local operationPrice = TSM:GetMaxPrice(opSettings.maxPrice, itemString) |
|
private.itemOperationMaxPrices[itemString][opName] = operationPrice or false |
|
return operationPrice |
|
end |
|
|
|
local function GetItemOperationSettings(itemString, operations) |
|
local settingsList = private.itemOperationSettings[itemString] |
|
if settingsList then return settingsList end |
|
settingsList = {} |
|
for _, opName in ipairs(operations or {}) do |
|
local opSettings = GetOperationSettings(opName) |
|
if opSettings then |
|
tinsert(settingsList, {name=opName, settings=opSettings}) |
|
end |
|
end |
|
private.itemOperationSettings[itemString] = settingsList |
|
return settingsList |
|
end |
|
|
|
local function GetActiveOperations(itemString, operations) |
|
if not operations or #operations == 0 then return end |
|
local totalQty = GetCachedItemQuantity(itemString) |
|
local active = {} |
|
for _, opEntry in ipairs(GetItemOperationSettings(itemString, operations)) do |
|
local opSettings = opEntry.settings |
|
if opSettings then |
|
local maxRestock = tonumber(opSettings.maxRestock) or 0 |
|
if maxRestock <= 0 or totalQty < maxRestock then |
|
tinsert(active, opEntry) |
|
end |
|
end |
|
end |
|
return active |
|
end |
|
|
|
function private.Create(parent) |
|
local frame = CreateFrame("Frame", nil, parent) |
|
frame:SetAllPoints() |
|
|
|
local stContainer = CreateFrame("Frame", nil, frame) |
|
stContainer:SetPoint("TOPLEFT", 0, -35) |
|
stContainer:SetPoint("BOTTOMRIGHT", 0, 30) |
|
TSMAPI.Design:SetFrameColor(stContainer) |
|
frame.groupTree = TSMAPI:CreateGroupTree(stContainer, "Shopping", "Shopping_AH") |
|
private.groupTree = frame.groupTree |
|
|
|
local helpText = TSMAPI.GUI:CreateLabel(frame) |
|
helpText:SetPoint("TOPLEFT") |
|
helpText:SetPoint("TOPRIGHT") |
|
helpText:SetHeight(35) |
|
helpText:SetJustifyH("CENTER") |
|
helpText:SetJustifyV("CENTER") |
|
helpText:SetText(L["Select the groups which you would like to include in the search."]) |
|
frame.helpText = helpText |
|
|
|
local startBtn = TSMAPI.GUI:CreateButton(frame, 16) |
|
startBtn:SetPoint("BOTTOMLEFT", 3, 3) |
|
startBtn:SetPoint("BOTTOMRIGHT", -3, 3) |
|
startBtn:SetHeight(20) |
|
startBtn:SetText(L["Start Search"]) |
|
startBtn:SetScript("OnClick", private.StartScan) |
|
frame.startBtn = startBtn |
|
|
|
return frame |
|
end |
|
|
|
function private.ScanCallback(event, ...) |
|
if event == "filter" then |
|
local filter = ... |
|
local maxPrice |
|
for _, itemString in ipairs(filter.items) do |
|
local operations = GetActiveOperations(itemString, private.itemOperations[itemString]) |
|
if not operations or #operations == 0 then return end |
|
local itemMaxPrice |
|
for _, opEntry in ipairs(operations) do |
|
local opSettings = opEntry.settings |
|
if opSettings.showAboveMaxPrice then |
|
itemMaxPrice = nil |
|
break |
|
end |
|
local operationPrice = GetOperationMaxPrice(itemString, opEntry.name, opSettings) |
|
if operationPrice then |
|
itemMaxPrice = itemMaxPrice and max(itemMaxPrice, operationPrice) or operationPrice |
|
end |
|
end |
|
if itemMaxPrice == nil then |
|
maxPrice = nil |
|
break |
|
end |
|
if not itemMaxPrice then return end |
|
maxPrice = maxPrice and max(maxPrice, itemMaxPrice) or itemMaxPrice |
|
end |
|
return maxPrice |
|
elseif event == "process" then |
|
local itemString, auctionItem = ... |
|
-- filter out auctions according to operation settings |
|
itemString = TSMAPI:GetBaseItemString(itemString, true) |
|
local operations = GetActiveOperations(itemString, private.itemOperations[itemString]) |
|
if not operations or #operations == 0 then return end |
|
local totalQty = GetCachedItemQuantity(itemString) |
|
auctionItem:FilterRecords(function(record) |
|
local buyout = record:GetItemBuyout() or 0 |
|
for _, opEntry in ipairs(operations) do |
|
local opSettings = opEntry.settings |
|
local maxRestock = tonumber(opSettings.maxRestock) or 0 |
|
if maxRestock > 0 and (totalQty + record.count) > maxRestock then |
|
-- this operation can't accept more of this item |
|
elseif opSettings.evenStacks and record.count % 5 ~= 0 then |
|
-- not an even stack for this operation |
|
elseif opSettings.showAboveMaxPrice then |
|
return false |
|
else |
|
local operationPrice = GetOperationMaxPrice(itemString, opEntry.name, opSettings) |
|
if operationPrice and buyout <= operationPrice then |
|
return false |
|
end |
|
end |
|
end |
|
return true |
|
end) |
|
local marketValue |
|
for _, opEntry in ipairs(operations) do |
|
local operationPrice = GetOperationMaxPrice(itemString, opEntry.name, opEntry.settings) |
|
if operationPrice then |
|
marketValue = marketValue and max(marketValue, operationPrice) or operationPrice |
|
end |
|
end |
|
auctionItem:SetMarketValue(marketValue) |
|
return auctionItem |
|
elseif event == "done" then |
|
TSM.Search:SetSearchBarDisabled(false) |
|
return |
|
end |
|
end |
|
|
|
function private.StartScan() |
|
TSMAPI:FireEvent("SHOPPING:GROUPS:STARTSCAN") |
|
TSM.shoppingGroupSearchActive = true |
|
wipe(private.itemOperations) |
|
wipe(private.purchasedCounts) |
|
private.itemQuantities = {} |
|
private.operationSettings = {} |
|
private.itemOperationSettings = {} |
|
private.itemOperationMaxPrices = {} |
|
TSM.searchCallback = function(event, auction) |
|
if event == "OnBuyout" and auction then |
|
local linkItemString = auction.link and TSMAPI:GetItemString(auction.link) |
|
if linkItemString then |
|
local itemString = TSMAPI:GetBaseItemString(linkItemString, true) |
|
private.purchasedCounts[itemString] = (private.purchasedCounts[itemString] or 0) + (auction.count or 0) |
|
private.itemQuantities[itemString] = nil |
|
end |
|
end |
|
end |
|
TSM.groupBuyoutCheck = function(itemString, count, buyoutPerItem) |
|
itemString = TSMAPI:GetBaseItemString(itemString, true) |
|
local operations = GetActiveOperations(itemString, private.itemOperations[itemString]) |
|
if not operations or #operations == 0 then return false end |
|
local totalQty = GetCachedItemQuantity(itemString) |
|
for _, opEntry in ipairs(operations) do |
|
local opSettings = opEntry.settings |
|
local maxRestock = tonumber(opSettings.maxRestock) or 0 |
|
if maxRestock > 0 and (totalQty + count) > maxRestock then |
|
-- doesn't fit this operation |
|
elseif opSettings.evenStacks and count % 5 ~= 0 then |
|
-- not an even stack for this operation |
|
elseif opSettings.showAboveMaxPrice then |
|
return true |
|
else |
|
local operationPrice = GetOperationMaxPrice(itemString, opEntry.name, opSettings) |
|
if operationPrice and buyoutPerItem and buyoutPerItem > 0 and buyoutPerItem <= operationPrice then |
|
return true |
|
end |
|
end |
|
end |
|
return false |
|
end |
|
for groupName, data in pairs(private.groupTree:GetSelectedGroupInfo()) do |
|
groupName = TSMAPI:FormatGroupPath(groupName, true) |
|
for _, opName in ipairs(data.operations) do |
|
TSMAPI:UpdateOperation("Shopping", opName) |
|
local opSettings = TSM.operations[opName] |
|
if not opSettings then |
|
-- operation doesn't exist anymore in Auctioning |
|
TSM:Printf(L["'%s' has a Shopping operation of '%s' which no longer exists. Shopping will ignore this group until this is fixed."], groupName, opName) |
|
else |
|
-- it's a valid operation |
|
for itemString in pairs(data.items) do |
|
local baseItemString = TSMAPI:GetBaseItemString(itemString, true) or itemString |
|
local _, err = TSM:GetMaxPrice(opSettings.maxPrice, itemString) |
|
if err then |
|
TSM:Printf(L["Invalid custom price source for %s. %s"], TSMAPI:GetSafeItemInfo(itemString) or itemString, err) |
|
else |
|
local totalQty = GetCachedItemQuantity(itemString) |
|
local maxRestock = tonumber(opSettings.maxRestock) or 0 |
|
if maxRestock <= 0 or totalQty < maxRestock then |
|
private.itemOperations[baseItemString] = private.itemOperations[baseItemString] or {} |
|
tinsert(private.itemOperations[baseItemString], opName) |
|
end |
|
end |
|
end |
|
end |
|
end |
|
end |
|
|
|
local itemList = {} |
|
for itemString in pairs(private.itemOperations) do |
|
tinsert(itemList, itemString) |
|
end |
|
|
|
TSM.Search:SetSearchBarDisabled(true) |
|
TSM.Util:ShowSearchFrame(nil, L["% Max Price"]) |
|
TSM.Util:StartItemScan(itemList, private.ScanCallback) |
|
end |
|
|
|
do |
|
TSM:AddSidebarFeature(L["TSM Groups"], private.Create) |
|
end
|
|
|