@willwade/aac-processors 0.0.11 → 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 (56) hide show
  1. package/README.md +44 -41
  2. package/dist/cli/index.js +7 -0
  3. package/dist/core/analyze.js +1 -0
  4. package/dist/core/treeStructure.d.ts +45 -2
  5. package/dist/core/treeStructure.js +22 -3
  6. package/dist/index.d.ts +2 -1
  7. package/dist/index.js +20 -3
  8. package/dist/{analytics → optional/analytics}/history.d.ts +15 -4
  9. package/dist/{analytics → optional/analytics}/history.js +3 -3
  10. package/dist/optional/analytics/index.d.ts +30 -0
  11. package/dist/optional/analytics/index.js +78 -0
  12. package/dist/optional/analytics/metrics/comparison.d.ts +36 -0
  13. package/dist/optional/analytics/metrics/comparison.js +334 -0
  14. package/dist/optional/analytics/metrics/core.d.ts +45 -0
  15. package/dist/optional/analytics/metrics/core.js +575 -0
  16. package/dist/optional/analytics/metrics/effort.d.ts +147 -0
  17. package/dist/optional/analytics/metrics/effort.js +211 -0
  18. package/dist/optional/analytics/metrics/index.d.ts +15 -0
  19. package/dist/optional/analytics/metrics/index.js +36 -0
  20. package/dist/optional/analytics/metrics/obl-types.d.ts +93 -0
  21. package/dist/optional/analytics/metrics/obl-types.js +7 -0
  22. package/dist/optional/analytics/metrics/obl.d.ts +40 -0
  23. package/dist/optional/analytics/metrics/obl.js +287 -0
  24. package/dist/optional/analytics/metrics/sentence.d.ts +49 -0
  25. package/dist/optional/analytics/metrics/sentence.js +112 -0
  26. package/dist/optional/analytics/metrics/types.d.ts +157 -0
  27. package/dist/optional/analytics/metrics/types.js +7 -0
  28. package/dist/optional/analytics/metrics/vocabulary.d.ts +65 -0
  29. package/dist/optional/analytics/metrics/vocabulary.js +142 -0
  30. package/dist/optional/analytics/reference/index.d.ts +51 -0
  31. package/dist/optional/analytics/reference/index.js +102 -0
  32. package/dist/optional/analytics/utils/idGenerator.d.ts +59 -0
  33. package/dist/optional/analytics/utils/idGenerator.js +96 -0
  34. package/dist/optional/symbolTools.js +13 -16
  35. package/dist/processors/astericsGridProcessor.d.ts +15 -0
  36. package/dist/processors/astericsGridProcessor.js +17 -0
  37. package/dist/processors/gridset/helpers.d.ts +4 -1
  38. package/dist/processors/gridset/helpers.js +4 -0
  39. package/dist/processors/gridset/pluginTypes.js +51 -50
  40. package/dist/processors/gridset/symbolExtractor.js +3 -2
  41. package/dist/processors/gridset/symbolSearch.js +9 -7
  42. package/dist/processors/gridsetProcessor.js +82 -20
  43. package/dist/processors/index.d.ts +1 -0
  44. package/dist/processors/index.js +5 -3
  45. package/dist/processors/obfProcessor.js +37 -2
  46. package/dist/processors/obfsetProcessor.d.ts +26 -0
  47. package/dist/processors/obfsetProcessor.js +179 -0
  48. package/dist/processors/snap/helpers.d.ts +5 -1
  49. package/dist/processors/snap/helpers.js +5 -0
  50. package/dist/processors/snapProcessor.d.ts +2 -0
  51. package/dist/processors/snapProcessor.js +184 -5
  52. package/dist/processors/touchchatProcessor.js +50 -4
  53. package/dist/types/aac.d.ts +67 -0
  54. package/dist/types/aac.js +33 -0
  55. package/dist/validation/gridsetValidator.js +10 -0
  56. 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
- ---
package/dist/cli/index.js CHANGED
@@ -17,6 +17,13 @@ function detectFormat(filePath) {
17
17
  filePath.endsWith('.ascconfig')) {
18
18
  return 'ascconfig';
19
19
  }
