Merge pull request #9338 from keymanapp/chore/web/test-cleanup-and-stat-typing

chore(web): test/test-resource cleanup & generic typing on stats object 🐵
This commit is contained in:
Joshua Horton 2023-07-31 16:01:36 +07:00 • committed by GitHub
commit 35fc5b602d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 32 additions and 20 deletions

View file

@ -26,6 +26,9 @@
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
},
"imports": {
"#tools": "./build/tools/obj/index.js"
},
"scripts": {
"build": "gosh ./build.sh",
"test": "gosh ./test.sh"

View file

@ -45,7 +45,7 @@ export function sigMinus(operand1: number, operand2: number) {
*
* Instances of this class are immutable.
*/
export class CumulativePathStats {
export class CumulativePathStats<Type = any> {
/**
* Provides linear-regression statistics & fitting values based on the underlying `CumulativePathStats`
* object used to generate it. All operations are O(1).
@ -204,8 +204,8 @@ export class CumulativePathStats {
constructor();
constructor(sample: InputSample<any>);
constructor(instance: CumulativePathStats);
constructor(obj?: InputSample<any> | CumulativePathStats) {
constructor(instance: CumulativePathStats<Type>);
constructor(obj?: InputSample<any> | CumulativePathStats<Type>) {
if(!obj) {
return;
}
@ -232,7 +232,7 @@ export class CumulativePathStats {
* @returns A new, separate instance for the cumulative properties up to the
* newly-sampled point.
*/
public extend(sample: InputSample<any>): CumulativePathStats {
public extend(sample: InputSample<any>): CumulativePathStats<Type> {
if(!this._initialSample) {
this._initialSample = sample;
this.baseSample = sample;
@ -301,7 +301,7 @@ export class CumulativePathStats {
* from this instance's current accumulation.
* @returns
*/
public deaccumulate(subsetStats?: CumulativePathStats): CumulativePathStats {
public deaccumulate(subsetStats?: CumulativePathStats<Type>): CumulativePathStats<Type> {
// Possible addition: use `this.buildRenormalized` on the returned version
// if catastrophic cancellation effects (random, small floating point errors)
// are not sufficiently mitigated & handled by the measures currently in place.
@ -509,7 +509,7 @@ export class CumulativePathStats {
* errors than the old instance whenever they do occur.
* @returns
*/
public buildRenormalized(): CumulativePathStats {
public buildRenormalized(): CumulativePathStats<Type> {
// Other (internal) notes: the internal mapping of the new instance will not
// match that of the old instance. This should not affect the practical
// results of any mapping to and from the external coordinate space, however.

View file

@ -48,7 +48,7 @@ export class GesturePath<Type> extends EventEmitter<EventMap<Type>> {
private _isComplete: boolean = false;
private _wasCancelled?: boolean;
private _stats: CumulativePathStats;
private _stats: CumulativePathStats<Type>;
public get stats() {
// Is (practically) immutable, so it's safe to expose the instance directly.
@ -75,7 +75,7 @@ export class GesturePath<Type> extends EventEmitter<EventMap<Type>> {
instance._isComplete = true;
instance._wasCancelled = jsonObj.wasCancelled;
let stats = instance.samples.reduce((stats: CumulativePathStats, sample) => stats.extend(sample), new CumulativePathStats());
let stats = instance.samples.reduce((stats: CumulativePathStats<Type>, sample) => stats.extend(sample), new CumulativePathStats<Type>());
instance._stats = stats;
return instance;

View file

@ -6,7 +6,7 @@ import fs from 'fs';
import { GesturePath } from '@keymanapp/gesture-recognizer';
import { timedPromise } from '@keymanapp/web-utils';
import { TouchpathTurtle } from '../../../../build/tools/obj/index.js';
import { TouchpathTurtle } from '#tools';
// Ensures that the resources are resolved relative to this script, not to the cwd when the test
// runner was launched.

View file

@ -1,7 +1,7 @@
import { assert } from 'chai';
import { CumulativePathStats, InputSample } from '@keymanapp/gesture-recognizer';
import { TouchpathTurtle } from '../../../../build/tools/obj/index.js';
import { TouchpathTurtle } from '#tools';
describe("CumulativePathStats", function() {
it("Sample count = 0", function() {

View file

@ -10,7 +10,7 @@ const PromiseStatuses = PromiseStatusModule.PromiseStatuses;
import { PathSegmenter } from '@keymanapp/gesture-recognizer';
import { HeadlessInputEngine } from '../../../../build/tools/obj/index.js';
import { HeadlessInputEngine } from '#tools';
// Ensures that the resources are resolved relative to this script, not to the cwd when the test
// runner was launched.

View file

@ -0,0 +1,11 @@
/*
* VS Code Intellisense needs this helper in order to properly use subpath imports in the
* test specs found under the `headless` subfolder. Otherwise, it'll report errors while
* editing - even if the tests themselves actually work.
*/
{
"extends": "../../../../tsconfig.kmw-main-base.json",
"compilerOptions": {
"moduleResolution": "Node16",
}
}

View file

@ -76,6 +76,7 @@ export class TouchpathTurtle<HoveredItemType> extends EventEmitter<EventMap<Hove
this.emit('sample', pending);
}
this.pendingSample = null;
return pending;
}
protected trackSample(sample: InputSample<HoveredItemType>) {
@ -102,23 +103,20 @@ export class TouchpathTurtle<HoveredItemType> extends EventEmitter<EventMap<Hove
*/
}
wait(totalTime: number, repeatInterval: number) {
if(repeatInterval < 0 || totalTime < 0) {
throw new Error("Invalid parameter value: may not be negative!");
wait(totalTime: number, sampleCount: number) {
if(sampleCount <= 0 || totalTime < 0) {
throw new Error("Invalid parameter value: totalTime may not be negative and sampleCount must be > 0!");
}
const startSample = this.location;
const timeDelta = totalTime / sampleCount;
// Base sample always exists in advance.
for(let timeDelta = 0; timeDelta < totalTime; timeDelta += repeatInterval) {
for(let i = 1; i <= sampleCount; i++) {
let sample = {...startSample};
sample.t += timeDelta;
sample.t += timeDelta * i;
this.trackSample(sample);
}
let currentSample = {...startSample};
currentSample.t += totalTime;
this.trackSample(currentSample);
}
move(angleInDegrees: number, distance: number, time: number, sampleCount: number) {