Skip to content

Commit 27ed5bd

Browse files
committed
pair skill groups using Jaccard similarity
1 parent ea630c7 commit 27ed5bd

1 file changed

Lines changed: 58 additions & 18 deletions

File tree

src/Classes/CompareTab.lua

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,34 +1696,74 @@ function CompareTabClass:DrawSkills(vp, compareEntry)
16961696
local pGroups = self.primaryBuild.skillsTab and self.primaryBuild.skillsTab.socketGroupList or {}
16971697
local cGroups = compareEntry.skillsTab and compareEntry.skillsTab.socketGroupList or {}
16981698

1699-
-- Helper: get the main (non-support) skill name from a socket group
1700-
local function getMainSkillName(group)
1699+
-- Helper: get the set of gem names in a socket group
1700+
local function getGemNameSet(group)
1701+
local set = {}
17011702
for _, gem in ipairs(group.gemList or {}) do
1702-
if gem.grantedEffect and not gem.grantedEffect.support then
1703-
return gem.grantedEffect.name
1703+
local name = gem.grantedEffect and gem.grantedEffect.name or gem.nameSpec
1704+
if name then
1705+
set[name] = true
17041706
end
17051707
end
1706-
return group.displayLabel or group.label
1708+
return set
17071709
end
17081710

1709-
-- Build lookup: main skill name → compare group index
1710-
local cNameToIndex = {}
1711+
-- Helper: compute Jaccard similarity between two gem name sets
1712+
local function groupSimilarity(setA, setB)
1713+
local intersection = 0
1714+
local union = 0
1715+
local allKeys = {}
1716+
for k in pairs(setA) do allKeys[k] = true end
1717+
for k in pairs(setB) do allKeys[k] = true end
1718+
for k in pairs(allKeys) do
1719+
union = union + 1
1720+
if setA[k] and setB[k] then
1721+
intersection = intersection + 1
1722+
end
1723+
end
1724+
if union == 0 then return 0 end
1725+
return intersection / union
1726+
end
1727+
1728+
-- Build gem name sets for all groups
1729+
local pSets = {}
1730+
for i, group in ipairs(pGroups) do
1731+
pSets[i] = getGemNameSet(group)
1732+
end
1733+
local cSets = {}
17111734
for i, group in ipairs(cGroups) do
1712-
local name = getMainSkillName(group)
1713-
if name and not cNameToIndex[name] then
1714-
cNameToIndex[name] = i
1735+
cSets[i] = getGemNameSet(group)
1736+
end
1737+
1738+
-- Compute all pairwise similarity scores
1739+
local scorePairs = {}
1740+
for pi = 1, #pGroups do
1741+
for ci = 1, #cGroups do
1742+
local score = groupSimilarity(pSets[pi], cSets[ci])
1743+
if score > 0 then
1744+
t_insert(scorePairs, { pIdx = pi, cIdx = ci, score = score })
1745+
end
17151746
end
17161747
end
17171748

1718-
-- Match primary groups to compare groups by main skill name
1719-
local renderPairs = {}
1749+
-- Sort by similarity descending (best matches first)
1750+
table.sort(scorePairs, function(a, b) return a.score > b.score end)
1751+
1752+
-- Greedy matching: assign best pairs first, each group used at most once
1753+
local pMatched = {}
17201754
local cMatched = {}
1721-
for i, group in ipairs(pGroups) do
1722-
local name = getMainSkillName(group)
1723-
if name and cNameToIndex[name] and not cMatched[cNameToIndex[name]] then
1724-
t_insert(renderPairs, { pIdx = i, cIdx = cNameToIndex[name] })
1725-
cMatched[cNameToIndex[name]] = true
1726-
else
1755+
local renderPairs = {}
1756+
for _, sp in ipairs(scorePairs) do
1757+
if not pMatched[sp.pIdx] and not cMatched[sp.cIdx] then
1758+
t_insert(renderPairs, { pIdx = sp.pIdx, cIdx = sp.cIdx })
1759+
pMatched[sp.pIdx] = true
1760+
cMatched[sp.cIdx] = true
1761+
end
1762+
end
1763+
1764+
-- Add unmatched primary groups
1765+
for i = 1, #pGroups do
1766+
if not pMatched[i] then
17271767
t_insert(renderPairs, { pIdx = i, cIdx = nil })
17281768
end
17291769
end

0 commit comments

Comments
 (0)