initial commit

This commit is contained in:
Gitea
2020-11-13 14:13:12 -05:00
commit 05df49ff60
368 changed files with 128754 additions and 0 deletions

View File

@@ -0,0 +1,152 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Auctioning = TSM.Operations:NewPackage("Auctioning")
local private = {}
local L = TSM.Include("Locale").GetTable()
local TempTable = TSM.Include("Util.TempTable")
local Money = TSM.Include("Util.Money")
local OPERATION_INFO = {
-- general
blacklist = { type = "string", default = "" },
ignoreLowDuration = { type = "number", default = 0 },
-- post
postCap = { type = "string", default = "5" },
keepQuantity = { type = "string", default = "0" },
maxExpires = { type = "string", default = "0" },
duration = { type = "number", default = 2, customSanitizeFunction = nil },
bidPercent = { type = "number", default = 1 },
undercut = { type = "string", default = "0c", customSanitizeFunction = nil },
minPrice = { type = "string", default = "check(first(crafting,dbmarket,dbregionmarketavg),max(0.25*avg(crafting,dbmarket,dbregionmarketavg),1.5*vendorsell))" },
maxPrice = { type = "string", default = "check(first(crafting,dbmarket,dbregionmarketavg),max(5*avg(crafting,dbmarket,dbregionmarketavg),30*vendorsell))" },
normalPrice = { type = "string", default = "check(first(crafting,dbmarket,dbregionmarketavg),max(2*avg(crafting,dbmarket,dbregionmarketavg),12*vendorsell))" },
priceReset = { type = "string", default = "none" },
aboveMax = { type = "string", default = "maxPrice" },
-- cancel
cancelUndercut = { type = "boolean", default = true },
cancelRepost = { type = "boolean", default = true },
cancelRepostThreshold = { type = "string", default = "1g" },
}
local OPERATION_VALUE_LIMITS = {
postCap = { min = 0, max = 50000 },
keepQuantity = { min = 0, max = 50000 },
maxExpires = { min = 0, max = 50000 },
}
if TSM.IsWowClassic() then
OPERATION_INFO.undercut.default = "1c"
OPERATION_INFO.matchStackSize = { type = "boolean", default = false }
OPERATION_INFO.stackSize = { type = "string", default = "1" }
OPERATION_INFO.stackSizeIsCap = { type = "boolean", default = false }
OPERATION_VALUE_LIMITS.stackSize = { min = 1, max = 200 }
OPERATION_VALUE_LIMITS.postCap.max = 200
end
-- ============================================================================
-- Module Functions
-- ============================================================================
function Auctioning.OnInitialize()
OPERATION_INFO.duration.customSanitizeFunction = private.SanitizeDuration
OPERATION_INFO.undercut.customSanitizeFunction = private.SanitizeUndercut
TSM.Operations.Register("Auctioning", L["Auctioning"], OPERATION_INFO, 20, private.GetOperationInfo, private.OperationSanitize)
end
function Auctioning.GetMinMaxValues(key)
local info = OPERATION_VALUE_LIMITS[key]
return info and info.min or -math.huge, info and info.max or math.huge
end
function Auctioning.GetMinPrice(itemString)
return private.GetOperationValueHelper(itemString, "minPrice")
end
function Auctioning.GetMaxPrice(itemString)
return private.GetOperationValueHelper(itemString, "maxPrice")
end
function Auctioning.GetNormalPrice(itemString)
return private.GetOperationValueHelper(itemString, "normalPrice")
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.OperationSanitize(operation)
if not TSM.IsWowClassic() then
if operation.stackSize then
operation.postCap = tonumber(operation.postCap) * tonumber(operation.stackSize)
end
if (type(operation.undercut) == "number" and operation.undercut or Money.FromString(operation.undercut) or math.huge) < COPPER_PER_SILVER then
operation.undercut = "0c"
end
end
end
function private.SanitizeDuration(value)
-- convert from 12/24/48 durations to 1/2/3 API values
if value == 12 then
return 1
elseif value == 24 then
return 2
elseif value == 48 then
return 3
else
return value
end
end
function private.SanitizeUndercut(value)
if not TSM.IsWowClassic() and (Money.FromString(Money.ToString(value) or value) or math.huge) < COPPER_PER_SILVER then
return "0c"
end
return value
end
function private.GetOperationValueHelper(itemString, key)
local origItemString = itemString
itemString = TSM.Groups.TranslateItemString(itemString)
local operationName, operationSettings = TSM.Operations.GetFirstOperationByItem("Auctioning", itemString)
if not operationName then
return
end
return TSM.Auctioning.Util.GetPrice(key, operationSettings, origItemString)
end
function private.GetOperationInfo(operationSettings)
local parts = TempTable.Acquire()
-- get the post string
if operationSettings.postCap == 0 then
tinsert(parts, L["No posting."])
else
if TSM.IsWowClassic() then
tinsert(parts, format(L["Posting %d stack(s) of %d for %s hours."], operationSettings.postCap, operationSettings.stackSize, strmatch(TSM.CONST.AUCTION_DURATIONS[operationSettings.duration], "%d+")))
else
tinsert(parts, format(L["Posting %d items for %s hours."], operationSettings.postCap, strmatch(TSM.CONST.AUCTION_DURATIONS[operationSettings.duration], "%d+")))
end
end
-- get the cancel string
if operationSettings.cancelUndercut and operationSettings.cancelRepost then
tinsert(parts, format(L["Canceling undercut auctions and to repost higher."]))
elseif operationSettings.cancelUndercut then
tinsert(parts, format(L["Canceling undercut auctions."]))
elseif operationSettings.cancelRepost then
tinsert(parts, format(L["Canceling to repost higher."]))
else
tinsert(parts, L["Not canceling."])
end
local result = table.concat(parts, " ")
TempTable.Release(parts)
return result
end

