diff --git a/TradeSkillMaster/Auction/AuctionControl.lua b/TradeSkillMaster/Auction/AuctionControl.lua index b891015..9200eda 100644 --- a/TradeSkillMaster/Auction/AuctionControl.lua +++ b/TradeSkillMaster/Auction/AuctionControl.lua @@ -16,6 +16,8 @@ LibStub("AceEvent-3.0"):Embed(private) private.matchList = {} private.currentPage = {} private.shoppingPurchasedCounts = {} +private.shoppingTotalCache = {} +private.shoppingOperationSettings = {} local function GetNumInBags(baseItemString) @@ -46,6 +48,10 @@ end local function GetShoppingTotalQuantity(itemString) itemString = TSMAPI:GetBaseItemString(itemString, true) or itemString + local cached = private.shoppingTotalCache[itemString] + if cached ~= nil then + return cached + end local player, alts = TSMAPI:ModuleAPI("ItemTracker", "playertotal", itemString) if not player then alts = nil @@ -55,7 +61,9 @@ local function GetShoppingTotalQuantity(itemString) local guild = TSMAPI:ModuleAPI("ItemTracker", "guildtotal", itemString) or 0 local auctions = TSMAPI:ModuleAPI("ItemTracker", "auctionstotal", itemString) or 0 local bought = private.shoppingPurchasedCounts[itemString] or 0 - return player + alts + guild + auctions + bought + local total = player + alts + guild + auctions + bought + private.shoppingTotalCache[itemString] = total + return total end local function GetOperationMaxPrice(opSettings, itemString) @@ -68,16 +76,25 @@ local function GetOperationMaxPrice(opSettings, itemString) end end +local function GetShoppingOperationSettings(opName) + local settings = private.shoppingOperationSettings[opName] + if settings == nil then + TSMAPI:UpdateOperation("Shopping", opName) + settings = TSM.operations["Shopping"] and TSM.operations["Shopping"][opName] or nil + private.shoppingOperationSettings[opName] = settings or false + end + return settings ~= false and settings or nil +end + local function ShoppingBuyoutAllowed(itemString, count, perItemBuyout) local operations = TSMAPI:GetItemOperation(itemString, "Shopping") if not operations or #operations == 0 then return true end itemString = TSMAPI:GetBaseItemString(itemString, true) or itemString + local totalQty = GetShoppingTotalQuantity(itemString) for _, opName in ipairs(operations) do - TSMAPI:UpdateOperation("Shopping", opName) - local opSettings = TSM.operations["Shopping"] and TSM.operations["Shopping"][opName] + local opSettings = GetShoppingOperationSettings(opName) if opSettings then local maxRestock = tonumber(opSettings.maxRestock) or 0 - local totalQty = GetShoppingTotalQuantity(itemString) if maxRestock > 0 and (totalQty + count) > maxRestock then -- over restock for this operation elseif opSettings.evenStacks and count % 5 ~= 0 then @@ -339,6 +356,7 @@ function private:AUCTION_ITEM_LIST_UPDATE() if private.module == "Shopping" and prevAuction.itemString and prevAuction.count then local baseItemString = TSMAPI:GetBaseItemString(prevAuction.itemString, true) private.shoppingPurchasedCounts[baseItemString] = (private.shoppingPurchasedCounts[baseItemString] or 0) + prevAuction.count + private.shoppingTotalCache[baseItemString] = nil end TSM:AuctionControlCallback("OnBuyout", prevAuction) @@ -379,6 +397,8 @@ function TSMAPI.AuctionControl:ShowControlButtons(parent, rt, callback, module, private.module = module if module == "Shopping" then wipe(private.shoppingPurchasedCounts) + wipe(private.shoppingTotalCache) + wipe(private.shoppingOperationSettings) end private.postBidPercent = postBidPercent private.postUndercut = postUndercut diff --git a/TradeSkillMaster_AuctionDB/Modules/ChannelSync.lua b/TradeSkillMaster_AuctionDB/Modules/ChannelSync.lua index 0c54943..98af052 100644 --- a/TradeSkillMaster_AuctionDB/Modules/ChannelSync.lua +++ b/TradeSkillMaster_AuctionDB/Modules/ChannelSync.lua @@ -28,6 +28,7 @@ local private = { sendQueue = {}, isSending = false, notifiedNewer = {}, + cachedFullScan = {time=nil, itemIDs=nil}, } local strbyte = string.byte @@ -260,12 +261,17 @@ function ChannelSync:CollectItemIDs(items) end else local scanTime = TSM.db.realm.lastCompleteScan + if private.cachedFullScan.time == scanTime and private.cachedFullScan.itemIDs then + return private.cachedFullScan.itemIDs + end for itemID in pairs(TSM.data) do TSM:DecodeItemData(itemID) if TSM.data[itemID].lastScan == scanTime then tinsert(list, itemID) end end + private.cachedFullScan.time = scanTime + private.cachedFullScan.itemIDs = list end return list end diff --git a/TradeSkillMaster_Auctioning/modules/PostScan.lua b/TradeSkillMaster_Auctioning/modules/PostScan.lua index 5240bb5..35297db 100644 --- a/TradeSkillMaster_Auctioning/modules/PostScan.lua +++ b/TradeSkillMaster_Auctioning/modules/PostScan.lua @@ -16,6 +16,8 @@ local postQueue, currentItem, itemLocations = {}, {}, {} local scanItems local totalToPost, totalPosted, count = 0, 0, 0 local isScanning, GUI +local lastProcessedAuctionDataHash +local lastProcessedAuctionDataCount function Post:ValidateOperation(itemString, operation) local itemLink, salePrice = TSMAPI:Select({2, 11}, TSMAPI:GetSafeItemInfo(itemString)) @@ -529,7 +531,13 @@ end function Post:DoneScanning() isScanning = false if scanItems and next(TSM.Scan.auctionData) then - TSMAPI:ModuleAPI("AuctionDB", "processScanData", TSM.Scan.auctionData, scanItems, time()) + local currentHash = TSM.Scan.auctionDataHash + local currentCount = TSM.Scan.auctionDataCount + if currentHash and currentCount and (currentHash ~= lastProcessedAuctionDataHash or currentCount ~= lastProcessedAuctionDataCount) then + lastProcessedAuctionDataHash = currentHash + lastProcessedAuctionDataCount = currentCount + TSMAPI:ModuleAPI("AuctionDB", "processScanData", TSM.Scan.auctionData, scanItems, time()) + end end return totalToPost end diff --git a/TradeSkillMaster_Auctioning/modules/ScanUtil.lua b/TradeSkillMaster_Auctioning/modules/ScanUtil.lua index 0b2e502..21a52fb 100644 --- a/TradeSkillMaster_Auctioning/modules/ScanUtil.lua +++ b/TradeSkillMaster_Auctioning/modules/ScanUtil.lua @@ -12,6 +12,21 @@ local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- l Scan.auctionData = {} Scan.skipped = {} +Scan.auctionDataHash = nil +Scan.auctionDataCount = 0 + +local function HashAuctionData(scanData) + local hash = 0 + local count = 0 + for itemString, auctionItem in pairs(scanData) do + count = count + 1 + hash = (hash * 31 + (auctionItem and #auctionItem.records or 0)) % 4294967296 + hash = (hash * 31 + (auctionItem and #auctionItem.compactRecords or 0)) % 4294967296 + local itemId = TSMAPI:GetItemID(itemString) or 0 + hash = (hash * 31 + itemId) % 4294967296 + end + return hash, count +end local function CallbackHandler(event, ...) @@ -62,6 +77,8 @@ end function Scan:StartItemScan(itemList) wipe(Scan.auctionData) wipe(Scan.skipped) + Scan.auctionDataHash = nil + Scan.auctionDataCount = 0 TSMAPI:GenerateQueries(itemList, CallbackHandler) TSM.Manage:UpdateStatus("query", 0, -1) end @@ -79,6 +96,7 @@ function Scan:ScanNextFilter() -- NOTE: Our scan progress counter below starts counting from 0 as the first item. if #Scan.filterList == 0 then TSM.Manage:UpdateStatus("scan", Scan.numFilters, Scan.numFilters) + Scan.auctionDataHash, Scan.auctionDataCount = HashAuctionData(Scan.auctionData) return TSM.Manage:ScanComplete() end TSM.Manage:UpdateStatus("scan", Scan.numFilters-#Scan.filterList, Scan.numFilters) diff --git a/TradeSkillMaster_Crafting/Modules/CraftingGUI.lua b/TradeSkillMaster_Crafting/Modules/CraftingGUI.lua index 00da16c..7261d54 100644 --- a/TradeSkillMaster_Crafting/Modules/CraftingGUI.lua +++ b/TradeSkillMaster_Crafting/Modules/CraftingGUI.lua @@ -2638,6 +2638,28 @@ function GUI:UpdateGathering() if not GUI.gatheringFrame or not GUI.gatheringFrame:IsVisible() then return end if not TSM.db.realm.gathering.crafter or not next(TSM.db.realm.gathering.neededMats) then return end + local nameCache = {} + local merchantCache = {} + local function GetItemName(itemString) + local name = nameCache[itemString] + if name == nil then + name = TSMAPI:GetSafeItemInfo(itemString) + if not name then + name = GetItemInfo(itemString) + end + nameCache[itemString] = name or false + end + return name ~= false and name or nil + end + local function MerchantSells(itemString) + local sells = merchantCache[itemString] + if sells == nil then + sells = TSM.Gather:MerchantSells(itemString) and true or false + merchantCache[itemString] = sells + end + return sells + end + -- recheck the craft queue and update neededMats local _, queuedMats = TSM.Queue:GetQueue() local neededMats = {} @@ -2789,7 +2811,7 @@ function GUI:UpdateGathering() else needQty = neededMats[itemString] - (crafterBags[itemString] or 0) end - local name = TSMAPI:GetSafeItemInfo(itemString) or itemString + local name = GetItemName(itemString) or itemString local row -- if task.taskType == L["Search for Mats"] or task.taskType == L["Visit Vendor"] or task.taskType == L["Collect Mail"] or task.taskType == L["Mail Items"] then @@ -2853,10 +2875,7 @@ function GUI:UpdateGathering() availQty = min(need, taskQuantity) -- (crafterBags[itemString] or 0) end availableMats[itemString] = availQty - local name = select(1, TSMAPI:GetSafeItemInfo(itemString)) - if not name then - name = GetItemInfo(itemString) - end + local name = GetItemName(itemString) local color if need == availQty then color = "|cff00ff00" diff --git a/TradeSkillMaster_Shopping/sidebar/Groups.lua b/TradeSkillMaster_Shopping/sidebar/Groups.lua index da7dd7a..0a01fb0 100644 --- a/TradeSkillMaster_Shopping/sidebar/Groups.lua +++ b/TradeSkillMaster_Shopping/sidebar/Groups.lua @@ -1,20 +1,64 @@ local TSM = select(2, ...) local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Shopping") -- loads the localization table -local private = {itemOperations={}, purchasedCounts={}} +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 = TSM:GetTotalQuantity(itemString) or 0 - totalQty = totalQty + (private.purchasedCounts[itemString] or 0) + local totalQty = GetCachedItemQuantity(itemString) local active = {} - for _, opName in ipairs(operations) do - TSMAPI:UpdateOperation("Shopping", opName) - local opSettings = TSM.operations[opName] + 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, opSettings) + tinsert(active, opEntry) end end end @@ -60,12 +104,13 @@ function private.ScanCallback(event, ...) local operations = GetActiveOperations(itemString, private.itemOperations[itemString]) if not operations or #operations == 0 then return end local itemMaxPrice - for _, operation in ipairs(operations) do - if operation.showAboveMaxPrice then + for _, opEntry in ipairs(operations) do + local opSettings = opEntry.settings + if opSettings.showAboveMaxPrice then itemMaxPrice = nil break end - local operationPrice = TSM:GetMaxPrice(operation.maxPrice, itemString) + local operationPrice = GetOperationMaxPrice(itemString, opEntry.name, opSettings) if operationPrice then itemMaxPrice = itemMaxPrice and max(itemMaxPrice, operationPrice) or operationPrice end @@ -84,20 +129,20 @@ function private.ScanCallback(event, ...) 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 - local totalQty = TSM:GetTotalQuantity(itemString) or 0 - totalQty = totalQty + (private.purchasedCounts[itemString] or 0) - for _, operation in ipairs(operations) do - local maxRestock = tonumber(operation.maxRestock) 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 operation.evenStacks and record.count % 5 ~= 0 then + elseif opSettings.evenStacks and record.count % 5 ~= 0 then -- not an even stack for this operation - elseif operation.showAboveMaxPrice then + elseif opSettings.showAboveMaxPrice then return false else - local operationPrice = TSM:GetMaxPrice(operation.maxPrice, itemString) + local operationPrice = GetOperationMaxPrice(itemString, opEntry.name, opSettings) if operationPrice and buyout <= operationPrice then return false end @@ -106,8 +151,8 @@ function private.ScanCallback(event, ...) return true end) local marketValue - for _, operation in ipairs(operations) do - local operationPrice = TSM:GetMaxPrice(operation.maxPrice, itemString) + 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 @@ -125,12 +170,17 @@ function private.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 @@ -138,18 +188,18 @@ function private.StartScan() itemString = TSMAPI:GetBaseItemString(itemString, true) local operations = GetActiveOperations(itemString, private.itemOperations[itemString]) if not operations or #operations == 0 then return false end - for _, operation in ipairs(operations) do - local maxRestock = tonumber(operation.maxRestock) or 0 - local totalQty = TSM:GetTotalQuantity(itemString) or 0 - totalQty = totalQty + (private.purchasedCounts[itemString] or 0) + 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 operation.evenStacks and count % 5 ~= 0 then + elseif opSettings.evenStacks and count % 5 ~= 0 then -- not an even stack for this operation - elseif operation.showAboveMaxPrice then + elseif opSettings.showAboveMaxPrice then return true else - local operationPrice = TSM:GetMaxPrice(operation.maxPrice, itemString) + local operationPrice = GetOperationMaxPrice(itemString, opEntry.name, opSettings) if operationPrice and buyoutPerItem and buyoutPerItem > 0 and buyoutPerItem <= operationPrice then return true end @@ -173,7 +223,7 @@ function private.StartScan() if err then TSM:Printf(L["Invalid custom price source for %s. %s"], TSMAPI:GetSafeItemInfo(itemString) or itemString, err) else - local totalQty = TSM:GetTotalQuantity(itemString) or 0 + 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 {} diff --git a/TradeSkillMaster_Shopping/sidebar/Other.lua b/TradeSkillMaster_Shopping/sidebar/Other.lua index 5372cfd..be0937c 100644 --- a/TradeSkillMaster_Shopping/sidebar/Other.lua +++ b/TradeSkillMaster_Shopping/sidebar/Other.lua @@ -1,7 +1,37 @@ local TSM = select(2, ...) local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Shopping") -- loads the localization table -local private = {} +local private = {sniperItemQuantities={}, sniperOperationSettings={}, sniperItemMaxPrices={}} + +local function GetSniperItemQuantity(itemString) + local quantity = private.sniperItemQuantities[itemString] + if quantity == nil then + quantity = TSM:GetTotalQuantity(itemString) or 0 + private.sniperItemQuantities[itemString] = quantity + end + return quantity +end + +local function GetSniperOperationSettings(opName) + local settings = private.sniperOperationSettings[opName] + if settings == nil then + TSMAPI:UpdateOperation("Shopping", opName) + settings = TSM.operations[opName] + private.sniperOperationSettings[opName] = settings or false + end + return settings ~= false and settings or nil +end + +local function GetSniperOperationMaxPrice(itemString, opName, opSettings) + private.sniperItemMaxPrices[itemString] = private.sniperItemMaxPrices[itemString] or {} + local cached = private.sniperItemMaxPrices[itemString][opName] + if cached ~= nil then + return cached ~= false and cached or nil + end + local opPrice = TSM:GetMaxPrice(opSettings.maxPrice, itemString) + private.sniperItemMaxPrices[itemString][opName] = opPrice or false + return opPrice +end function private.Create(parent) local frame = CreateFrame("Frame", nil, parent) @@ -210,6 +240,9 @@ end function private:StartSniperSearch() + private.sniperItemQuantities = {} + private.sniperOperationSettings = {} + private.sniperItemMaxPrices = {} TSM.Util:ShowSearchFrame(nil, L["% Market Value"]) TSM.Search:SetSearchBarDisabled(true) TSM.Util:StartLastPageScan(private.SniperScanCallback) @@ -230,16 +263,15 @@ function private.SniperScanCallback(event, itemString, auctionItem) vendorPrice = vendor end local operations = TSMAPI:GetItemOperation(itemString, "Shopping") - local totalQty = TSM:GetTotalQuantity(itemString) or 0 + local totalQty = GetSniperItemQuantity(itemString) for _, opName in ipairs(operations or {}) do - TSMAPI:UpdateOperation("Shopping", opName) - local opSettings = TSM.operations[opName] + local opSettings = GetSniperOperationSettings(opName) if opSettings and opSettings.maxPrice then local maxRestock = tonumber(opSettings.maxRestock) or 0 if maxRestock > 0 and totalQty >= maxRestock then -- skip this operation if we're already restocked else - local opPrice = TSM:GetMaxPrice(opSettings.maxPrice, itemString) + local opPrice = GetSniperOperationMaxPrice(itemString, opName, opSettings) if opPrice then maxPrice = maxPrice and max(maxPrice, opPrice) or opPrice end