From 0598e080bd7a9882c302dd62a2c3f8cd79deaf4e Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Tue, 12 Aug 2025 08:41:15 -0500 Subject: [PATCH] change(web): import ordering, SearchSpace.inputSequence getter --- .../src/main/correction/context-token.ts | 13 ++++++------ .../src/main/correction/distance-modeler.ts | 19 +++++++++++------ ...ontext-token.js => context-token.tests.js} | 21 ++++++++++++------- 3 files changed, 34 insertions(+), 19 deletions(-) rename web/src/engine/predictive-text/worker-thread/src/tests/mocha/cases/edit-distance/{context-token.js => context-token.tests.js} (92%) diff --git a/web/src/engine/predictive-text/worker-thread/src/main/correction/context-token.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/context-token.ts index de715522e6..c637dea3e6 100644 --- a/web/src/engine/predictive-text/worker-thread/src/main/correction/context-token.ts +++ b/web/src/engine/predictive-text/worker-thread/src/main/correction/context-token.ts @@ -1,16 +1,17 @@ /* * Keyman is copyright (C) SIL Global. MIT License. - * + * * Created by jahorton on 2025-07-30 - * + * * Represents cached data about one token (either a word or a unit of whitespace) * in the context and associated correction-search progress and results. */ -import { buildMergedTransform } from "@keymanapp/models-templates"; -import { SearchSpace } from "./distance-modeler.js"; -import { KMWString } from "@keymanapp/web-utils"; +import { buildMergedTransform } from "@keymanapp/models-templates"; import { LexicalModelTypes } from '@keymanapp/common-types'; + +import { SearchSpace } from "./distance-modeler.js"; + import Distribution = LexicalModelTypes.Distribution; import LexicalModel = LexicalModelTypes.LexicalModel; import Suggestion = LexicalModelTypes.Suggestion; @@ -31,7 +32,7 @@ function textToCharTransforms(text: string, transformId?: number): Transform[] { return transformId ? [...text].map(insert => ({insert, deleteLeft: 0, id: transformId})) : [...text].map(insert => ({insert, deleteLeft: 0})); -} +} /** * Represents cached data about one token (either a word or a unit of whitespace) diff --git a/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts b/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts index f61b804b4a..956a369bc3 100644 --- a/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts +++ b/web/src/engine/predictive-text/worker-thread/src/main/correction/distance-modeler.ts @@ -366,7 +366,7 @@ export class SearchSpace { private tierOrdering: SearchSpaceTier[] = []; private selectionQueue: PriorityQueue; - inputSequence: Distribution[] = []; + private _inputSequence: Distribution[] = []; private minInputCost: number[] = []; private rootNode: SearchNode; @@ -397,7 +397,7 @@ export class SearchSpace { this.buildQueueSpaceComparator(); if(arg1 instanceof SearchSpace) { - this.inputSequence = [].concat(arg1.inputSequence); + this._inputSequence = [].concat(arg1._inputSequence); this.minInputCost = [].concat(arg1.minInputCost); this.rootNode = arg1.rootNode; this.completedPaths = [].concat(arg1.completedPaths); @@ -475,6 +475,13 @@ export class SearchSpace { } } + /** + * Retrieves the sequence of inputs + */ + public get inputSequence() { + return [...this._inputSequence]; + } + increaseMaxEditDistance() { this.tierOrdering.forEach(function(tier) { tier.increaseMaxEditDistance() }); } @@ -482,11 +489,11 @@ export class SearchSpace { get correctionsEnabled() { // When corrections are disabled, the Web engine will only provide individual Transforms // for an input, not a distribution. No distributions means we shouldn't do corrections. - return !!this.inputSequence.find((distribution) => distribution.length > 1); + return !!this._inputSequence.find((distribution) => distribution.length > 1); } addInput(inputDistribution: Distribution) { - this.inputSequence.push(inputDistribution); + this._inputSequence.push(inputDistribution); // Assumes that `inputDistribution` is already sorted. this.minInputCost.push(-Math.log(inputDistribution[0].p)); @@ -607,9 +614,9 @@ export class SearchSpace { let deletionEdges: SearchNode[] = []; if(!substitutionsOnly) { - deletionEdges = currentNode.buildDeletionEdges(this.inputSequence[inputIndex-1]); + deletionEdges = currentNode.buildDeletionEdges(this._inputSequence[inputIndex-1]); } - let substitutionEdges = currentNode.buildSubstitutionEdges(this.inputSequence[inputIndex-1]); + let substitutionEdges = currentNode.buildSubstitutionEdges(this._inputSequence[inputIndex-1]); // Note: we're live-modifying the tier's cost here! The priority queue loses its guarantees as a result. nextTier.correctionQueue.enqueueAll(deletionEdges.concat(substitutionEdges)); diff --git a/web/src/engine/predictive-text/worker-thread/src/tests/mocha/cases/edit-distance/context-token.js b/web/src/engine/predictive-text/worker-thread/src/tests/mocha/cases/edit-distance/context-token.tests.js similarity index 92% rename from web/src/engine/predictive-text/worker-thread/src/tests/mocha/cases/edit-distance/context-token.js rename to web/src/engine/predictive-text/worker-thread/src/tests/mocha/cases/edit-distance/context-token.tests.js index 78df8e9c2b..dc8701dc25 100644 --- a/web/src/engine/predictive-text/worker-thread/src/tests/mocha/cases/edit-distance/context-token.js +++ b/web/src/engine/predictive-text/worker-thread/src/tests/mocha/cases/edit-distance/context-token.tests.js @@ -1,14 +1,21 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by jahorton on 2025-07-30 + * + * This file contains low-level unit tests designed to validate the behavior + * of the ContextToken class. + */ + import { assert } from 'chai'; +// Aliased due to JS keyword. +import { default as defaultBreaker } from '@keymanapp/models-wordbreakers'; +import { jsonFixture } from '@keymanapp/common-test-resources/model-helpers.mjs'; + import { ContextToken } from '#./correction/context-token.js'; import { ExecutionTimer } from '#./correction/execution-timer.js'; -import * as models from '#./models/index.js'; - -import { default as defaultBreaker } from '@keymanapp/models-wordbreakers'; - -import { jsonFixture } from '@keymanapp/common-test-resources/model-helpers.mjs'; - -var TrieModel = models.TrieModel; +import { TrieModel } from '#./models/index.js'; var plainModel = new TrieModel(jsonFixture('models/tries/english-1000'), {wordBreaker: defaultBreaker});