Files
XZBT/tools/gc3-resolution-model.mjs
T

88 lines
2.5 KiB
JavaScript

/**
* Deterministic executable model for the XZBT 0.1 GC3 resolution contract.
*
* This is a Phase 0 contract oracle, not the production runtime resolver.
*/
export function clamp(value, minimum, maximum) {
return Math.min(maximum, Math.max(minimum, value));
}
export function bindingValue(source, { scale = 1, offset = 0, clamp: limits } = {}) {
let result = source * scale + offset;
if (limits) result = clamp(result, limits[0], limits[1]);
return result;
}
export function smoothBinding(previous, input, dtSeconds, tauSeconds) {
if (tauSeconds === 0 || previous === undefined) return input;
const alpha = 1 - Math.exp(-dtSeconds / tauSeconds);
return previous + alpha * (input - previous);
}
export function easingValue(name, t) {
const bounded = clamp(t, 0, 1);
switch (name) {
case 'linear':
return bounded;
case 'ease-in':
return bounded * bounded;
case 'ease-out':
return 1 - (1 - bounded) * (1 - bounded);
case 'ease-in-out':
return bounded < 0.5
? 2 * bounded * bounded
: 1 - ((-2 * bounded + 2) ** 2) / 2;
default:
throw new RangeError(`Unsupported easing: ${name}`);
}
}
export function lerp(from, to, amount) {
return from + (to - from) * amount;
}
export function attackValue(origin, target, progress, easing = 'linear') {
return lerp(origin, target, easingValue(easing, progress));
}
export function releaseValue(releaseStart, currentLower, progress, easing = 'linear') {
return lerp(currentLower, releaseStart, 1 - easingValue(easing, progress));
}
export function selectWinningOverride(overrides) {
return overrides
.filter((override) => override.live !== false)
.reduce((winner, candidate) => {
if (!winner) return candidate;
if (candidate.priority !== winner.priority) {
return candidate.priority > winner.priority ? candidate : winner;
}
return candidate.activationSequence > winner.activationSequence ? candidate : winner;
}, null);
}
export function resolveNumericTarget({
base,
binding,
automation,
overrides = [],
modulation = 0,
safetyClamp = [-Infinity, Infinity]
}) {
const afterBinding = binding ?? base;
const lower = automation ?? afterBinding;
const winner = selectWinningOverride(overrides);
const afterOverride = winner ? winner.value : lower;
const beforeClamp = afterOverride + modulation;
return {
base,
afterBinding,
lower,
winner: winner?.id ?? null,
afterOverride,
beforeClamp,
resolved: clamp(beforeClamp, safetyClamp[0], safetyClamp[1])
};
}