Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions spec/System/TestItemParse_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,29 @@ describe("TestAdvancedItemParse #item", function()
assert.are.equals(195, chaosDamageInc())
end)

it("calculates catalyst and magnitude scaling for a proposed explicit mod", function()
local item = new("Item"):Item([[
Rarity: RARE
Test Subject
Sapphire Ring
Catalyst: Intrinsic
CatalystQuality: 20
Implicits: 0
{range:0.5}50% increased effect of prefixes
]])
item.modMagnitudeMods = {
{ tags = { "prefix" }, multiplier = 2 },
{ tags = { "prefix" }, quality = 50 },
}
local attributePrefix = { modTags = { "attribute" }, prefix = true }
local attributeSuffix = { modTags = { "attribute" }, suffix = true }

assert.are.equals(2.9, item:GetModLineValueScalar(attributePrefix, "explicit"))
assert.are.equals(1.2, item:GetModLineValueScalar(attributeSuffix, "explicit"))
attributePrefix.unscalable = true
assert.are.equals(1, item:GetModLineValueScalar(attributePrefix, "explicit"))
end)

-- actually a ring so we don't have to allocate a socket
local realJewel = [[
Rarity: Rare
Expand Down
182 changes: 182 additions & 0 deletions spec/System/TestTradeQueryGenerator_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,136 @@ describe("TradeQueryGenerator", function()
end)
end)

describe("EstimateBenchCraftWeight", function()
it("adds the weighted values of every craft line", function()
local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = { } })
queryGen.modData = {
Explicit = {
["1203_TestAttributes"] = { tradeMod = { id = "explicit.stat_4080418644", text = "+# to Strength" } },
["1204_TestAttributes"] = { tradeMod = { id = "explicit.stat_3261801346", text = "+# to Dexterity" } },
},
}
queryGen.modWeights = {
{ tradeModId = "explicit.stat_4080418644", weight = 2 },
{ tradeModId = "explicit.stat_3261801346", weight = 3 },
}
local craft = {
"+(10-10) to Strength",
"+(20-20) to Dexterity",
statOrder = { 1203, 1204 },
group = "TestAttributes",
}
local evaluationPlan = queryGen:CreateBenchCraftEvaluationPlan({ { stat = "Life", weightMult = 1 } })

assert.are.equal(80, queryGen:EstimateBenchCraftWeight(craft, evaluationPlan))
assert.are.equal(96, queryGen:EstimateBenchCraftWeight(craft, evaluationPlan, 1.2))
assert.are.equal(120, queryGen:EstimateBenchCraftWeight(craft, evaluationPlan, 1.5))
assert.are.equal(80, queryGen:EstimateBenchCraftWeight(craft, evaluationPlan))
assert.are.equal(80, evaluationPlan.craftWeights[craft])
end)

it("keeps the first craft when the highest levels in a group are tied", function()
local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = { } })
local low = { group = "Test", level = 1 }
local firstHigh = { group = "Test", level = 2 }
local secondHigh = { group = "Test", level = 2 }

local crafts = queryGen:GetHighestLevelBenchCrafts({ low, firstHigh, secondHigh })

assert.are.same({ firstHigh }, crafts)
end)

it("keeps generated mod and stat weights immutable", function()
local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = { } })
queryGen.modWeights = { { tradeModId = "explicit.test", weight = 2 } }
local statWeights = { { stat = "Life", weightMult = 1 } }

local evaluationPlan = queryGen:CreateBenchCraftEvaluationPlan(statWeights)
queryGen.modWeights[1].weight = 20
statWeights[1].weightMult = 10

assert.are.equal(2, evaluationPlan.weightsByTradeMod["explicit.test"].weight)
assert.are.equal(1, evaluationPlan.statWeights[1].weightMult)
end)

it("finds the best positive compatible bench craft query weight", function()
local prefixLow = {
"+(10-10) to Strength",
type = "Prefix",
level = 1,
types = { Ring = true },
statOrder = { 1203 },
group = "TestStrength",
}
local prefixHigh = {
"+(20-20) to Strength",
type = "Prefix",
level = 2,
types = { Ring = true },
statOrder = { 1203 },
group = "TestStrength",
}
local suffix = {
"+(10-10) to Dexterity",
type = "Suffix",
types = { Ring = true },
statOrder = { 1204 },
group = "TestDexterity",
}
local incompatible = {
"+(100-100) to Strength",
type = "Prefix",
types = { Amulet = true },
statOrder = { 1203 },
group = "TestStrength",
}
local negative = {
"+(10-10) to Intelligence",
type = "Prefix",
types = { Belt = true },
statOrder = { 1205 },
group = "TestIntelligence",
}
local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({
itemsTab = { build = { data = { masterMods = { prefixLow, prefixHigh, suffix, incompatible, negative } } } },
})
queryGen.modData = {
Explicit = {
["1203_TestStrength"] = { tradeMod = { id = "explicit.stat_4080418644", text = "+# to Strength" } },
["1204_TestDexterity"] = { tradeMod = { id = "explicit.stat_3261801346", text = "+# to Dexterity" } },
["1205_TestIntelligence"] = { tradeMod = { id = "explicit.stat_328541901", text = "+# to Intelligence" } },
},
}
queryGen.modWeights = {
{ tradeModId = "explicit.stat_4080418644", weight = 2 },
{ tradeModId = "explicit.stat_3261801346", weight = 3 },
{ tradeModId = "explicit.stat_328541901", weight = -4 },
}
local evaluationPlan = queryGen:CreateBenchCraftEvaluationPlan({ })

local weight = queryGen:GetBenchCraftQueryWeight({ type = "Ring" }, evaluationPlan)

assert.are.equal(40, weight)
assert.is_nil(queryGen:GetBenchCraftQueryWeight({ type = "Belt" }, evaluationPlan))
end)