20
+ // Map multi-file formats to their base processor
21
+ if (filePath.endsWith('.obfset')) {
22
+ return 'obf'; // Use ObfProcessor for .obfset files
23
+ }
24
+ if (filePath.endsWith('.gridset')) {
25
+ return 'gridset';
26
+ }
20
27
  // Otherwise use file extension
21
28
  return path_1.default.extname(filePath).slice(1);
22
29
  }
@@ -22,6 +22,7 @@ function getProcessor(format, options) {
22
22
  case 'opml':
23
23
  return new opmlProcessor_1.OpmlProcessor(options);
24
24
  case 'obf':
25
+ case 'obfset': // Obfset files use ObfProcessor
25
26
  return new obfProcessor_1.ObfProcessor(options);
26
27
  case 'touchchat':
27
28
  case 'ce': // TouchChat file extension
@@ -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;
@@ -83,6 +102,8 @@ export interface AACSemanticAction {
83
102
  type: 'SPEAK' | 'NAVIGATE' | 'ACTION';
84
103
  message?: string;
85
104
  targetPageId?: string;
105
+ temporary_home?: boolean | string | null;
106
+ add_to_sentence?: boolean;
86
107
  };
87
108
  }
88
109
  export declare class AACButton implements IAACButton {
@@ -108,14 +129,23 @@ export declare class AACButton implements IAACButton {
108
129
  y?: number;
109
130
  columnSpan?: number;
110
131
  rowSpan?: number;
132
+ /**
133
+ * @deprecated Use scanBlock instead (singular, not array)
134
+ */
111
135
  scanBlocks?: number[];
136
+ /**
137
+ * Scan block number (1-8) for block scanning
138
+ */
139
+ scanBlock?: number;
112
140
  visibility?: 'Visible' | 'Hidden' | 'Disabled' | 'PointerAndTouchOnly' | 'Empty';
113
141
  directActivate?: boolean;
114
142
  audioDescription?: string;
115
143
  parameters?: {
116
144
  [key: string]: any;
117
145
  };
118
- constructor({ id, label, message, targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, visibility, directActivate, parameters, type, action, }: {
146
+ semantic_id?: string;
147
+ clone_id?: string;
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, }: {
119
149
  id: string;
120
150
  label?: string;
121
151
  message?: string;
@@ -139,11 +169,14 @@ export declare class AACButton implements IAACButton {
139
169
  columnSpan?: number;
140
170
  rowSpan?: number;
141
171
  scanBlocks?: number[];
172
+ scanBlock?: number;
142
173
  visibility?: 'Visible' | 'Hidden' | 'Disabled' | 'PointerAndTouchOnly' | 'Empty';
143
174
  directActivate?: boolean;
144
175
  parameters?: {
145
176
  [key: string]: any;
146
177
  };
178
+ semantic_id?: string;
179
+ clone_id?: string;
147
180
  type?: 'SPEAK' | 'NAVIGATE' | 'ACTION';
148
181
  action?: {
149
182
  type: 'SPEAK' | 'NAVIGATE' | 'ACTION';
@@ -169,7 +202,12 @@ export declare class AACPage implements IAACPage {
169
202
  descriptionHtml?: string;
170
203
  images?: any[];
171
204
  sounds?: any[];
172
- constructor({ id, name, grid, buttons, parentId, style, locale, descriptionHtml, images, sounds, }: {
205
+ semantic_ids?: string[];
206
+ clone_ids?: string[];
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, }: {
173
211
  id: string;
174
212
  name?: string;
175
213
  grid?: Array<Array<AACButton | null>> | {
@@ -183,6 +221,11 @@ export declare class AACPage implements IAACPage {
183
221
  descriptionHtml?: string;
184
222
  images?: any[];
185
223
  sounds?: any[];
224
+ semantic_ids?: string[];
225
+ clone_ids?: string[];
226
+ scanningConfig?: import('../types/aac').ScanningConfig;
227
+ scanBlocksConfig?: AACScanBlock[];
228
+ scanType?: AACScanType;
186
229
  });
187
230
  addButton(button: AACButton): void;
188
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,
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,9 +75,12 @@ 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;
82
+ this.semantic_id = semantic_id;
83
+ this.clone_id = clone_id;
70
84
  // Legacy mapping: if no semanticAction provided, derive from legacy `action` first
71
85
  if (!this.semanticAction && action) {
72
86
  if (action.type === 'NAVIGATE' && (action.targetPageId || this.targetPageId)) {
@@ -154,7 +168,7 @@ class AACButton {
154
168
  }
155
169
  exports.AACButton = AACButton;
156
170
  class AACPage {
157
- constructor({ id, name = '', grid = [], buttons = [], parentId = null, style, locale, descriptionHtml, images, sounds, }) {
171
+ constructor({ id, name = '', grid = [], buttons = [], parentId = null, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, scanningConfig, scanBlocksConfig, scanType, }) {
158
172
  this.id = id;
159
173
  this.name = name;
160
174
  if (Array.isArray(grid)) {
@@ -175,6 +189,11 @@ class AACPage {
175
189
  this.descriptionHtml = descriptionHtml;
176
190
  this.images = images;
177
191
  this.sounds = sounds;
192
+ this.semantic_ids = semantic_ids;
193
+ this.clone_ids = clone_ids;
194
+ this.scanningConfig = scanningConfig;
195
+ this.scanBlocksConfig = scanBlocksConfig;
196
+ this.scanType = scanType;
178
197
  }
179
198
  addButton(button) {
180
199
  this.buttons.push(button);
package/dist/index.d.ts CHANGED
@@ -2,8 +2,9 @@ export * from './core/treeStructure';
2
2
  export * from './core/baseProcessor';
3
3
  export * from './core/stringCasing';
4
4
  export * from './processors';
5
- export { collectUnifiedHistory, listGrid3Users as listHistoryGrid3Users, listSnapUsers as listHistorySnapUsers, } from './analytics/history';
6
5
  export * from './validation';
6
+ export * as Analytics from './optional/analytics';
7
+ export { collectUnifiedHistory, listGrid3Users as listHistoryGrid3Users, listSnapUsers as listHistorySnapUsers, } from './optional/analytics/history';
7
8
  import { BaseProcessor } from './core/baseProcessor';
8
9
  /**
9
10
  * Factory function to get the appropriate processor for a file extension
package/dist/index.js CHANGED
@@ -10,11 +10,23 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
13
18
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
19
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
20
  };
21
+ var __importStar = (this && this.__importStar) || function (mod) {
22
+ if (mod && mod.__esModule) return mod;
23
+ var result = {};
24
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25
+ __setModuleDefault(result, mod);
26
+ return result;
27
+ };
16
28
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.listHistorySnapUsers = exports.listHistoryGrid3Users = exports.collectUnifiedHistory = void 0;
29
+ exports.listHistorySnapUsers = exports.listHistoryGrid3Users = exports.collectUnifiedHistory = exports.Analytics = void 0;
18
30
  exports.getProcessor = getProcessor;
19
31
  exports.getSupportedExtensions = getSupportedExtensions;
20
32
  exports.isExtensionSupported = isExtensionSupported;
@@ -23,11 +35,12 @@ __exportStar(require("./core/treeStructure"), exports);
23
35
  __exportStar(require("./core/baseProcessor"), exports);
24
36
  __exportStar(require("./core/stringCasing"), exports);
25
37
  __exportStar(require("./processors"), exports);
26
- var history_1 = require("./analytics/history");
38
+ __exportStar(require("./validation"), exports);
39
+ exports.Analytics = __importStar(require("./optional/analytics"));
40
+ var history_1 = require("./optional/analytics/history");
27
41
  Object.defineProperty(exports, "collectUnifiedHistory", { enumerable: true, get: function () { return history_1.collectUnifiedHistory; } });
28
42
  Object.defineProperty(exports, "listHistoryGrid3Users", { enumerable: true, get: function () { return history_1.listGrid3Users; } });
29
43
  Object.defineProperty(exports, "listHistorySnapUsers", { enumerable: true, get: function () { return history_1.listSnapUsers; } });
30
- __exportStar(require("./validation"), exports);
31
44
  const dotProcessor_1 = require("./processors/dotProcessor");
32
45
  const excelProcessor_1 = require("./processors/excelProcessor");
33
46
  const opmlProcessor_1 = require("./processors/opmlProcessor");
@@ -37,6 +50,7 @@ const snapProcessor_1 = require("./processors/snapProcessor");
37
50
  const touchchatProcessor_1 = require("./processors/touchchatProcessor");
38
51
  const applePanelsProcessor_1 = require("./processors/applePanelsProcessor");
39
52
  const astericsGridProcessor_1 = require("./processors/astericsGridProcessor");
53
+ const obfsetProcessor_1 = require("./processors/obfsetProcessor");
40
54
  /**
41
55
  * Factory function to get the appropriate processor for a file extension
42
56
  * @param filePathOrExtension - File path or extension (e.g., '.dot', '/path/to/file.obf')
@@ -58,6 +72,8 @@ function getProcessor(filePathOrExtension) {
58
72
  case '.obf':
59
73
  case '.obz':
60
74
  return new obfProcessor_1.ObfProcessor();
75
+ case '.obfset':
76
+ return new obfsetProcessor_1.ObfsetProcessor();
61
77
  case '.gridset':
62
78
  case '.gridsetx':
63
79
  return new gridsetProcessor_1.GridsetProcessor();
@@ -85,6 +101,7 @@ function getSupportedExtensions() {
85
101
  '.opml',
86
102
  '.obf',
87
103
  '.obz',
104
+ '.obfset',
88
105
  '.gridset',
89
106
  '.gridsetx',
90
107
  '.spb',
@@ -1,7 +1,8 @@
1
- import { dotNetTicksToDate } from '../utils/dotnetTicks';
2
- import { Grid3UserPath } from '../processors/gridset/helpers';
3
- import { SnapUserInfo } from '../processors/snap/helpers';
4
- export type HistorySource = 'Grid' | 'Snap';
1
+ import { dotNetTicksToDate } from '../../utils/dotnetTicks';
2
+ import { Grid3UserPath } from '../../processors/gridset/helpers';
3
+ import { SnapUserInfo } from '../../processors/snap/helpers';
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;
@@ -9,10 +9,10 @@ exports.readSnapUsageForUser = readSnapUsageForUser;
9
9
  exports.listSnapUsers = listSnapUsers;
10
10
  exports.listGrid3Users = listGrid3Users;
11
11
  exports.collectUnifiedHistory = collectUnifiedHistory;
12
- const dotnetTicks_1 = require("../utils/dotnetTicks");
12
+ const dotnetTicks_1 = require("../../utils/dotnetTicks");
13
13
  Object.defineProperty(exports, "dotNetTicksToDate", { enumerable: true, get: function () { return dotnetTicks_1.dotNetTicksToDate; } });
14
- const helpers_1 = require("../processors/gridset/helpers");
15
- const helpers_2 = require("../processors/snap/helpers");
14
+ const helpers_1 = require("../../processors/gridset/helpers");
15
+ const helpers_2 = require("../../processors/snap/helpers");
16
16
  /**
17
17
  * Read Grid 3 phrase history from a history.sqlite database and tag entries with their source.
18
18
  */
@@ -0,0 +1,30 @@
1
+ /**
2
+ * AAC Analytics Module (Optional)
3
+ *
4
+ * This module provides metrics calculation and analysis for AAC board sets.
5
+ * The core types, utilities, and effort functions are always available.
6
+ *
7
+ * This module is similar to symbolTools - the functionality is here but
8
+ * you only use it if you need it. No special installation required.
9
+ *
10
+ * @module
11
+ */
12
+ export * from './metrics/types';
13
+ export * from './metrics/effort';
14
+ export * from './utils/idGenerator';
15
+ export * from './history';
16
+ export * from './metrics/obl-types';
17
+ export { OblUtil, OblAnonymizer } from './metrics/obl';
18
+ export { MetricsCalculator } from './metrics/core';
19
+ export { VocabularyAnalyzer } from './metrics/vocabulary';
20
+ export { SentenceAnalyzer } from './metrics/sentence';
21
+ export { ComparisonAnalyzer } from './metrics/comparison';
22
+ export { ReferenceLoader } from './reference';
23
+ /**
24
+ * Get the default reference data path
25
+ */
26
+ export declare function getReferenceDataPath(): string;
27
+ /**
28
+ * Check if reference data files exist
29
+ */
30
+ export declare function hasReferenceData(): boolean;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * AAC Analytics Module (Optional)
4
+ *
5
+ * This module provides metrics calculation and analysis for AAC board sets.
6
+ * The core types, utilities, and effort functions are always available.
7
+ *
8
+ * This module is similar to symbolTools - the functionality is here but
9
+ * you only use it if you need it. No special installation required.
10
+ *
11
+ * @module
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
25
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
26
+ };
27
+ var __importDefault = (this && this.__importDefault) || function (mod) {
28
+ return (mod && mod.__esModule) ? mod : { "default": mod };
29
+ };
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.ReferenceLoader = exports.ComparisonAnalyzer = exports.SentenceAnalyzer = exports.VocabularyAnalyzer = exports.MetricsCalculator = exports.OblAnonymizer = exports.OblUtil = void 0;
32
+ exports.getReferenceDataPath = getReferenceDataPath;
33
+ exports.hasReferenceData = hasReferenceData;
34
+ const path_1 = __importDefault(require("path"));
35
+ const fs_1 = __importDefault(require("fs"));
36
+ // Always-available exports
37
+ __exportStar(require("./metrics/types"), exports);
38
+ __exportStar(require("./metrics/effort"), exports);
39
+ __exportStar(require("./utils/idGenerator"), exports);
40
+ // Export history functionality
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; } });
47
+ // Export core metrics calculator
48
+ var core_1 = require("./metrics/core");
49
+ Object.defineProperty(exports, "MetricsCalculator", { enumerable: true, get: function () { return core_1.MetricsCalculator; } });
50
+ // Export vocabulary and comparison analyzers
51
+ var vocabulary_1 = require("./metrics/vocabulary");
52
+ Object.defineProperty(exports, "VocabularyAnalyzer", { enumerable: true, get: function () { return vocabulary_1.VocabularyAnalyzer; } });
53
+ var sentence_1 = require("./metrics/sentence");
54
+ Object.defineProperty(exports, "SentenceAnalyzer", { enumerable: true, get: function () { return sentence_1.SentenceAnalyzer; } });
55
+ var comparison_1 = require("./metrics/comparison");
56
+ Object.defineProperty(exports, "ComparisonAnalyzer", { enumerable: true, get: function () { return comparison_1.ComparisonAnalyzer; } });
57
+ var reference_1 = require("./reference");
58
+ Object.defineProperty(exports, "ReferenceLoader", { enumerable: true, get: function () { return reference_1.ReferenceLoader; } });
59
+ /**
60
+ * Get the default reference data path
61
+ */
62
+ function getReferenceDataPath() {
63
+ return path_1.default.join(__dirname, 'reference', 'data');
64
+ }
65
+ /**
66
+ * Check if reference data files exist
67
+ */
68
+ function hasReferenceData() {
69
+ const dataPath = getReferenceDataPath();
70
+ const requiredFiles = [
71
+ 'core_lists.en.json',
72
+ 'common_words.en.json',
73
+ 'sentences.en.json',
74
+ 'synonyms.en.json',
75
+ 'fringe.en.json',
76
+ ];
77
+ return requiredFiles.every((file) => fs_1.default.existsSync(path_1.default.join(dataPath, file)));
78
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Comparative Analysis
3
+ *
4
+ * Compares two AAC board sets to identify missing/extra words,
5
+ * analyze vocabulary differences, and generate CARE component scores.
6
+ */
7
+ import { MetricsResult, ComparisonResult } from './types';
8
+ export declare class ComparisonAnalyzer {
9
+ private vocabAnalyzer;
10
+ private sentenceAnalyzer;
11
+ private referenceLoader;
12
+ constructor();
13
+ /**
14
+ * Compare two board sets
15
+ */
16
+ compare(targetResult: MetricsResult, compareResult: MetricsResult, options?: {
17
+ includeSentences?: boolean;
18
+ locale?: string;
19
+ }): ComparisonResult;
20
+ /**
21
+ * Calculate CARE component scores
22
+ */
23
+ private calculateCareComponents;
24
+ /**
25
+ * Analyze fringe vocabulary
26
+ */
27
+ private analyzeFringe;
28
+ /**
29
+ * Analyze common fringe vocabulary
30
+ */
31
+ private analyzeCommonFringe;
32
+ /**
33
+ * Calculate overall effort score for a metrics result
34
+ */
35
+ private calculateEffortScore;
36
+ }