Optimize itemLib.applyRange, improve startup time (#6407)
* Add applyRange tests * Optimize itemLib.applyRange, improve startup time
This commit is contained in:
48
spec/System/TestItemTools_spec.lua
Normal file
48
spec/System/TestItemTools_spec.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
local applyRangeTests = {
|
||||
-- Number without range
|
||||
[{ "+10 to maximum Life", 1.0, 1.0 }] = "+10 to maximum Life",
|
||||
[{ "+10 to maximum Life", 1.0, 1.5 }] = "+15 to maximum Life",
|
||||
[{ "+10 to maximum Life", 0.5, 1.0 }] = "+10 to maximum Life",
|
||||
[{ "+10 to maximum Life", 0.5, 1.5 }] = "+15 to maximum Life",
|
||||
-- One range
|
||||
[{ "+(10-20) to maximum Life", 1.0, 1.0 }] = "+20 to maximum Life",
|
||||
[{ "+(10-20) to maximum Life", 1.0, 1.5 }] = "+30 to maximum Life",
|
||||
[{ "+(10-20) to maximum Life", 0.5, 1.0 }] = "+15 to maximum Life",
|
||||
[{ "+(10-20) to maximum Life", 0.5, 1.5 }] = "+22 to maximum Life",
|
||||
-- Two ranges
|
||||
[{ "Adds (60-80) to (270-300) Physical Damage", 1.0, 1.0 }] = "Adds 80 to 300 Physical Damage",
|
||||
[{ "Adds (60-80) to (270-300) Physical Damage", 1.0, 1.5 }] = "Adds 120 to 450 Physical Damage",
|
||||
[{ "Adds (60-80) to (270-300) Physical Damage", 0.5, 1.0 }] = "Adds 70 to 285 Physical Damage",
|
||||
[{ "Adds (60-80) to (270-300) Physical Damage", 0.5, 1.5 }] = "Adds 105 to 427 Physical Damage",
|
||||
-- Range with increased/reduced
|
||||
[{ "(10--10)% increased Charges per use", 1.0, 1.0 }] = "10% reduced Charges per use",
|
||||
[{ "(10--10)% increased Charges per use", 1.0, 1.5 }] = "15% reduced Charges per use",
|
||||
[{ "(10--10)% increased Charges per use", 0.5, 1.0 }] = "0% increased Charges per use",
|
||||
[{ "(10--10)% increased Charges per use", 0.5, 1.5 }] = "0% increased Charges per use",
|
||||
[{ "(10--10)% increased Charges per use", 0.0, 1.0 }] = "10% increased Charges per use",
|
||||
[{ "(10--10)% increased Charges per use", 0.0, 1.5 }] = "15% increased Charges per use",
|
||||
-- Range with constant numbers after
|
||||
[{ "(15-20)% increased Cold Damage per 1% Cold Resistance above 75%", 1.0, 1.0 }] = "20% increased Cold Damage per 1% Cold Resistance above 75%",
|
||||
[{ "(15-20)% increased Cold Damage per 1% Cold Resistance above 75%", 1.0, 1.5 }] = "30% increased Cold Damage per 1% Cold Resistance above 75%",
|
||||
[{ "(15-20)% increased Cold Damage per 1% Cold Resistance above 75%", 0.5, 1.0 }] = "18% increased Cold Damage per 1% Cold Resistance above 75%",
|
||||
[{ "(15-20)% increased Cold Damage per 1% Cold Resistance above 75%", 0.5, 1.5 }] = "27% increased Cold Damage per 1% Cold Resistance above 75%",
|
||||
-- High precision range
|
||||
[{ "Regenerate (66.7-75) Life per second", 1.0, 1.0 }] = "Regenerate 75 Life per second",
|
||||
[{ "Regenerate (66.7-75) Life per second", 1.0, 1.5 }] = "Regenerate 112.5 Life per second",
|
||||
[{ "Regenerate (66.7-75) Life per second", 0.5, 1.0 }] = "Regenerate 70.9 Life per second",
|
||||
[{ "Regenerate (66.7-75) Life per second", 0.5, 1.5 }] = "Regenerate 106.3 Life per second",
|
||||
-- Range with plus sign that is removed when negative
|
||||
[{ "+(-25-50)% to Fire Resistance", 1.0, 1.0 }] = "+50% to Fire Resistance",
|
||||
[{ "+(-25-50)% to Fire Resistance", 1.0, 1.5 }] = "+75% to Fire Resistance",
|
||||
[{ "+(-25-50)% to Fire Resistance", 0.0, 1.0 }] = "-25% to Fire Resistance",
|
||||
[{ "+(-25-50)% to Fire Resistance", 0.0, 1.5 }] = "-37% to Fire Resistance",
|
||||
}
|
||||
|
||||
describe("TestItemTools", function()
|
||||
for args, expected in pairs(applyRangeTests) do
|
||||
it(string.format("tests applyRange('%s', %.2f, %.2f)", unpack(args)), function()
|
||||
local result = itemLib.applyRange(unpack(args))
|
||||
assert.are.equals(expected, result)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
@@ -563,9 +563,9 @@ Suffix: FireResist4
|
||||
Suffix: ColdResist4
|
||||
Suffix: LightningResist4
|
||||
Implicits: 3
|
||||
{variant:1}+(12 to 16)% to Fire and Cold Resistances
|
||||
{variant:2}+(12 to 16)% to Cold and Lightning Resistances
|
||||
{variant:3}+(12 to 16)% to Fire and Lightning Resistances
|
||||
{variant:1}+(12-16)% to Fire and Cold Resistances
|
||||
{variant:2}+(12-16)% to Cold and Lightning Resistances
|
||||
{variant:3}+(12-16)% to Fire and Lightning Resistances
|
||||
]],[[
|
||||
Ring
|
||||
Unset Ring
|
||||
|
||||
@@ -59,18 +59,39 @@ function itemLib.getLineRangeMinMax(line)
|
||||
return rangeMin, rangeMax
|
||||
end
|
||||
|
||||
-- Apply range value (0 to 1) to a modifier that has a range: (x to x) or (x-x to x-x)
|
||||
local antonyms = {
|
||||
["increased"] = "reduced",
|
||||
["reduced"] = "increased",
|
||||
["more"] = "less",
|
||||
["less"] = "more",
|
||||
}
|
||||
|
||||
-- Apply range value (0 to 1) to a modifier that has a range: "(x-x)" or "(x-x) to (x-x)"
|
||||
function itemLib.applyRange(line, range, valueScalar)
|
||||
local numbers = 0
|
||||
local precision = nil
|
||||
local precisionSame = true
|
||||
-- Create a line with ranges removed to check if the mod is a high precision mod.
|
||||
local testLine = line:gsub("%((%d+)%-(%d+) to (%d+)%-(%d+)%)", "(%1-%2) to (%3-%4)")
|
||||
:gsub("(%+?)%((%-?%d+) to (%d+)%)", "%1(%2-%3)")
|
||||
:gsub("(%+?)%((%-?%d+%.?%d*)%-(%-?%d+%.?%d*)%)", function(plus, min, max) return plus.."1" end)
|
||||
:gsub("%-(%d+%%) increased", function(num) return num.." reduced" end)
|
||||
:gsub("%-(%d+%%) reduced", function(num) return num.." increased" end)
|
||||
:gsub("%-(%d+%%) more", function(num) return num.." less" end)
|
||||
:gsub("%-(%d+%%) less", function(num) return num.." more" end)
|
||||
local testLine = not line:find("-", 1, true) and line or
|
||||
line:gsub("(%+?)%((%-?%d+%.?%d*)%-(%-?%d+%.?%d*)%)",
|
||||
function(plus, min, max)
|
||||
min = tonumber(min)
|
||||
local maxPrecision = min + range * (tonumber(max) - min)
|
||||
local minPrecision = m_floor(maxPrecision + 0.5)
|
||||
if minPrecision ~= maxPrecision then
|
||||
precisionSame = false
|
||||
end
|
||||
return (minPrecision < 0 and "" or plus) .. tostring(minPrecision)
|
||||
end)
|
||||
:gsub("%-(%d+%%) (%a+)",
|
||||
function(num, word)
|
||||
local antonym = antonyms[word]
|
||||
return antonym and (num.." "..antonym) or ("-"..num.." "..word)
|
||||
end)
|
||||
|
||||
if precisionSame and (not valueScalar or valueScalar == 1) then
|
||||
return testLine
|
||||
end
|
||||
|
||||
local precision = nil
|
||||
local modList, extra = modLib.parseMod(testLine)
|
||||
if modList and not extra then
|
||||
for _, mod in pairs(modList) do
|
||||
@@ -86,27 +107,25 @@ function itemLib.applyRange(line, range, valueScalar)
|
||||
if not precision and line:match("(%d+%.%d*)") then
|
||||
precision = data.defaultHighPrecision
|
||||
end
|
||||
line = line:gsub("%((%d+)%-(%d+) to (%d+)%-(%d+)%)", "(%1-%2) to (%3-%4)")
|
||||
:gsub("(%+?)%((%-?%d+) to (%d+)%)", "%1(%2-%3)")
|
||||
:gsub("(%+?)%((%-?%d+%.?%d*)%-(%-?%d+%.?%d*)%)",
|
||||
|
||||
local numbers = 0
|
||||
line = line:gsub("(%+?)%((%-?%d+%.?%d*)%-(%-?%d+%.?%d*)%)",
|
||||
function(plus, min, max)
|
||||
numbers = numbers + 1
|
||||
local power = 10 ^ (precision or 0)
|
||||
local numVal = m_floor((tonumber(min) + range * (tonumber(max) - tonumber(min))) * power + 0.5) / power
|
||||
if numVal < 0 then
|
||||
if plus == "+" then
|
||||
plus = ""
|
||||
end
|
||||
end
|
||||
return plus .. tostring(numVal)
|
||||
return (numVal < 0 and "" or plus) .. tostring(numVal)
|
||||
end)
|
||||
:gsub("%-(%d+%%) increased", function(num) return num.." reduced" end)
|
||||
:gsub("%-(%d+%%) reduced", function(num) return num.." increased" end)
|
||||
:gsub("%-(%d+%%) more", function(num) return num.." less" end)
|
||||
:gsub("%-(%d+%%) less", function(num) return num.." more" end)
|
||||
if numbers == 0 and line:match("(%d+%.?%d*)%%? ") then --If a mod contains x or x% and is not already a ranged value, then only the first number will be scalable as any following numbers will always be conditions or unscalable values.
|
||||
numbers = 1
|
||||
end
|
||||
:gsub("%-(%d+%%) (%a+)",
|
||||
function(num, word)
|
||||
local antonym = antonyms[word]
|
||||
return antonym and (num.." "..antonym) or ("-"..num.." "..word)
|
||||
end)
|
||||
|
||||
if numbers == 0 and line:match("(%d+%.?%d*)%%? ") then --If a mod contains x or x% and is not already a ranged value, then only the first number will be scalable as any following numbers will always be conditions or unscalable values.
|
||||
numbers = 1
|
||||
end
|
||||
|
||||
return itemLib.applyValueScalar(line, valueScalar, numbers, precision)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user