it("weights only items with exactly one empty affix", function()
local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = { } })
queryGen.GetBenchCraftQueryWeight = function()
return 60
end

local filter, priority = queryGen:GetBenchCraftQueryFilter({ type = "Ring" }, { })

assert.are.equal("pseudo.pseudo_number_of_empty_affix_mods", filter.id)
assert.are.equal(1, filter.value.min)
assert.are.equal(1, filter.value.max)
assert.are.equal(60, filter.value.weight)
assert.are.equal(60, priority)
assert.is_nil(filter.priority)
end)
end)

describe("Filter prioritization", function()
it("counts socket and link constraints against MAX_FILTERS", function()
local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = { items = {} } })
Expand Down Expand Up @@ -191,5 +321,57 @@ describe("TradeQueryGenerator", function()
assert.is_not_nil(query.filters.socket_filters.filters.sockets)
assert.is_not_nil(query.filters.socket_filters.filters.links)
end)

it("ranks the single empty affix weight with regular filters before applying MAX_FILTERS", function()
local queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = { items = { } } })
queryGen.modWeights = { }
for index = 1, 40 do
table.insert(queryGen.modWeights, {
tradeModId = "explicit.stat_" .. index,
weight = 1,
meanStatDiff = 41 - index,
})
end
queryGen.calcContext = {
testItem = new("Item"):Item("Rarity: RARE\nNew Item\nGold Ring\nImplicits: 0"),
baseOutput = { },
baseStatValue = 0,
itemCategoryQueryStr = "accessory.ring",
special = { },
options = {
statWeights = { },
influence1 = 1,
influence2 = 1,
includeMirrored = false,
sockets = 6,
links = 6,
},
}
queryGen.tradeTypeIndex = 1
queryGen.requesterContext = { slotTbl = { considerBenchCraft = true } }
local receivedPlan
queryGen.GetBenchCraftQueryFilter = function(_, _, evaluationPlan)
receivedPlan = evaluationPlan
return {
id = "pseudo.pseudo_number_of_empty_affix_mods",
value = { min = 1, max = 1, weight = 35.5 },
}, 35.5
end
local query
queryGen.requesterCallback = function(_, queryJson)
query = require("dkjson").decode(queryJson).query
end

queryGen:FinishQuery()
local filtersById = { }
for _, filter in ipairs(query.stats[1].filters) do
filtersById[filter.id] = filter
end
assert.are.equal(31, #query.stats[1].filters)
assert.are.equal(35.5, filtersById["pseudo.pseudo_number_of_empty_affix_mods"].value.weight)
assert.is_not_nil(filtersById["explicit.stat_30"])
assert.is_nil(filtersById["explicit.stat_31"])
assert.are.equal(receivedPlan, queryGen.requesterContext.benchCraftEvaluationPlan)
end)
end)
end)
49 changes: 49 additions & 0 deletions spec/System/TestTradeQueryRequests_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,55 @@ Strict-Transport-Security: max-age=63115200; includeSubDomains; preload]]
assert.are.equal("42", itemsById.legacy.weight)
assert.are.equal("0", itemsById.empty.weight)
end)

it("preserves prefix and suffix metadata from trade modifier tiers", function()
local response = dkjson.encode({
result = { {
id = "affix-metadata",
listing = {
price = { amount = 1, currency = "chaos", type = "~price" },
whisper = "hi",
account = { name = "seller" },
},
item = {
rarity = "Rare",
name = "Test Band",
typeLine = "Sapphire Ring",
explicitMods = {
{ description = "+50 to maximum Life", domain = "explicit", hash = "stat.explicit.life", mods = { { name = "Sanguine", tier = "P2", level = 50 } } },
{ description = "20% increased Armour", domain = "explicit", hash = "stat.explicit.armour", mods = { { name = "Sanguine", tier = "P2", level = 50 } } },
{ description = "+30% to Fire Resistance", domain = "explicit", hash = "stat.explicit.fire", mods = { { name = "of Craft", tier = "S3", level = 30 } } },
{ description = "+30% to Cold Resistance", domain = "explicit", hash = "stat.explicit.cold", mods = { { name = "of Craft", tier = "S3", level = 30 } } },
},
extended = { hashes = { explicit = {
{ "explicit.life", { 0 } },
{ "explicit.armour", { 0 } },
{ "explicit.fire", { 1 } },
{ "explicit.cold", { 2 } },
} } },
},
} },
})
local fetchedItems
requests.requestQueue.fetch = { }
requests:FetchResultBlock("test", function(items)
fetchedItems = items
end)

local request = table.remove(requests.requestQueue.fetch, 1)
request.callback(response)

local item = new("Item"):Item(fetchedItems[1].item_string)
assert.is_true(item.explicitModLines[1].prefix)
assert.is_true(item.explicitModLines[2].prefix)
assert.are.equal(item.explicitModLines[1].modGroup, item.explicitModLines[2].modGroup)
assert.is_true(item.explicitModLines[3].suffix)
assert.is_true(item.explicitModLines[4].suffix)
assert.are_not.equal(item.explicitModLines[3].modGroup, item.explicitModLines[4].modGroup)
local availability = new("TradeQuery"):TradeQuery({ itemsTab = { } }):GetBenchCraftAvailability(item)
assert.are.equal(2, availability.Prefix)
assert.are.equal(1, availability.Suffix)
end)
end)

describe("FetchResults", function()
Expand Down
Loading
Loading