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

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