feat(phase0): complete shared contracts and milestone plan
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* 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])
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user