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.

217 lines
8.4 KiB

4 years ago
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster_Auctioning --
-- http://www.curse.com/addons/wow/tradeskillmaster_auctioning --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local TSM = select(2, ...)
local Scan = TSM:NewModule("Scan", "AceEvent-3.0")
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster_Auctioning") -- loads the localization table
Scan.auctionData = {}
Scan.skipped = {}
local function CallbackHandler(event, ...)
if event == "QUERY_COMPLETE" then
local filterList = ...
Scan.filterList = filterList
Scan.numFilters = #filterList
Scan:ScanNextFilter()
elseif event == "QUERY_UPDATE" then
local current, total, skipped = ...
TSM.Manage:UpdateStatus("query", current, total)
for _, itemString in ipairs(skipped) do
TSM.Manage:ProcessScannedItem(itemString)
tinsert(Scan.skipped, itemString)
end
elseif event == "SCAN_PAGE_UPDATE" then
-- Simply forward the "currently received" and "total" page counts
-- for the current item we're scanning.
-- NOTE: Private servers sometimes give totally insane "total page counts"
-- on the first response, such as "page 1/142", but those server errors
-- always correct themselves to "page 2/REAL" when the scan has reached
-- page 2. There's nothing we can do to avoid that rare page-count issue
-- (which happens on many popular private servers, such as Warmane).
4 years ago
TSM.Manage:UpdateStatus("page", ...)
elseif event == "SCAN_INTERRUPTED" or event == "INTERRUPTED" then
-- We've been interrupted by the Auction House closing.
-- NOTE: "SCAN_INTERRUPTED" is from LibAuctionScan-1.0, which isn't used
-- by TSM anymore, and "INTERRUPTED" is from "TSM/Auction/AuctionScanning.lua",
-- which is what this scanner uses nowadays.
4 years ago
TSM.Manage:ScanComplete(true)
elseif event == "SCAN_TIMEOUT" then
tremove(Scan.filterList, 1)
Scan:ScanNextFilter()
elseif event == "SCAN_COMPLETE" then
local data = ...
for _, itemString in ipairs(Scan.filterList[1].items) do
-- make sure we haven't already scanned this item (possible with common search terms)
if not Scan.auctionData[itemString] then
Scan:ProcessItem(itemString, data[itemString])
TSM.Manage:ProcessScannedItem(itemString)
end
end
tremove(Scan.filterList, 1)
Scan:ScanNextFilter()
end
end
function Scan:StartItemScan(itemList)
wipe(Scan.auctionData)
wipe(Scan.skipped)
TSMAPI:GenerateQueries(itemList, CallbackHandler)
TSM.Manage:UpdateStatus("query", 0, -1)
end
function Scan:ScanNextFilter()
-- We must reset the page counter, otherwise the next scan will keep the
-- page count of the previous item until we receive "SCAN_PAGE_UPDATE".
-- NOTE: The "nil" signals that we don't know the item's page count yet.
-- NOTE: The recipient may want to ignore "page" events that have nil values
-- and not update their status bars based on those, since we send these empty
-- page events before we start each new scan!
TSM.Manage:UpdateStatus("page", nil, nil)
-- Now update the scan counter.
-- NOTE: Our scan progress counter below starts counting from 0 as the first item.
4 years ago
if #Scan.filterList == 0 then
TSM.Manage:UpdateStatus("scan", Scan.numFilters, Scan.numFilters)
return TSM.Manage:ScanComplete()
end
TSM.Manage:UpdateStatus("scan", Scan.numFilters-#Scan.filterList, Scan.numFilters)
TSMAPI.AuctionScan:RunQuery(Scan.filterList[1], CallbackHandler, true)
end
function Scan:ProcessItem(itemString, auctionItem)
if not itemString or not auctionItem then return end
auctionItem:SetRecordParams({"GetItemBuyout", "GetItemDisplayedBid", "seller", "count"})
auctionItem:PopulateCompactRecords()
auctionItem:SetAlts(TSM.db.realm.player)
4 years ago
if #auctionItem.records > 0 then
auctionItem:SetMarketValue(TSMAPI:GetItemValue(itemString, "DBMarket"))
Scan.auctionData[itemString] = auctionItem
end
end
function Scan:ShouldIgnoreAuction(record, operation)
if type(operation) ~= "table" then return end
if record.timeLeft <= operation.ignoreLowDuration then
-- ignoring low duration
return true
elseif operation.matchStackSize and record.count ~= operation.stackSize then
-- matching stack size
return true
else
local minPrice = TSM.Util:GetItemPrices(operation, record.parent:GetItemString()).minPrice
if operation.priceReset == "ignore" and minPrice and record:GetItemBuyout() and record:GetItemBuyout() <= minPrice then
-- ignoring auctions below threshold
return true
end
end
end
-- This gets how many auctions are posted specifically on this tier, it does not get how many of the items they up at this tier
-- but purely the number of auctions
function Scan:GetPlayerAuctionCount(itemString, findBuyout, findBid, findQuantity, operation)
findBuyout = floor(findBuyout)
findBid = floor(findBid)
local quantity = 0
for _, record in ipairs(Scan.auctionData[itemString].compactRecords) do
if not Scan:ShouldIgnoreAuction(record, operation) and record:IsPlayer() then
if record:GetItemBuyout() == findBuyout and record:GetItemDisplayedBid() == findBid and record.count == findQuantity then
quantity = quantity + record.numAuctions
end
end
end
return quantity
end
-- gets the buyout / bid of the second lowest auction for this item
function Scan:GetSecondLowest(itemString, lowestBuyout, operation)
local auctionItem = Scan.auctionData[itemString]
if not auctionItem then return end
local buyout, bid
for _, record in ipairs(auctionItem.compactRecords) do
if not Scan:ShouldIgnoreAuction(record, operation) then
local recordBuyout = record:GetItemBuyout()
if recordBuyout and (not buyout or recordBuyout < buyout) and recordBuyout > lowestBuyout then
buyout, bid = recordBuyout, record:GetItemDisplayedBid()
end
end
end
return buyout, bid
end
-- Find out the lowest price for this item
function Scan:GetLowestAuction(auctionItem, operation)
if type(auctionItem) == "string" or type(auctionItem) == "number" then -- it's an itemString
auctionItem = Scan.auctionData[auctionItem]
end
if not auctionItem then return end
-- Find lowest
local buyout, bid, owner, invalidSellerEntry
for _, record in ipairs(auctionItem.compactRecords) do
if not Scan:ShouldIgnoreAuction(record, operation) then
local recordBuyout = record:GetItemBuyout()
if recordBuyout then
local recordBid = record:GetItemDisplayedBid()
if not buyout or recordBuyout < buyout or (recordBuyout == buyout and recordBid < bid) then
buyout, bid, owner = recordBuyout, recordBid, record.seller
end
end
end
end
if owner == "?" and next(TSM.db.realm.whitelist) then
4 years ago
invalidSellerEntry = true
end
-- Now that we know the lowest, find out if this price "level" is a friendly person
-- the reason we do it like this, is so if Apple posts an item at 50g, Orange posts one at 50g
-- but you only have Apple on your white list, it'll undercut it because Orange posted it as well
local isWhitelist, isPlayer = true, true
for _, record in ipairs(auctionItem.compactRecords) do
if not Scan:ShouldIgnoreAuction(record, operation) then
local recordBuyout = record:GetItemBuyout()
if not record:IsPlayer() and recordBuyout and recordBuyout == buyout then
isPlayer = nil
if not TSM.db.realm.whitelist[strlower(record.seller)] then
4 years ago
isWhitelist = nil
end
-- If the lowest we found was from the player, but someone else is matching it (and they aren't on our white list)
-- then we swap the owner to that person
buyout, bid, owner = recordBuyout, record:GetItemDisplayedBid(), record.seller
end
end
end
if owner == "?" and next(TSM.db.realm.whitelist) then
4 years ago
invalidSellerEntry = true
end
return buyout, bid, owner, isWhitelist, isPlayer, invalidSellerEntry
end
function Scan:GetPlayerLowestBuyout(auctionItem, operation)
if not auctionItem then return end
-- Find lowest
local buyout
for _, record in ipairs(auctionItem.compactRecords) do
if not Scan:ShouldIgnoreAuction(record, operation) then
local recordBuyout = record:GetItemBuyout()
if record:IsPlayer() and recordBuyout and (not buyout or recordBuyout < buyout) then
buyout = recordBuyout
end
end
end
return buyout
end