View File

@@ -0,0 +1,466 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Operations = TSM:NewPackage("Operations")
local TempTable = TSM.Include("Util.TempTable")
local Log = TSM.Include("Util.Log")
local Database = TSM.Include("Util.Database")
local private = {
db = nil,
operations = nil,
operationInfo = {},
operationModules = {},
shouldCreateDefaultOperations = false,
ignoreProfileUpdate = false,
}
local COMMON_OPERATION_INFO = {
ignorePlayer = { type = "table", default = {} },
ignoreFactionrealm = { type = "table", default = {} },
relationships = { type = "table", default = {} },
}
local FACTION_REALM = UnitFactionGroup("player").." - "..GetRealmName()
local PLAYER_KEY = UnitName("player").." - "..FACTION_REALM
-- ============================================================================
-- Modules Functions
-- ============================================================================
function Operations.OnInitialize()
private.db = Database.NewSchema("OPERATIONS")
:AddStringField("moduleName")
:AddStringField("operationName")
:AddIndex("moduleName")
:Commit()
if TSM.db.global.coreOptions.globalOperations then
private.operations = TSM.db.global.userData.operations
else
private.operations = TSM.db.profile.userData.operations
end
private.RebuildDB()
private.shouldCreateDefaultOperations = not TSM.db.profile.internalData.createdDefaultOperations
TSM.db.profile.internalData.createdDefaultOperations = true
TSM.db:RegisterCallback("OnProfileUpdated", private.OnProfileUpdated)
end
function Operations.Register(moduleName, localizedName, operationInfo, maxOperations, infoCallback, customSanitizeFunction)
for key, info in pairs(operationInfo) do
assert(type(key) == "string" and type(info) == "table")
assert(info.type == type(info.default))
end
for key, info in pairs(COMMON_OPERATION_INFO) do
assert(not operationInfo[key])
operationInfo[key] = info
end
tinsert(private.operationModules, moduleName)
private.operationInfo[moduleName] = {
info = operationInfo,
localizedName = localizedName,
maxOperations = maxOperations,
infoCallback = infoCallback,
customSanitizeFunction = customSanitizeFunction,
}
local shouldCreateDefaultOperations = private.shouldCreateDefaultOperations or not private.operations[moduleName]
private.operations[moduleName] = private.operations[moduleName] or {}
if shouldCreateDefaultOperations and not private.operations[moduleName]["#Default"] then
-- create default operation
Operations.Create(moduleName, "#Default")
end
private.ValidateOperations(moduleName)
private.RebuildDB()
end
function Operations.IsCommonKey(key)
return COMMON_OPERATION_INFO[key] and true or false
end
function Operations.IsValidName(operationName)
return operationName == strtrim(operationName) and operationName ~= "" and not strmatch(operationName, TSM.CONST.OPERATION_SEP)
end
function Operations.ModuleIterator()
return ipairs(private.operationModules)
end
function Operations.ModuleExists(moduleName)
return private.operationInfo[moduleName] and true or false
end
function Operations.GetLocalizedName(moduleName)
return private.operationInfo[moduleName].localizedName
end
function Operations.GetMaxNumber(moduleName)
return private.operationInfo[moduleName].maxOperations
end
function Operations.GetSettingDefault(moduleName, key)
local info = private.operationInfo[moduleName].info[key]
return info.type == "table" and CopyTable(info.default) or info.default
end
function Operations.OperationIterator(moduleName)
local operations = TempTable.Acquire()
for operationName in pairs(private.operations[moduleName]) do
tinsert(operations, operationName)
end
sort(operations)
return TempTable.Iterator(operations)
end
function Operations.Exists(moduleName, operationName)
return private.operations[moduleName][operationName] and true or false
end
function Operations.GetSettings(moduleName, operationName)
return private.operations[moduleName][operationName]
end
function Operations.Create(moduleName, operationName)
assert(not private.operations[moduleName][operationName])
private.operations[moduleName][operationName] = {}
Operations.Reset(moduleName, operationName)
private.RebuildDB()
end
function Operations.BulkCreateFromImport(operations, replaceExisting)
for moduleName, moduleOperations in pairs(operations) do
for operationName, operationSettings in pairs(moduleOperations) do
assert(replaceExisting or not private.operations[moduleName][operationName])
private.operations[moduleName][operationName] = operationSettings
end
end
private.RebuildDB()
end
function Operations.Rename(moduleName, oldName, newName)
assert(private.operations[moduleName][oldName])
private.operations[moduleName][newName] = private.operations[moduleName][oldName]
private.operations[moduleName][oldName] = nil
-- redirect relationships
for _, operation in pairs(private.operations[moduleName]) do
for key, target in pairs(operation.relationships) do
if target == oldName then
operation.relationships[key] = newName
end
end
end
TSM.Groups.OperationRenamed(moduleName, oldName, newName)
private.RebuildDB()
end
function Operations.Copy(moduleName, operationName, sourceOperationName)
assert(private.operations[moduleName][operationName] and private.operations[moduleName][sourceOperationName])
for key, info in pairs(private.operationInfo[moduleName].info) do
local sourceValue = private.operations[moduleName][sourceOperationName][key]
private.operations[moduleName][operationName][key] = info.type == "table" and CopyTable(sourceValue) or sourceValue
end
private.RemoveDeadRelationships(moduleName)
private.RebuildDB()
end
function Operations.Delete(moduleName, operationName)
assert(private.operations[moduleName][operationName])
private.operations[moduleName][operationName] = nil
private.RemoveDeadRelationships(moduleName)
TSM.Groups.RemoveOperationFromAllGroups(moduleName, operationName)
private.RebuildDB()
end
function Operations.DeleteList(moduleName, operationNames)
for _, operationName in ipairs(operationNames) do
assert(private.operations[moduleName][operationName])
private.operations[moduleName][operationName] = nil
private.RemoveDeadRelationships(moduleName)
TSM.Groups.RemoveOperationFromAllGroups(moduleName, operationName)
end
private.RebuildDB()
end
function Operations.Reset(moduleName, operationName)
for key in pairs(private.operationInfo[moduleName].info) do
private.operations[moduleName][operationName][key] = Operations.GetSettingDefault(moduleName, key)
end
end
function Operations.Update(moduleName, operationName)
for key in pairs(private.operations[moduleName][operationName].relationships) do
local operation = private.operations[moduleName][operationName]
while operation.relationships[key] do
local newOperation = private.operations[moduleName][operation.relationships[key]]
if not newOperation then
break
end
operation = newOperation
end
private.operations[moduleName][operationName][key] = operation[key]
end
end
function Operations.IsCircularRelationship(moduleName, operationName, key)
local visited = TempTable.Acquire()
while operationName do
if visited[operationName] then
TempTable.Release(visited)
return true
end
visited[operationName] = true
operationName = private.operations[moduleName][operationName].relationships[key]
end
TempTable.Release(visited)
return false
end
function Operations.GetFirstOperationByItem(moduleName, itemString)
local groupPath = TSM.Groups.GetPathByItem(itemString)
for _, operationName in TSM.Groups.OperationIterator(groupPath, moduleName) do
Operations.Update(moduleName, operationName)
if not private.IsIgnored(moduleName, operationName) then
return operationName, private.operations[moduleName][operationName]
end
end
end
function Operations.GroupOperationIterator(moduleName, groupPath)
local operations = TempTable.Acquire()
operations.moduleName = moduleName
for _, operationName in TSM.Groups.OperationIterator(groupPath, moduleName) do
Operations.Update(moduleName, operationName)
if not private.IsIgnored(moduleName, operationName) then
tinsert(operations, operationName)
end
end
return private.GroupOperationIteratorHelper, operations, 0
end
function Operations.GroupHasOperation(moduleName, groupPath, targetOperationName)
for _, operationName in TSM.Groups.OperationIterator(groupPath, moduleName) do
if operationName == targetOperationName then
return true
end
end
return false
end
function Operations.GetDescription(moduleName, operationName)
local operationSettings = private.operations[moduleName][operationName]
assert(operationSettings)
Operations.Update(moduleName, operationName)
return private.operationInfo[moduleName].infoCallback(operationSettings)
end
function Operations.SanitizeSettings(moduleName, operationName, operationSettings, silentMissingCommonKeys, noRelationshipCheck)
local didReset = false
local operationInfo = private.operationInfo[moduleName].info
if private.operationInfo[moduleName].customSanitizeFunction then
private.operationInfo[moduleName].customSanitizeFunction(operationSettings)
end
for key, value in pairs(operationSettings) do
if not noRelationshipCheck and Operations.IsCircularRelationship(moduleName, operationName, key) then
Log.Err("Removing circular relationship (%s, %s, %s)", moduleName, operationName, key)
operationSettings.relationships[key] = nil
end
if not operationInfo[key] then
operationSettings[key] = nil
elseif type(value) ~= operationInfo[key].type then
if operationInfo[key].type == "string" and type(value) == "number" then
-- some custom price settings were potentially stored as numbers previously, so just convert them
operationSettings[key] = tostring(value)
else
didReset = true
Log.Err("Resetting operation setting %s,%s,%s (%s)", moduleName, operationName, tostring(key), tostring(value))
operationSettings[key] = operationInfo[key].type == "table" and CopyTable(operationInfo[key].default) or operationInfo[key].default
end
elseif operationInfo[key].customSanitizeFunction then
operationSettings[key] = operationInfo[key].customSanitizeFunction(value)
end
end
for key in pairs(operationInfo) do
if operationSettings[key] == nil then
-- this key was missing
if operationInfo[key].type == "boolean" then
-- we previously stored booleans as nil instead of false
operationSettings[key] = false
else
if not silentMissingCommonKeys or not Operations.IsCommonKey(key) then
didReset = true
Log.Err("Resetting missing operation setting %s,%s,%s", moduleName, operationName, tostring(key))
end
operationSettings[key] = operationInfo[key].type == "table" and CopyTable(operationInfo[key].default) or operationInfo[key].default
end
end
end
return didReset
end
function Operations.HasRelationship(moduleName, operationName, settingKey)
return Operations.GetRelationship(moduleName, operationName, settingKey) and true or false
end
function Operations.GetRelationship(moduleName, operationName, settingKey)
assert(private.operationInfo[moduleName].info[settingKey])
return private.operations[moduleName][operationName].relationships[settingKey]
end
function Operations.SetRelationship(moduleName, operationName, settingKey, targetOperationName)
assert(targetOperationName == nil or private.operations[moduleName][targetOperationName])
assert(private.operationInfo[moduleName].info[settingKey])
private.operations[moduleName][operationName].relationships[settingKey] = targetOperationName
end
function Operations.GetRelationshipColors(operationType, operationName, settingKey, value)
local relationshipSet = Operations.HasRelationship(operationType, operationName, settingKey)
local linkColor = nil
if not value and relationshipSet then
linkColor = "INDICATOR_DISABLED"
elseif not value then
linkColor = "TEXT_DISABLED"
elseif relationshipSet then
linkColor = "INDICATOR"
else
linkColor = "TEXT"
end
local linkTexture = TSM.UI.TexturePacks.GetColoredKey("iconPack.14x14/Link", linkColor)
return relationshipSet, linkTexture, value and not relationshipSet and "TEXT" or "TEXT_DISABLED"
end
function Operations.IsStoredGlobally()
return TSM.db.global.coreOptions.globalOperations
end
function Operations.SetStoredGlobally(storeGlobally)
TSM.db.global.coreOptions.globalOperations = storeGlobally
-- we shouldn't be running the OnProfileUpdated callback while switching profiles
private.ignoreProfileUpdate = true
if storeGlobally then
-- move current profile to global
TSM.db.global.userData.operations = CopyTable(TSM.db.profile.userData.operations)
-- clear out old operations
for _ in TSM.GetTSMProfileIterator() do
TSM.db.profile.userData.operations = nil
end
else
-- move global to all profiles
for _ in TSM.GetTSMProfileIterator() do
TSM.db.profile.userData.operations = CopyTable(TSM.db.global.userData.operations)
end
-- clear out old operations
TSM.db.global.userData.operations = nil
end
private.ignoreProfileUpdate = false
private.OnProfileUpdated()
end
function Operations.ReplaceProfileOperations(newOperations)
for k, v in pairs(newOperations) do
TSM.db.profile.userData.operations[k] = v
end
end
function Operations.CreateQuery()
return private.db:NewQuery()
end
function Operations.GroupIterator(moduleName, filterOperationName, overrideOnly)
local result = TempTable.Acquire()
-- check the base group
if Operations.GroupHasOperation(moduleName, TSM.CONST.ROOT_GROUP_PATH, filterOperationName) then
tinsert(result, TSM.CONST.ROOT_GROUP_PATH)
end
-- need to filter out the groups without operations
for _, groupPath in TSM.Groups.GroupIterator() do
if (not overrideOnly or TSM.Groups.HasOperationOverride(groupPath, moduleName)) and Operations.GroupHasOperation(moduleName, groupPath, filterOperationName) then
tinsert(result, groupPath)
end
end
return TempTable.Iterator(result)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.OnProfileUpdated()
if private.ignoreProfileUpdate then
return
end
if TSM.db.global.coreOptions.globalOperations then
private.operations = TSM.db.global.userData.operations
else
private.operations = TSM.db.profile.userData.operations
end
for _, moduleName in Operations.ModuleIterator() do
private.ValidateOperations(moduleName)
end
private.RebuildDB()
TSM.Groups.RebuildDatabase()
end
function private.ValidateOperations(moduleName)
if not private.operations[moduleName] then
-- this is a new profile
private.operations[moduleName] = {}
Operations.Create(moduleName, "#Default")
return
end
for operationName, operationSettings in pairs(private.operations[moduleName]) do
if type(operationName) ~= "string" or not Operations.IsValidName(operationName) then
Log.Err("Removing %s operation with invalid name: ", moduleName, tostring(operationName))
private.operations[moduleName][operationName] = nil
else
Operations.SanitizeSettings(moduleName, operationName, operationSettings)
for key, target in pairs(operationSettings.relationships) do
if not private.operations[moduleName][target] then
Log.Err("Removing invalid relationship %s,%s,%s -> %s", moduleName, operationName, tostring(key), tostring(target))
operationSettings.relationships[key] = nil
end
end
end
end
end
function private.IsIgnored(moduleName, operationName)
local operationSettings = private.operations[moduleName][operationName]
assert(operationSettings)
return operationSettings.ignorePlayer[PLAYER_KEY] or operationSettings.ignoreFactionrealm[FACTION_REALM]
end
function private.GroupOperationIteratorHelper(operations, index)
index = index + 1
if index > #operations then
TempTable.Release(operations)
return
end
local operationName = operations[index]
return index, operationName, private.operations[operations.moduleName][operationName]
end
function private.RemoveDeadRelationships(moduleName)
for _, operation in pairs(private.operations[moduleName]) do
for key, target in pairs(operation.relationships) do
if not private.operations[moduleName][target] then
operation.relationships[key] = nil
end
end
end
end
function private.RebuildDB()
private.db:TruncateAndBulkInsertStart()
for moduleName, operations in pairs(private.operations) do
for operationName in pairs(operations) do
private.db:BulkInsertNewRow(moduleName, operationName)
end
end
private.db:BulkInsertEnd()
end

