Skip to content
Open
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
18 changes: 18 additions & 0 deletions spec/System/TestTradeQueryCurrency_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ describe("TradeQuery Currency Conversion", function()
end)
end)

describe("ReduceOutput", function()
it("uses selected minion stats for weighted result comparison", function()
mock_tradeQuery.statSortSelectionList = { { stat = "AverageDamage" } }

local result = mock_tradeQuery:ReduceOutput({
AverageDamage = 10,
Life = 100,
Minion = {
AverageDamage = 250,
Life = 200,
},
})

assert.are.equals(250, result.AverageDamage)
assert.is_nil(result.Life)
end)
end)

describe("PriceBuilderProcessPoENinjaResponse", function()
-- Pass: Processes without error, restoring map while adding a notice
-- Fail: Corrupts map or crashes, indicating fragile API response handling, breaking future conversions
Expand Down
44 changes: 44 additions & 0 deletions spec/System/TestTradeQueryGenerator_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,50 @@ describe("TradeQueryGenerator", function()
local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)
assert.are.equal(result, 100)
end)

it("uses minion output for non-FullDPS stats when minion output is available", function()
local baseOutput = { AverageDamage = 10, Minion = { AverageDamage = 100 } }
local newOutput = { AverageDamage = 10, Minion = { AverageDamage = 250 } }
local statWeights = { { stat = "AverageDamage", weightMult = 1 } }
data.misc.maxStatIncrease = 1000

local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)

assert.are.equal(result, 2.5)
end)

it("uses player output for FullDPS even when minion output is available", function()
local baseOutput = { FullDPS = 100, Minion = { FullDPS = 100 } }
local newOutput = { FullDPS = 250, Minion = { FullDPS = 1000 } }
local statWeights = { { stat = "FullDPS", weightMult = 1 } }
data.misc.maxStatIncrease = 1000

local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)

assert.are.equal(result, 2.5)
end)

it("uses the fallback DPS ratio once when FullDPS is unavailable", function()
local baseOutput = { Minion = { TotalDPS = 10, TotalDotDPS = 0, CombinedDPS = 10 } }
local newOutput = { Minion = { TotalDPS = 25, TotalDotDPS = 0, CombinedDPS = 25 } }
local statWeights = { { stat = "FullDPS", weightMult = 1 } }
data.misc.maxStatIncrease = 1000

local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)

assert.are.equal(result, 2.5)
end)

it("falls back to player output when the selected stat is not on minion output", function()
local baseOutput = { Spirit = 100, Minion = { AverageDamage = 100 } }
local newOutput = { Spirit = 120, Minion = { AverageDamage = 100 } }
local statWeights = { { stat = "Spirit", weightMult = 1 } }
data.misc.maxStatIncrease = 1000

local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights)

assert.are.equal(result, 1.2)
end)
end)

describe("Filter prioritization", function()
Expand Down
18 changes: 18 additions & 0 deletions spec/System/TestTreeTab_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,22 @@ describe("TreeTab", function()
assert.is_nil(build.treeTab.specList[1].allocNodes[2])
end)
end)

describe("Power stat calculation", function()
it("uses minion output for non-FullDPS stats when minion output is available", function()
local selection = { stat = "AverageDamage" }
local outputWithNode = { AverageDamage = 10, Minion = { AverageDamage = 250 } }
local baseOutput = { AverageDamage = 10, Minion = { AverageDamage = 100 } }

assert.are.equals(150, build.calcsTab:CalculatePowerStat(selection, outputWithNode, baseOutput))
end)

it("uses player output for FullDPS even when minion output is available", function()
local selection = { stat = "FullDPS" }
local outputWithNode = { FullDPS = 250, Minion = { FullDPS = 1000 } }
local baseOutput = { FullDPS = 100, Minion = { FullDPS = 1000 } }

assert.are.equals(150, build.calcsTab:CalculatePowerStat(selection, outputWithNode, baseOutput))
end)
end)
end)
2 changes: 1 addition & 1 deletion src/Classes/CalcsTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ function CalcsTabClass:PowerBuilder()
end

function CalcsTabClass:CalculatePowerStat(selection, original, modified)
if modified.Minion and not selection.stat == "FullDPS" then
if modified.Minion and selection.stat ~= "FullDPS" then
original = original.Minion
modified = modified.Minion
end
Expand Down
2 changes: 1 addition & 1 deletion src/Classes/TradeQuery.lua
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ end
function TradeQueryClass:ReduceOutput(output)
local smallOutput = {}
for _, statTable in ipairs(self.statSortSelectionList) do
smallOutput[statTable.stat] = output[statTable.stat]
smallOutput[statTable.stat] = output.Minion and output.Minion[statTable.stat] or output[statTable.stat]
end
return smallOutput
end
Expand Down
24 changes: 20 additions & 4 deletions src/Classes/TradeQueryGenerator.lua
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,26 @@ end

function TradeQueryGeneratorClass.WeightedRatioOutputs(baseOutput, newOutput, statWeights)
local meanStatDiff = 0
local function getOutputStatValue(output, stat)
if stat == "FullDPS" then
if output[stat] ~= nil then
return output[stat]
end
if output.Minion and output.Minion.CombinedDPS ~= nil then
return output.Minion.CombinedDPS
end
end
if output.Minion and output.Minion[stat] ~= nil then
return output.Minion[stat]
end
return output[stat] or 0
end
local function ratioModSums(...)
local baseModSum = 0
local newModSum = 0
for _, mod in ipairs({ ... }) do
baseModSum = baseModSum + (baseOutput[mod] or 0)
newModSum = newModSum + (newOutput[mod] or 0)
baseModSum = baseModSum + getOutputStatValue(baseOutput, mod)
newModSum = newModSum + getOutputStatValue(newOutput, mod)
end

if baseModSum == math.huge then
Expand All @@ -176,10 +190,12 @@ function TradeQueryGeneratorClass.WeightedRatioOutputs(baseOutput, newOutput, st
end
end
for _, statTable in ipairs(statWeights) do
local modSumRatio
if statTable.stat == "FullDPS" and not (baseOutput["FullDPS"] and newOutput["FullDPS"]) then
meanStatDiff = meanStatDiff + ratioModSums("TotalDPS", "TotalDotDPS", "CombinedDPS") * statTable.weightMult
modSumRatio = ratioModSums("TotalDPS", "TotalDotDPS", "CombinedDPS")
else
modSumRatio = ratioModSums(statTable.stat)
end
local modSumRatio = ratioModSums(statTable.stat)
-- some weights, such as damage taken from hit need to be negated as lower is better for them
if statTable.transform then
modSumRatio = statTable.transform(modSumRatio)
Expand Down
Loading