Skip to content

Commit 0808a5b

Browse files
committed
Port PoB2 buy similar mod matching and UI
1 parent b3481fa commit 0808a5b

35 files changed

Lines changed: 204942 additions & 70649 deletions
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
describe("Buy similar mod stat matching", function()
2+
local bs = LoadModule("Classes/CompareBuySimilar")
3+
4+
describe("addModEntries mod matching", function()
5+
it("matches impossible escape mods as options", function()
6+
local fromNothing = new("Item", [[
7+
Impossible Escape
8+
Viridian Jewel
9+
LevelReq: 0
10+
Radius: Small
11+
Limited to: 1
12+
Implicits: 0
13+
Passive skills in radius of Elemental Overload can be Allocated without being connected to your tree
14+
Corrupted]])
15+
16+
local modSources = {
17+
{ list = fromNothing.explicitModLines, type = "explicit" }
18+
}
19+
local modEntries = bs.addModEntries(fromNothing, modSources)
20+
assert.equal(1, #modEntries)
21+
assert.same(
22+
{
23+
formattedLines = { colorCodes.MAGIC .. "Passive skills in radius of Elemental Overload can be Allocated without being connected to your tree" },
24+
type =
25+
"explicit",
26+
isOption = true,
27+
invert = false,
28+
tradeIds = { "explicit.stat_2422708892" },
29+
value = 22088
30+
},
31+
modEntries[1])
32+
33+
local thread = new("Item", [[
34+
Rarity: UNIQUE
35+
Thread of Hope
36+
Crimson Jewel
37+
Radius: Variable
38+
Implicits: 0
39+
Only affects Passives in Massive Ring
40+
-15% to all Elemental Resistances
41+
Passive Skills in Radius can be Allocated without being connected to your tree
42+
Passage]])
43+
local modSources = {
44+
{ list = thread.explicitModLines, type = "explicit" }
45+
}
46+
local modEntries = bs.addModEntries(thread, modSources)
47+
assert.equal(4, #modEntries)
48+
assert.equal(modEntries[1].tradeIds[1], "explicit.stat_3642528642")
49+
assert.equal(modEntries[1].value, 5)
50+
end)
51+
52+
it("combines mods that are the same stat", function()
53+
local lifeDiamond = new("Item", [[
54+
Test Subject
55+
Diamond
56+
Implicits: 0
57+
+100 to Maximum Life
58+
+50 to Maximum Life
59+
+50% to Fire Resistance]])
60+
61+
local entries = bs.addModEntries(lifeDiamond, { { list = lifeDiamond.explicitModLines, type = "explicit" } })
62+
assert.equal(2, #entries)
63+
assert.equal(2, #entries[1].formattedLines)
64+
assert.equal("+100 to Maximum Life", StripEscapes(entries[1].formattedLines[1]))
65+
assert.equal("+50 to Maximum Life", StripEscapes(entries[1].formattedLines[2]))
66+
assert.equal(150, entries[1].value)
67+
68+
local lifelessDiamond = new("Item", [[
69+
Test Subject
70+
Diamond
71+
Implicits: 0
72+
-100 to Maximum Life
73+
+50 to Maximum Life
74+
+50% to Fire Resistance]])
75+
local entries = bs.addModEntries(lifelessDiamond,
76+
{ { list = lifelessDiamond.explicitModLines, type = "explicit" } })
77+
assert.equal(2, #entries)
78+
assert.equal(2, #entries[1].formattedLines)
79+
assert.equal(-50, entries[1].value)
80+
end)
81+
82+
it("is not case-sensitive", function ()
83+
local funnyItem = new("Item", [[
84+
Test Subject
85+
Diamond
86+
Implicits: 1
87+
+50 tO MaxIMum lifE]])
88+
89+
local entries = bs.addModEntries(funnyItem, {{list = funnyItem.implicitModLines, type = "implicit"}})
90+
assert.equal(1, #entries)
91+
end)
92+
93+
it("does not combine implicit and explicit mods", function()
94+
local lifelessDiamond = new("Item", [[
95+
Test Subject
96+
Diamond
97+
Implicits: 1
98+
-100 to Maximum Life
99+
+50 to Maximum Life]])
100+
local entries = bs.addModEntries(lifelessDiamond,
101+
{ { list = lifelessDiamond.implicitModLines, type = "implicit" }, { list = lifelessDiamond.explicitModLines, type = "explicit" } })
102+
assert.equal(2, #entries)
103+
assert.equal(-100, entries[1].value)
104+
assert.equal(50, entries[2].value)
105+
end)
106+
end)
107+
end)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
describe("TradeHelpers trade hash matching", function()
2+
local tradeHelpers = LoadModule("Classes/TradeHelpers")
3+
4+
---@param ids number[]
5+
---@param expected number
6+
---@return boolean contains whether the given array contains the expected id
7+
local function contains(ids, expected)
8+
for _, id in ipairs(ids) do
9+
if id == expected then return true end
10+
end
11+
return false
12+
end
13+
14+
describe("modLineValue", function()
15+
it("returns the single number on a line", function()
16+
assert.equal(50, tradeHelpers.modLineValue("+50 to maximum Life"))
17+
end)
18+
19+
it("returns the midpoint of a '# to #' range", function()
20+
assert.equal(15, tradeHelpers.modLineValue("Adds 10 to 20 Fire Damage"))
21+
assert.equal(12.5, tradeHelpers.modLineValue("Adds 10 to 15 Fire Damage"))
22+
end)
23+
24+
it("handles negative numbers", function()
25+
assert.equal(-10, tradeHelpers.modLineValue("-10% to Fire Resistance"))
26+
end)
27+
28+
it("returns nil when onlyFromTo is set and there is no range", function()
29+
assert.is_nil(tradeHelpers.modLineValue("+50 to maximum Life", true))
30+
end)
31+
end)
32+
33+
describe("findTradeHash", function()
34+
it("matches a simple mod", function()
35+
local ids, value = tradeHelpers.findTradeHash("+50 to maximum Life")
36+
assert.equal(50, value)
37+
assert.is_true(contains(ids, HashStats({ "base_maximum_life" })))
38+
end)
39+
40+
it("matches a percentage mod", function()
41+
local ids, value = tradeHelpers.findTradeHash("25% reduced maximum Energy Shield")
42+
assert.equal(25, value)
43+
assert.is_true(contains(ids, HashStats({ "maximum_energy_shield_+%" })))
44+
end)
45+
46+
it("matches a # to # mod", function()
47+
local ids, value = tradeHelpers.findTradeHash("Adds 5 to 15 Fire Damage")
48+
assert.equal(10, value)
49+
assert.is_true(contains(ids,
50+
HashStats({ "local_minimum_added_fire_damage", "local_maximum_added_fire_damage" })))
51+
end)
52+
53+
it("is case-insensitive", function()
54+
local ids = tradeHelpers.findTradeHash(
55+
"1 aDDED PASSiVe sKilL IS ONE wITh The ShiELd")
56+
assert.is_true(contains(ids, HashStats({ "local_affliction_notable_one_with_the_shield" })))
57+
end)
58+
59+
it("returns no results for an unmatchable line", function()
60+
local ids = tradeHelpers.findTradeHash("+100 to IQ")
61+
assert.equal(0, #ids)
62+
end)
63+
64+
it("works thrice in a row", function()
65+
local a = tradeHelpers.findTradeHash("+50 to maximum Life")
66+
local b = tradeHelpers.findTradeHash("+50 to maximum Life")
67+
local c = tradeHelpers.findTradeHash("+50 to maximum Life")
68+
assert.same(a, b)
69+
assert.same(b, c)
70+
end)
71+
72+
it("detects inverted mods correctly", function()
73+
-- note that this stat is a handwrap mod and doesn't actually exist on the trade site
74+
local ids, value, shouldNegate = tradeHelpers.findTradeHash(
75+
"Debuffs on you expire 100% slower while affected by Haste")
76+
assert.equal(100, value)
77+
assert.is_true(shouldNegate)
78+
assert.equal(1, #ids)
79+
80+
local ids, value, shouldNegate = tradeHelpers.findTradeHash("67% reduced maximum life")
81+
assert.equal(67, value)
82+
assert.is_true(shouldNegate)
83+
assert.equal(1, #ids)
84+
end)
85+
it("detects mods with lua pattern characters correctly", function()
86+
local ids, value = tradeHelpers.findTradeHash(
87+
"trigger Socketed Spells when you focus, with a 0.25 second cooldown")
88+
assert.is_true(contains(ids, HashStats({ "trigger_socketed_spells_when_you_focus_%" })))
89+
assert.equal(100, value)
90+
91+
local ids, value, shouldNegate = tradeHelpers.findTradeHash(
92+
"10% reduced effect of Non-Curse Auras from your Skills on your Minions")
93+
assert.is_true(contains(ids, HashStats({ "minions_have_non_curse_aura_effect_+%_from_parent_skills" })))
94+
assert.equal(10, value)
95+
assert.is_true(shouldNegate)
96+
end)
97+
it("detects passage modline correctly", function()
98+
local ids = tradeHelpers.findTradeHash(
99+
"Passive Skills in Radius can be Allocated without being connected to your tree")
100+
assert.is_true(contains(ids,
101+
HashStats({ "local_unique_jewel_nearby_disconnected_passives_can_be_allocated",
102+
"unique_thread_of_hope_base_resist_all_elements_%" })))
103+
end)
104+
end)
105+
end)

0 commit comments

Comments
 (0)