View File

@@ -0,0 +1,161 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Crafting = TSM.Operations:NewPackage("Crafting")
local L = TSM.Include("Locale").GetTable()
local Log = TSM.Include("Util.Log")
local CustomPrice = TSM.Include("Service.CustomPrice")
local ItemInfo = TSM.Include("Service.ItemInfo")
local private = {}
local OPERATION_INFO = {
minRestock = { type = "string", default = "10" },
maxRestock = { type = "string", default = "20" },
minProfit = { type = "string", default = "100g" },
craftPriceMethod = { type = "string", default = "" },
}
local MIN_RESTOCK_VALUE = 0
local MAX_RESTOCK_VALUE = 2000
local BAD_CRAFTING_PRICE_SOURCES = {
crafting = true,
}
-- ============================================================================
-- Module Functions
-- ============================================================================
function Crafting.OnInitialize()
TSM.Operations.Register("Crafting", L["Crafting"], OPERATION_INFO, 1, private.GetOperationInfo)
for _, name in TSM.Operations.OperationIterator("Crafting") do
local operation = TSM.Operations.GetSettings("Crafting", name)
if operation.craftPriceMethod ~= "" then
local isValid, err = CustomPrice.Validate(operation.craftPriceMethod, BAD_CRAFTING_PRICE_SOURCES)
if not isValid then
Log.PrintfUser(L["Your craft value method for '%s' was invalid so it has been returned to the default. Details: %s"], name, err)
operation.craftPriceMethod = ""
end
end
end
end
function Crafting.HasOperation(itemString)
return private.GetOperationSettings(itemString) and true or false
end
function Crafting.GetRestockRange()
return MIN_RESTOCK_VALUE, MAX_RESTOCK_VALUE
end
function Crafting.IsValid(itemString)
local origItemString = itemString
itemString = TSM.Groups.TranslateItemString(itemString)
local operationName, operationSettings = TSM.Operations.GetFirstOperationByItem("Crafting", itemString)
if not operationSettings then
return false
end
local minRestock, maxRestock, errMsg = nil, nil, nil
minRestock, errMsg = private.GetMinRestock(operationSettings, origItemString)
if not minRestock then
return false, errMsg
end
maxRestock, errMsg = private.GetMaxRestock(operationSettings, origItemString)
if not maxRestock then
return false, errMsg
end
if minRestock > maxRestock then
-- invalid cause min > max restock quantity
return false, format(L["'%s' is an invalid operation. Min restock of %d is higher than max restock of %d for %s."], operationName, minRestock, maxRestock, ItemInfo.GetLink(origItemString))
end
return true
end
function Crafting.GetMinProfit(itemString)
local operationSettings = private.GetOperationSettings(itemString)
if not operationSettings then
return false
end
if operationSettings.minProfit == "" then
return false
end
return true, CustomPrice.GetValue(operationSettings.minProfit, itemString)
end
function Crafting.GetRestockQuantity(itemString, haveQuantity)
local operationSettings = private.GetOperationSettings(itemString)
if not operationSettings then
return 0
end
local minRestock = private.GetMinRestock(operationSettings, itemString)
local maxRestock = private.GetMaxRestock(operationSettings, itemString)
if not minRestock or not maxRestock or minRestock > maxRestock then
return 0
end
local neededQuantity = maxRestock - haveQuantity
if neededQuantity <= 0 then
-- don't need to queue any
return 0
elseif neededQuantity < minRestock then
-- we're below the min restock quantity
return 0
end
return neededQuantity
end
function Crafting.GetCraftedItemValue(itemString)
local operationSettings = private.GetOperationSettings(itemString)
if not operationSettings then
return false
end
if operationSettings.craftPriceMethod == "" then
return false
end
return true, CustomPrice.GetValue(operationSettings.craftPriceMethod, itemString)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GetMinRestock(operationSettings, itemString)
local minRestock, errMsg = CustomPrice.GetValue(operationSettings.minRestock, itemString, true)
if not minRestock then
return nil, format(L["Your min restock (%s) is invalid for %s."], operationSettings.minRestock, ItemInfo.GetLink(itemString) or "?").." "..errMsg
elseif minRestock < MIN_RESTOCK_VALUE or minRestock > MAX_RESTOCK_VALUE then
return nil, format(L["Your min restock (%s) is invalid for %s."], operationSettings.minRestock, ItemInfo.GetLink(itemString) or "?").." "..format(L["Must be between %d and %s."], MIN_RESTOCK_VALUE, MAX_RESTOCK_VALUE)
end
return minRestock
end
function private.GetMaxRestock(operationSettings, itemString)
local maxRestock, errMsg = CustomPrice.GetValue(operationSettings.maxRestock, itemString, true)
if not maxRestock then
return nil, format(L["Your max restock (%s) is invalid for %s."], operationSettings.maxRestock, ItemInfo.GetLink(itemString) or "?").." "..errMsg
elseif maxRestock < MIN_RESTOCK_VALUE or maxRestock > MAX_RESTOCK_VALUE then
return nil, format(L["Your max restock (%s) is invalid for %s."], operationSettings.maxRestock, ItemInfo.GetLink(itemString) or "?").." "..format(L["Must be between %d and %s."], MIN_RESTOCK_VALUE, MAX_RESTOCK_VALUE)
end
return maxRestock
end
function private.GetOperationInfo(operationSettings)
if operationSettings.minProfit ~= "" then
return L["Restocking with a min profit."]
else
return L["Restocking with no min profit."]
end
end
function private.GetOperationSettings(itemString)
itemString = TSM.Groups.TranslateItemString(itemString)
local operationName, operationSettings = TSM.Operations.GetFirstOperationByItem("Crafting", itemString)
if not operationName then
return
end
return operationSettings
end

