@willwade/aac-processors 0.0.12 โ†’ 0.0.13

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.
Files changed (35) hide show
  1. package/README.md +44 -41
  2. package/dist/core/treeStructure.d.ts +35 -2
  3. package/dist/core/treeStructure.js +18 -3
  4. package/dist/optional/analytics/history.d.ts +12 -1
  5. package/dist/optional/analytics/index.d.ts +2 -0
  6. package/dist/optional/analytics/index.js +6 -1
  7. package/dist/optional/analytics/metrics/comparison.js +8 -4
  8. package/dist/optional/analytics/metrics/core.d.ts +9 -0
  9. package/dist/optional/analytics/metrics/core.js +190 -37
  10. package/dist/optional/analytics/metrics/effort.d.ts +10 -0
  11. package/dist/optional/analytics/metrics/effort.js +13 -0
  12. package/dist/optional/analytics/metrics/obl-types.d.ts +93 -0
  13. package/dist/optional/analytics/metrics/obl-types.js +7 -0
  14. package/dist/optional/analytics/metrics/obl.d.ts +40 -0
  15. package/dist/optional/analytics/metrics/obl.js +287 -0
  16. package/dist/optional/analytics/metrics/vocabulary.js +6 -4
  17. package/dist/optional/symbolTools.js +13 -16
  18. package/dist/processors/astericsGridProcessor.d.ts +15 -0
  19. package/dist/processors/astericsGridProcessor.js +17 -0
  20. package/dist/processors/gridset/helpers.d.ts +4 -1
  21. package/dist/processors/gridset/helpers.js +4 -0
  22. package/dist/processors/gridset/pluginTypes.js +51 -50
  23. package/dist/processors/gridset/symbolExtractor.js +3 -2
  24. package/dist/processors/gridset/symbolSearch.js +9 -7
  25. package/dist/processors/gridsetProcessor.js +57 -20
  26. package/dist/processors/obfProcessor.js +12 -0
  27. package/dist/processors/snap/helpers.d.ts +5 -1
  28. package/dist/processors/snap/helpers.js +5 -0
  29. package/dist/processors/snapProcessor.d.ts +2 -0
  30. package/dist/processors/snapProcessor.js +155 -4
  31. package/dist/processors/touchchatProcessor.js +24 -5
  32. package/dist/types/aac.d.ts +63 -0
  33. package/dist/types/aac.js +33 -0
  34. package/dist/validation/gridsetValidator.js +10 -0
  35. package/package.json +1 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # AACProcessors
2
2
 
