zenno: format & lint

This commit is contained in:
2026-07-06 09:41:11 -04:00
parent 06e5a06680
commit 55175c9c40
7 changed files with 413 additions and 341 deletions
+57 -50
View File
@@ -2,22 +2,22 @@
* Instantaneous characteristics of a horse in motion.
*/
export interface Instant {
/** Timestamp of the instant. */
t: number;
/** Forward position along the course. */
x: number;
/** Actual speed. */
v: number;
/** Timestamp of the instant. */
t: number;
/** Forward position along the course. */
x: number;
/** Actual speed. */
v: number;
}
/**
* Forward travel characteristics under the effects of acceleration.
*/
export interface Travel {
start: Instant;
end: Instant;
/** Actual acceleration value applied between start and end. */
a: number;
start: Instant;
end: Instant;
/** Actual acceleration value applied between start and end. */
a: number;
}
/**
@@ -30,31 +30,38 @@ export interface Travel {
* @param decel Negative acceleration value for cases where target speed is below start speed
* @returns Travel segment after reaching the first of the given limits
*/
export function travelSegment(start: Instant, targetSpeed: number, totalAccel: number, maxDur?: number, maxDist?: number, decel?: number): Travel {
const a = start.v < targetSpeed ? totalAccel : decel ?? -1;
const dvt = (targetSpeed - start.v) / a;
const dxt = maxDist != null ? (-start.v + Math.sqrt(start.v*start.v + 4*a*maxDist)) / (2*a) : dvt;
const time = maxDur != null ? Math.min(dvt, dxt, maxDur) : Math.min(dvt, dxt);
// To address numerical imprecision, if accel time comes from velocity or distance,
// set the reached values directly.
const v = time === dvt ? targetSpeed : start.v + time * a;
const dist = maxDist != null && time === dxt ? maxDist : (start.v + 0.5 * a * time) * time;
const end = { t: start.t + time, x: start.x + dist, v };
return {start, end, a};
export function travelSegment(
start: Instant,
targetSpeed: number,
totalAccel: number,
maxDur?: number,
maxDist?: number,
decel?: number,
): Travel {
const a = start.v < targetSpeed ? totalAccel : (decel ?? -1);
const dvt = (targetSpeed - start.v) / a;
const dxt = maxDist != null ? (-start.v + Math.sqrt(start.v * start.v + 4 * a * maxDist)) / (2 * a) : dvt;
const time = maxDur != null ? Math.min(dvt, dxt, maxDur) : Math.min(dvt, dxt);
// To address numerical imprecision, if accel time comes from velocity or distance,
// set the reached values directly.
const v = time === dvt ? targetSpeed : start.v + time * a;
const dist = maxDist != null && time === dxt ? maxDist : (start.v + 0.5 * a * time) * time;
const end = { t: start.t + time, x: start.x + dist, v };
return { start, end, a };
}
/**
* Acceleration bonus from skills.
*/
export interface Skill {
/**
* Acceleration modifier in m/s².
*/
accel: number;
/**
* Remaining actual duration in seconds.
*/
dur: number;
/**
* Acceleration modifier in m/s².
*/
accel: number;
/**
* Remaining actual duration in seconds.
*/
dur: number;
}
/**
@@ -66,25 +73,25 @@ export interface Skill {
* @returns Acceleration segments and remainders of skills upon reaching the target speed
*/
export function up(start: Instant, targetSpeed: number, baseAccel: number, skills: Skill[]) {
const segments: Travel[] = [];
const sk = skills.map((s) => ({...s})).filter((s) => s.dur > 0);
while (start.v < targetSpeed) {
const active = sk.filter((s) => s.dur > 0);
if (active.length === 0) {
segments.push(travelSegment(start, targetSpeed, baseAccel));
break;
}
const boost = active.reduce((a, s) => a + s.accel, 0);
const time = Math.min(...active.map((s) => s.dur));
const seg = travelSegment(start, targetSpeed, baseAccel + boost, time);
segments.push(seg);
start = seg.end
for (const s of active) {
s.dur -= seg.end.t - seg.start.t;
if (s.dur < 1e-5) {
s.dur = 0
}
}
}
return {segments, skills: sk}
const segments: Travel[] = [];
const sk = skills.map((s) => ({ ...s })).filter((s) => s.dur > 0);
while (start.v < targetSpeed) {
const active = sk.filter((s) => s.dur > 0);
if (active.length === 0) {
segments.push(travelSegment(start, targetSpeed, baseAccel));
break;
}
const boost = active.reduce((a, s) => a + s.accel, 0);
const time = Math.min(...active.map((s) => s.dur));
const seg = travelSegment(start, targetSpeed, baseAccel + boost, time);
segments.push(seg);
start = seg.end;
for (const s of active) {
s.dur -= seg.end.t - seg.start.t;
if (s.dur < 1e-5) {
s.dur = 0;
}
}
}
return { segments, skills: sk };
}
+1 -1
View File
@@ -18,7 +18,7 @@ declare const __stage: unique symbol;
export type Stage = 'raw' | 'base' | 'adjusted' | 'final' | 'skills';
export type StatValue<T extends Stage> = number & {[__stage]: T};
export type StatValue<T extends Stage> = number & { [__stage]: T };
export interface Stats<T extends Stage> {
speed: StatValue<T>;