View File

@@ -0,0 +1,46 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Mailing = TSM.Operations:NewPackage("Mailing")
local private = {}
local L = TSM.Include("Locale").GetTable()
local OPERATION_INFO = {
maxQtyEnabled = { type = "boolean", default = false },
maxQty = { type = "number", default = 10 },
target = { type = "string", default = "" },
restock = { type = "boolean", default = false },
restockSources = { type = "table", default = { guild = false, bank = false } },
keepQty = { type = "number", default = 0 },
}
-- ============================================================================
-- Module Functions
-- ============================================================================
function Mailing.OnInitialize()
TSM.Operations.Register("Mailing", L["Mailing"], OPERATION_INFO, 50, private.GetOperationInfo)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GetOperationInfo(operationSettings)
if operationSettings.target == "" then
return
end
if operationSettings.maxQtyEnabled then
return format(L["Mailing up to %d to %s."], operationSettings.maxQty, operationSettings.target)
else
return format(L["Mailing all to %s."], operationSettings.target)
end
end

View File

@@ -0,0 +1,132 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Shopping = TSM.Operations:NewPackage("Shopping")
local private = {}
local L = TSM.Include("Locale").GetTable()
local CustomPrice = TSM.Include("Service.CustomPrice")
local Inventory = TSM.Include("Service.Inventory")
local OPERATION_INFO = {
restockQuantity = { type = "string", default = "0" },
maxPrice = { type = "string", default = "dbmarket" },
showAboveMaxPrice = { type = "boolean", default = true },
restockSources = { type = "table", default = { alts = false, auctions = false, bank = false, guild = false } },
}
local MIN_RESTOCK_VALUE = 0
local MAX_RESTOCK_VALUE = 50000
-- ============================================================================
-- Module Functions
-- ============================================================================
function Shopping.OnInitialize()
TSM.Operations.Register("Shopping", L["Shopping"], OPERATION_INFO, 1, private.GetOperationInfo)
end
function Shopping.GetRestockRange()
return MIN_RESTOCK_VALUE, MAX_RESTOCK_VALUE
end
function Shopping.GetMaxPrice(itemString)
local operationSettings = private.GetOperationSettings(itemString)
if not operationSettings then
return
end
return CustomPrice.GetValue(operationSettings.maxPrice, itemString)
end
function Shopping.ShouldShowAboveMaxPrice(itemString)
local operationSettings = private.GetOperationSettings(itemString)
if not operationSettings then
return
end
return operationSettings.showAboveMaxPrice
end
function Shopping.IsFiltered(itemString, itemBuyout)
local operationSettings = private.GetOperationSettings(itemString)
if not operationSettings then
return true
end
if operationSettings.showAboveMaxPrice then
return false
end
local maxPrice = CustomPrice.GetValue(operationSettings.maxPrice, itemString)
if itemBuyout > (maxPrice or 0) then
return true, true
end
return false
end
function Shopping.ValidAndGetRestockQuantity(itemString)
local operationSettings = private.GetOperationSettings(itemString)
if not operationSettings then
return false, nil
end
local isValid, err = CustomPrice.Validate(operationSettings.maxPrice)
if not isValid then
return false, err
end
local maxQuantity, restockQuantity = nil, nil
restockQuantity, err = CustomPrice.GetValue(operationSettings.restockQuantity, itemString, true)
if not restockQuantity then
return false, err
elseif restockQuantity < MIN_RESTOCK_VALUE or restockQuantity > MAX_RESTOCK_VALUE then
return false, format(L["Your restock quantity is invalid. It must be between %d and %s."], MIN_RESTOCK_VALUE, MAX_RESTOCK_VALUE)
end
if restockQuantity > 0 then
-- include mail and bags
local numHave = Inventory.GetBagQuantity(itemString) + Inventory.GetMailQuantity(itemString)
if operationSettings.restockSources.bank then
numHave = numHave + Inventory.GetBankQuantity(itemString) + Inventory.GetReagentBankQuantity(itemString)
end
if operationSettings.restockSources.guild then
numHave = numHave + Inventory.GetGuildQuantity(itemString)
end
local _, numAlts, numAuctions = Inventory.GetPlayerTotals(itemString)
if operationSettings.restockSources.alts then
numHave = numHave + numAlts
end
if operationSettings.restockSources.auctions then
numHave = numHave + numAuctions
end
if numHave >= restockQuantity then
return false, nil
end
maxQuantity = restockQuantity - numHave
end
if not operationSettings.showAboveMaxPrice and not CustomPrice.GetValue(operationSettings.maxPrice, itemString) then
-- we're not showing auctions above the max price and the max price isn't valid for this item, so skip it
return false, nil
end
return true, maxQuantity
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GetOperationInfo(operationSettings)
if operationSettings.showAboveMaxPrice then
return format(L["Shopping for auctions including those above the max price."])
else
return format(L["Shopping for auctions with a max price set."])
end
end
function private.GetOperationSettings(itemString)
itemString = TSM.Groups.TranslateItemString(itemString)
local operationName, operationSettings = TSM.Operations.GetFirstOperationByItem("Shopping", itemString)
if not operationName then
return
end
return operationSettings
end

