mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-27 01:57:41 +00:00
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:
commit
35fc5b602d
8 changed files with 32 additions and 20 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
11
common/web/gesture-recognizer/src/test/auto/tsconfig.json
Normal file
11
common/web/gesture-recognizer/src/test/auto/tsconfig.json
Normal 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",
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue