672 lines
20 KiB
Lua
672 lines
20 KiB
Lua
|
-- ------------------------------------------------------------------------------ --
|
||
|
-- TradeSkillMaster --
|
||
|
-- https://tradeskillmaster.com --
|
||
|
-- All Rights Reserved - Detailed license information included with addon. --
|
||
|
-- ------------------------------------------------------------------------------ --
|
||
|
|
||
|
local _, TSM = ...
|
||
|
local ResultRow = TSM.Init("Service.AuctionScanClasses.ResultRow")
|
||
|
local ItemString = TSM.Include("Util.ItemString")
|
||
|
local ObjectPool = TSM.Include("Util.ObjectPool")
|
||
|
local TempTable = TSM.Include("Util.TempTable")
|
||
|
local Table = TSM.Include("Util.Table")
|
||
|
local ItemInfo = TSM.Include("Service.ItemInfo")
|
||
|
local LibTSMClass = TSM.Include("LibTSMClass")
|
||
|
local Util = TSM.Include("Service.AuctionScanClasses.Util")
|
||
|
local AuctionHouseWrapper = TSM.Include("Service.AuctionHouseWrapper")
|
||
|
local ResultSubRow = TSM.Include("Service.AuctionScanClasses.ResultSubRow")
|
||
|
local ResultRowWrapper = LibTSMClass.DefineClass("ResultRowWrapper")
|
||
|
local private = {
|
||
|
objectPool = ObjectPool.New("AUCTION_SCAN_RESULT_ROW", ResultRowWrapper),
|
||
|
}
|
||
|
local SUB_ROW_SEARCH_INDEX_MULTIPLIER = 1000000
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- Module Functions
|
||
|
-- ============================================================================
|
||
|
|
||
|
function ResultRow.Get(query, itemKey, minPrice, totalQuantity)
|
||
|
local row = private.objectPool:Get()
|
||
|
row:_Acquire(query, itemKey, minPrice, totalQuantity)
|
||
|
return row
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- ResultRowWrapper - Meta Class Methods
|
||
|
-- ============================================================================
|
||
|
|
||
|
function ResultRowWrapper.__init(self)
|
||
|
self._query = nil
|
||
|
self._items = {}
|
||
|
self._baseItemString = nil
|
||
|
self._canHaveNonBaseItemString = nil
|
||
|
self._minPrice = nil
|
||
|
self._hasItemInfo = nil
|
||
|
self._isCommodity = nil
|
||
|
self._notFiltered = false
|
||
|
self._searchIndex = nil
|
||
|
self._subRows = {}
|
||
|
self._minBrowseId = nil
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper._Acquire(self, query, item, minPrice, totalQuantity)
|
||
|
self._query = query
|
||
|
if TSM.IsWowClassic() then
|
||
|
assert(not minPrice and not totalQuantity)
|
||
|
tinsert(self._items, item)
|
||
|
self._baseItemString = ItemString.GetBase(item)
|
||
|
else
|
||
|
item._minPrice = minPrice
|
||
|
item._totalQuantity = totalQuantity
|
||
|
tinsert(self._items, item)
|
||
|
self._baseItemString = ItemString.GetBaseFromItemKey(item)
|
||
|
end
|
||
|
self._canHaveNonBaseItemString = nil
|
||
|
self._minPrice = nil
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- ResultRowWrapper - Public Class Methods
|
||
|
-- ============================================================================
|
||
|
|
||
|
function ResultRowWrapper.Merge(self, item, minPrice, totalQuantity)
|
||
|
-- check if we already have this item
|
||
|
for i = 1, #self._items do
|
||
|
if item == self._items[i] then
|
||
|
return
|
||
|
end
|
||
|
if type(item) == "table" then
|
||
|
local isEqual = true
|
||
|
for k in pairs(item) do
|
||
|
if item[k] ~= self._items[i][k] then
|
||
|
isEqual = false
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
if isEqual then
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
self._hasItemInfo = nil
|
||
|
if TSM.IsWowClassic() then
|
||
|
assert(not minPrice and not totalQuantity)
|
||
|
assert(self._baseItemString == ItemString.GetBase(item))
|
||
|
tinsert(self._items, item)
|
||
|
self._notFiltered = false
|
||
|
else
|
||
|
assert(self._baseItemString == ItemString.GetBaseFromItemKey(item))
|
||
|
item._minPrice = minPrice
|
||
|
item._totalQuantity = totalQuantity
|
||
|
tinsert(self._items, item)
|
||
|
self._notFiltered = false
|
||
|
end
|
||
|
self._canHaveNonBaseItemString = nil
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.Release(self)
|
||
|
wipe(self._items)
|
||
|
self._baseItemString = nil
|
||
|
self._canHaveNonBaseItemString = nil
|
||
|
self._minPrice = nil
|
||
|
self._hasItemInfo = nil
|
||
|
self._isCommodity = nil
|
||
|
self._notFiltered = false
|
||
|
self._searchIndex = nil
|
||
|
self._minBrowseId = nil
|
||
|
for _, subRow in pairs(self._subRows) do
|
||
|
subRow:Release()
|
||
|
end
|
||
|
wipe(self._subRows)
|
||
|
private.objectPool:Recycle(self)
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.IsSubRow(self)
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.PopulateBrowseData(self)
|
||
|
assert(self._baseItemString)
|
||
|
if self._hasItemInfo then
|
||
|
-- already have our item info
|
||
|
return true
|
||
|
elseif not Util.HasItemInfo(self._baseItemString) then
|
||
|
-- don't have item info yet
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
if not TSM.IsWowClassic() then
|
||
|
-- cache the commodity status since it's referenced a ton
|
||
|
if self._isCommodity == nil then
|
||
|
self._isCommodity = ItemInfo.IsCommodity(self._baseItemString)
|
||
|
assert(self._isCommodity ~= nil)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- check if we have info for all the items and try to fetch it if not
|
||
|
local missingInfo = false
|
||
|
for _, item in ipairs(self._items) do
|
||
|
if TSM.IsWowClassic() then
|
||
|
if not Util.HasItemInfo(ItemString.Get(item)) then
|
||
|
missingInfo = true
|
||
|
end
|
||
|
else
|
||
|
if not item._itemKeyInfo then
|
||
|
item._itemKeyInfo = C_AuctionHouse.GetItemKeyInfo(item, true)
|
||
|
if not item._itemKeyInfo then
|
||
|
missingInfo = true
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
if missingInfo then
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
self._hasItemInfo = true
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.IsFiltered(self, query)
|
||
|
assert(#self._items > 0)
|
||
|
if self._notFiltered then
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
-- check if the whole row is filtered
|
||
|
if query:_IsFiltered(self, false) then
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
-- filter our items
|
||
|
for i = #self._items, 1, -1 do
|
||
|
if query:_IsFiltered(self, false, self._items[i]) then
|
||
|
tremove(self._items, i)
|
||
|
end
|
||
|
end
|
||
|
self._canHaveNonBaseItemString = nil
|
||
|
self._minPrice = nil
|
||
|
if #self._items == 0 then
|
||
|
-- no more items, so the entire row is filtered
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
-- not filtered (cache this result)
|
||
|
self._notFiltered = true
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.SearchReset(self)
|
||
|
assert(not TSM.IsWowClassic())
|
||
|
assert(#self._items > 0)
|
||
|
self._searchIndex = 1
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.SearchNext(self)
|
||
|
assert(not TSM.IsWowClassic())
|
||
|
assert(self._searchIndex)
|
||
|
if self._searchIndex == #self._items then
|
||
|
self._searchIndex = nil
|
||
|
return false
|
||
|
end
|
||
|
self._searchIndex = self._searchIndex + 1
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.SearchIsReady(self)
|
||
|
assert(not TSM.IsWowClassic())
|
||
|
assert(self._searchIndex)
|
||
|
-- the client needs to have the item key info cached before we can run the search
|
||
|
return C_AuctionHouse.GetItemKeyInfo(self._items[self._searchIndex], true) and true or false
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.SearchSend(self)
|
||
|
assert(not TSM.IsWowClassic())
|
||
|
assert(self._searchIndex)
|
||
|
local itemKey = self._items[self._searchIndex]
|
||
|
-- send a sell query if we don't have browse results for the itemKey
|
||
|
-- for some reason sell queries don't work for commodities or pets
|
||
|
local isSellQuery = not self._isCommodity and not ItemString.IsPet(self._baseItemString) and not itemKey._totalQuantity
|
||
|
return AuctionHouseWrapper.SendSearchQuery(itemKey, isSellQuery)
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.HasCachedSearchData(self)
|
||
|
local itemKey = self._items[self._searchIndex]
|
||
|
if self._isCommodity then
|
||
|
return C_AuctionHouse.HasFullCommoditySearchResults(itemKey.itemID)
|
||
|
else
|
||
|
return C_AuctionHouse.HasFullItemSearchResults(itemKey)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.SearchCheckStatus(self)
|
||
|
assert(not TSM.IsWowClassic())
|
||
|
assert(self._searchIndex)
|
||
|
local itemKey = self._items[self._searchIndex]
|
||
|
|
||
|
-- check if we have the full results
|
||
|
local hasFullResults = nil
|
||
|
if self._isCommodity then
|
||
|
hasFullResults = C_AuctionHouse.HasFullCommoditySearchResults(itemKey.itemID)
|
||
|
else
|
||
|
hasFullResults = C_AuctionHouse.HasFullItemSearchResults(itemKey)
|
||
|
end
|
||
|
if hasFullResults then
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
-- request more results
|
||
|
if self._isCommodity then
|
||
|
return false, AuctionHouseWrapper.RequestMoreCommoditySearchResults(itemKey.itemID)
|
||
|
else
|
||
|
return false, AuctionHouseWrapper.RequestMoreItemSearchResults(itemKey)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.PopulateSubRows(self, browseId, index, itemLink)
|
||
|
if TSM.IsWowClassic() then
|
||
|
-- remove any prior results with a different browseId
|
||
|
assert(index and not self._searchIndex)
|
||
|
local subRow = ResultSubRow.Get(self)
|
||
|
subRow:_SetRawData(index, browseId, itemLink)
|
||
|
local _, hashNoSeller = subRow:GetHashes()
|
||
|
if self._minBrowseId and self._minBrowseId ~= browseId then
|
||
|
-- check if this subRow already exists with a prior browseId
|
||
|
for i, existingSubRow in ipairs(self._subRows) do
|
||
|
local _, existingHashNoSeller = existingSubRow:GetHashes()
|
||
|
local _, _, existingBrowseId = existingSubRow:GetListingInfo()
|
||
|
if hashNoSeller == existingHashNoSeller and browseId ~= existingBrowseId then
|
||
|
-- replace the existing subRow
|
||
|
existingSubRow:Release()
|
||
|
self._subRows[i] = subRow
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
tinsert(self._subRows, subRow)
|
||
|
else
|
||
|
assert(self._searchIndex and not index)
|
||
|
local subRowOffset = self._searchIndex * SUB_ROW_SEARCH_INDEX_MULTIPLIER
|
||
|
local itemKey = self._items[self._searchIndex]
|
||
|
local numAuctions = nil
|
||
|
if self:IsCommodity() then
|
||
|
numAuctions = C_AuctionHouse.GetNumCommoditySearchResults(itemKey.itemID)
|
||
|
else
|
||
|
numAuctions = C_AuctionHouse.GetNumItemSearchResults(itemKey)
|
||
|
end
|
||
|
if itemKey._numAuctions and numAuctions ~= itemKey._numAuctions then
|
||
|
-- the results changed so clear out our existing data
|
||
|
for i = itemKey._numAuctions, 1, -1 do
|
||
|
if i > numAuctions then
|
||
|
self._subRows[subRowOffset + i]:Release()
|
||
|
self._subRows[subRowOffset + i] = nil
|
||
|
else
|
||
|
self._subRows[subRowOffset + i]:_SetRawData(nil)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
itemKey._numAuctions = numAuctions
|
||
|
for i = 1, numAuctions do
|
||
|
self._subRows[subRowOffset + i] = self._subRows[subRowOffset + i] or ResultSubRow.Get(self)
|
||
|
local subRow = self._subRows[subRowOffset + i]
|
||
|
if not subRow:HasRawData() or not subRow:HasOwners() then
|
||
|
local result = nil
|
||
|
if self:IsCommodity() then
|
||
|
result = C_AuctionHouse.GetCommoditySearchResultInfo(itemKey.itemID, i)
|
||
|
else
|
||
|
result = C_AuctionHouse.GetItemSearchResultInfo(itemKey, i)
|
||
|
end
|
||
|
subRow:_SetRawData(result, browseId)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
self._minBrowseId = min(self._minBrowseId or math.huge, browseId)
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.FilterSubRows(self, query)
|
||
|
local subRowOffset = TSM.IsWowClassic() and 0 or (self._searchIndex * SUB_ROW_SEARCH_INDEX_MULTIPLIER)
|
||
|
if TSM.IsWowClassic() then
|
||
|
for i = #self._subRows, 1, -1 do
|
||
|
if query:_IsFiltered(self._subRows[i], true) then
|
||
|
self:_RemoveSubRowByIndex(i)
|
||
|
end
|
||
|
end
|
||
|
else
|
||
|
local itemKey = self._items[self._searchIndex]
|
||
|
for j = itemKey._numAuctions, 1, -1 do
|
||
|
local subRow = self._subRows[subRowOffset + j]
|
||
|
if query:_IsFiltered(subRow, true) then
|
||
|
self:_RemoveSubRowByIndex(j)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- merge subRows with identical hashes
|
||
|
local numSubRows = nil
|
||
|
local hashIndexLookup = TempTable.Acquire()
|
||
|
local index = 1
|
||
|
while true do
|
||
|
numSubRows = TSM.IsWowClassic() and #self._subRows or self._items[self._searchIndex]._numAuctions
|
||
|
if index > numSubRows then
|
||
|
break
|
||
|
end
|
||
|
local subRow = self._subRows[subRowOffset + index]
|
||
|
local hash = subRow:GetHashes()
|
||
|
local prevIndex = hashIndexLookup[hash]
|
||
|
if prevIndex then
|
||
|
-- there was a previous subRow with the same hash
|
||
|
self._subRows[subRowOffset + prevIndex]:Merge(subRow)
|
||
|
-- remove this subRow
|
||
|
self:_RemoveSubRowByIndex(index)
|
||
|
else
|
||
|
hashIndexLookup[hash] = index
|
||
|
index = index + 1
|
||
|
end
|
||
|
end
|
||
|
TempTable.Release(hashIndexLookup)
|
||
|
return numSubRows == 0
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetNumSubRows(self)
|
||
|
if TSM.IsWowClassic() then
|
||
|
return #self._subRows
|
||
|
else
|
||
|
local result = 0
|
||
|
for _, itemKey in ipairs(self._items) do
|
||
|
result = result + (itemKey._numAuctions or 0)
|
||
|
end
|
||
|
return result
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.SubRowIterator(self, searchOnly)
|
||
|
if TSM.IsWowClassic() then
|
||
|
return ipairs(self._subRows)
|
||
|
else
|
||
|
if searchOnly then
|
||
|
local result = TempTable.Acquire()
|
||
|
assert(self._searchIndex)
|
||
|
for i = 1, self._items[self._searchIndex]._numAuctions do
|
||
|
local subRow = self._subRows[self._searchIndex * SUB_ROW_SEARCH_INDEX_MULTIPLIER + i]
|
||
|
assert(subRow)
|
||
|
tinsert(result, subRow)
|
||
|
end
|
||
|
return TempTable.Iterator(result)
|
||
|
else
|
||
|
return private.SubRowIteratorHelper, self, SUB_ROW_SEARCH_INDEX_MULTIPLIER
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.IsCommodity(self)
|
||
|
assert(self._isCommodity ~= nil)
|
||
|
return self._isCommodity
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.HasItemInfo(self)
|
||
|
return self._hasItemInfo
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetBaseItemString(self)
|
||
|
return self._baseItemString
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetItemString(self)
|
||
|
if TSM.IsWowClassic() or not self._hasItemInfo or self._canHaveNonBaseItemString then
|
||
|
return nil
|
||
|
end
|
||
|
if self._canHaveNonBaseItemString == nil then
|
||
|
for _, itemKey in ipairs(self._items) do
|
||
|
if ItemInfo.CanHaveVariations(self._baseItemString) or itemKey.battlePetSpeciesID ~= 0 or itemKey.itemSuffix ~= 0 or itemKey.itemLevel ~= 0 then
|
||
|
-- this item can have variations, so we don't know its itemString
|
||
|
self._canHaveNonBaseItemString = true
|
||
|
return nil
|
||
|
end
|
||
|
end
|
||
|
self._canHaveNonBaseItemString = false
|
||
|
end
|
||
|
return self._baseItemString
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetItemInfo(self, itemKey)
|
||
|
if TSM.IsWowClassic() or not self._hasItemInfo then
|
||
|
return nil, nil, nil, nil
|
||
|
end
|
||
|
itemKey = itemKey or (#self._items == 1 and self._items[1] or nil)
|
||
|
assert(not itemKey or itemKey._itemKeyInfo)
|
||
|
local baseItemString = self:GetBaseItemString()
|
||
|
local itemString = self:GetItemString()
|
||
|
local itemName, quality, itemLevel, maxItemLevel = nil, nil, nil, nil
|
||
|
if itemString then
|
||
|
-- this item can't have variations, so we can know the name / level / quality
|
||
|
itemName = ItemInfo.GetName(baseItemString)
|
||
|
itemLevel = ItemInfo.GetItemLevel(baseItemString)
|
||
|
quality = ItemInfo.GetQuality(baseItemString)
|
||
|
assert(itemName and itemLevel and quality)
|
||
|
else
|
||
|
if itemKey and not itemKey._totalQuantity then
|
||
|
-- if we didn't do a browse, then don't use this itemKey
|
||
|
itemKey = nil
|
||
|
end
|
||
|
if itemKey then
|
||
|
-- grab the name from the itemKeyInfo
|
||
|
itemName = itemKey._itemKeyInfo.itemName
|
||
|
assert(itemName)
|
||
|
end
|
||
|
local hasSingleAuction = itemKey and itemKey._totalQuantity == 1
|
||
|
if hasSingleAuction then
|
||
|
-- grab the quality from the itemKeyInfo since there's only one listing
|
||
|
quality = itemKey._itemKeyInfo.quality
|
||
|
assert(quality)
|
||
|
end
|
||
|
if not ItemString.IsPet(self._baseItemString) then
|
||
|
-- for non-pets, we can maybe grab the itemLevel from the itemKey
|
||
|
if itemKey then
|
||
|
itemLevel = itemKey.itemLevel ~= 0 and itemKey.itemLevel or nil
|
||
|
else
|
||
|
-- only use the itemLevel from the itemKeys if they are all the same
|
||
|
local itemKeyItemLevel = self._items[1].itemLevel
|
||
|
for i = 2, #self._items do
|
||
|
if self._items[i].itemLevel ~= itemKeyItemLevel then
|
||
|
itemKeyItemLevel = nil
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
itemLevel = (itemKeyItemLevel or 0) ~= 0 and itemKeyItemLevel or nil
|
||
|
end
|
||
|
elseif itemKey and itemKey._itemKeyInfo.battlePetLink then
|
||
|
if hasSingleAuction then
|
||
|
-- grab the itemLevel from the link since there's only one listing
|
||
|
itemLevel = ItemInfo.GetItemLevel(itemKey._itemKeyInfo.battlePetLink)
|
||
|
assert(itemLevel)
|
||
|
else
|
||
|
-- grab the maxItemLevel from the link
|
||
|
maxItemLevel = ItemInfo.GetItemLevel(itemKey._itemKeyInfo.battlePetLink)
|
||
|
assert(maxItemLevel)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
return itemName, quality, itemLevel, maxItemLevel
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetBuyouts(self, resultItemKey)
|
||
|
if TSM.IsWowClassic() then
|
||
|
return nil, nil, nil
|
||
|
end
|
||
|
assert(#self._items > 0)
|
||
|
if resultItemKey then
|
||
|
return nil, nil, resultItemKey._minPrice
|
||
|
else
|
||
|
if self._minPrice == nil then
|
||
|
for _, itemKey in ipairs(self._items) do
|
||
|
if not itemKey._minPrice then
|
||
|
self._minPrice = -1
|
||
|
return nil, nil, nil
|
||
|
end
|
||
|
self._minPrice = min(self._minPrice or math.huge, itemKey._minPrice)
|
||
|
end
|
||
|
elseif self._minPrice == -1 then
|
||
|
return nil, nil, nil
|
||
|
end
|
||
|
return nil, nil, self._minPrice
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetQuantities(self)
|
||
|
local totalQuantity = 0
|
||
|
if TSM.IsWowClassic() then
|
||
|
for _, subRow in ipairs(self._subRows) do
|
||
|
local quantity, numAuctions = subRow:GetQuantities()
|
||
|
totalQuantity = totalQuantity + quantity * numAuctions
|
||
|
end
|
||
|
else
|
||
|
for _, itemKey in ipairs(self._items) do
|
||
|
if not itemKey._totalQuantity then
|
||
|
return
|
||
|
end
|
||
|
totalQuantity = totalQuantity + itemKey._totalQuantity
|
||
|
end
|
||
|
end
|
||
|
return totalQuantity, 1
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetMaxQuantities(self)
|
||
|
assert(self:IsCommodity())
|
||
|
local totalQuantity = 0
|
||
|
for _, subRow in self:SubRowIterator() do
|
||
|
local _, numOwnerItems = subRow:GetOwnerInfo()
|
||
|
local quantityAvailable = subRow:GetQuantities() - numOwnerItems
|
||
|
totalQuantity = totalQuantity + quantityAvailable
|
||
|
end
|
||
|
return totalQuantity
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.RemoveSubRow(self, subRow)
|
||
|
local index = Table.KeyByValue(self._subRows, subRow)
|
||
|
if TSM.IsWowClassic() then
|
||
|
self:_RemoveSubRowByIndex(index)
|
||
|
else
|
||
|
local searchIndex = floor(index / SUB_ROW_SEARCH_INDEX_MULTIPLIER)
|
||
|
index = index % SUB_ROW_SEARCH_INDEX_MULTIPLIER
|
||
|
assert(self._subRows[searchIndex * SUB_ROW_SEARCH_INDEX_MULTIPLIER + index] == subRow)
|
||
|
local prevSearchIndex = self._searchIndex
|
||
|
self._searchIndex = searchIndex
|
||
|
self:_RemoveSubRowByIndex(index)
|
||
|
self._searchIndex = prevSearchIndex
|
||
|
end
|
||
|
self._query:_OnSubRowRemoved(self)
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.WipeSearchResults(self)
|
||
|
wipe(self._subRows)
|
||
|
if not TSM.IsWowClassic() then
|
||
|
for _, itemKey in ipairs(self._items) do
|
||
|
itemKey._numAuctions = nil
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetQuery(self)
|
||
|
return self._query
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.DecrementQuantity(self, amount)
|
||
|
assert(self:IsCommodity() and not TSM.IsWowClassic() and #self._items == 1)
|
||
|
local index = 1
|
||
|
while amount > 0 do
|
||
|
local subRow = self._subRows[index + SUB_ROW_SEARCH_INDEX_MULTIPLIER]
|
||
|
assert(subRow)
|
||
|
local _, numOwnerItems = subRow:GetOwnerInfo()
|
||
|
local quantityAvailable = subRow:GetQuantities() - numOwnerItems
|
||
|
if quantityAvailable > 0 then
|
||
|
local usedQuantity = min(quantityAvailable, amount)
|
||
|
local prevItemBuyout = floor(subRow._buyout / subRow._quantity)
|
||
|
amount = amount - usedQuantity
|
||
|
subRow._quantity = subRow._quantity - usedQuantity
|
||
|
subRow._buyout = prevItemBuyout * subRow._quantity
|
||
|
subRow._minBid = subRow._buyout
|
||
|
if numOwnerItems == 0 and subRow._quantity == 0 then
|
||
|
self:RemoveSubRow(subRow)
|
||
|
else
|
||
|
index = index + 1
|
||
|
end
|
||
|
else
|
||
|
index = index + 1
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper.GetMinBrowseId(self)
|
||
|
return self._minBrowseId
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- ResultRowWrapper - Private Class Methods
|
||
|
-- ============================================================================
|
||
|
|
||
|
function ResultRowWrapper._RemoveSubRowByIndex(self, index)
|
||
|
if TSM.IsWowClassic() then
|
||
|
self._subRows[index]:Release()
|
||
|
tremove(self._subRows, index)
|
||
|
else
|
||
|
local subRowOffset = self._searchIndex * SUB_ROW_SEARCH_INDEX_MULTIPLIER
|
||
|
local itemKey = self._items[self._searchIndex]
|
||
|
self._subRows[subRowOffset + index]:Release()
|
||
|
self._subRows[subRowOffset + index] = nil
|
||
|
-- shift the other subRows for this item down
|
||
|
for i = index, itemKey._numAuctions - 1 do
|
||
|
self._subRows[subRowOffset + i] = self._subRows[subRowOffset + i + 1]
|
||
|
end
|
||
|
self._subRows[subRowOffset + itemKey._numAuctions] = nil
|
||
|
itemKey._numAuctions = itemKey._numAuctions - 1
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ResultRowWrapper._GetSearchProgress(self)
|
||
|
assert(not TSM.IsWowClassic())
|
||
|
if #self._items == 0 then
|
||
|
return 0
|
||
|
end
|
||
|
local numSearched = 0
|
||
|
for _, itemKey in ipairs(self._items) do
|
||
|
if itemKey._numAuctions then
|
||
|
numSearched = numSearched + 1
|
||
|
end
|
||
|
end
|
||
|
return numSearched / #self._items
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
-- ============================================================================
|
||
|
-- Private Helper Functions
|
||
|
-- ============================================================================
|
||
|
|
||
|
function private.SubRowIteratorHelper(row, index)
|
||
|
local searchIndex = floor(index / SUB_ROW_SEARCH_INDEX_MULTIPLIER)
|
||
|
local subRowIndex = index % SUB_ROW_SEARCH_INDEX_MULTIPLIER
|
||
|
while true do
|
||
|
local itemKey = row._items[searchIndex]
|
||
|
if not itemKey then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
if subRowIndex >= (itemKey._numAuctions or 0) then
|
||
|
searchIndex = searchIndex + 1
|
||
|
subRowIndex = 0
|
||
|
else
|
||
|
subRowIndex = subRowIndex + 1
|
||
|
index = searchIndex * SUB_ROW_SEARCH_INDEX_MULTIPLIER + subRowIndex
|
||
|
return index, row._subRows[index]
|
||
|
end
|
||
|
end
|
||
|
end
|