Performance improvement for ruleset validation

This commit is contained in:
Yair Morgenstern
2024-01-09 23:25:43 +02:00
parent b9b0a63d64
commit 7064f6a1ec

View File

@ -496,6 +496,13 @@ class RulesetValidator(val ruleset: Ruleset) {
checkUnitRulesetSpecific(unit, lines)
uniqueValidator.checkUniques(unit, lines, false, tryFixUnknownUniques)
}
// We start with the units that are further along the tech tree, since they are likely to contain previous units.
// This allows us to minimize the double-checking.
val checkedUnits = HashSet<BaseUnit>()
for (unit in ruleset.units.values.sortedByDescending { it.techColumn(ruleset)?.columnNumber })
if (unit !in checkedUnits)
checkedUnits += checkUnitUpgradePath(unit, lines)
}
private fun addResourceErrorsRulesetInvariant(
@ -723,8 +730,6 @@ class RulesetValidator(val ruleset: Ruleset) {
RulesetErrorSeverity.WarningOptionsOnly)
}
}
checkUnitUpgradePath(unit, lines)
}
// for UnitTypes fallback, used if and only if the 'Ruleset Specific Part' runs,
@ -752,6 +757,7 @@ class RulesetValidator(val ruleset: Ruleset) {
/** Checks all possible upgrade paths of [unit], reporting to [lines].
* @param path used in recursion collecting the BaseUnits seen so far
* @return units checked in this session - includes all units in this tree
*
* Note: Since the units down the path will also be checked, this could log the same mistakes
* repeatedly, but that is mostly prevented by RulesetErrorList.add(). Each unit involved in a
@ -761,21 +767,23 @@ class RulesetValidator(val ruleset: Ruleset) {
unit: BaseUnit,
lines: RulesetErrorList,
path: Set<BaseUnit> = emptySet()
) {
) : Set<BaseUnit> {
// This is similar to UnitUpgradeManager.getUpgradePath but without the dependency on a Civilization instance
// It also branches over all possible nation-unique replacements in one go, since we only look for loops.
if (unit in path) {
lines += "Circular or self-referencing upgrade path for ${unit.name}"
return
return setOf(unit)
}
val upgrade = ruleset.units[unit.upgradesTo] ?: return
val upgrade = ruleset.units[unit.upgradesTo] ?: return setOf(unit)
val newPath = path + unit // All Set additions are new Sets - we're recursing!
val newPathWithReplacements = unitReplacesMap[unit.name]?.let { newPath + it } ?: newPath
checkUnitUpgradePath(upgrade, lines, newPathWithReplacements)
val replacements = unitReplacesMap[upgrade.name] ?: return
val replacements = unitReplacesMap[upgrade.name] ?: return setOf(unit)
val checkedUnits = HashSet<BaseUnit>()
for (toCheck in replacements) {
checkUnitUpgradePath(toCheck, lines, newPath)
checkedUnits += checkUnitUpgradePath(toCheck, lines, newPath)
}
return checkedUnits
}
private fun checkTilesetSanity(lines: RulesetErrorList) {