Skip to content

Commit 859cd82

Browse files
vaisestLocalIdentity
andauthored
Buy similar: combine same stats from different mods (#2118)
* Fix repeated mods resulting from new runes in buy similar * Avoid combining mods in buy similar that shouldnt be combined * Fix # to # modlineValue pattern * Show each original mod line when summing mods in buy similar * Add float filter to buy similar fields * Fix input issues Regex was wrong and was rejecting integers Unsupported mods text issue --------- Co-authored-by: LocalIdentity <localidentity2@gmail.com>
1 parent eabe806 commit 859cd82

2 files changed

Lines changed: 66 additions & 25 deletions

File tree

src/Classes/CompareBuySimilar.lua

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,6 @@ local function buildURL(item, slotName, controls, modEntries, defenceEntries, is
152152
filter.value = value
153153
end
154154
end
155-
156155
t_insert(queryTable.query.stats[1].filters, filter)
157156
end
158157
end
@@ -200,6 +199,22 @@ function M.openPopup(item, slotName, primaryBuild)
200199
{ list = item.implicitModLines, type = "implicit" },
201200
{ list = item.explicitModLines, type = "explicit" },
202201
}
202+
-- this adds a single aggregated entry for matching stats (e.g. transformed flat dmg mods) which avoids issues with confusing results. different types are not summed as e.g. implicit and explicit mods are separate in the search. options are also avoided as they don't represent values that can be added combined
203+
local function insertOrAddToExisting(entry)
204+
for _, existingFilter in ipairs(modEntries) do
205+
if (not existingFilter.isOption) and entry.value
206+
and existingFilter.tradeId and existingFilter.tradeId == entry.tradeId
207+
and existingFilter.type == entry.type
208+
then
209+
existingFilter.count = existingFilter.count + 1
210+
local value = (entry.invert ~= existingFilter.invert) and -entry.value or entry.value
211+
existingFilter.value = (existingFilter.value or 0) + value
212+
t_insert(existingFilter.formattedLines, entry.formattedLines[1])
213+
return
214+
end
215+
end
216+
t_insert(modEntries, entry)
217+
end
203218
for _, source in ipairs(modTypeSources) do
204219
if source.list then
205220
for _, modLine in ipairs(source.list) do
@@ -220,14 +235,16 @@ function M.openPopup(item, slotName, primaryBuild)
220235
value = tradeHelpers.modLineValue(resolvedLine)
221236
end
222237
local invert = (not isOption) and tradeHelpers.shouldBeInverted(identifier, resolvedLine, source.type)
223-
t_insert(modEntries, {
224-
line = modLine.line,
225-
formatted = formatted,
238+
insertOrAddToExisting({
239+
-- this array will always start with one line, but if multiple mods are
240+
-- aggregated together it will contain the original mod lines for each
241+
formattedLines = {formatted},
226242
tradeId = identifier,
227243
value = value,
228244
isOption = isOption,
229245
type = source.type,
230246
invert = invert,
247+
count = 1,
231248
})
232249
end
233250
end
@@ -332,8 +349,9 @@ function M.openPopup(item, slotName, primaryBuild)
332349

333350
-- Helper: create a numeric EditControl without +/- spinner buttons, and
334351
-- with a preset changeFunc
335-
local function newPlainNumericEdit(anchor, rect, init, prompt, limit)
336-
local ctrl = new("EditControl", anchor, rect, init, prompt, "%D", limit, rebuildUrl)
352+
local function newPlainNumericEdit(anchor, rect, init, prompt, limit, integer)
353+
local format = integer and "%D" or "^%d."
354+
local ctrl = new("EditControl", anchor, rect, init, prompt, format, limit, rebuildUrl)
337355
-- Remove the +/- spinner buttons that "%D" filter triggers
338356
ctrl.isNumeric = false
339357
if ctrl.controls then
@@ -360,17 +378,17 @@ function M.openPopup(item, slotName, primaryBuild)
360378
-- Item level
361379
ctrlY = ctrlY + 4
362380
controls.ilvlLabel = new("LabelControl", {"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Item Level:")
363-
controls.ilvlMin = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Min", 4)
364-
controls.ilvlMax = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Max", 4)
381+
controls.ilvlMin = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Min", 4, true)
382+
controls.ilvlMax = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Max", 4, true)
365383
ctrlY = ctrlY + rowHeight
366384

367385
-- Defence stat rows
368386
for i, def in ipairs(defenceEntries) do
369387
local prefix = "def" .. i
370388
controls[prefix .. "Check"] = new("CheckBoxControl", nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", rebuildUrl)
371389
controls[prefix .. "Label"] = new("LabelControl", {"LEFT", controls[prefix .. "Check"], "RIGHT"}, {4, 0, 0, 16}, "^7" .. def.label)
372-
controls[prefix .. "Min"] = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, tostring(m_floor(def.value)), "Min", 6)
373-
controls[prefix .. "Max"] = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Max", 6)
390+
controls[prefix .. "Min"] = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, tostring(m_floor(def.value)), "Min", 6, true)
391+
controls[prefix .. "Max"] = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Max", 6, true)
374392
ctrlY = ctrlY + rowHeight
375393
end
376394

@@ -390,33 +408,51 @@ function M.openPopup(item, slotName, primaryBuild)
390408
prevType = entry.type
391409
local prefix = "mod" .. i
392410
local canSearch = entry.tradeId ~= nil
393-
controls[prefix .. "Check"] = new("CheckBoxControl", nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", rebuildUrl)
411+
412+
local rows = #entry.formattedLines
413+
414+
local fontSize = 16
415+
-- adjust down by half a text row for each row over 1
416+
local controlYPos = ctrlY + (rows - 1) * 8
417+
local checkBoxXPos = -popupWidth/2 + leftMargin + checkboxSize/2
418+
controls[prefix .. "Check"] = new("CheckBoxControl", nil, {checkBoxXPos, controlYPos, checkboxSize}, "", rebuildUrl)
394419
controls[prefix .. "Check"].enabled = function() return canSearch end
420+
421+
395422
-- Truncate long mod text to fit
396-
--- @type string
397-
local displayText = entry.formatted
398-
local colorCodeLength = displayText:match("(%^x%x%x%x%x%x%x)") or displayText:gsub("(%^%x)", "") or ""
399-
if not canSearch then
400-
-- strip color codes and replace with gray
401-
displayText = "^8" .. displayText:gsub("%^x%x%x%x%x%x%x", ""):gsub("%^%x", "")
402-
end
403-
if #displayText > (#colorCodeLength + 60) then
404-
displayText = displayText:sub(1, #colorCodeLength + 54) .. "..."
423+
--- @type string[]
424+
local displayTexts = entry.formattedLines
425+
for index, displayText in ipairs(displayTexts) do
426+
local colorCodeLength = displayText:match("(%^x%x%x%x%x%x%x)") or displayText:gsub("(%^%x)", "") or ""
427+
428+
if not canSearch then
429+
-- strip color codes and replace with gray
430+
displayText = "^8" .. displayText:gsub("%^x%x%x%x%x%x%x", ""):gsub("%^%x", "")
431+
end
432+
if #displayText > (#colorCodeLength + 62) then
433+
displayText = displayText:sub(1, #colorCodeLength + 54) .. "..."
434+
end
435+
displayTexts[index] = displayText
405436
end
406437

407-
controls[prefix .. "Label"] = new("LabelControl", { "LEFT", controls[prefix .. "Check"], "RIGHT" }, { 4, 0, 0, 16 },
438+
439+
local displayText = table.concat(displayTexts, "\n")
440+
-- labels anchor based on the first row instead of the middle row, so adjust upwards
441+
local labelXOffset = (rows - 1) * -8
442+
443+
controls[prefix .. "Label"] = new("LabelControl", {"LEFT", controls[prefix .. "Check"], "RIGHT"},{ 4, labelXOffset, 0, fontSize },
408444
displayText)
409445
-- when the trade site has a dropdown for the value, we opt to disable
410446
-- the inputs as they are numeric
411447
if not (entry.isOption or entry.needsExactValue) and entry.value then
412-
controls[prefix .. "Min"] = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, entry.value ~= 0 and tostring(m_floor(entry.value)) or "", "Min", 8)
413-
controls[prefix .. "Max"] = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Max", 8)
448+
controls[prefix .. "Min"] = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, controlYPos, fieldW, fieldH}, entry.value ~= 0 and tostring(entry.value) or "", "Min", 8)
449+
controls[prefix .. "Max"] = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, controlYPos, fieldW, fieldH}, "", "Max", 8)
414450
if not canSearch then
415451
controls[prefix .. "Min"].enabled = function() return false end
416452
controls[prefix .. "Max"].enabled = function() return false end
417453
end
418454
end
419-
ctrlY = ctrlY + rowHeight
455+
ctrlY = ctrlY + math.max(rowHeight, fontSize*rows + 8)
420456
end
421457

422458
-- Search button

src/Classes/TradeHelpers.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,14 @@ function M.modLineTemplate(line)
2626
return line:gsub("%-?[%d]+%.?[%d]*", "#")
2727
end
2828

29-
-- Helper: extract the first number from a mod line for value comparison
29+
-- Helper: extract the first number from a mod line for value comparison, or in the case of # to #
30+
-- mods, the midpoint of that range
3031
--- @param line string
3132
function M.modLineValue(line)
33+
local low, high = line:match("(%-?%d+%.?%d*) to (%-?%d+%.?%d*)")
34+
if low and high then
35+
return (tonumber(low) + tonumber(high)) / 2
36+
end
3237
return tonumber(line:match("%-?[%d]+%.?[%d]*"))
3338
end
3439

0 commit comments

Comments
 (0)