3
- [![Coverage](https://img.shields.io/badge/coverage-77%25-green.svg)](./coverage)
3
+ [![Coverage](https://img.shields.io/badge/coverage-74%25-green.svg)](./coverage)
4
4
  [![TypeScript](https://img.shields.io/badge/TypeScript-100%25-blue.svg)](https://www.typescriptlang.org/)
5
- [![Tests](https://img.shields.io/badge/tests-140%20tests-brightgreen.svg)](./test)
5
+ [![Tests](https://img.shields.io/badge/tests-495%20tests-brightgreen.svg)](./test)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
8
  A comprehensive **TypeScript library** for processing AAC (Augmentative and Alternative Communication) file formats with advanced translation support, cross-format conversion, and robust error handling.
@@ -20,6 +20,7 @@ A comprehensive **TypeScript library** for processing AAC (Augmentative and Alte
20
20
  - **Apple Panels** (MacOS) - Plist format support
21
21
  - **Asterics Grid** - Native Asterics Grid format with audio
22
22
  - **Excel** - Export to Microsoft Excel for vocabulary analysis
23
+ - **Analyics & Metrics** - High-parity AAC effort metrics and clinical analysis tools
23
24
 
24
25
  ### **Advanced Capabilities**
25
26
 
@@ -28,6 +29,7 @@ A comprehensive **TypeScript library** for processing AAC (Augmentative and Alte
28
29
  - ๐ŸŽจ **Comprehensive styling support** - Preserve visual appearance across formats
29
30
  - ๐Ÿงช **Property-based testing** - Robust validation with 140+ tests
30
31
  - โœ… **Format validation** - Spec-based validation for all supported formats
32
+ - ๐Ÿ“Š **Clinical Metrics** - High-parity AAC effort algorithm (v0.2) and vocabulary coverage analysis
31
33
  - โšก **Performance optimized** - Memory-efficient processing of large files
32
34
  - ๐Ÿ›ก๏ธ **Error recovery** - Graceful handling of corrupted data
33
35
  - ๐Ÿ”’ **Thread-safe** - Concurrent processing support
@@ -192,6 +194,29 @@ const translatedBuffer = processor.processTexts(
192
194
  console.log("Translation complete!");
193
195
  ```
194
196
 
197
+ ### ๐Ÿ“Š AAC Analytics & Clinical Metrics
198
+
199
+ The library includes an optional high-performance analytics engine for evaluating AAC board sets based on the **AAC Effort Algorithm (v0.2)**.
200
+
201
+ #### **Key Metrics Features**
202
+ - **Effort Scores**: Calculate the physical/cognitive cost of any word (Distance, Field Size, Motor Planning).
203
+ - **Vocabulary Coverage**: Compare board sets against core vocabulary lists (e.g., Anderson & Bitner).
204
+ - **Sentence Analysis**: Measure the effort required to construct common test sentences.
205
+ - **Comparative Analysis**: Identify gaps and improvements between two pageset versions.
206
+
207
+ For detailed documentation, see the **[AAC Metrics Guide](./src/optional/analytics/docs/AAC_METRICS_GUIDE.md)** and **[Vocabulary Analysis Guide](./src/optional/analytics/docs/VOCABULARY_ANALYSIS_GUIDE.md)**.
208
+
209
+ ```typescript
210
+ import { ObfsetProcessor, Analytics } from '@willwade/aac-processors';
211
+
212
+ const processor = new ObfsetProcessor();
213
+ const tree = processor.loadIntoTree('my_pageset.obfset');
214
+
215
+ // Run clinical effort analysis
216
+ const result = new Analytics.MetricsCalculator().analyze(tree);
217
+ console.log(`Average Effort: ${result.total_words}`);
218
+ ```
219
+
195
220
  ### Format Validation
196
221
 
197
222
  Validate AAC files against format specifications to ensure data integrity:
@@ -710,6 +735,14 @@ npm run coverage:report
710
735
 
711
736
  **Note**: All test commands automatically run `npm run build` first to ensure CLI tests have the required `dist/` files. CLI integration tests require the compiled JavaScript files to test the command-line interface.
712
737
 
738
+ ### ๐Ÿ› ๏ธ Utility Scripts
739
+
740
+ A wide range of utility scripts for batch processing, audio generation, and advanced analysis are available in the **[scripts/](./scripts/README.md)** directory. These include:
741
+ - **Analysis**: Pageset reporting and vocabulary extraction.
742
+ - **Audio**: Automated TTS generation and audio-enhanced pageset creation.
743
+ - **Conversion**: TSV-to-Gridset and other format-shifting tools.
744
+ - **Translation**: Batch translation workflows using Google, Azure, and Gemini.
745
+
713
746
  ### Development Commands
714
747
 
715
748
  ```bash
@@ -798,57 +831,27 @@ Inspired by the Python AACProcessors project
798
831
 
799
832
  ### ๐Ÿ”ฅ Critical Priority (Immediate Action Required)
800
833
 
801
- - [ ] **Fix audio persistence issues** (5 tests failing) - Resolve functional audio recording persistence in SnapProcessor save/load cycle (reduced from 21 failing tests)
802
- - [ ] **Resolve database constraint violations** - Fix UNIQUE constraint failures in Page.Id and buttons.id when processing real-world data files (blocks production usage)
803
- - [ ] **Fix Grid3 layout issues** - Grid sizes not reliable and X,Y positions incorrect, particularly affecting Grid3 processor functionality
834
+ - [ ] **Road Testing** - Perform comprehensive layout and formatting validation across diverse pagesets to verify conversion fidelity.
835
+ - [ ] **Fix audio persistence issues** - Resolve functional audio recording persistence in `SnapProcessor` save/load cycle (5 failing tests remaining).
836
+ - [x] **Access Method Modeling** - Support for switch scanning (linear, row-column, block) integrated into AAC metrics.
804
837
 
805
838
  ### ๐Ÿšจ High Priority (Next Sprint)
806
839
 
807
- - [ ] **Complete SnapProcessor coverage** (currently 48.32% - lowest processor) - Add comprehensive audio handling, database corruption tests, and SQLite schema validation to reach >75% coverage
808
- - [ ] **Reduce remaining linting issues** (123 remaining) - Address TypeScript eslint errors and warnings in test files and less critical areas
809
- - [ ] **Improve GridsetProcessor coverage** (currently 71.69%) - Enhance ZIP handling and complex Grid3 archive support to reach >80% coverage
810
-
811
- ### โš ๏ธ Medium Priority (Following Sprint)
840
+ - [ ] **Complete SnapProcessor coverage** (currently ~60%) - Reach >75% coverage by adding comprehensive audio handling and database corruption tests.
841
+ - [ ] **Symbol System Rethink** - Explore treating "Symbols" as a first-class entity (alongside Pages/Buttons) to support richer metadata (library IDs, synonyms, multi-lang names).
842
+ - [ ] **Language & Locale Persistence** - Ensure current language and locale information is correctly preserved and bubbled up to the `AACTree` level.
812
843
 
813
- - [ ] **Improve GridsetProcessor coverage** (currently 71.69%) - Enhance ZIP handling and complex Grid3 archive support to reach >80% coverage
814
- - [ ] **Improve AstericsGridProcessor coverage** (currently 62.5%) - Add comprehensive tests for Asterics Grid format processing to reach >80% coverage
815
- - [ ] **Add Symbol Tools coverage** (currently 0%) - Implement tests for PCS and ARASAAC symbol lookups to reach >70% coverage
816
- - [ ] **Fix property-based test failures** - Resolve TypeScript interface compatibility issues in edge case generators
844
+ ### โš ๏ธ Medium Priority
817
845
 
818
- ### Medium Priority
846
+ - [ ] **Adaptive Metrics** - Expand scanning analysis to include dwell times and more complex switch logic configurations.
819
847
 
820
- - [ ] **Performance optimization** - Optimize memory usage for very large communication boards (1000+ buttons)
821
- - [ ] **Add GridsetProcessor ZIP handling** - Improve support for complex Grid3 ZIP archives
822
- - [ ] **Enhance error recovery** - Better handling of partially corrupted database files
823
- - [ ] **Add streaming support** - Process very large files without loading entirely into memory
824
- - [ ] **Improve translation workflows** - Add support for translation service integrations (Google Translate, Azure, etc.)
825
- - [ ] **Add symbol library integration** - Complete implementation of PCS, ARASAAC symbol lookups
826
848
 
827
849
  ### Low Priority
828
850
 
829
- - [ ] **Add more AAC formats** - Look for other common AAC formats to add
830
- - [ ] **Plugin system** - Allow third-party processors and extensions
831
- - [ ] **Batch processing CLI** - Process multiple files in parallel
832
- - [ ] **Configuration file support** - Allow .aacprocessors.json config files
833
851
 
834
- ### Testing & Quality
852
+ - [ ] **Batch processing CLI** - Process multiple files/directories in parallel.
835
853
 
836
- - [ ] **Reach 80%+ test coverage** - Current: 65.15% (target: 80%+)
837
- - [ ] **Add mutation testing** - Use Stryker.js for mutation testing
838
- - [ ] **Add benchmark suite** - Performance regression testing
839
- - [ ] **CI/CD improvements** - Add automated releases and npm publishing
840
- - [ ] **Documentation improvements** - Add more real-world examples and tutorials
841
-
842
- ## More enhancements
843
-
844
- - Much more effort put into fixing the layout issues. Grid sizes are not reliably and X, Y positions too. Particularly in the Grid3
845
- - Action types on buttons. We have SPEAK, NAVIGATE, but we could also have things like "PLAY_AUDIO", "SEND_MESSAGE", "OPEN_URL", etc. This would allow us to have a more flexible structure for actions, especially if we want to support different types of actions or additional metadata in the future. This needs to be very flexible. eaach system has a very different set of actions. We could have a set of core actions that are supported by all systems, and then allow each system to define its own additional actions. This could be done by having a set of core action types that are defined in the AACSystem type, and then allowing each system to define its own additional action types in the AACPageSet or AACPage types.
846
- - Current language and locale information of aac pageset
847
- - Symbols and their associated data. Now we have an optional part but I think this might need rethinking. I wonder if "Symbols" should be a separate type - alongside AACPageSet and AACPage. that then AACPageSet and AACPage can reference. This would allow us to have a more flexible structure for symbols, especially if we want to support different types of symbols or additional metadata in the future. Symbols would have: Library name, ID, Text name, Reference (URL, DB ID, etc.), and an optional part for additional metadata. We could have synoynms, antonyms, also and for different languages somehow.
848
- - Somehow we need to deal with access. Switch scanning: Blocks probably being the main aspect. But also - we need to identify somewhere a set of core rules for each aac system. Like for example - what access methods are supported, what languages are supported, what symbols are supported, etc. This could be a set of rules that can be referenced by AACSystem - a different type altogether maybe? It could be in a JSON format maybe. (use case here being for a MCP).
849
854
 
850
855
  ### Contributing
851
856
 
852
857
  Want to help with any of these items? See our [Contributing Guidelines](#-contributing) and pick an issue that interests you!
853
-
854
- ---
@@ -29,6 +29,25 @@ export declare enum AACSemanticIntent {
29
29
  SCAN_SELECT = "SCAN_SELECT",
30
30
  PLATFORM_SPECIFIC = "PLATFORM_SPECIFIC"
31
31
  }
32
+ /**
33
+ * Scanning types for accessibility
34
+ */
35
+ export declare enum AACScanType {
36
+ LINEAR = "linear",// Left-to-right, top-to-bottom
37
+ ROW_COLUMN = "row-column",// Scan rows, then columns
38
+ COLUMN_ROW = "column-row",// Scan columns, then rows
39
+ BLOCK_ROW_COLUMN = "block-row-column",// Scan blocks, then rows, then columns
40
+ BLOCK_COLUMN_ROW = "block-column-row"
41
+ }
42
+ /**
43
+ * Configuration for a scan block
44
+ */
45
+ export interface AACScanBlock {
46
+ id: number;
47
+ name?: string;
48
+ order?: number;
49
+ scanType?: AACScanType;
50
+ }
32
51
  export interface AACSemanticAction {
33
52
  category?: AACSemanticCategory;
34
53
  intent: AACSemanticIntent | string;
@@ -110,7 +129,14 @@ export declare class AACButton implements IAACButton {
110
129
  y?: number;
111
130
  columnSpan?: number;
112
131
  rowSpan?: number;
132
+ /**
133
+ * @deprecated Use scanBlock instead (singular, not array)
134
+ */
113
135
  scanBlocks?: number[];
136
+ /**
137
+ * Scan block number (1-8) for block scanning
138
+ */
139
+ scanBlock?: number;
114
140
  visibility?: 'Visible' | 'Hidden' | 'Disabled' | 'PointerAndTouchOnly' | 'Empty';
115
141
  directActivate?: boolean;
116
142
  audioDescription?: string;
@@ -119,7 +145,7 @@ export declare class AACButton implements IAACButton {
119
145
  };
120
146
  semantic_id?: string;
121
147
  clone_id?: string;
122
- constructor({ id, label, message, targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, visibility, directActivate, parameters, semantic_id, clone_id, type, action, }: {
148
+ 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, }: {
123
149
  id: string;
124
150
  label?: string;
125
151
  message?: string;
@@ -143,6 +169,7 @@ export declare class AACButton implements IAACButton {
143
169
  columnSpan?: number;
144
170
  rowSpan?: number;
145
171
  scanBlocks?: number[];
172
+ scanBlock?: number;
146
173
  visibility?: 'Visible' | 'Hidden' | 'Disabled' | 'PointerAndTouchOnly' | 'Empty';
147
174
  directActivate?: boolean;
148
175
  parameters?: {
@@ -177,7 +204,10 @@ export declare class AACPage implements IAACPage {
177
204
  sounds?: any[];
178
205
  semantic_ids?: string[];
179
206
  clone_ids?: string[];
180
- constructor({ id, name, grid, buttons, parentId, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, }: {
207
+ scanningConfig?: import('../types/aac').ScanningConfig;
208
+ scanType?: AACScanType;
209
+ scanBlocksConfig?: AACScanBlock[];
210
+ constructor({ id, name, grid, buttons, parentId, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, scanningConfig, scanBlocksConfig, scanType, }: {
181
211
  id: string;
182
212
  name?: string;
183
213
  grid?: Array<Array<AACButton | null>> | {
@@ -193,6 +223,9 @@ export declare class AACPage implements IAACPage {
193
223
  sounds?: any[];
194
224
  semantic_ids?: string[];
195
225
  clone_ids?: string[];
226
+ scanningConfig?: import('../types/aac').ScanningConfig;
227
+ scanBlocksConfig?: AACScanBlock[];
228
+ scanType?: AACScanType;
196
229
  });
197
230
  addButton(button: AACButton): void;
198
231
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AACTree = exports.AACPage = exports.AACButton = exports.AACSemanticIntent = exports.AACSemanticCategory = void 0;
3
+ exports.AACTree = exports.AACPage = exports.AACButton = exports.AACScanType = exports.AACSemanticIntent = exports.AACSemanticCategory = void 0;
4
4
  // Semantic action categories for cross-platform compatibility
5
5
  var AACSemanticCategory;
6
6
  (function (AACSemanticCategory) {
@@ -42,8 +42,19 @@ var AACSemanticIntent;
42
42
  // Custom
43
43
  AACSemanticIntent["PLATFORM_SPECIFIC"] = "PLATFORM_SPECIFIC";
44
44
  })(AACSemanticIntent || (exports.AACSemanticIntent = AACSemanticIntent = {}));
45
+ /**
46
+ * Scanning types for accessibility
47
+ */
48
+ var AACScanType;
49
+ (function (AACScanType) {
50
+ AACScanType["LINEAR"] = "linear";
51
+ AACScanType["ROW_COLUMN"] = "row-column";
52
+ AACScanType["COLUMN_ROW"] = "column-row";
53
+ AACScanType["BLOCK_ROW_COLUMN"] = "block-row-column";
54
+ AACScanType["BLOCK_COLUMN_ROW"] = "block-column-row";
55
+ })(AACScanType || (exports.AACScanType = AACScanType = {}));
45
56
  class AACButton {
46
- constructor({ id, label = '', message = '', targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, visibility, directActivate, parameters, semantic_id, clone_id,
57
+ 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,
47
58
  // Legacy input support
48
59
  type, action, }) {
49
60
  this.id = id;
@@ -64,6 +75,7 @@ class AACButton {
64
75
  this.columnSpan = columnSpan;
65
76
  this.rowSpan = rowSpan;
66
77
  this.scanBlocks = scanBlocks;
78
+ this.scanBlock = scanBlock;
67
79
  this.visibility = visibility;
68
80
  this.directActivate = directActivate;
69
81
  this.parameters = parameters;
@@ -156,7 +168,7 @@ class AACButton {
156
168
  }
157
169
  exports.AACButton = AACButton;
158
170
  class AACPage {
159
- constructor({ id, name = '', grid = [], buttons = [], parentId = null, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, }) {
171
+ constructor({ id, name = '', grid = [], buttons = [], parentId = null, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, scanningConfig, scanBlocksConfig, scanType, }) {
160
172
  this.id = id;
161
173
  this.name = name;
162
174
  if (Array.isArray(grid)) {
@@ -179,6 +191,9 @@ class AACPage {
179
191
  this.sounds = sounds;
180
192
  this.semantic_ids = semantic_ids;
181
193
  this.clone_ids = clone_ids;
194
+ this.scanningConfig = scanningConfig;
195
+ this.scanBlocksConfig = scanBlocksConfig;
196
+ this.scanType = scanType;
182
197
  }
183
198
  addButton(button) {
184
199
  this.buttons.push(button);
@@ -1,7 +1,8 @@
1
1
  import { dotNetTicksToDate } from '../../utils/dotnetTicks';
2
2
  import { Grid3UserPath } from '../../processors/gridset/helpers';
3
3
  import { SnapUserInfo } from '../../processors/snap/helpers';
4
- export type HistorySource = 'Grid' | 'Snap';
4
+ import { AACSemanticCategory, AACSemanticIntent } from '../../core/treeStructure';
5
+ export type HistorySource = 'Grid' | 'Snap' | 'OBL' | string;
5
6
  export interface HistoryOccurrence {
6
7
  timestamp: Date;
7
8
  latitude?: number | null;
@@ -9,12 +10,22 @@ export interface HistoryOccurrence {
9
10
  modeling?: boolean;
10
11
  accessMethod?: number | null;
11
12
  pageId?: string | null;
13
+ buttonId?: string | null;
14
+ boardId?: string | null;
15
+ spoken?: boolean;
16
+ vocalization?: string;
17
+ imageUrl?: string;
18
+ actions?: any[];
19
+ type?: 'button' | 'action' | 'utterance' | 'note' | 'other';
20
+ intent?: AACSemanticIntent | string;
21
+ category?: AACSemanticCategory;
12
22
  }
13
23
  export interface HistoryPlatformExtras {
14
24
  label?: string;
15
25
  message?: string;
16
26
  buttonId?: string;
17
27
  contentXml?: string;
28
+ [key: string]: any;
18
29
  }
19
30
  export interface HistoryEntry {
20
31
  id: string;
@@ -13,6 +13,8 @@ export * from './metrics/types';
13
13
  export * from './metrics/effort';
14
14
  export * from './utils/idGenerator';
15
15
  export * from './history';
16
+ export * from './metrics/obl-types';
17
+ export { OblUtil, OblAnonymizer } from './metrics/obl';
16
18
  export { MetricsCalculator } from './metrics/core';
17
19
  export { VocabularyAnalyzer } from './metrics/vocabulary';
18
20
  export { SentenceAnalyzer } from './metrics/sentence';
@@ -28,7 +28,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  return (mod && mod.__esModule) ? mod : { "default": mod };
29
29
  };
30
30
  Object.defineProperty(exports, "__esModule", { value: true });
31
- exports.ReferenceLoader = exports.ComparisonAnalyzer = exports.SentenceAnalyzer = exports.VocabularyAnalyzer = exports.MetricsCalculator = void 0;
31
+ exports.ReferenceLoader = exports.ComparisonAnalyzer = exports.SentenceAnalyzer = exports.VocabularyAnalyzer = exports.MetricsCalculator = exports.OblAnonymizer = exports.OblUtil = void 0;
32
32
  exports.getReferenceDataPath = getReferenceDataPath;
33
33
  exports.hasReferenceData = hasReferenceData;
34
34
  const path_1 = __importDefault(require("path"));
@@ -39,6 +39,11 @@ __exportStar(require("./metrics/effort"), exports);
39
39
  __exportStar(require("./utils/idGenerator"), exports);
40
40
  // Export history functionality
41
41
  __exportStar(require("./history"), exports);
42
+ // Export OBL logging support
43
+ __exportStar(require("./metrics/obl-types"), exports);
44
+ var obl_1 = require("./metrics/obl");
45
+ Object.defineProperty(exports, "OblUtil", { enumerable: true, get: function () { return obl_1.OblUtil; } });
46
+ Object.defineProperty(exports, "OblAnonymizer", { enumerable: true, get: function () { return obl_1.OblAnonymizer; } });
42
47
  // Export core metrics calculator
43
48
  var core_1 = require("./metrics/core");
44
49
  Object.defineProperty(exports, "MetricsCalculator", { enumerable: true, get: function () { return core_1.MetricsCalculator; } });
@@ -87,13 +87,17 @@ class ComparisonAnalyzer {
87
87
  }
88
88
  });
89
89
  highEffortWords.sort((a, b) => {
90
- const diffA = targetWords.get(a).effort - (compareWords.get(a)?.effort || 0);
91
- const diffB = targetWords.get(b).effort - (compareWords.get(b)?.effort || 0);
90
+ const targetBtnA = targetWords.get(a);
91
+ const targetBtnB = targetWords.get(b);
92
+ const diffA = (targetBtnA?.effort || 0) - (compareWords.get(a)?.effort || 0);
93
+ const diffB = (targetBtnB?.effort || 0) - (compareWords.get(b)?.effort || 0);
92
94
  return diffB - diffA;
93
95
  });
94
96
  lowEffortWords.sort((a, b) => {
95
- const diffA = (compareWords.get(a)?.effort || 0) - targetWords.get(a).effort;
96
- const diffB = (compareWords.get(b)?.effort || 0) - targetWords.get(b).effort;
97
+ const targetBtnA = targetWords.get(a);
98
+ const targetBtnB = targetWords.get(b);
99
+ const diffA = (compareWords.get(a)?.effort || 0) - (targetBtnA?.effort || 0);
100
+ const diffB = (compareWords.get(b)?.effort || 0) - (targetBtnB?.effort || 0);
97
101
  return diffB - diffA;
98
102
  });
99
103
  // Sentence analysis
@@ -21,6 +21,11 @@ export declare class MetricsCalculator {
21
21
  * Build reference maps for semantic_id and clone_id frequencies
22
22
  */
23
23
  private buildReferenceMaps;
24
+ /**
25
+ * Count scan items for visual scanning effort
26
+ * When block scanning is enabled, count unique scan blocks instead of individual buttons
27
+ */
28
+ private countScanItems;
24
29
  /**
25
30
  * Analyze starting from a specific board
26
31
  */
@@ -33,4 +38,8 @@ export declare class MetricsCalculator {
33
38
  * Calculate grid dimensions from the tree
34
39
  */
35
40
  private calculateGridDimensions;
41
+ /**
42
+ * Calculate scanning steps and selections for a button based on access method
43
+ */
44
+ private calculateScanSteps;
36
45
  }