diff --git a/spec/System/TestTradeQueryCurrency_spec.lua.rej b/spec/System/TestTradeQueryCurrency_spec.lua.rej new file mode 100644 index 0000000000..870856ac48 --- /dev/null +++ b/spec/System/TestTradeQueryCurrency_spec.lua.rej @@ -0,0 +1,26 @@ +diff a/spec/System/TestTradeQueryCurrency_spec.lua b/spec/System/TestTradeQueryCurrency_spec.lua (rejected hunks) +@@ -23,24 +23,6 @@ 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 diff --git a/spec/System/TestTradeQueryGenerator_spec.lua.rej b/spec/System/TestTradeQueryGenerator_spec.lua.rej new file mode 100644 index 0000000000..4360660c03 --- /dev/null +++ b/spec/System/TestTradeQueryGenerator_spec.lua.rej @@ -0,0 +1,10 @@ +diff a/spec/System/TestTradeQueryGenerator_spec.lua b/spec/System/TestTradeQueryGenerator_spec.lua (rejected hunks) +@@ -54,7 +54,7 @@ describe("TradeQueryGenerator", function() + + local result = mock_queryGen.WeightedRatioOutputs(baseOutput, newOutput, statWeights) + +- local close_enough = (result - -0.1) < 0.0001 ++ local close_enough = math.abs(result - -0.1) < 0.0001 + assert.True(close_enough) + end) + diff --git a/spec/System/TestTradeQuery_spec.lua.rej b/spec/System/TestTradeQuery_spec.lua.rej new file mode 100644 index 0000000000..7d2c443fde --- /dev/null +++ b/spec/System/TestTradeQuery_spec.lua.rej @@ -0,0 +1,38 @@ +diff a/spec/System/TestTradeQuery_spec.lua b/spec/System/TestTradeQuery_spec.lua (rejected hunks) +@@ -1,8 +1,10 @@ + describe("TradeQuery", function () + local mock_tradeQuery ++ local mock_queryGen + + before_each(function() + mock_tradeQuery = new("TradeQuery", { itemsTab = {} }) ++ mock_queryGen = new("TradeQueryGenerator", { itemsTab = {} }) + end) + + describe("ReduceOutput", function() +@@ -21,5 +23,24 @@ describe("TradeQuery", function () + assert.are.equals(260, result.AverageDamage) + assert.is_nil(result.Life) + end) ++ ++ it("keeps fallback DPS stats when FullDPS is selected but not present", function() ++ mock_tradeQuery.statSortSelectionList = { { stat = "FullDPS", weightMult = 1 } } ++ ++ local baseOutput = { ++ CombinedDPS = 100, ++ TotalDPS = 100, ++ TotalDotDPS = 0, ++ } ++ local reducedOutput = mock_tradeQuery:ReduceOutput({ ++ CombinedDPS = 120, ++ TotalDPS = 120, ++ TotalDotDPS = 0, ++ }) ++ ++ local result = mock_queryGen.WeightedRatioOutputs(baseOutput, reducedOutput, mock_tradeQuery.statSortSelectionList) ++ ++ assert.are.equals(1.2, result) ++ end) + end) + end) +\ No newline at end of file diff --git a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua index 690103ba09..a713979737 100644 --- a/src/Classes/CalcsTab.lua +++ b/src/Classes/CalcsTab.lua @@ -712,16 +712,8 @@ function CalcsTabClass:PowerBuilder() end function CalcsTabClass:CalculatePowerStat(selection, original, modified) - if modified.Minion and selection.stat ~= "FullDPS" then - original = original.Minion - modified = modified.Minion - end - local originalValue = original[selection.stat] or 0 - local modifiedValue = modified[selection.stat] or 0 - if selection.transform then - originalValue = selection.transform(originalValue) - modifiedValue = selection.transform(modifiedValue) - end + local originalValue = data.powerStatList.GetFromOutput(original, selection) + local modifiedValue = data.powerStatList.GetFromOutput(modified, selection) return originalValue - modifiedValue end @@ -732,10 +724,9 @@ function CalcsTabClass:CalculateCombinedOffDefStat(original, modified) (original.Evasion - modified.Evasion) / m_max(10000, modified.Evasion) + (original.LifeRegenRecovery - modified.LifeRegenRecovery) / 500 + (original.EnergyShieldRegenRecovery - modified.EnergyShieldRegenRecovery) / 1000 - if modified.Minion then - return (original.Minion.CombinedDPS - modified.Minion.CombinedDPS) / modified.Minion.CombinedDPS, defence - end - return (original.CombinedDPS - modified.CombinedDPS) / modified.CombinedDPS, defence + local modifiedDps = modified.CombinedDPS + (modified.Minion and modified.Minion.CombinedDPS or 0) + local dpsIncr = original.CombinedDPS + (original.Minion and original.Minion.CombinedDPS or 0) - modifiedDps + return dpsIncr / modifiedDps, defence end function CalcsTabClass:GetNodeCalculator() diff --git a/src/Classes/CompareTab.lua b/src/Classes/CompareTab.lua index 24506313c6..946c580f4b 100644 --- a/src/Classes/CompareTab.lua +++ b/src/Classes/CompareTab.lua @@ -2544,10 +2544,7 @@ function CompareTabClass:ComparePowerBuilder(compareEntry, powerStat, categories end -- Get baseline stat value for percentage calculation - local baseStatValue = calcBase[powerStat.stat] or 0 - if powerStat.transform then - baseStatValue = powerStat.transform(baseStatValue) - end + local baseStatValue = data.powerStatList.GetFromOutput(calcBase, powerStat) -- Helper to format an impact value and compute percentage local function formatImpact(impact) diff --git a/src/Classes/ItemDBControl.lua b/src/Classes/ItemDBControl.lua index 3136d1a847..0fc8303b2f 100644 --- a/src/Classes/ItemDBControl.lua +++ b/src/Classes/ItemDBControl.lua @@ -190,7 +190,7 @@ end function ItemDBClass:BuildSortOrder() wipeTable(self.sortDropList) - for id,stat in pairs(data.powerStatList) do + for id, stat in ipairs(data.powerStatList) do if not stat.ignoreForItems then t_insert(self.sortDropList, { label="Sort by "..stat.label, diff --git a/src/Classes/ItemDBControl.lua.rej b/src/Classes/ItemDBControl.lua.rej new file mode 100644 index 0000000000..bb65957caa --- /dev/null +++ b/src/Classes/ItemDBControl.lua.rej @@ -0,0 +1,11 @@ +diff a/src/Classes/ItemDBControl.lua b/src/Classes/ItemDBControl.lua (rejected hunks) +@@ -244,9 +244,6 @@ function ItemDBClass:ListBuilder() + if self.itemsTab:IsItemValidForSlot(item, slotName) and not slot.inactive and (not slot.weaponSet or slot.weaponSet == (self.itemsTab.activeItemSet.useSecondWeaponSet and 2 or 1)) then + local output = calcFunc(item.base.flask and { toggleFlask = item } or item.base.charm and { toggleCharm = item } or { repSlotName = slotName, repItem = item }, useFullDPS) + local measuredPower = data.powerStatList.GetFromOutput(output, self.sortDetail) +- if self.sortDetail.transform then +- measuredPower = self.sortDetail.transform(measuredPower) +- end + item.measuredPower = item.measuredPower and m_max(item.measuredPower, measuredPower) or measuredPower + end + end diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index e6083ea783..6320011f41 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -1122,7 +1122,15 @@ function ItemsTabClass:Load(xml, dbFileName) stat = child.attrib.stat, weightMult = tonumber(child.attrib.weightMult) } - t_insert(self.tradeQuery.statSortSelectionList, statSort) + for _, statEntry in ipairs(data.powerStatList) do + if statSort.stat == statEntry.stat then + -- update information which can be out of data or missing in the xml + statSort.label = statEntry.label + statSort.transform = statEntry.transform + t_insert(self.tradeQuery.statSortSelectionList, statSort) + break + end + end end end end diff --git a/src/Classes/NotableDBControl.lua b/src/Classes/NotableDBControl.lua index d08ec4080c..e3fb85b5bb 100644 --- a/src/Classes/NotableDBControl.lua +++ b/src/Classes/NotableDBControl.lua @@ -87,7 +87,7 @@ end function NotableDBClass:BuildSortOrder() wipeTable(self.sortDropList) - for id,stat in pairs(data.powerStatList) do + for id, stat in ipairs(data.powerStatList) do if not stat.ignoreForItems then t_insert(self.sortDropList, { label="Sort by "..stat.label, @@ -111,16 +111,8 @@ function NotableDBClass:BuildSortOrder() end function NotableDBClass:CalculatePowerStat(selection, original, modified) - if modified.Minion then - original = original.Minion - modified = modified.Minion - end - local originalValue = original[selection.stat] or 0 - local modifiedValue = modified[selection.stat] or 0 - if selection.transform then - originalValue = selection.transform(originalValue) - modifiedValue = selection.transform(modifiedValue) - end + local originalValue = data.powerStatList.GetFromOutput(original, selection) + local modifiedValue = data.powerStatList.GetFromOutput(modified, selection) return originalValue - modifiedValue end diff --git a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua index 9e1308bfb9..697fa84f87 100644 --- a/src/Classes/TradeQuery.lua +++ b/src/Classes/TradeQuery.lua @@ -553,11 +553,16 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) local controls = { } local statList = { } local sliderController = { index = 1 } - local popupHeight = 285 + local popupHeight = 500 - controls.ListControl = new("TradeStatWeightMultiplierListControl", {"TOPLEFT", nil, "TOPRIGHT"}, {-410, 45, 400, 200}, statList, sliderController) + local listYOffset = 45 + -- account for top gap, bottom button size and gap, and a gap before buttons + local listHeight = popupHeight - 45 - 30 - 10 - for id, stat in pairs(data.powerStatList) do + controls.ListControl = new("TradeStatWeightMultiplierListControl", { "TOPLEFT", nil, "TOPRIGHT" }, + { -410, 45, 400, listHeight }, statList, sliderController) + + for _, stat in ipairs(data.powerStatList) do if not stat.ignoreForItems and stat.label ~= "Name" then t_insert(statList, { label = "0 : "..stat.label, diff --git a/src/Classes/TradeQuery.lua.rej b/src/Classes/TradeQuery.lua.rej new file mode 100644 index 0000000000..20900eede4 --- /dev/null +++ b/src/Classes/TradeQuery.lua.rej @@ -0,0 +1,13 @@ +diff a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua (rejected hunks) +@@ -780,6 +780,11 @@ function TradeQueryClass:ReduceOutput(output) + local smallOutput = {} + for _, statTable in ipairs(self.statSortSelectionList) do + smallOutput[statTable.stat] = data.powerStatList.GetFromOutput(output, statTable) ++ if statTable.stat == "FullDPS" and not output.FullDPS then ++ smallOutput.TotalDPS = data.powerStatList.GetFromOutput(output, { stat = "TotalDPS" }) ++ smallOutput.TotalDotDPS = data.powerStatList.GetFromOutput(output, { stat = "TotalDotDPS" }) ++ smallOutput.CombinedDPS = data.powerStatList.GetFromOutput(output, { stat = "CombinedDPS" }) ++ end + end + return smallOutput + end diff --git a/src/Classes/TradeQueryGenerator.lua.rej b/src/Classes/TradeQueryGenerator.lua.rej new file mode 100644 index 0000000000..9255b3fe21 --- /dev/null +++ b/src/Classes/TradeQueryGenerator.lua.rej @@ -0,0 +1,12 @@ +diff a/src/Classes/TradeQueryGenerator.lua b/src/Classes/TradeQueryGenerator.lua (rejected hunks) +@@ -162,8 +162,8 @@ function TradeQueryGeneratorClass.WeightedRatioOutputs(baseOutput, newOutput, st + local baseModSum = 0 + local newModSum = 0 + for _, mod in ipairs({ ... }) do +- baseModSum = baseModSum + data.powerStatList.GetFromOutput(baseOutput, mod) +- newModSum = newModSum + data.powerStatList.GetFromOutput(newOutput, mod) ++ baseModSum = baseModSum + data.powerStatList.GetFromOutput(baseOutput, mod, true) ++ newModSum = newModSum + data.powerStatList.GetFromOutput(newOutput, mod, true) + end + + if baseModSum == math.huge then diff --git a/src/Classes/TradeStatWeightMultiplierListControl.lua b/src/Classes/TradeStatWeightMultiplierListControl.lua index 0d528470f5..f0260d89de 100644 --- a/src/Classes/TradeStatWeightMultiplierListControl.lua +++ b/src/Classes/TradeStatWeightMultiplierListControl.lua @@ -25,7 +25,7 @@ end function TradeStatWeightMultiplierListControlClass:AddValueTooltip(tooltip, index, data) tooltip:Clear() if not self.noTooltip then - tooltip:AddLine(16, "^7Double click to modify this stats weight multiplier.") + tooltip:AddLine(16, "^7Click to modify this stats weight multiplier.") end end diff --git a/src/Classes/TreeTab.lua.rej b/src/Classes/TreeTab.lua.rej new file mode 100644 index 0000000000..4870341236 --- /dev/null +++ b/src/Classes/TreeTab.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Classes/TreeTab.lua b/src/Classes/TreeTab.lua (rejected hunks) +@@ -1850,7 +1850,7 @@ function TreeTabClass:FindTimelessJewel() + + controls.fallbackWeightsLabel = new("LabelControl", {"TOPRIGHT", nil, "TOPLEFT"}, {405, 225, 0, 16}, "^7Fallback Weight Mode:") + local fallbackWeightsList = { } +- for id, stat in pairs(data.powerStatList) do ++ for _, stat in ipairs(data.powerStatList) do + if not stat.ignoreForItems and stat.label ~= "Name" then + t_insert(fallbackWeightsList, { + label = "Sort by " .. stat.label, diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index a880019c7f..c581cb661f 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -108,6 +108,16 @@ data = { } -- Misc data tables LoadModule("Data/Misc", data) +---@class StatTable +---@field stat? string stat ID +---@field label string A short description of the stat +---@field transform fun(in: number|string): number|string A function to e.g. invert the value, if the stat represents something where lower is better +---@field combinedOffDef? boolean +---@field ignoreForNodes? boolean +---@field ignoreForItems? boolean +---@field reverseSort? boolean + +---@type StatTable[] data.powerStatList = { { stat=nil, label="Offence/Defence", combinedOffDef=true, ignoreForItems=true }, { stat=nil, label="Name", itemField="Name", ignoreForNodes=true, reverseSort=true, transform=function(value) return value:gsub("^The ","") end}, diff --git a/src/Modules/Data.lua.rej b/src/Modules/Data.lua.rej new file mode 100644 index 0000000000..0b84cbfa09 --- /dev/null +++ b/src/Modules/Data.lua.rej @@ -0,0 +1,10 @@ +diff a/src/Modules/Data.lua b/src/Modules/Data.lua (rejected hunks) +@@ -189,7 +189,7 @@ function data.powerStatList.GetFromOutput(output, statTable, skipTransform) + return output[statTable.stat] or 0 + end + -- if the user doesn't have full dps, we default to adding the player and minion dps together +- return (output.CombinedDPS or 0) + (output.Minion and output.Minion.CombinedDPS) ++ return (output.CombinedDPS or 0) + (output.Minion and output.Minion.CombinedDPS or 0) + end + -- minion-only stats + local minionStat = statTable.stat:match("^Minion(.+)")