View File

@@ -0,0 +1,57 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Sniper = TSM.Operations:NewPackage("Sniper")
local private = {}
local L = TSM.Include("Locale").GetTable()
local CustomPrice = TSM.Include("Service.CustomPrice")
local OPERATION_INFO = {
belowPrice = { type = "string", default = "max(vendorsell, ifgt(DBRegionMarketAvg, 250000g, 0.8, ifgt(DBRegionMarketAvg, 100000g, 0.7, ifgt(DBRegionMarketAvg, 50000g, 0.6, ifgt(DBRegionMarketAvg, 25000g, 0.5, ifgt(DBRegionMarketAvg, 10000g, 0.4, ifgt(DBRegionMarketAvg, 5000g, 0.3, ifgt(DBRegionMarketAvg, 2000g, 0.2, ifgt(DBRegionMarketAvg, 1000g, 0.1, 0.05)))))))) * DBRegionMarketAvg)" },
}
-- ============================================================================
-- Module Functions
-- ============================================================================
function Sniper.OnInitialize()
TSM.Operations.Register("Sniper", L["Sniper"], OPERATION_INFO, 1, private.GetOperationInfo)
end
function Sniper.IsOperationValid(itemString)
local _, operationSettings = TSM.Operations.GetFirstOperationByItem("Sniper", itemString)
if not operationSettings then
return false
end
local isValid = CustomPrice.Validate(operationSettings.belowPrice)
return isValid
end
function Sniper.HasOperation(itemString)
itemString = TSM.Groups.TranslateItemString(itemString)
return TSM.Operations.GetFirstOperationByItem("Sniper", itemString) and true or false
end
function Sniper.GetBelowPrice(itemString)
itemString = TSM.Groups.TranslateItemString(itemString)
local operationName, operationSettings = TSM.Operations.GetFirstOperationByItem("Sniper", itemString)
if not operationName then
return
end
return CustomPrice.GetValue(operationSettings.belowPrice, itemString)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GetOperationInfo(operationSettings)
return L["Sniping items below a max price"]
end

