Skip to content

Commit 3283e06

Browse files
committed
Fix comparison tool issues with local vs global mods, inverted values
1 parent 3df428e commit 3283e06

13 files changed

Lines changed: 7691 additions & 7770 deletions

src/Classes/CalcSectionControl.lua.rej

Lines changed: 0 additions & 66 deletions
This file was deleted.

src/Classes/CalcsTab.lua.rej

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/Classes/CompareBuySimilar.lua

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ local REALM_API_IDS = {
2020

2121
-- Listed status display names and their API option values
2222
local LISTED_STATUS_OPTIONS = {
23-
{ label = "Instant Buyout & In Person", apiValue = "available" },
2423
{ label = "Instant Buyout", apiValue = "securable" },
24+
{ label = "Instant Buyout & In Person", apiValue = "available" },
2525
{ label = "In Person (Online)", apiValue = "online" },
2626
{ label = "Any", apiValue = "any" },
2727
}
@@ -129,7 +129,7 @@ local function buildURL(item, slotName, controls, modEntries, defenceEntries, is
129129
end
130130
end
131131
if next(armourFilters) then
132-
queryFilters.armour_filters = {
132+
queryFilters.equipment_filters = {
133133
filters = armourFilters
134134
}
135135
end
@@ -143,8 +143,17 @@ local function buildURL(item, slotName, controls, modEntries, defenceEntries, is
143143
local maxVal = tonumber(controls[prefix .. "Max"].buf)
144144
local filter = { id = entry.tradeId }
145145
local value = {}
146-
if minVal then value.min = minVal end
147-
if maxVal then value.max = maxVal end
146+
if minVal then
147+
value.min = minVal
148+
end
149+
if maxVal then
150+
value.max = maxVal
151+
end
152+
if entry.invert then
153+
value.min, value.max = value.max, value.min
154+
value.min = value.min and -value.min
155+
value.max = value.max and -value.max
156+
end
148157
if next(value) then
149158
filter.value = value
150159
end
@@ -190,26 +199,29 @@ function M.openPopup(item, slotName, primaryBuild)
190199
-- Collect mod entries with trade IDs
191200
local modEntries = {}
192201
local modTypeSources = {
193-
{ list = item.implicitModLines, type = "implicit" },
194202
{ list = item.enchantModLines, type = "enchant" },
203+
{ list = item.implicitModLines, type = "implicit" },
195204
{ list = item.explicitModLines, type = "explicit" },
196205
}
197206
for _, source in ipairs(modTypeSources) do
198207
if source.list then
199208
for _, modLine in ipairs(source.list) do
200209
if item:CheckModLineVariant(modLine) then
201210
local formatted = itemLib.formatModLine(modLine)
211+
formatted = formatted and formatted:gsub(main.notSupportedTooltipText, "")
202212
if formatted then
203213
-- Use range-resolved text for matching
204214
local resolvedLine = (modLine.range and itemLib.applyRange(modLine.line, modLine.range, modLine.valueScalar)) or modLine.line
205-
local tradeId = tradeHelpers.findTradeModId(resolvedLine, source.type)
215+
local tradeHash = tradeHelpers.findTradeHash(item, resolvedLine, source.type)
216+
local identifier = tradeHash and string.format("%s.stat_%s", source.type, tradeHash)
206217
local value = tradeHelpers.modLineValue(resolvedLine)
207218
t_insert(modEntries, {
208219
line = modLine.line,
209220
formatted = formatted:gsub("%^x%x%x%x%x%x%x", ""):gsub("%^%x", ""), -- strip color codes
210-
tradeId = tradeId,
221+
tradeId = identifier,
211222
value = value,
212223
modType = source.type,
224+
invert = tradeHelpers.shouldBeInverted(identifier, resolvedLine, source.type)
213225
})
214226
end
215227
end

src/Classes/CompareTradeHelpers.lua

Lines changed: 78 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -29,48 +29,11 @@ function M.modLineValue(line)
2929
return tonumber(line:match("[%d]+%.?[%d]*")) or 0
3030
end
3131

32-
-- Helper: lazily build a reverse lookup from QueryMods tradeMod.text → tradeMod.id
33-
local _tradeModLookup = nil
34-
local function getTradeModLookup()
35-
if _tradeModLookup then return _tradeModLookup end
36-
_tradeModLookup = {}
37-
if not queryModsData then return _tradeModLookup end
38-
for _groupName, mods in pairs(queryModsData) do
39-
for _modKey, modData in pairs(mods) do
40-
if type(modData) == "table" and modData.tradeMod then
41-
local text = modData.tradeMod.text
42-
local modType = modData.tradeMod.type or "explicit"
43-
local id = modData.tradeMod.id
44-
local key = text .. "|" .. modType
45-
_tradeModLookup[key] = id
46-
if not _tradeModLookup[text] then
47-
_tradeModLookup[text] = id
48-
end
49-
-- Also store with template-converted text for mods with literal numbers
50-
-- (e.g. "1 Added Passive Skill is X" → "# Added Passive Skill is X")
51-
local template = M.modLineTemplate(text)
52-
if template ~= text then
53-
local templateKey = template .. "|" .. modType
54-
if not _tradeModLookup[templateKey] then
55-
_tradeModLookup[templateKey] = id
56-
end
57-
if not _tradeModLookup[template] then
58-
_tradeModLookup[template] = id
59-
end
60-
end
61-
end
62-
end
63-
end
64-
return _tradeModLookup
65-
end
66-
67-
-- Helper: lazily fetch and cache the trade API stats for comprehensive mod matching
68-
-- Covers mods not in QueryMods.lua (cluster enchants, unique-specific mods, etc.)
69-
local _tradeStatsLookup = nil
32+
-- Helper: fetch and cache the trade API stats
33+
local _tradeStats = nil
7034
local _tradeStatsFetched = false
7135
local function getTradeStatsLookup()
72-
if _tradeStatsFetched then return _tradeStatsLookup end
73-
_tradeStatsFetched = true
36+
if _tradeStats then return _tradeStats end
7437
local tradeStats = ""
7538
local easy = common.curl.easy()
7639
if not easy then return nil end
@@ -82,24 +45,10 @@ local function getTradeStatsLookup()
8245
end)
8346
local ok = easy:perform()
8447
easy:close()
85-
if not ok or tradeStats == "" then return nil end
48+
if not ok or tradeStats == "" then return {} end
8649
local parsed = dkjson.decode(tradeStats)
87-
if not parsed or not parsed.result then return nil end
88-
_tradeStatsLookup = {}
89-
for _, category in ipairs(parsed.result) do
90-
local catLabel = category.label
91-
for _, entry in ipairs(category.entries) do
92-
local stripped = entry.text:gsub("[#()0-9%-%+%.]", "")
93-
local key = stripped .. "|" .. catLabel
94-
if not _tradeStatsLookup[key] then
95-
_tradeStatsLookup[key] = entry
96-
end
97-
if not _tradeStatsLookup[stripped] then
98-
_tradeStatsLookup[stripped] = entry
99-
end
100-
end
101-
end
102-
return _tradeStatsLookup
50+
_tradeStats = parsed.result
51+
return _tradeStats
10352
end
10453

10554
-- Map source types used in OpenBuySimilarPopup to trade API category labels
@@ -109,48 +58,83 @@ M.sourceTypeToCategory = {
10958
["enchant"] = "Enchant",
11059
}
11160

112-
-- Helper: find the trade stat ID for a mod line
113-
function M.findTradeModId(modLine, modType)
114-
-- Try QueryMods-based lookup
115-
local lookup = getTradeModLookup()
116-
local template = M.modLineTemplate(modLine)
117-
-- Try exact match with type first
118-
local key = template .. "|" .. modType
119-
if lookup[key] then
120-
return lookup[key]
121-
end
122-
-- Try without leading +/- sign
123-
local stripped = template:gsub("^[%+%-]", "")
124-
key = stripped .. "|" .. modType
125-
if lookup[key] then
126-
return lookup[key]
127-
end
128-
-- Fallback: match by template text only (any type)
129-
if lookup[template] then
130-
return lookup[template]
131-
end
132-
if lookup[stripped] then
133-
return lookup[stripped]
61+
function M.shouldBeInverted(tradeId, modLine, modType)
62+
local formattedLine = M.formatDatabaseText(M.formatDatabaseText(modLine))
63+
for _, category in ipairs(getTradeStatsLookup()) do
64+
if category.id == modType then
65+
for _, stat in ipairs(category.entries) do
66+
if tradeId == stat.id then
67+
-- local modifiers don't seem to be inverted
68+
if stat.text:match("(Local)") then
69+
return false
70+
end
71+
-- trade site sometimes has a + sign, sometimes not
72+
return not (formattedLine == stat.text or formattedLine:gsub("^%+", "") == stat.text)
73+
end
74+
end
75+
end
13476
end
77+
end
13578

136-
-- Try trade API stats (covers mods not in QueryMods)
137-
local tradeStats = getTradeStatsLookup()
138-
if tradeStats then
139-
local strippedLine = modLine:gsub("[#()0-9%-%+%.]", "")
140-
local category = M.sourceTypeToCategory[modType]
141-
if category then
142-
local catKey = strippedLine .. "|" .. category
143-
if tradeStats[catKey] then
144-
return tradeStats[catKey].id
79+
-- Helper: normalise data texts to # format
80+
function M.formatDatabaseText(text)
81+
-- decimal -> integer
82+
text = text:gsub("%d+%.%d+", "1")
83+
-- (123-124) -> #
84+
text = text:gsub("%(%d+%-%d+%)", "#")
85+
text = text:gsub("%d+", "#")
86+
return text
87+
end
88+
89+
-- Helper: find the trade stat ID for a mod line
90+
function M.findTradeHash(item, modLine, modType)
91+
local formattedLine = M.formatDatabaseText(modLine)
92+
-- the data export splits some mods into different parts, even though they
93+
-- are technically just one stat. we handle that here
94+
function findStat(dbMod)
95+
local lineIdx = 1
96+
local statIdx = 1
97+
while dbMod.statOrder[lineIdx] do
98+
local skipped = false
99+
while dbMod.statOrder[lineIdx] == m_floor(dbMod.statOrder[lineIdx + 1] or -1) do
100+
-- some stats are split, skip those for now
101+
lineIdx = lineIdx + 1
102+
skipped = true
103+
end
104+
if not skipped and dbMod[lineIdx] then
105+
local dbFormatted = M.formatDatabaseText(dbMod[lineIdx])
106+
if formattedLine == dbFormatted and item:GetModSpawnWeight(dbMod, nil, {default = true}) then
107+
return dbMod.tradeHashes[statIdx]
108+
end
109+
end
110+
lineIdx = lineIdx + 1
111+
statIdx = statIdx + 1
112+
end
113+
end
114+
-- corruptions
115+
if modType == "enchant" then
116+
for _, dbMod in pairs(data.itemMods.Corruption) do
117+
local tradeHashMaybe = findStat(dbMod)
118+
if tradeHashMaybe then
119+
return tradeHashMaybe
145120
end
146121
end
147-
-- Fallback: any category
148-
if tradeStats[strippedLine] then
149-
return tradeStats[strippedLine].id
122+
-- explicit
123+
elseif modType ~= "implicit" then
124+
for _, dbMod in pairs(data.itemMods.Item) do
125+
local tradeHashMaybe = findStat(dbMod)
126+
if tradeHashMaybe then
127+
return tradeHashMaybe
128+
end
150129
end
151130
end
152-
153-
return nil
131+
-- implicit, and special explicit (e.g. unique and essence)
132+
for _, dbMod in pairs(data.itemMods.Exclusive) do
133+
local tradeHashMaybe = findStat(dbMod)
134+
if tradeHashMaybe then
135+
return tradeHashMaybe
136+
end
137+
end
154138
end
155139

156140
-- Map slot name + item type to (trade API category string, itemCategoryTags key).
@@ -164,6 +148,7 @@ function M.getTradeCategoryInfo(slotName, item)
164148
if itemType == "Shield" then return "armour.shield", "Shield"
165149
elseif itemType == "Quiver" then return "armour.quiver", "Quiver"
166150
elseif itemType == "Bow" then return "weapon.bow", "Bow"
151+
elseif itemType == "Staff" and item.base.subType == "Warstaff" then return "weapon.warstaff", "Staff"
167152
elseif itemType == "Staff" then return "weapon.staff", "Staff"
168153
elseif itemType == "Two Handed Sword" then return "weapon.twosword", "2HSword"
169154
elseif itemType == "Two Handed Axe" then return "weapon.twoaxe", "2HAxe"

0 commit comments

Comments
 (0)