Update mechanic authoring persistence

This commit is contained in:
jb
2026-08-20 23:07:14 -04:00
parent 29d26bd036
commit 8c021c134f
15 changed files with 838 additions and 75 deletions
+54 -6
View File
@@ -13,6 +13,7 @@ import {
type Predicate,
type Reducer,
type ScenarioInputDefinition,
type ValueReference,
} from './mechanic.js';
type DatabaseValue = string | number | bigint | boolean | null | undefined;
@@ -257,6 +258,55 @@ function isNumericExpression(value: unknown): value is NumericExpression {
);
}
function resolveVariantExpression(
value: unknown,
variantValue: number,
): NumericExpression | null {
if (finite(value)) return value;
if (!object(value)) return null;
if ('ref' in value) {
if (
object(value.ref) &&
value.ref.source === 'variant_value' &&
Object.keys(value.ref).length === 1
) {
return variantValue;
}
return isValueReference(value.ref)
? { ref: value.ref as ValueReference }
: null;
}
if (value.op === 'floor') {
const nested = resolveVariantExpression(value.value, variantValue);
return nested === null ? null : { op: 'floor', value: nested };
}
if (value.op === 'clamp') {
const nested = resolveVariantExpression(value.value, variantValue);
const min = resolveVariantExpression(value.min, variantValue);
const max = resolveVariantExpression(value.max, variantValue);
return nested === null || min === null || max === null
? null
: { op: 'clamp', value: nested, min, max };
}
if (
!['add', 'subtract', 'multiply', 'divide', 'min', 'max'].includes(
String(value.op),
)
) {
return null;
}
const left = resolveVariantExpression(value.left, variantValue);
const right = resolveVariantExpression(value.right, variantValue);
return left === null || right === null
? null
: {
op: value.op as
'add' | 'subtract' | 'multiply' | 'divide' | 'min' | 'max',
left,
right,
};
}
function isPredicate(value: unknown): value is Predicate {
if (!object(value) || typeof value.kind !== 'string') return false;
if (value.kind === 'true') return true;
@@ -673,11 +723,8 @@ function parseOutcome(
) {
errors.push(`${path} has an unsupported application phase.`);
}
let value: NumericExpression = requiredNumber(
row.value,
`${path} value`,
errors,
);
const variantValue = requiredNumber(row.value, `${path} value`, errors);
let value: NumericExpression = variantValue;
if (
row.value_expression_json !== null &&
row.value_expression_json !== undefined &&
@@ -689,7 +736,8 @@ function parseOutcome(
errors,
);
if (parsed.ok) {
if (isNumericExpression(parsed.value)) value = parsed.value;
const resolved = resolveVariantExpression(parsed.value, variantValue);
if (resolved !== null) value = resolved;
else
errors.push(
`${path} value expression is not a valid numeric expression.`,