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
fb3c109
feat(weighted-score): add shared WeightedScore module and integrate i…
mcagnion Mar 21, 2026
fd21b85
test(weighted-score): add WeightedScore test coverage
mcagnion Mar 21, 2026
aef0bc9
feat(weighted-score): add WeightedScore sort support to anoint panel
mcagnion Mar 22, 2026
fc1522d
feat(weighted-score): add getValue to WeightedScore powerStatList entry
mcagnion Mar 22, 2026
c4ad3cb
fix(weighted-score): cache WeightedScore module load in Data.lua
mcagnion Mar 23, 2026
f1fecb1
fix(weighted-score): support getValue in generateFallbackWeights
mcagnion Mar 24, 2026
3706859
fix(weighted-score): propagate getValue into fallbackWeightsList entries
mcagnion Mar 24, 2026
64f93f9
fix(trade): initialize stat weights before opening editor
mcagnion Mar 28, 2026
e454a33
feat(weighted-score): show weighted score in Power Report
mcagnion May 9, 2026
81a2988
refactor(weighted-score): unify Edit Weights affordance via dropdown …
mcagnion May 10, 2026
51551a3
fix(weighted-score): preserve output stat semantics
mcagnion Jul 26, 2026
f46ef88
fix(weighted-score): limit sorting to supported surfaces
mcagnion Jul 26, 2026
7f54fe4
fix(weighted-score): preserve Item DB ranking
mcagnion Jul 26, 2026
884e1c2
fix(weighted-score): preserve comparison context
mcagnion Jul 26, 2026
bb48441
test(weighted-score): cover combined stat weights
mcagnion Jul 26, 2026
b3709c2
refactor(weighted-score): share default weights
mcagnion Jul 26, 2026
0137fd0
fix(weighted-score): use Full DPS for anoint ranking
mcagnion Jul 26, 2026
5cc4da4
fix(weighted-score): persist weight edits
mcagnion Jul 26, 2026
7ed1bc6
fix(weighted-score): place score last in menus
mcagnion Jul 28, 2026
7f428e8
fix(weighted-score): place weight editor after score
mcagnion Jul 28, 2026
ddeca82
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 @@ -52,6 +52,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