@willwade/aac-processors 0.0.25 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/treeStructure.d.ts +3 -1
- package/dist/core/treeStructure.js +2 -1
- package/dist/processors/gridsetProcessor.js +6 -0
- package/dist/types/aac.d.ts +1 -0
- package/dist/utilities/analytics/metrics/core.d.ts +14 -0
- package/dist/utilities/analytics/metrics/core.js +74 -0
- package/dist/utilities/analytics/metrics/types.d.ts +3 -0
- package/package.json +1 -1
|
@@ -145,9 +145,10 @@ export declare class AACButton implements IAACButton {
|
|
|
145
145
|
parameters?: {
|
|
146
146
|
[key: string]: any;
|
|
147
147
|
};
|
|
148
|
+
predictions?: string[];
|
|
148
149
|
semantic_id?: string;
|
|
149
150
|
clone_id?: string;
|
|
150
|
-
constructor({ id, label, message, targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, scanBlock, visibility, directActivate, parameters, semantic_id, clone_id, type, action, }: {
|
|
151
|
+
constructor({ id, label, message, targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, scanBlock, visibility, directActivate, parameters, predictions, semantic_id, clone_id, type, action, }: {
|
|
151
152
|
id: string;
|
|
152
153
|
label?: string;
|
|
153
154
|
message?: string;
|
|
@@ -177,6 +178,7 @@ export declare class AACButton implements IAACButton {
|
|
|
177
178
|
parameters?: {
|
|
178
179
|
[key: string]: any;
|
|
179
180
|
};
|
|
181
|
+
predictions?: string[];
|
|
180
182
|
semantic_id?: string;
|
|
181
183
|
clone_id?: string;
|
|
182
184
|
type?: 'SPEAK' | 'NAVIGATE' | 'ACTION';
|
|
@@ -57,7 +57,7 @@ var AACScanType;
|
|
|
57
57
|
AACScanType["BLOCK_COLUMN_ROW"] = "block-column-row";
|
|
58
58
|
})(AACScanType || (exports.AACScanType = AACScanType = {}));
|
|
59
59
|
class AACButton {
|
|
60
|
-
constructor({ id, label = '', message = '', targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, scanBlock, visibility, directActivate, parameters, semantic_id, clone_id,
|
|
60
|
+
constructor({ id, label = '', message = '', targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, scanBlock, visibility, directActivate, parameters, predictions, semantic_id, clone_id,
|
|
61
61
|
// Legacy input support
|
|
62
62
|
type, action, }) {
|
|
63
63
|
this.id = id;
|
|
@@ -82,6 +82,7 @@ class AACButton {
|
|
|
82
82
|
this.visibility = visibility;
|
|
83
83
|
this.directActivate = directActivate;
|
|
84
84
|
this.parameters = parameters;
|
|
85
|
+
this.predictions = predictions;
|
|
85
86
|
this.semantic_id = semantic_id;
|
|
86
87
|
this.clone_id = clone_id;
|
|
87
88
|
// Legacy mapping: if no semanticAction provided, derive from legacy `action` first
|
|
@@ -1226,6 +1226,12 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1226
1226
|
...cellStyle,
|
|
1227
1227
|
...inlineStyle, // Inline styles override referenced styles
|
|
1228
1228
|
},
|
|
1229
|
+
// Store predictions directly on button for easy access
|
|
1230
|
+
predictions: predictionWords?.length
|
|
1231
|
+
? [...predictionWords]
|
|
1232
|
+
: gridPredictionWords.length > 0
|
|
1233
|
+
? [...gridPredictionWords]
|
|
1234
|
+
: undefined,
|
|
1229
1235
|
parameters: {
|
|
1230
1236
|
pluginMetadata: pluginMetadata, // Store full plugin metadata for future use
|
|
1231
1237
|
grid3Commands: detectedCommands, // Store detected command metadata
|
package/dist/types/aac.d.ts
CHANGED
|
@@ -39,6 +39,20 @@ export declare class MetricsCalculator {
|
|
|
39
39
|
* Calculate what percentage of links to this board match semantic_id/clone_id
|
|
40
40
|
*/
|
|
41
41
|
private calculateBoardLinkPercentages;
|
|
42
|
+
/**
|
|
43
|
+
* Calculate metrics for word forms (smart grammar predictions)
|
|
44
|
+
*
|
|
45
|
+
* Word forms are dynamically generated and not part of the tree structure.
|
|
46
|
+
* Their effort is calculated as:
|
|
47
|
+
* - Parent button's cumulative effort (to reach the button)
|
|
48
|
+
* - + Effort to select the word form from its position in predictions grid
|
|
49
|
+
*
|
|
50
|
+
* @param tree - The AAC tree
|
|
51
|
+
* @param buttons - Already calculated button metrics
|
|
52
|
+
* @param options - Metrics options
|
|
53
|
+
* @returns Array of word form button metrics
|
|
54
|
+
*/
|
|
55
|
+
private calculateWordFormMetrics;
|
|
42
56
|
/**
|
|
43
57
|
* Calculate grid dimensions from the tree
|
|
44
58
|
*/
|
|
@@ -83,6 +83,11 @@ class MetricsCalculator {
|
|
|
83
83
|
});
|
|
84
84
|
// Update buttons using dynamic spelling effort if applicable
|
|
85
85
|
const buttons = Array.from(knownButtons.values()).sort((a, b) => a.effort - b.effort);
|
|
86
|
+
// Calculate metrics for word forms (smart grammar predictions)
|
|
87
|
+
const wordFormMetrics = this.calculateWordFormMetrics(tree, buttons, options);
|
|
88
|
+
buttons.push(...wordFormMetrics);
|
|
89
|
+
// Re-sort after adding word forms
|
|
90
|
+
buttons.sort((a, b) => a.effort - b.effort);
|
|
86
91
|
// Calculate grid dimensions
|
|
87
92
|
const grid = this.calculateGridDimensions(tree);
|
|
88
93
|
// Identify prediction metrics
|
|
@@ -560,6 +565,75 @@ class MetricsCalculator {
|
|
|
560
565
|
boardPcts['all'] = totalLinks;
|
|
561
566
|
return boardPcts;
|
|
562
567
|
}
|
|
568
|
+
/**
|
|
569
|
+
* Calculate metrics for word forms (smart grammar predictions)
|
|
570
|
+
*
|
|
571
|
+
* Word forms are dynamically generated and not part of the tree structure.
|
|
572
|
+
* Their effort is calculated as:
|
|
573
|
+
* - Parent button's cumulative effort (to reach the button)
|
|
574
|
+
* - + Effort to select the word form from its position in predictions grid
|
|
575
|
+
*
|
|
576
|
+
* @param tree - The AAC tree
|
|
577
|
+
* @param buttons - Already calculated button metrics
|
|
578
|
+
* @param options - Metrics options
|
|
579
|
+
* @returns Array of word form button metrics
|
|
580
|
+
*/
|
|
581
|
+
calculateWordFormMetrics(tree, buttons, _options = {}) {
|
|
582
|
+
const wordFormMetrics = [];
|
|
583
|
+
// Track which buttons already exist to avoid duplicates
|
|
584
|
+
const existingLabels = new Map();
|
|
585
|
+
buttons.forEach((btn) => existingLabels.set(btn.label.toLowerCase(), btn));
|
|
586
|
+
// Iterate through all pages to find buttons with predictions
|
|
587
|
+
Object.values(tree.pages).forEach((page) => {
|
|
588
|
+
page.grid.forEach((row) => {
|
|
589
|
+
row.forEach((btn) => {
|
|
590
|
+
if (!btn || !btn.predictions || btn.predictions.length === 0)
|
|
591
|
+
return;
|
|
592
|
+
// Find the parent button's metrics
|
|
593
|
+
const parentMetrics = buttons.find((b) => b.id === btn.id);
|
|
594
|
+
if (!parentMetrics)
|
|
595
|
+
return;
|
|
596
|
+
// Calculate effort for each word form
|
|
597
|
+
btn.predictions.forEach((wordForm, index) => {
|
|
598
|
+
const wordFormLower = wordForm.toLowerCase();
|
|
599
|
+
// Skip if this word form already exists as a regular button
|
|
600
|
+
if (existingLabels.has(wordFormLower)) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
// Calculate effort based on position in predictions array
|
|
604
|
+
// Assume predictions are displayed in a grid layout (e.g., 2 columns)
|
|
605
|
+
const predictionsGridCols = 2; // Typical predictions layout
|
|
606
|
+
const predictionRowIndex = Math.floor(index / predictionsGridCols);
|
|
607
|
+
const predictionColIndex = index % predictionsGridCols;
|
|
608
|
+
// Calculate visual scan effort to reach this word form position
|
|
609
|
+
// Using similar logic to button scanning effort
|
|
610
|
+
const predictionPriorItems = predictionRowIndex * predictionsGridCols + predictionColIndex;
|
|
611
|
+
const predictionSelectionEffort = (0, effort_1.visualScanEffort)(predictionPriorItems);
|
|
612
|
+
// Word form effort = parent button's cumulative effort + selection effort
|
|
613
|
+
const wordFormEffort = parentMetrics.effort + predictionSelectionEffort;
|
|
614
|
+
// Mark as word form with a special ID pattern
|
|
615
|
+
const wordFormBtn = {
|
|
616
|
+
id: `${btn.id}_wordform_${index}`,
|
|
617
|
+
label: wordForm,
|
|
618
|
+
level: parentMetrics.level,
|
|
619
|
+
effort: wordFormEffort,
|
|
620
|
+
count: 1,
|
|
621
|
+
semantic_id: parentMetrics.semantic_id,
|
|
622
|
+
clone_id: parentMetrics.clone_id,
|
|
623
|
+
temporary_home_id: parentMetrics.temporary_home_id,
|
|
624
|
+
is_word_form: true, // Mark this as a word form metric
|
|
625
|
+
parent_button_id: btn.id, // Track parent button
|
|
626
|
+
parent_button_label: parentMetrics.label, // Track parent label
|
|
627
|
+
};
|
|
628
|
+
wordFormMetrics.push(wordFormBtn);
|
|
629
|
+
existingLabels.set(wordFormLower, wordFormBtn);
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
});
|
|
633
|
+
});
|
|
634
|
+
console.log(`📝 Calculated ${wordFormMetrics.length} word form metrics from predictions`);
|
|
635
|
+
return wordFormMetrics;
|
|
636
|
+
}
|
|
563
637
|
/**
|
|
564
638
|
* Calculate grid dimensions from the tree
|
|
565
639
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@willwade/aac-processors",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.27",
|
|
4
4
|
"description": "A comprehensive TypeScript library for processing AAC (Augmentative and Alternative Communication) file formats with translation support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|