initial commit
This commit is contained in:
326
Core/Service/Auctioning/Util.lua
Normal file
326
Core/Service/Auctioning/Util.lua
Normal file
@@ -0,0 +1,326 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster --
|
||||
-- https://tradeskillmaster.com --
|
||||
-- All Rights Reserved - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local _, TSM = ...
|
||||
local Util = TSM.Auctioning:NewPackage("Util")
|
||||
local TempTable = TSM.Include("Util.TempTable")
|
||||
local Vararg = TSM.Include("Util.Vararg")
|
||||
local String = TSM.Include("Util.String")
|
||||
local Math = TSM.Include("Util.Math")
|
||||
local CustomPrice = TSM.Include("Service.CustomPrice")
|
||||
local PlayerInfo = TSM.Include("Service.PlayerInfo")
|
||||
local private = {
|
||||
priceCache = {},
|
||||
}
|
||||
local INVALID_PRICE = {}
|
||||
local VALID_PRICE_KEYS = {
|
||||
minPrice = true,
|
||||
normalPrice = true,
|
||||
maxPrice = true,
|
||||
undercut = true,
|
||||
cancelRepostThreshold = true,
|
||||
priceReset = true,
|
||||
aboveMax = true,
|
||||
postCap = true,
|
||||
stackSize = true,
|
||||
keepQuantity = true,
|
||||
maxExpires = true,
|
||||
}
|
||||
local IS_GOLD_PRICE_KEY = {
|
||||
minPrice = true,
|
||||
normalPrice = true,
|
||||
maxPrice = true,
|
||||
undercut = TSM.IsWowClassic(),
|
||||
priceReset = true,
|
||||
aboveMax = true,
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Module Functions
|
||||
-- ============================================================================
|
||||
|
||||
function Util.GetPrice(key, operation, itemString)
|
||||
assert(VALID_PRICE_KEYS[key])
|
||||
local cacheKey = key..tostring(operation)..itemString
|
||||
if private.priceCache.updateTime ~= GetTime() then
|
||||
wipe(private.priceCache)
|
||||
private.priceCache.updateTime = GetTime()
|
||||
end
|
||||
if not private.priceCache[cacheKey] then
|
||||
local value = nil
|
||||
if key == "aboveMax" or key == "priceReset" then
|
||||
-- redirect to the selected price (if applicable)
|
||||
local priceKey = operation[key]
|
||||
if VALID_PRICE_KEYS[priceKey] then
|
||||
value = Util.GetPrice(priceKey, operation, itemString)
|
||||
end
|
||||
else
|
||||
value = CustomPrice.GetValue(operation[key], itemString, not IS_GOLD_PRICE_KEY[key])
|
||||
end
|
||||
if not TSM.IsWowClassic() and IS_GOLD_PRICE_KEY[key] then
|
||||
value = value and Math.Ceil(value, COPPER_PER_SILVER) or nil
|
||||
else
|
||||
value = value and Math.Round(value) or nil
|
||||
end
|
||||
local minValue, maxValue = TSM.Operations.Auctioning.GetMinMaxValues(key)
|
||||
private.priceCache[cacheKey] = (value and value >= minValue and value <= maxValue) and value or INVALID_PRICE
|
||||
end
|
||||
if private.priceCache[cacheKey] == INVALID_PRICE then
|
||||
return nil
|
||||
end
|
||||
return private.priceCache[cacheKey]
|
||||
end
|
||||
|
||||
function Util.GetLowestAuction(subRows, itemString, operationSettings, resultTbl)
|
||||
if not TSM.IsWowClassic() then
|
||||
local foundLowest = false
|
||||
for _, subRow in ipairs(subRows) do
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local quantity = subRow:GetQuantities()
|
||||
local timeLeft = subRow:GetListingInfo()
|
||||
if not foundLowest and not Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft) then
|
||||
local ownerStr = subRow:GetOwnerInfo()
|
||||
local _, auctionId = subRow:GetListingInfo()
|
||||
local _, itemMinBid = subRow:GetBidInfo()
|
||||
local firstSeller = strsplit(",", ownerStr)
|
||||
resultTbl.buyout = itemBuyout
|
||||
resultTbl.bid = itemMinBid
|
||||
resultTbl.seller = firstSeller
|
||||
resultTbl.auctionId = auctionId
|
||||
resultTbl.isWhitelist = TSM.db.factionrealm.auctioningOptions.whitelist[strlower(firstSeller)] and true or false
|
||||
resultTbl.isPlayer = PlayerInfo.IsPlayer(firstSeller, true, true, true)
|
||||
if not subRow:HasOwners() then
|
||||
resultTbl.hasInvalidSeller = true
|
||||
end
|
||||
foundLowest = true
|
||||
end
|
||||
end
|
||||
return foundLowest
|
||||
else
|
||||
local hasInvalidSeller = nil
|
||||
local ignoreWhitelist = nil
|
||||
local lowestItemBuyout = nil
|
||||
local lowestAuction = nil
|
||||
for _, subRow in ipairs(subRows) do
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local quantity = subRow:GetQuantities()
|
||||
local timeLeft = subRow:GetListingInfo()
|
||||
if not Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft) then
|
||||
assert(itemBuyout and itemBuyout > 0)
|
||||
lowestItemBuyout = lowestItemBuyout or itemBuyout
|
||||
if itemBuyout == lowestItemBuyout then
|
||||
local ownerStr = subRow:GetOwnerInfo()
|
||||
local _, auctionId = subRow:GetListingInfo()
|
||||
local _, itemMinBid = subRow:GetBidInfo()
|
||||
local temp = TempTable.Acquire()
|
||||
temp.buyout = itemBuyout
|
||||
temp.bid = itemMinBid
|
||||
temp.seller = ownerStr
|
||||
temp.auctionId = auctionId
|
||||
temp.isWhitelist = TSM.db.factionrealm.auctioningOptions.whitelist[strlower(ownerStr)] and true or false
|
||||
temp.isPlayer = PlayerInfo.IsPlayer(ownerStr, true, true, true)
|
||||
if not temp.isWhitelist and not temp.isPlayer then
|
||||
-- there is a non-whitelisted competitor, so we don't care if a whitelisted competitor also posts at this price
|
||||
ignoreWhitelist = true
|
||||
end
|
||||
if not subRow:HasOwners() and next(TSM.db.factionrealm.auctioningOptions.whitelist) then
|
||||
hasInvalidSeller = true
|
||||
end
|
||||
if operationSettings.blacklist then
|
||||
for _, player in Vararg.Iterator(strsplit(",", operationSettings.blacklist)) do
|
||||
if String.SeparatedContains(strlower(ownerStr), ",", strlower(strtrim(player))) then
|
||||
temp.isBlacklist = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if not lowestAuction then
|
||||
lowestAuction = temp
|
||||
elseif private.LowestAuctionCompare(temp, lowestAuction) then
|
||||
TempTable.Release(lowestAuction)
|
||||
lowestAuction = temp
|
||||
else
|
||||
TempTable.Release(temp)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not lowestAuction then
|
||||
return false
|
||||
end
|
||||
for k, v in pairs(lowestAuction) do
|
||||
resultTbl[k] = v
|
||||
end
|
||||
TempTable.Release(lowestAuction)
|
||||
if resultTbl.isWhitelist and ignoreWhitelist then
|
||||
resultTbl.isWhitelist = false
|
||||
end
|
||||
resultTbl.hasInvalidSeller = hasInvalidSeller
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function Util.GetPlayerAuctionCount(subRows, itemString, operationSettings, findBid, findBuyout, findStackSize)
|
||||
local playerQuantity = 0
|
||||
for _, subRow in ipairs(subRows) do
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local quantity = subRow:GetQuantities()
|
||||
local timeLeft = subRow:GetListingInfo()
|
||||
if not Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft) then
|
||||
local _, itemMinBid = subRow:GetBidInfo()
|
||||
if itemMinBid == findBid and itemBuyout == findBuyout and (not TSM.IsWowClassic() or quantity == findStackSize) then
|
||||
local count = private.GetPlayerAuctionCount(subRow)
|
||||
if not TSM.IsWowClassic() and count == 0 and playerQuantity > 0 then
|
||||
-- there's another player's auction after ours, so stop counting
|
||||
break
|
||||
end
|
||||
playerQuantity = playerQuantity + count
|
||||
end
|
||||
end
|
||||
end
|
||||
return playerQuantity
|
||||
end
|
||||
|
||||
function Util.GetPlayerLowestBuyout(subRows, itemString, operationSettings)
|
||||
local lowestItemBuyout, lowestItemAuctionId = nil, nil
|
||||
for _, subRow in ipairs(subRows) do
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local quantity = subRow:GetQuantities()
|
||||
local timeLeft, auctionId = subRow:GetListingInfo()
|
||||
if not lowestItemBuyout and not Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft) and private.GetPlayerAuctionCount(subRow) > 0 then
|
||||
lowestItemBuyout = itemBuyout
|
||||
lowestItemAuctionId = auctionId
|
||||
end
|
||||
end
|
||||
return lowestItemBuyout, lowestItemAuctionId
|
||||
end
|
||||
|
||||
function Util.GetLowestNonPlayerAuctionId(subRows, itemString, operationSettings, lowestItemBuyout)
|
||||
local lowestItemAuctionId = nil
|
||||
for _, subRow in ipairs(subRows) do
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local quantity = subRow:GetQuantities()
|
||||
local timeLeft, auctionId = subRow:GetListingInfo()
|
||||
if not lowestItemAuctionId and not Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft) and private.GetPlayerAuctionCount(subRow) == 0 and itemBuyout == lowestItemBuyout then
|
||||
lowestItemAuctionId = auctionId
|
||||
end
|
||||
end
|
||||
return lowestItemAuctionId
|
||||
end
|
||||
|
||||
function Util.IsPlayerOnlySeller(subRows, itemString, operationSettings)
|
||||
local isOnly = true
|
||||
for _, subRow in ipairs(subRows) do
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local quantity = subRow:GetQuantities()
|
||||
local timeLeft = subRow:GetListingInfo()
|
||||
if isOnly and not Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft) and private.GetPlayerAuctionCount(subRow) < (TSM.IsWowClassic() and 1 or quantity) then
|
||||
isOnly = false
|
||||
end
|
||||
end
|
||||
return isOnly
|
||||
end
|
||||
|
||||
function Util.GetNextLowestItemBuyout(subRows, itemString, lowestAuction, operationSettings)
|
||||
local nextLowestItemBuyout = nil
|
||||
for _, subRow in ipairs(subRows) do
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local quantity = subRow:GetQuantities()
|
||||
local timeLeft, auctionId = subRow:GetListingInfo()
|
||||
local isLower = itemBuyout > lowestAuction.buyout or (itemBuyout == lowestAuction.buyout and auctionId < lowestAuction.auctionId)
|
||||
if not nextLowestItemBuyout and not Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft) and isLower then
|
||||
nextLowestItemBuyout = itemBuyout
|
||||
end
|
||||
end
|
||||
return nextLowestItemBuyout
|
||||
end
|
||||
|
||||
function Util.GetQueueStatus(query)
|
||||
local numProcessed, numConfirmed, numFailed, totalNum = 0, 0, 0, 0
|
||||
query:OrderBy("auctionId", true)
|
||||
for _, row in query:Iterator() do
|
||||
local rowNumStacks, rowNumProcessed, rowNumConfirmed, rowNumFailed = row:GetFields("numStacks", "numProcessed", "numConfirmed", "numFailed")
|
||||
totalNum = totalNum + rowNumStacks
|
||||
numProcessed = numProcessed + rowNumProcessed
|
||||
numConfirmed = numConfirmed + rowNumConfirmed
|
||||
numFailed = numFailed + rowNumFailed
|
||||
end
|
||||
query:Release()
|
||||
return numProcessed, numConfirmed, numFailed, totalNum
|
||||
end
|
||||
|
||||
function Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft)
|
||||
if timeLeft <= operationSettings.ignoreLowDuration then
|
||||
-- ignoring low duration
|
||||
return true
|
||||
elseif TSM.IsWowClassic() and operationSettings.matchStackSize and quantity ~= Util.GetPrice("stackSize", operationSettings, itemString) then
|
||||
-- matching stack size
|
||||
return true
|
||||
elseif operationSettings.priceReset == "ignore" then
|
||||
local minPrice = Util.GetPrice("minPrice", operationSettings, itemString)
|
||||
local undercut = Util.GetPrice("undercut", operationSettings, itemString)
|
||||
if minPrice and itemBuyout - undercut < minPrice then
|
||||
-- ignoring auctions below threshold
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Util.GetFilteredSubRows(query, itemString, operationSettings, result)
|
||||
for _, subRow in query:ItemSubRowIterator(itemString) do
|
||||
local _, itemBuyout = subRow:GetBuyouts()
|
||||
local quantity = subRow:GetQuantities()
|
||||
local timeLeft = subRow:GetListingInfo()
|
||||
if not Util.IsFiltered(itemString, operationSettings, itemBuyout, quantity, timeLeft) then
|
||||
tinsert(result, subRow)
|
||||
end
|
||||
end
|
||||
sort(result, private.SubRowSortHelper)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Private Helper Functions
|
||||
-- ============================================================================
|
||||
|
||||
function private.SubRowSortHelper(a, b)
|
||||
local _, aItemBuyout = a:GetBuyouts()
|
||||
local _, bItemBuyout = b:GetBuyouts()
|
||||
if aItemBuyout ~= bItemBuyout then
|
||||
return aItemBuyout < bItemBuyout
|
||||
end
|
||||
local _, aAuctionId = a:GetListingInfo()
|
||||
local _, bAuctionId = b:GetListingInfo()
|
||||
return aAuctionId > bAuctionId
|
||||
end
|
||||
|
||||
function private.LowestAuctionCompare(a, b)
|
||||
if a.isBlacklist ~= b.isBlacklist then
|
||||
return a.isBlacklist
|
||||
end
|
||||
if a.isWhitelist ~= b.isWhitelist then
|
||||
return a.isWhitelist
|
||||
end
|
||||
if a.auctionId ~= b.auctionId then
|
||||
return a.auctionId > b.auctionId
|
||||
end
|
||||
if a.isPlayer ~= b.isPlayer then
|
||||
return b.isPlayer
|
||||
end
|
||||
return tostring(a) < tostring(b)
|
||||
end
|
||||
|
||||
function private.GetPlayerAuctionCount(subRow)
|
||||
local ownerStr, numOwnerItems = subRow:GetOwnerInfo()
|
||||
if TSM.IsWowClassic() then
|
||||
return PlayerInfo.IsPlayer(ownerStr, true, true, true) and select(2, subRow:GetQuantities()) or 0
|
||||
else
|
||||
return numOwnerItems
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user