View File

@@ -0,0 +1,60 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Vendoring = TSM.Operations:NewPackage("Vendoring")
local private = {}
local L = TSM.Include("Locale").GetTable()
local TempTable = TSM.Include("Util.TempTable")
local OPERATION_INFO = {
sellAfterExpired = { type = "number", default = 20 },
sellSoulbound = { type = "boolean", default = false },
keepQty = { type = "number", default = 0 },
restockQty = { type = "number", default = 0 },
restockSources = { type = "table", default = { alts = false, ah = false, bank = false, guild = false, alts_ah = false, mail = false } },
enableBuy = { type = "boolean", default = true },
enableSell = { type = "boolean", default = true },
vsMarketValue = { type = "string", default = "dbmarket" },
vsMaxMarketValue = { type = "string", default = "0c" },
vsDestroyValue = { type = "string", default = "destroy" },
vsMaxDestroyValue = { type = "string", default = "0c" },
}
-- ============================================================================
-- Module Functions
-- ============================================================================
function Vendoring.OnInitialize()
TSM.Operations.Register("Vendoring", L["Vendoring"], OPERATION_INFO, 1, private.GetOperationInfo)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GetOperationInfo(operationSettings)
local parts = TempTable.Acquire()
if operationSettings.enableBuy and operationSettings.restockQty > 0 then
tinsert(parts, format(L["Restocking to %d."], operationSettings.restockQty))
end
if operationSettings.enableSell then
if operationSettings.keepQty > 0 then
tinsert(parts, format(L["Keeping %d."], operationSettings.keepQty))
end
if operationSettings.sellSoulbound then
tinsert(parts, L["Selling soulbound items."])
end
end
local result = table.concat(parts, " ")
TempTable.Release(parts)
return result
end

