Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6afe3b8
feat(weighted-score): add shared WeightedScore module and integrate i…
mcagnion Mar 21, 2026
3cc82c3
test(weighted-score): add WeightedScore test coverage
mcagnion Mar 21, 2026
ed9127b
feat(weighted-score): add WeightedScore sort support to anoint panel
mcagnion Mar 22, 2026
e5df786
feat(weighted-score): add getValue to WeightedScore powerStatList entry
mcagnion Mar 22, 2026
616b587
fix(weighted-score): cache WeightedScore module load in Data.lua
mcagnion Mar 23, 2026
6202d51
fix(weighted-score): support getValue in generateFallbackWeights
mcagnion Mar 24, 2026
e544569
fix(weighted-score): propagate getValue into fallbackWeightsList entries
mcagnion Mar 24, 2026
4b41283
fix(trade): initialize stat weights before opening editor
mcagnion Mar 28, 2026
a663ade
feat(weighted-score): show weighted score in Power Report
mcagnion May 9, 2026
253ec71
refactor(weighted-score): unify Edit Weights affordance via dropdown …
mcagnion May 10, 2026
ba12df8
fix(weighted-score): preserve output stat semantics
mcagnion Jul 26, 2026
40b211e
fix(weighted-score): limit sorting to supported surfaces
mcagnion Jul 26, 2026
5bd07ac
fix(weighted-score): preserve Item DB ranking
mcagnion Jul 26, 2026
c299819
fix(weighted-score): preserve comparison context
mcagnion Jul 26, 2026
9efde53
test(weighted-score): cover combined stat weights
mcagnion Jul 26, 2026
9e9b047
refactor(weighted-score): share default weights
mcagnion Jul 26, 2026
43007e6
fix(weighted-score): use Full DPS for anoint ranking
mcagnion Jul 26, 2026
23b5d21
fix(weighted-score): persist weight edits
mcagnion Jul 26, 2026
4dd0878
fix(weighted-score): place score last in menus
mcagnion Jul 28, 2026
5209fde
fix(weighted-score): place weight editor after score
mcagnion Jul 28, 2026
c48337f
feat(weighted-score): sort item modifiers by score
mcagnion Jul 28, 2026
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
97 changes: 97 additions & 0 deletions spec/System/TestItemDBControl_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,103 @@ describe("ItemDBControl", function()
assert.are.equal(-math.huge, invalidItem.measuredPower)
end)

it("preserves negative WeightedScore results and skips unneeded FullDPS", function()
local function makeItem(name)
return {
name = name,
base = {},
enchantModLines = {},
implicitModLines = {},
explicitModLines = {},
baseModList = {},
}
end
local betterItem = makeItem("Better Item")
local worseItem = makeItem("Worse Item")
local invalidItem = makeItem("Invalid Item")
local takenDamage = {
[betterItem] = 80,
[worseItem] = 120,
}
local requestedFullDPS = { }
local itemsTab = {
activeItemSet = { useSecondWeaponSet = false },
slots = { ["Body Armour"] = {} },
tradeQuery = {
statSortSelectionList = {
{ stat = "PhysicalTakenHit", weightMult = 1, transform = function(value) return -value end },
},
},
IsItemValidForSlot = function(_, item)
return item ~= invalidItem
end,
}
itemsTab.build = {
itemsTab = itemsTab,
calcsTab = {
GetMiscCalculator = function()
return function(args, useFullDPS)
table.insert(requestedFullDPS, useFullDPS)
return { PhysicalTakenHit = takenDamage[args.repItem] }
end, { PhysicalTakenHit = 100 }
end,
},
}
local control = new("ItemDBControl", nil, { 0, 0, 100, 100 }, itemsTab, {
list = { invalidItem, betterItem, worseItem },
}, "RARE")
control.sortDetail = { stat = "WeightedScore", isWeightedScore = true }
control.sortOrder = { control.sortControl.STAT, control.sortControl.NAME }

control:ListBuilder()

assert.are.equal(betterItem, control.list[1])
assert.are.equal(worseItem, control.list[2])
assert.are.equal(invalidItem, control.list[3])
assert.are.equal(-0.8, betterItem.measuredPower)
assert.are.equal(-1.2, worseItem.measuredPower)
assert.are.equal(-math.huge, invalidItem.measuredPower)
assert.are.same({ false, false }, requestedFullDPS)
end)

