Module:Sandbox/Vergir: Difference between revisionsGive feedback
Jump to navigation
Jump to search
Testing reworked HeroData: parity harness (with help from vergir-bot LLM) |
Parity test for get_hero_scaling_data refactored onto get_scalings (with help from vergir-bot LLM) |
||
| Line 1: | Line 1: | ||
local p = {} | -- TEMPORARY test module. | ||
-- {{#invoke:Sandbox/Vergir|test}} | |||
local p = {} | |||
local heroes_data = mw.loadJsonData("Data:HeroData.json") | local heroes_data = mw.loadJsonData("Data:HeroData.json") | ||
local | local old_module = require('Module:HeroData') | ||
local function raw_scaling(hero_data, scaling_type, stat) | local function raw_scaling(hero_data, scaling_type, stat) | ||
local scaling = hero_data and hero_data[scaling_type .. "Scaling"] | local scaling = hero_data and hero_data[scaling_type .. "Scaling"] | ||
| Line 26: | Line 11: | ||
end | end | ||
function p.get_scalings(hero_data, stat, include_zero) | |||
function p. | |||
local scalings = {} | local scalings = {} | ||
for _, scaling_type in ipairs({"Level", "Spirit"}) do | for _, scaling_type in ipairs({"Level", "Spirit"}) do | ||
local value = raw_scaling(hero_data, scaling_type, stat) | local value = raw_scaling(hero_data, scaling_type, stat) | ||
if (value ~= nil and value ~= 0) then | if (value ~= nil and (include_zero or value ~= 0)) then | ||
table.insert(scalings, { type = scaling_type, value = value }) | table.insert(scalings, { type = scaling_type, value = value }) | ||
end | end | ||
| Line 118: | Line 22: | ||
end | end | ||
function p.get_hero_scaling_data(hero_data, hero_stat_key) | function p.get_hero_scaling_data(hero_data, hero_stat_key) | ||
local scaling_data_returned = {} | local scaling_data_returned = {} | ||
-- Walked backwards so Level is written last and wins a value collision, | |||
-- matching the original Spirit-then-Level assignment order. | |||
local scalings = p.get_scalings(hero_data, hero_stat_key, true) | |||
for i = #scalings, 1, -1 do | |||
scaling_data_returned[scalings[i].value] = scalings[i].type | |||
end | end | ||
return scaling_data_returned | return scaling_data_returned | ||
end | end | ||
local function repr(v) | |||
local function repr(v | |||
if type(v) ~= 'table' then return tostring(v) end | if type(v) ~= 'table' then return tostring(v) end | ||
local entries = {} | local entries = {} | ||
for k, val in pairs(v) do | for k, val in pairs(v) do | ||
table.insert(entries, | table.insert(entries, tostring(k) .. '=' .. tostring(val)) | ||
end | end | ||
table.sort(entries | table.sort(entries) | ||
return '{' .. table.concat(entries, ',') .. '}' | |||
return '{' .. table.concat( | |||
end | end | ||
function p.test(frame) | |||
local hero_keys, stat_keys, seen = {}, {}, {} | |||
local | for hero_key in pairs(heroes_data) do table.insert(hero_keys, hero_key) end | ||
table.sort(hero_keys) | |||
for hero_key in pairs(heroes_data) do table.insert( | |||
table.sort( | |||
for _, hero in pairs(heroes_data) do | for _, hero in pairs(heroes_data) do | ||
local sources = { | local sources = { | ||
| Line 503: | Line 61: | ||
end | end | ||
end | end | ||
for stat in pairs(seen) do table.insert(stat_keys, stat) end | |||
for stat in pairs(seen) do table.insert( | table.sort(stat_keys) | ||
table.sort | |||
local checked, mismatches = 0, {} | local checked, mismatches = 0, {} | ||
local | local zero_cases, collision_cases = 0, 0 | ||
for _, hero_key in ipairs(hero_keys) do | |||
for _, hero_key in ipairs( | |||
local hero_data = heroes_data[hero_key] | local hero_data = heroes_data[hero_key] | ||
for _, stat in ipairs(stat_keys) do | for _, stat in ipairs(stat_keys) do | ||
local a = | local a = repr(old_module.get_hero_scaling_data(hero_data, stat)) | ||
local b = | local b = repr(p.get_hero_scaling_data(hero_data, stat)) | ||
checked = checked + 1 | checked = checked + 1 | ||
if a ~= b then | if a ~= b then | ||
table.insert(mismatches, | table.insert(mismatches, hero_key .. ' / ' .. stat .. ': ' .. a .. ' vs ' .. b) | ||
end | end | ||
-- Coverage: does the data actually exercise the tricky paths? | |||
local with_zero = p.get_scalings(hero_data, stat, true) | |||
local without_zero = p.get_scalings(hero_data, stat) | |||
if #with_zero ~= #without_zero then zero_cases = zero_cases + 1 end | |||
if #with_zero == 2 and with_zero[1].value == with_zero[2].value then | |||
-- | collision_cases = collision_cases + 1 | ||
local | |||
if | |||
end | end | ||
end | end | ||
end | end | ||
local out = { | |||
'Comparisons: ' .. checked, | |||
'Mismatches: ' .. #mismatches, | |||
'Cases with a zero scaling (shim must keep them): ' .. zero_cases, | |||
for | 'Cases where Level and Spirit share a value (collision order): ' .. collision_cases, | ||
table.insert( | '', | ||
} | |||
for i, m in ipairs(mismatches) do | |||
if i > 30 then table.insert(out, '... and ' .. (#mismatches - 30) .. ' more') break end | |||
table.insert(out, '* <code>' .. m .. '</code>') | |||
end | end | ||
if #mismatches == 0 then table.insert(out, 'No differences.') end | |||
return table.concat(out, '\n') | |||
end | end | ||
return p | return p | ||
Revision as of 13:32, 11 August 2026
Documentation for this module may be created at Module:Sandbox/Vergir/doc
-- TEMPORARY test module.
-- {{#invoke:Sandbox/Vergir|test}}
local p = {}
local heroes_data = mw.loadJsonData("Data:HeroData.json")
local old_module = require('Module:HeroData')
local function raw_scaling(hero_data, scaling_type, stat)
local scaling = hero_data and hero_data[scaling_type .. "Scaling"]
if (scaling == nil or stat == nil) then return nil end
return scaling[stat]
end
function p.get_scalings(hero_data, stat, include_zero)
local scalings = {}
for _, scaling_type in ipairs({"Level", "Spirit"}) do
local value = raw_scaling(hero_data, scaling_type, stat)
if (value ~= nil and (include_zero or value ~= 0)) then
table.insert(scalings, { type = scaling_type, value = value })
end
end
return scalings
end
function p.get_hero_scaling_data(hero_data, hero_stat_key)
local scaling_data_returned = {}
-- Walked backwards so Level is written last and wins a value collision,
-- matching the original Spirit-then-Level assignment order.
local scalings = p.get_scalings(hero_data, hero_stat_key, true)
for i = #scalings, 1, -1 do
scaling_data_returned[scalings[i].value] = scalings[i].type
end
return scaling_data_returned
end
local function repr(v)
if type(v) ~= 'table' then return tostring(v) end
local entries = {}
for k, val in pairs(v) do
table.insert(entries, tostring(k) .. '=' .. tostring(val))
end
table.sort(entries)
return '{' .. table.concat(entries, ',') .. '}'
end
function p.test(frame)
local hero_keys, stat_keys, seen = {}, {}, {}
for hero_key in pairs(heroes_data) do table.insert(hero_keys, hero_key) end
table.sort(hero_keys)
for _, hero in pairs(heroes_data) do
local sources = {
hero,
hero.Weapon or {},
(hero.Weapon and hero.Weapon.AltFire) or {},
hero.LevelScaling or {},
hero.SpiritScaling or {},
}
for _, source in ipairs(sources) do
for stat in pairs(source) do
if type(stat) == 'string' then seen[stat] = true end
end
end
end
for stat in pairs(seen) do table.insert(stat_keys, stat) end
table.sort(stat_keys)
local checked, mismatches = 0, {}
local zero_cases, collision_cases = 0, 0
for _, hero_key in ipairs(hero_keys) do
local hero_data = heroes_data[hero_key]
for _, stat in ipairs(stat_keys) do
local a = repr(old_module.get_hero_scaling_data(hero_data, stat))
local b = repr(p.get_hero_scaling_data(hero_data, stat))
checked = checked + 1
if a ~= b then
table.insert(mismatches, hero_key .. ' / ' .. stat .. ': ' .. a .. ' vs ' .. b)
end
-- Coverage: does the data actually exercise the tricky paths?
local with_zero = p.get_scalings(hero_data, stat, true)
local without_zero = p.get_scalings(hero_data, stat)
if #with_zero ~= #without_zero then zero_cases = zero_cases + 1 end
if #with_zero == 2 and with_zero[1].value == with_zero[2].value then
collision_cases = collision_cases + 1
end
end
end
local out = {
'Comparisons: ' .. checked,
'Mismatches: ' .. #mismatches,
'Cases with a zero scaling (shim must keep them): ' .. zero_cases,
'Cases where Level and Spirit share a value (collision order): ' .. collision_cases,
'',
}
for i, m in ipairs(mismatches) do
if i > 30 then table.insert(out, '... and ' .. (#mismatches - 30) .. ' more') break end
table.insert(out, '* <code>' .. m .. '</code>')
end
if #mismatches == 0 then table.insert(out, 'No differences.') end
return table.concat(out, '\n')
end
return p