initial commit
This commit is contained in:
263
Core/Service/MyAuctions/Core.lua
Normal file
263
Core/Service/MyAuctions/Core.lua
Normal file
@@ -0,0 +1,263 @@
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
-- TradeSkillMaster --
|
||||
-- https://tradeskillmaster.com --
|
||||
-- All Rights Reserved - Detailed license information included with addon. --
|
||||
-- ------------------------------------------------------------------------------ --
|
||||
|
||||
local _, TSM = ...
|
||||
local MyAuctions = TSM:NewPackage("MyAuctions")
|
||||
local L = TSM.Include("Locale").GetTable()
|
||||
local Database = TSM.Include("Util.Database")
|
||||
local Event = TSM.Include("Util.Event")
|
||||
local TempTable = TSM.Include("Util.TempTable")
|
||||
local Log = TSM.Include("Util.Log")
|
||||
local AuctionTracking = TSM.Include("Service.AuctionTracking")
|
||||
local ItemInfo = TSM.Include("Service.ItemInfo")
|
||||
local AuctionHouseWrapper = TSM.Include("Service.AuctionHouseWrapper")
|
||||
local private = {
|
||||
pendingDB = nil,
|
||||
ahOpen = false,
|
||||
pendingHashes = {},
|
||||
expectedCounts = {},
|
||||
auctionInfo = { numPosted = 0, numSold = 0, postedGold = 0, soldGold = 0 },
|
||||
dbHashFields = {},
|
||||
pendingFuture = nil,
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Module Functions
|
||||
-- ============================================================================
|
||||
|
||||
function MyAuctions.OnInitialize()
|
||||
private.pendingDB = Database.NewSchema("MY_AUCTIONS_PENDING")
|
||||
:AddUniqueNumberField("index")
|
||||
:AddNumberField("hash")
|
||||
:AddBooleanField("isPending")
|
||||
:AddNumberField("pendingAuctionId")
|
||||
:AddIndex("index")
|
||||
:Commit()
|
||||
for field in AuctionTracking.DatabaseFieldIterator() do
|
||||
if field ~= "index" and field ~= "auctionId" then
|
||||
tinsert(private.dbHashFields, field)
|
||||
end
|
||||
end
|
||||
|
||||
Event.Register("AUCTION_HOUSE_SHOW", private.AuctionHouseShowEventHandler)
|
||||
Event.Register("AUCTION_HOUSE_CLOSED", private.AuctionHouseHideEventHandler)
|
||||
Event.Register("CHAT_MSG_SYSTEM", private.ChatMsgSystemEventHandler)
|
||||
Event.Register("UI_ERROR_MESSAGE", private.UIErrorMessageEventHandler)
|
||||
AuctionTracking.RegisterCallback(private.OnAuctionsUpdated)
|
||||
end
|
||||
|
||||
function MyAuctions.CreateQuery()
|
||||
local query = AuctionTracking.CreateQuery()
|
||||
:LeftJoin(private.pendingDB, "index")
|
||||
:InnerJoin(ItemInfo.GetDBForJoin(), "itemString")
|
||||
:VirtualField("group", "string", private.AuctionsGetGroupText, "itemString")
|
||||
if TSM.IsWowClassic() then
|
||||
query:OrderBy("index", false)
|
||||
else
|
||||
query:OrderBy("saleStatus", false)
|
||||
query:OrderBy("name", true)
|
||||
query:OrderBy("auctionId", true)
|
||||
end
|
||||
return query
|
||||
end
|
||||
|
||||
function MyAuctions.CancelAuction(auctionId)
|
||||
local row = private.pendingDB:NewQuery()
|
||||
:Equal("pendingAuctionId", auctionId)
|
||||
:GetFirstResultAndRelease()
|
||||
local hash = row:GetField("hash")
|
||||
assert(hash)
|
||||
|
||||
Log.Info("Canceling (auctionId=%d, hash=%d)", auctionId, hash)
|
||||
if TSM.IsWowClassic() then
|
||||
CancelAuction(auctionId)
|
||||
else
|
||||
private.pendingFuture = AuctionHouseWrapper.CancelAuction(auctionId)
|
||||
if not private.pendingFuture then
|
||||
Log.PrintUser(L["Failed to cancel auction due to the auction house being busy. Ensure no other addons are scanning the AH and try again."])
|
||||
return
|
||||
end
|
||||
private.pendingFuture:SetScript("OnDone", private.PendingFutureOnDone)
|
||||
end
|
||||
|
||||
if private.expectedCounts[hash] and private.expectedCounts[hash] > 0 then
|
||||
private.expectedCounts[hash] = private.expectedCounts[hash] - 1
|
||||
else
|
||||
private.expectedCounts[hash] = private.GetNumRowsByHash(hash) - 1
|
||||
end
|
||||
assert(private.expectedCounts[hash] >= 0)
|
||||
assert(not row:GetField("isPending"))
|
||||
row:SetField("isPending", true)
|
||||
:Update()
|
||||
row:Release()
|
||||
|
||||
tinsert(private.pendingHashes, hash)
|
||||
end
|
||||
|
||||
function MyAuctions.CanCancel(index)
|
||||
if TSM.IsWowClassic() then
|
||||
local numPending = private.pendingDB:NewQuery()
|
||||
:Equal("isPending", true)
|
||||
:LessThanOrEqual("index", index)
|
||||
:CountAndRelease()
|
||||
return numPending == 0
|
||||
else
|
||||
return not private.pendingFuture
|
||||
end
|
||||
end
|
||||
|
||||
function MyAuctions.GetNumPending()
|
||||
if TSM.IsWowClassic() then
|
||||
return private.pendingDB:NewQuery()
|
||||
:Equal("isPending", true)
|
||||
:CountAndRelease()
|
||||
else
|
||||
return private.pendingFuture and 1 or 0
|
||||
end
|
||||
end
|
||||
|
||||
function MyAuctions.GetAuctionInfo()
|
||||
if not private.ahOpen then
|
||||
return
|
||||
end
|
||||
return private.auctionInfo.numPosted, private.auctionInfo.numSold, private.auctionInfo.postedGold, private.auctionInfo.soldGold
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- Private Helper Functions
|
||||
-- ============================================================================
|
||||
|
||||
function private.AuctionHouseShowEventHandler()
|
||||
private.ahOpen = true
|
||||
end
|
||||
|
||||
function private.AuctionHouseHideEventHandler()
|
||||
private.ahOpen = false
|
||||
if private.pendingFuture then
|
||||
private.pendingFuture:Cancel()
|
||||
private.pendingFuture = nil
|
||||
end
|
||||
end
|
||||
|
||||
function private.ChatMsgSystemEventHandler(_, msg)
|
||||
if msg == ERR_AUCTION_REMOVED and #private.pendingHashes > 0 and TSM.IsWowClassic() then
|
||||
local hash = tremove(private.pendingHashes, 1)
|
||||
assert(hash)
|
||||
Log.Info("Confirmed (hash=%d)", hash)
|
||||
end
|
||||
end
|
||||
|
||||
function private.UIErrorMessageEventHandler(_, _, msg)
|
||||
if (msg == ERR_ITEM_NOT_FOUND or msg == ERR_NOT_ENOUGH_MONEY) and #private.pendingHashes > 0 and TSM.IsWowClassic() then
|
||||
local hash = tremove(private.pendingHashes, 1)
|
||||
assert(hash)
|
||||
Log.Info("Failed to cancel (hash=%d)", hash)
|
||||
if private.expectedCounts[hash] then
|
||||
private.expectedCounts[hash] = private.expectedCounts[hash] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function private.PendingFutureOnDone()
|
||||
local result = private.pendingFuture:GetValue()
|
||||
private.pendingFuture = nil
|
||||
local hash = tremove(private.pendingHashes, 1)
|
||||
assert(hash)
|
||||
if result then
|
||||
Log.Info("Confirmed (hash=%d)", hash)
|
||||
else
|
||||
Log.Info("Failed to cancel (hash=%d)", hash)
|
||||
if private.expectedCounts[hash] then
|
||||
private.expectedCounts[hash] = private.expectedCounts[hash] + 1
|
||||
end
|
||||
private.OnAuctionsUpdated()
|
||||
AuctionTracking.QueryOwnedAuctions()
|
||||
end
|
||||
end
|
||||
|
||||
function private.GetNumRowsByHash(hash)
|
||||
return private.pendingDB:NewQuery()
|
||||
:Equal("hash", hash)
|
||||
:CountAndRelease()
|
||||
end
|
||||
|
||||
function private.AuctionsGetGroupText(itemString)
|
||||
local groupPath = TSM.Groups.GetPathByItem(itemString)
|
||||
if not groupPath then
|
||||
return ""
|
||||
end
|
||||
return groupPath
|
||||
end
|
||||
|
||||
function private.OnAuctionsUpdated()
|
||||
local minPendingIndexByHash = TempTable.Acquire()
|
||||
local numByHash = TempTable.Acquire()
|
||||
local query = AuctionTracking.CreateQuery()
|
||||
:OrderBy("index", true)
|
||||
for _, row in query:Iterator() do
|
||||
local index = row:GetField("index")
|
||||
local hash = row:CalculateHash(private.dbHashFields)
|
||||
numByHash[hash] = (numByHash[hash] or 0) + 1
|
||||
if not minPendingIndexByHash[hash] and private.pendingDB:GetUniqueRowField("index", index, "isPending") then
|
||||
minPendingIndexByHash[hash] = index
|
||||
end
|
||||
end
|
||||
local numUsed = TempTable.Acquire()
|
||||
private.pendingDB:TruncateAndBulkInsertStart()
|
||||
for _, row in query:Iterator() do
|
||||
local hash = row:CalculateHash(private.dbHashFields)
|
||||
assert(numByHash[hash] > 0)
|
||||
local expectedCount = private.expectedCounts[hash]
|
||||
local isPending = nil
|
||||
if not expectedCount then
|
||||
-- this was never pending
|
||||
isPending = false
|
||||
elseif numByHash[hash] <= expectedCount then
|
||||
-- this is no longer pending
|
||||
isPending = false
|
||||
private.expectedCounts[hash] = nil
|
||||
elseif row:GetField("index") >= (minPendingIndexByHash[hash] or math.huge) then
|
||||
local numPending = numByHash[hash] - expectedCount
|
||||
assert(numPending > 0)
|
||||
numUsed[hash] = (numUsed[hash] or 0) + 1
|
||||
isPending = numUsed[hash] <= numPending
|
||||
else
|
||||
-- it's a later auction which is pending
|
||||
isPending = false
|
||||
end
|
||||
private.pendingDB:BulkInsertNewRow(row:GetField("index"), hash, isPending, row:GetField("auctionId"))
|
||||
end
|
||||
private.pendingDB:BulkInsertEnd()
|
||||
TempTable.Release(numByHash)
|
||||
TempTable.Release(numUsed)
|
||||
TempTable.Release(minPendingIndexByHash)
|
||||
|
||||
-- update the player's auction status
|
||||
private.auctionInfo.numPosted = 0
|
||||
private.auctionInfo.numSold = 0
|
||||
private.auctionInfo.postedGold = 0
|
||||
private.auctionInfo.soldGold = 0
|
||||
for _, row in query:Iterator() do
|
||||
local itemString, saleStatus, buyout, currentBid, stackSize = row:GetFields("itemString", "saleStatus", "buyout", "currentBid", "stackSize")
|
||||
if saleStatus == 1 then
|
||||
private.auctionInfo.numSold = private.auctionInfo.numSold + 1
|
||||
-- if somebody did a buyout, then bid will be equal to buyout, otherwise it'll be the winning bid
|
||||
private.auctionInfo.soldGold = private.auctionInfo.soldGold + currentBid
|
||||
else
|
||||
private.auctionInfo.numPosted = private.auctionInfo.numPosted + 1
|
||||
if ItemInfo.IsCommodity(itemString) then
|
||||
private.auctionInfo.postedGold = private.auctionInfo.postedGold + (buyout * stackSize)
|
||||
else
|
||||
private.auctionInfo.postedGold = private.auctionInfo.postedGold + buyout
|
||||
end
|
||||
end
|
||||
end
|
||||
query:Release()
|
||||
end
|
||||
Reference in New Issue
Block a user