it("requests FullDPS for WeightedScore when active weights need it", function()
local item = {
name = "Full DPS Item",
base = {},
enchantModLines = {},
implicitModLines = {},
explicitModLines = {},
baseModList = {},
}
local requestedFullDPS = { }
local itemsTab = {
activeItemSet = { useSecondWeaponSet = false },
slots = { ["Body Armour"] = {} },
tradeQuery = { statSortSelectionList = { { stat = "FullDPS", weightMult = 1 } } },
IsItemValidForSlot = function()
return true
end,
}
itemsTab.build = {
itemsTab = itemsTab,
calcsTab = {
GetMiscCalculator = function()
return function(_, useFullDPS)
table.insert(requestedFullDPS, useFullDPS)
return { FullDPS = 120 }
end, { FullDPS = 100 }
end,
},
}
local control = new("ItemDBControl", nil, { 0, 0, 100, 100 }, itemsTab, { list = { item } }, "RARE")
control.sortDetail = { stat = "WeightedScore", isWeightedScore = true }
control.sortOrder = { control.sortControl.STAT, control.sortControl.NAME }

control:ListBuilder()

assert.are.same({ true }, requestedFullDPS)
end)

it("searches Foulborn modifier text without case sensitivity", function()
local item = new("Item", [[
Rarity: Unique
Expand Down
37 changes: 37 additions & 0 deletions spec/System/TestNotableDBControl_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
describe("NotableDBControl", function()
it("requests FullDPS when sorting by WeightedScore with FullDPS weights", function()
local notable = {
dn = "Full DPS Notable",
sd = {},
recipe = { "Amber Oil" },
modKey = "NotableFullDPS",
}
local requestedFullDPS = {}
local itemsTab = {
displayItem = { base = { type = "Amulet" } },
tradeQuery = { statSortSelectionList = { { stat = "FullDPS", weightMult = 1 } } },
anointItem = function(_, node)
return node
end,
}
itemsTab.build = {
itemsTab = itemsTab,
calcsTab = {
GetMiscCalculator = function()
return function(args, useFullDPS)
table.insert(requestedFullDPS, useFullDPS)
return { FullDPS = args.repItem and 120 or 100 }
end
end,
},
}
local control = new("NotableDBControl", nil, { 0, 0, 100, 100 }, itemsTab, { [1] = notable }, "ANNOINT")
control.sortDetail = { stat = "WeightedScore", isWeightedScore = true }
control.sortOrder = { control.sortControl.STAT, control.sortControl.NAME }

control:ListBuilder()

assert.are.same({ true, true }, requestedFullDPS)
assert.are.equal(notable, control.list[1])
end)
end)
38 changes: 38 additions & 0 deletions spec/System/TestPowerReport_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
describe("PowerReportListControl", function()
local PowerReportListControl

before_each(function()
LoadModule("Classes/PowerReportListControl")
PowerReportListControl = common.classes.PowerReportListControl
end)

local function relist(originalList, showClusters, allocated)
local control = {
originalList = originalList,
showClusters = showClusters or false,
allocated = allocated or false,
}
PowerReportListControl.ReList(control)
return control.list
end

it("Show Unallocated excludes allocated nodes", function()
local list = relist({
{ name = "allocated", power = 10, pathDist = 1, allocated = true },
{ name = "unallocated", power = 5, pathDist = 1, allocated = false },
}, false, false)

assert.are.equal(1, #list)
assert.are.equal("unallocated", list[1].name)
end)

it("Show Allocated includes allocated nodes", function()
local list = relist({
{ name = "allocated", power = 10, pathDist = 1, allocated = true },
{ name = "unallocated", power = 5, pathDist = 1, allocated = false },
}, false, true)

assert.are.equal(1, #list)
assert.are.equal("allocated", list[1].name)
end)
end)
31 changes: 31 additions & 0 deletions spec/System/TestTradeQuery_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,35 @@ describe("TradeQuery", function()
assert.are.equals(1.2, result)
end)
end)

describe("SetStatWeights", function()
it("marks the build modified after saving changed weights", function()
local capturedControls
local originalOpenPopup = main.OpenPopup
local originalClosePopup = main.ClosePopup
main.OpenPopup = function(_, _, _, _, controls)
capturedControls = controls
end
main.ClosePopup = function() end

local itemsTab = {}
local tradeQuery = new("TradeQuery", itemsTab)
local ok, errMsg = pcall(function()
tradeQuery:SetStatWeights()
for _, entry in ipairs(capturedControls.ListControl.list) do
if entry.stat.stat == "FullDPS" then
entry.stat.weightMult = 0.75
break
end
end
capturedControls.finalise.onClick()
end)
main.OpenPopup = originalOpenPopup
main.ClosePopup = originalClosePopup

assert.is_true(ok, errMsg)
assert.is_true(itemsTab.modFlag)
assert.are.equal(0.75, tradeQuery.statSortSelectionList[1].weightMult)
end)
end)
end)
Loading
Loading