Skip to content

Commit 5aeb522

Browse files
committed
add metrics for wordforms
1 parent 68521d0 commit 5aeb522

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

src/utilities/analytics/metrics/core.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ export class MetricsCalculator {
118118
// Update buttons using dynamic spelling effort if applicable
119119
const buttons = Array.from(knownButtons.values()).sort((a, b) => a.effort - b.effort);
120120

121+
// Calculate metrics for word forms (smart grammar predictions)
122+
const wordFormMetrics = this.calculateWordFormMetrics(tree, buttons, options);
123+
buttons.push(...wordFormMetrics);
124+
125+
// Re-sort after adding word forms
126+
buttons.sort((a, b) => a.effort - b.effort);
127+
121128
// Calculate grid dimensions
122129
const grid = this.calculateGridDimensions(tree);
123130

@@ -719,6 +726,91 @@ export class MetricsCalculator {
719726
return boardPcts;
720727
}
721728

729+
/**
730+
* Calculate metrics for word forms (smart grammar predictions)
731+
*
732+
* Word forms are dynamically generated and not part of the tree structure.
733+
* Their effort is calculated as:
734+
* - Parent button's cumulative effort (to reach the button)
735+
* - + Effort to select the word form from its position in predictions grid
736+
*
737+
* @param tree - The AAC tree
738+
* @param buttons - Already calculated button metrics
739+
* @param options - Metrics options
740+
* @returns Array of word form button metrics
741+
*/
742+
private calculateWordFormMetrics(
743+
tree: AACTree,
744+
buttons: ButtonMetrics[],
745+
_options: MetricsOptions = {}
746+
): ButtonMetrics[] {
747+
const wordFormMetrics: ButtonMetrics[] = [];
748+
749+
// Track which buttons already exist to avoid duplicates
750+
const existingLabels = new Map<string, ButtonMetrics>();
751+
buttons.forEach((btn) => existingLabels.set(btn.label.toLowerCase(), btn));
752+
753+
// Iterate through all pages to find buttons with predictions
754+
Object.values(tree.pages).forEach((page: AACPage) => {
755+
page.grid.forEach((row: (AACButton | null)[]) => {
756+
row.forEach((btn: AACButton | null) => {
757+
if (!btn || !btn.predictions || btn.predictions.length === 0) return;
758+
759+
// Find the parent button's metrics
760+
const parentMetrics = buttons.find((b) => b.id === btn.id);
761+
if (!parentMetrics) return;
762+
763+
// Calculate effort for each word form
764+
btn.predictions.forEach((wordForm: string, index: number) => {
765+
const wordFormLower = wordForm.toLowerCase();
766+
767+
// Skip if this word form already exists as a regular button
768+
if (existingLabels.has(wordFormLower)) {
769+
return;
770+
}
771+
772+
// Calculate effort based on position in predictions array
773+
// Assume predictions are displayed in a grid layout (e.g., 2 columns)
774+
const predictionsGridCols = 2; // Typical predictions layout
775+
const predictionRowIndex = Math.floor(index / predictionsGridCols);
776+
const predictionColIndex = index % predictionsGridCols;
777+
778+
// Calculate visual scan effort to reach this word form position
779+
// Using similar logic to button scanning effort
780+
const predictionPriorItems =
781+
predictionRowIndex * predictionsGridCols + predictionColIndex;
782+
const predictionSelectionEffort = visualScanEffort(predictionPriorItems);
783+
784+
// Word form effort = parent button's cumulative effort + selection effort
785+
const wordFormEffort = parentMetrics.effort + predictionSelectionEffort;
786+
787+
// Mark as word form with a special ID pattern
788+
const wordFormBtn: ButtonMetrics = {
789+
id: `${btn.id}_wordform_${index}`,
790+
label: wordForm,
791+
level: parentMetrics.level,
792+
effort: wordFormEffort,
793+
count: 1,
794+
semantic_id: parentMetrics.semantic_id,
795+
clone_id: parentMetrics.clone_id,
796+
temporary_home_id: parentMetrics.temporary_home_id,
797+
is_word_form: true, // Mark this as a word form metric
798+
parent_button_id: btn.id, // Track parent button
799+
parent_button_label: parentMetrics.label, // Track parent label
800+
};
801+
802+
wordFormMetrics.push(wordFormBtn);
803+
existingLabels.set(wordFormLower, wordFormBtn);
804+
});
805+
});
806+
});
807+
});
808+
809+
console.log(`📝 Calculated ${wordFormMetrics.length} word form metrics from predictions`);
810+
811+
return wordFormMetrics;
812+
}
813+
722814
/**
723815
* Calculate grid dimensions from the tree
724816
*/

src/utilities/analytics/metrics/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export interface ButtonMetrics {
2222
temporary_home_id?: string; // For temporary home navigation
2323
comp_level?: number; // Comparison: level in comparison set
2424
comp_effort?: number; // Comparison: effort in comparison set
25+
// Word form metrics (for smart grammar predictions)
26+
is_word_form?: boolean; // True if this is a word form from predictions
27+
parent_button_id?: string; // ID of parent button that has these predictions
28+
parent_button_label?: string; // Label of parent button
2529
}
2630

2731
/**

0 commit comments

Comments
 (0)