View File

@@ -0,0 +1,95 @@
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local _, TSM = ...
local Warehousing = TSM.Operations:NewPackage("Warehousing")
local private = {}
local L = TSM.Include("Locale").GetTable()
local OPERATION_INFO = {
moveQuantity = { type = "number", default = 0 },
keepBagQuantity = { type = "number", default = 0 },
keepBankQuantity = { type = "number", default = 0 },
restockQuantity = { type = "number", default = 0 },
stackSize = { type = "number", default = 0 },
restockKeepBankQuantity = { type = "number", default = 0 },
restockStackSize = { type = "number", default = 0 },
}
-- ============================================================================
-- Module Functions
-- ============================================================================
function Warehousing.OnInitialize()
TSM.Operations.Register("Warehousing", L["Warehousing"], OPERATION_INFO, 12, private.GetOperationInfo)
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.GetOperationInfo(operationSettings)
if (operationSettings.keepBagQuantity ~= 0 or operationSettings.keepBankQuantity ~= 0) and operationSettings.moveQuantity == 0 then
if operationSettings.keepBagQuantity ~= 0 then
if operationSettings.keepBankQuantity ~= 0 then
if operationSettings.restockQuantity ~= 0 then
return format(L["Warehousing will move all of the items in this group keeping %d of each item back when bags > bank/gbank, %d of each item back when bank/gbank > bags. Restock will maintain %d items in your bags."], operationSettings.keepBagQuantity, operationSettings.keepBankQuantity, operationSettings.restockQuantity)
else
return format(L["Warehousing will move all of the items in this group keeping %d of each item back when bags > bank/gbank, %d of each item back when bank/gbank > bags."], operationSettings.keepBagQuantity, operationSettings.keepBankQuantity)
end
else
if operationSettings.restockQuantity ~= 0 then
return format(L["Warehousing will move all of the items in this group keeping %d of each item back when bags > bank/gbank. Restock will maintain %d items in your bags."], operationSettings.keepBagQuantity, operationSettings.restockQuantity)
else
return format(L["Warehousing will move all of the items in this group keeping %d of each item back when bags > bank/gbank."], operationSettings.keepBagQuantity)
end
end
else
if operationSettings.restockQuantity ~= 0 then
return format(L["Warehousing will move all of the items in this group keeping %d of each item back when bank/gbank > bags. Restock will maintain %d items in your bags."], operationSettings.keepBankQuantity, operationSettings.restockQuantity)
else
return format(L["Warehousing will move all of the items in this group keeping %d of each item back when bank/gbank > bags."], operationSettings.keepBankQuantity)
end
end
elseif (operationSettings.keepBagQuantity ~= 0 or operationSettings.keepBankQuantity ~= 0) and operationSettings.moveQuantity ~= 0 then
if operationSettings.keepBagQuantity ~= 0 then
if operationSettings.keepBankQuantity ~= 0 then
if operationSettings.restockQuantity ~= 0 then
return format(L["Warehousing will move a max of %d of each item in this group keeping %d of each item back when bags > bank/gbank, %d of each item back when bank/gbank > bags. Restock will maintain %d items in your bags."], operationSettings.moveQuantity, operationSettings.keepBagQuantity, operationSettings.keepBankQuantity, operationSettings.restockQuantity)
else
return format(L["Warehousing will move a max of %d of each item in this group keeping %d of each item back when bags > bank/gbank, %d of each item back when bank/gbank > bags."], operationSettings.moveQuantity, operationSettings.keepBagQuantity, operationSettings.keepBankQuantity)
end
else
if operationSettings.restockQuantity ~= 0 then
return format(L["Warehousing will move a max of %d of each item in this group keeping %d of each item back when bags > bank/gbank. Restock will maintain %d items in your bags."], operationSettings.keepBankQuantity, operationSettings.restockQuantity)
else
return format(L["Warehousing will move a max of %d of each item in this group keeping %d of each item back when bags > bank/gbank."], operationSettings.keepBankQuantity)
end
end
else
if operationSettings.restockQuantity ~= 0 then
return format(L["Warehousing will move a max of %d of each item in this group keeping %d of each item back when bank/gbank > bags. Restock will maintain %d items in your bags."], operationSettings.moveQuantity, operationSettings.keepBankQuantity, operationSettings.restockQuantity)
else
return format(L["Warehousing will move a max of %d of each item in this group keeping %d of each item back when bank/gbank > bags."], operationSettings.moveQuantity, operationSettings.keepBankQuantity)
end
end
elseif operationSettings.moveQuantity ~= 0 then
if operationSettings.restockQuantity ~= 0 then
return format(L["Warehousing will move a max of %d of each item in this group. Restock will maintain %d items in your bags."], operationSettings.moveQuantity, operationSettings.restockQuantity)
else
return format(L["Warehousing will move a max of %d of each item in this group."], operationSettings.moveQuantity)
end
else
if operationSettings.restockQuantity ~= 0 then
return format(L["Warehousing will move all of the items in this group. Restock will maintain %d items in your bags."], operationSettings.restockQuantity)
else
return L["Warehousing will move all of the items in this group."]
end
end
end