@pie-players/pie-assessment-toolkit 0.2.0
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/README.md +520 -0
- package/dist/attempt/TestSession.d.ts +90 -0
- package/dist/attempt/TestSession.d.ts.map +1 -0
- package/dist/attempt/TestSession.js +174 -0
- package/dist/attempt/TestSession.js.map +1 -0
- package/dist/core/TypedEventBus.d.ts +48 -0
- package/dist/core/TypedEventBus.d.ts.map +1 -0
- package/dist/core/TypedEventBus.js +63 -0
- package/dist/core/TypedEventBus.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/item-loader.d.ts +45 -0
- package/dist/item-loader.d.ts.map +1 -0
- package/dist/item-loader.js +62 -0
- package/dist/item-loader.js.map +1 -0
- package/dist/player/AssessmentPlayer.d.ts +388 -0
- package/dist/player/AssessmentPlayer.d.ts.map +1 -0
- package/dist/player/AssessmentPlayer.js +965 -0
- package/dist/player/AssessmentPlayer.js.map +1 -0
- package/dist/player/index.d.ts +17 -0
- package/dist/player/index.d.ts.map +1 -0
- package/dist/player/index.js +15 -0
- package/dist/player/index.js.map +1 -0
- package/dist/player/navigation-types.d.ts +63 -0
- package/dist/player/navigation-types.d.ts.map +1 -0
- package/dist/player/navigation-types.js +7 -0
- package/dist/player/navigation-types.js.map +1 -0
- package/dist/player/qti-navigation.d.ts +29 -0
- package/dist/player/qti-navigation.d.ts.map +1 -0
- package/dist/player/qti-navigation.js +160 -0
- package/dist/player/qti-navigation.js.map +1 -0
- package/dist/reference-layout/index.d.ts +19 -0
- package/dist/reference-layout/index.d.ts.map +1 -0
- package/dist/reference-layout/index.js +20 -0
- package/dist/reference-layout/index.js.map +1 -0
- package/dist/services/AccessibilityCatalogResolver.d.ts +141 -0
- package/dist/services/AccessibilityCatalogResolver.d.ts.map +1 -0
- package/dist/services/AccessibilityCatalogResolver.js +249 -0
- package/dist/services/AccessibilityCatalogResolver.js.map +1 -0
- package/dist/services/AssessmentAuthoringService.d.ts +60 -0
- package/dist/services/AssessmentAuthoringService.d.ts.map +1 -0
- package/dist/services/AssessmentAuthoringService.js +183 -0
- package/dist/services/AssessmentAuthoringService.js.map +1 -0
- package/dist/services/ContextVariableStore.d.ts +114 -0
- package/dist/services/ContextVariableStore.d.ts.map +1 -0
- package/dist/services/ContextVariableStore.js +207 -0
- package/dist/services/ContextVariableStore.js.map +1 -0
- package/dist/services/ElementToolStateStore.d.ts +125 -0
- package/dist/services/ElementToolStateStore.d.ts.map +1 -0
- package/dist/services/ElementToolStateStore.js +200 -0
- package/dist/services/ElementToolStateStore.js.map +1 -0
- package/dist/services/HighlightCoordinator.d.ts +179 -0
- package/dist/services/HighlightCoordinator.d.ts.map +1 -0
- package/dist/services/HighlightCoordinator.js +446 -0
- package/dist/services/HighlightCoordinator.js.map +1 -0
- package/dist/services/I18nService.d.ts +121 -0
- package/dist/services/I18nService.d.ts.map +1 -0
- package/dist/services/I18nService.js +276 -0
- package/dist/services/I18nService.js.map +1 -0
- package/dist/services/PNPMapper.d.ts +71 -0
- package/dist/services/PNPMapper.d.ts.map +1 -0
- package/dist/services/PNPMapper.js +98 -0
- package/dist/services/PNPMapper.js.map +1 -0
- package/dist/services/PNPToolResolver.d.ts +127 -0
- package/dist/services/PNPToolResolver.d.ts.map +1 -0
- package/dist/services/PNPToolResolver.js +222 -0
- package/dist/services/PNPToolResolver.js.map +1 -0
- package/dist/services/SSMLExtractor.d.ts +61 -0
- package/dist/services/SSMLExtractor.d.ts.map +1 -0
- package/dist/services/SSMLExtractor.js +181 -0
- package/dist/services/SSMLExtractor.js.map +1 -0
- package/dist/services/TTSService.d.ts +162 -0
- package/dist/services/TTSService.d.ts.map +1 -0
- package/dist/services/TTSService.js +465 -0
- package/dist/services/TTSService.js.map +1 -0
- package/dist/services/ThemeProvider.d.ts +95 -0
- package/dist/services/ThemeProvider.d.ts.map +1 -0
- package/dist/services/ThemeProvider.js +299 -0
- package/dist/services/ThemeProvider.js.map +1 -0
- package/dist/services/ToolConfigResolver.d.ts +162 -0
- package/dist/services/ToolConfigResolver.d.ts.map +1 -0
- package/dist/services/ToolConfigResolver.js +230 -0
- package/dist/services/ToolConfigResolver.js.map +1 -0
- package/dist/services/ToolCoordinator.d.ts +137 -0
- package/dist/services/ToolCoordinator.d.ts.map +1 -0
- package/dist/services/ToolCoordinator.js +318 -0
- package/dist/services/ToolCoordinator.js.map +1 -0
- package/dist/services/ToolkitCoordinator.d.ts +188 -0
- package/dist/services/ToolkitCoordinator.d.ts.map +1 -0
- package/dist/services/ToolkitCoordinator.js +252 -0
- package/dist/services/ToolkitCoordinator.js.map +1 -0
- package/dist/services/interfaces.d.ts +391 -0
- package/dist/services/interfaces.d.ts.map +1 -0
- package/dist/services/interfaces.js +12 -0
- package/dist/services/interfaces.js.map +1 -0
- package/dist/services/tool-providers/DesmosToolProvider.d.ts +103 -0
- package/dist/services/tool-providers/DesmosToolProvider.d.ts.map +1 -0
- package/dist/services/tool-providers/DesmosToolProvider.js +127 -0
- package/dist/services/tool-providers/DesmosToolProvider.js.map +1 -0
- package/dist/services/tool-providers/IToolProvider.d.ts +137 -0
- package/dist/services/tool-providers/IToolProvider.d.ts.map +1 -0
- package/dist/services/tool-providers/IToolProvider.js +13 -0
- package/dist/services/tool-providers/IToolProvider.js.map +1 -0
- package/dist/services/tool-providers/TIToolProvider.d.ts +107 -0
- package/dist/services/tool-providers/TIToolProvider.d.ts.map +1 -0
- package/dist/services/tool-providers/TIToolProvider.js +123 -0
- package/dist/services/tool-providers/TIToolProvider.js.map +1 -0
- package/dist/services/tool-providers/TTSToolProvider.d.ts +143 -0
- package/dist/services/tool-providers/TTSToolProvider.d.ts.map +1 -0
- package/dist/services/tool-providers/TTSToolProvider.js +168 -0
- package/dist/services/tool-providers/TTSToolProvider.js.map +1 -0
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +165 -0
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts.map +1 -0
- package/dist/services/tool-providers/ToolProviderRegistry.js +240 -0
- package/dist/services/tool-providers/ToolProviderRegistry.js.map +1 -0
- package/dist/services/tool-providers/index.d.ts +18 -0
- package/dist/services/tool-providers/index.d.ts.map +1 -0
- package/dist/services/tool-providers/index.js +15 -0
- package/dist/services/tool-providers/index.js.map +1 -0
- package/dist/services/tts/browser-provider.d.ts +24 -0
- package/dist/services/tts/browser-provider.d.ts.map +1 -0
- package/dist/services/tts/browser-provider.js +177 -0
- package/dist/services/tts/browser-provider.js.map +1 -0
- package/dist/services/tts/provider-interface.d.ts +131 -0
- package/dist/services/tts/provider-interface.d.ts.map +1 -0
- package/dist/services/tts/provider-interface.js +10 -0
- package/dist/services/tts/provider-interface.js.map +1 -0
- package/dist/tools/calculators/desmos-provider.d.ts +54 -0
- package/dist/tools/calculators/desmos-provider.d.ts.map +1 -0
- package/dist/tools/calculators/desmos-provider.js +384 -0
- package/dist/tools/calculators/desmos-provider.js.map +1 -0
- package/dist/tools/calculators/mathjs-provider.d.ts +50 -0
- package/dist/tools/calculators/mathjs-provider.d.ts.map +1 -0
- package/dist/tools/calculators/mathjs-provider.js +660 -0
- package/dist/tools/calculators/mathjs-provider.js.map +1 -0
- package/dist/tools/calculators/ti-provider.d.ts +122 -0
- package/dist/tools/calculators/ti-provider.d.ts.map +1 -0
- package/dist/tools/calculators/ti-provider.js +587 -0
- package/dist/tools/calculators/ti-provider.js.map +1 -0
- package/dist/tools/client.d.ts +17 -0
- package/dist/tools/client.d.ts.map +1 -0
- package/dist/tools/client.js +26 -0
- package/dist/tools/client.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +10 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/library-loader.d.ts +63 -0
- package/dist/tools/library-loader.d.ts.map +1 -0
- package/dist/tools/library-loader.js +292 -0
- package/dist/tools/library-loader.js.map +1 -0
- package/dist/tools/response-discovery.d.ts +72 -0
- package/dist/tools/response-discovery.d.ts.map +1 -0
- package/dist/tools/response-discovery.js +183 -0
- package/dist/tools/response-discovery.js.map +1 -0
- package/dist/tools/tool-coordinator.d.ts +76 -0
- package/dist/tools/tool-coordinator.d.ts.map +1 -0
- package/dist/tools/tool-coordinator.js +197 -0
- package/dist/tools/tool-coordinator.js.map +1 -0
- package/dist/tools/types.d.ts +427 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +13 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/variant-resolver.d.ts +48 -0
- package/dist/tools/variant-resolver.d.ts.map +1 -0
- package/dist/tools/variant-resolver.js +214 -0
- package/dist/tools/variant-resolver.js.map +1 -0
- package/dist/types/events.d.ts +157 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +11 -0
- package/dist/types/events.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +11 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +71 -0
- package/src/README.md +626 -0
- package/src/components/QuestionToolBar.svelte +406 -0
- package/src/player/AssessmentLayout.svelte +68 -0
- package/src/player/README.md +154 -0
- package/src/reference-layout/README.md +135 -0
- package/src/reference-layout/ReferenceLayout.svelte +209 -0
- package/src/reference-layout/components/AssessmentContent.svelte +259 -0
- package/src/reference-layout/components/AssessmentFooter.svelte +89 -0
- package/src/reference-layout/components/AssessmentHeader.svelte +250 -0
- package/src/reference-layout/components/AssessmentNavigation.svelte +134 -0
- package/src/reference-layout/components/AssessmentToolsBar.svelte +176 -0
- package/src/reference-layout/components/ItemPanel.svelte +200 -0
- package/src/reference-layout/components/NotesPanel.svelte +179 -0
- package/src/reference-layout/components/PassagePanel.svelte +76 -0
- package/src/tools/README.md +616 -0
- package/src/tools/calculators/README.md +395 -0
package/src/README.md
ADDED
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
# PIE Assessment Toolkit
|
|
2
|
+
|
|
3
|
+
**Independent, composable services** for coordinating tools, accommodations, and item players in assessment applications.
|
|
4
|
+
|
|
5
|
+
This is not an opinionated framework or monolithic "player" - it's a toolkit that solves specific problems.
|
|
6
|
+
|
|
7
|
+
## What Does It Solve?
|
|
8
|
+
|
|
9
|
+
- **Tool coordination**: z-index management, visibility state
|
|
10
|
+
- **Accommodation support**: IEP/504 tool configuration logic
|
|
11
|
+
- **TTS + annotation coordination**: Prevent conflicts between highlights
|
|
12
|
+
- **Event communication**: Standard contracts between components
|
|
13
|
+
- **Accessibility theming**: Consistent high-contrast, font sizing
|
|
14
|
+
|
|
15
|
+
## Architecture Overview
|
|
16
|
+
|
|
17
|
+
See [Tools & Accommodations Architecture](../../../docs/tools-and-accomodations/architecture.md) for complete design documentation.
|
|
18
|
+
|
|
19
|
+
### Primary Interface: Section Player
|
|
20
|
+
|
|
21
|
+
The **PIE Section Player** (`@pie-players/pie-section-player`) is the primary interface for integrating toolkit services. Pass services as JavaScript properties, and the player handles SSML extraction, catalog lifecycle, and TTS tool rendering automatically.
|
|
22
|
+
|
|
23
|
+
### Core Principles
|
|
24
|
+
|
|
25
|
+
1. **Composable Services**: Import only what you need
|
|
26
|
+
2. **No Framework Lock-in**: Works with any JavaScript framework
|
|
27
|
+
3. **Product Control**: Products control navigation, persistence, layout, backend
|
|
28
|
+
4. **Standard Contracts**: Well-defined event types for component communication
|
|
29
|
+
5. **Section Player Integration**: Seamless integration with the section player for automatic service coordination
|
|
30
|
+
|
|
31
|
+
## Implementation Status
|
|
32
|
+
|
|
33
|
+
### ✅ Core Infrastructure
|
|
34
|
+
|
|
35
|
+
- **TypedEventBus**: Type-safe event bus built on native EventTarget
|
|
36
|
+
- **Event Types**: Complete event definitions (player, tools, navigation, state, interaction)
|
|
37
|
+
|
|
38
|
+
### ✅ Toolkit Services
|
|
39
|
+
|
|
40
|
+
- **ToolCoordinator**: Manages z-index layering and visibility for floating tools
|
|
41
|
+
- **HighlightCoordinator**: Separate highlight layers for TTS (temporary) and annotations (persistent)
|
|
42
|
+
- **TTSService**: Singleton service providing text-to-speech across multiple entry points with QTI 3.0 catalog support
|
|
43
|
+
- **AccessibilityCatalogResolver**: QTI 3.0 accessibility catalog management for SSML, sign language, braille, etc.
|
|
44
|
+
- **SSMLExtractor**: Automatic extraction of embedded `<speak>` tags from content into accessibility catalogs
|
|
45
|
+
- **ThemeProvider**: Consistent accessibility theming across items and tools
|
|
46
|
+
- **ToolConfigResolver**: 3-tier hierarchy for IEP/504 tool configuration
|
|
47
|
+
|
|
48
|
+
### ✅ Section Player Integration
|
|
49
|
+
|
|
50
|
+
The toolkit integrates seamlessly with the **PIE Section Player**:
|
|
51
|
+
|
|
52
|
+
- **Primary Interface**: Section player is the main integration point
|
|
53
|
+
- **Automatic SSML Extraction**: Extracts embedded `<speak>` tags from passages and items
|
|
54
|
+
- **Catalog Lifecycle**: Manages item-level catalogs automatically (add on load, clear on navigation)
|
|
55
|
+
- **TTS Tool Rendering**: Shows inline TTS buttons in passage/item headers
|
|
56
|
+
- **Service Coordination**: All toolkit services work together automatically
|
|
57
|
+
|
|
58
|
+
**Integration Pattern**:
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
import {
|
|
62
|
+
TTSService,
|
|
63
|
+
AccessibilityCatalogResolver,
|
|
64
|
+
ToolCoordinator,
|
|
65
|
+
HighlightCoordinator
|
|
66
|
+
} from '@pie-players/pie-assessment-toolkit';
|
|
67
|
+
|
|
68
|
+
// Initialize services
|
|
69
|
+
const ttsService = new TTSService();
|
|
70
|
+
const catalogResolver = new AccessibilityCatalogResolver([], 'en-US');
|
|
71
|
+
// ... initialize other services
|
|
72
|
+
|
|
73
|
+
// Pass to section player
|
|
74
|
+
sectionPlayer.ttsService = ttsService;
|
|
75
|
+
sectionPlayer.catalogResolver = catalogResolver;
|
|
76
|
+
sectionPlayer.section = section;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### ✅ Reference Implementation (Future)
|
|
80
|
+
|
|
81
|
+
An optional **AssessmentPlayer** reference implementation may be provided for multi-section assessments. It would:
|
|
82
|
+
|
|
83
|
+
- Manage navigation across sections
|
|
84
|
+
- Coordinate section player instances
|
|
85
|
+
- Provide assessment-level state management
|
|
86
|
+
- But delegate to section players for rendering
|
|
87
|
+
|
|
88
|
+
## Project Structure
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
assessment-toolkit/
|
|
92
|
+
├── core/
|
|
93
|
+
│ └── TypedEventBus.ts # Event system
|
|
94
|
+
├── services/
|
|
95
|
+
│ ├── ToolCoordinator.ts # Z-index, visibility
|
|
96
|
+
│ ├── HighlightCoordinator.ts # TTS + annotation highlights
|
|
97
|
+
│ ├── TTSService.ts # Text-to-speech with catalog support
|
|
98
|
+
│ ├── AccessibilityCatalogResolver.ts # QTI 3.0 catalog management
|
|
99
|
+
│ ├── SSMLExtractor.ts # Automatic SSML extraction
|
|
100
|
+
│ ├── ThemeProvider.ts # Accessibility theming
|
|
101
|
+
│ └── ToolConfigResolver.ts # IEP/504 configuration
|
|
102
|
+
├── types/
|
|
103
|
+
│ └── events.ts # Event definitions
|
|
104
|
+
├── player/
|
|
105
|
+
│ ├── README.md # Optional reference patterns
|
|
106
|
+
│ └── navigation-types.ts # Navigation abstractions
|
|
107
|
+
└── index.ts # Public exports
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Usage Examples
|
|
111
|
+
|
|
112
|
+
### Minimal Integration (Just Events + Tools)
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import {
|
|
116
|
+
TypedEventBus,
|
|
117
|
+
ToolCoordinator,
|
|
118
|
+
type AssessmentToolkitEvents
|
|
119
|
+
} from '$lib/assessment-toolkit';
|
|
120
|
+
|
|
121
|
+
const eventBus = new TypedEventBus<AssessmentToolkitEvents>();
|
|
122
|
+
const toolCoordinator = new ToolCoordinator();
|
|
123
|
+
|
|
124
|
+
// Register tools
|
|
125
|
+
toolCoordinator.registerTool('calculator', 'Calculator', calcElement);
|
|
126
|
+
|
|
127
|
+
// Wire up events
|
|
128
|
+
eventBus.on('player:session-changed', async (e) => {
|
|
129
|
+
await myBackend.save(e.detail.session);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
eventBus.on('tool:activated', (e) => {
|
|
133
|
+
toolCoordinator.bringToFront(e.target);
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Advanced Integration (All Services)
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import {
|
|
141
|
+
TypedEventBus,
|
|
142
|
+
ToolCoordinator,
|
|
143
|
+
HighlightCoordinator,
|
|
144
|
+
TTSService,
|
|
145
|
+
ThemeProvider,
|
|
146
|
+
ToolConfigResolver,
|
|
147
|
+
type AssessmentToolkitEvents
|
|
148
|
+
} from '$lib/assessment-toolkit';
|
|
149
|
+
|
|
150
|
+
// Initialize services
|
|
151
|
+
const eventBus = new TypedEventBus<AssessmentToolkitEvents>();
|
|
152
|
+
const toolCoordinator = new ToolCoordinator();
|
|
153
|
+
const highlightCoordinator = new HighlightCoordinator();
|
|
154
|
+
const ttsService = TTSService.getInstance();
|
|
155
|
+
const themeProvider = new ThemeProvider();
|
|
156
|
+
const toolResolver = new ToolConfigResolver();
|
|
157
|
+
|
|
158
|
+
// Initialize TTS
|
|
159
|
+
await ttsService.initialize('browser');
|
|
160
|
+
ttsService.setHighlightCoordinator(highlightCoordinator);
|
|
161
|
+
|
|
162
|
+
// Apply accessibility theme
|
|
163
|
+
themeProvider.applyTheme({
|
|
164
|
+
highContrast: true,
|
|
165
|
+
fontSize: 'large'
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Resolve tool configuration
|
|
169
|
+
const toolConfig = toolResolver.resolveTool(
|
|
170
|
+
'calculator',
|
|
171
|
+
itemConfig.tools, // Item level
|
|
172
|
+
rosterConfig.allowances, // Roster level
|
|
173
|
+
studentProfile.accommodations // Student level
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// Wire up events
|
|
177
|
+
eventBus.on('player:session-changed', async (e) => {
|
|
178
|
+
await myBackend.saveSession(e.detail);
|
|
179
|
+
myAnalytics.track('response', e.detail);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
eventBus.on('tool:activated', (e) => {
|
|
183
|
+
toolCoordinator.bringToFront(e.target);
|
|
184
|
+
myAnalytics.track('tool-usage', e.detail);
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Tool Configuration Example
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import {
|
|
192
|
+
ToolConfigResolver,
|
|
193
|
+
type ItemToolConfig,
|
|
194
|
+
type RosterToolConfig,
|
|
195
|
+
type StudentAccommodations
|
|
196
|
+
} from '$lib/assessment-toolkit';
|
|
197
|
+
|
|
198
|
+
const resolver = new ToolConfigResolver();
|
|
199
|
+
|
|
200
|
+
// Scenario: Student with IEP requiring TTS and calculator
|
|
201
|
+
const studentProfile: StudentAccommodations = {
|
|
202
|
+
accommodations: ['tts', 'calculator', 'extended-time']
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// Test blocks dictionary but allows calculator
|
|
206
|
+
const rosterConfig: RosterToolConfig = {
|
|
207
|
+
calculator: "1",
|
|
208
|
+
dictionary: "0"
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// Current item requires scientific calculator
|
|
212
|
+
const itemConfig: ItemToolConfig = {
|
|
213
|
+
calculator: {
|
|
214
|
+
type: 'scientific',
|
|
215
|
+
required: true
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// Resolve all tools
|
|
220
|
+
const resolved = resolver.resolveAll({
|
|
221
|
+
itemConfig,
|
|
222
|
+
rosterConfig,
|
|
223
|
+
studentProfile
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Result:
|
|
227
|
+
// - calculator: enabled (scientific, required by item)
|
|
228
|
+
// - tts: enabled (student accommodation)
|
|
229
|
+
// - dictionary: disabled (blocked by roster)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Integration Patterns
|
|
233
|
+
|
|
234
|
+
### Pattern 1: Quiz Engine (Advanced - DIY Wiring)
|
|
235
|
+
|
|
236
|
+
Quiz Engine imports services and wires their own way.
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
class QuizEngineAssessmentPlayer {
|
|
240
|
+
private eventBus = new TypedEventBus<AssessmentToolkitEvents>();
|
|
241
|
+
private toolCoordinator = new ToolCoordinator();
|
|
242
|
+
|
|
243
|
+
constructor() {
|
|
244
|
+
this.setupEventHandlers();
|
|
245
|
+
this.setupQENavigation();
|
|
246
|
+
this.setupQEPersistence();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private setupEventHandlers() {
|
|
250
|
+
this.eventBus.on('player:session-changed', async (e) => {
|
|
251
|
+
await this.qeBackend.saveSession(e.detail);
|
|
252
|
+
this.qeAnalytics.track('response', e.detail);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Pattern 2: Reference Implementation (Pre-fab)
|
|
259
|
+
|
|
260
|
+
Use the reference implementation with custom navigation.
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// Coming soon - reference implementation
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## API Documentation
|
|
267
|
+
|
|
268
|
+
### TypedEventBus
|
|
269
|
+
|
|
270
|
+
Type-safe event bus built on native EventTarget.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
const eventBus = new TypedEventBus<AssessmentToolkitEvents>();
|
|
274
|
+
|
|
275
|
+
// Emit events
|
|
276
|
+
eventBus.emit('player:session-changed', { /* ... */ });
|
|
277
|
+
|
|
278
|
+
// Listen to events
|
|
279
|
+
eventBus.on('player:session-changed', (e) => {
|
|
280
|
+
console.log('Session changed:', e.detail);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// One-time listeners
|
|
284
|
+
eventBus.once('player:load-complete', (e) => { /* ... */ });
|
|
285
|
+
|
|
286
|
+
// Remove listeners
|
|
287
|
+
eventBus.off('player:session-changed', handler);
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### ToolCoordinator
|
|
291
|
+
|
|
292
|
+
Manages z-index layering and visibility.
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
const toolCoordinator = new ToolCoordinator();
|
|
296
|
+
|
|
297
|
+
// Register tools
|
|
298
|
+
toolCoordinator.registerTool('calculator', 'Calculator', element);
|
|
299
|
+
|
|
300
|
+
// Manage visibility
|
|
301
|
+
toolCoordinator.showTool('calculator');
|
|
302
|
+
toolCoordinator.hideTool('calculator');
|
|
303
|
+
toolCoordinator.toggleTool('calculator');
|
|
304
|
+
|
|
305
|
+
// Bring to front
|
|
306
|
+
toolCoordinator.bringToFront(element);
|
|
307
|
+
|
|
308
|
+
// Check state
|
|
309
|
+
const isVisible = toolCoordinator.isToolVisible('calculator');
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### HighlightCoordinator
|
|
313
|
+
|
|
314
|
+
Manages TTS and annotation highlights.
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
const highlightCoordinator = new HighlightCoordinator();
|
|
318
|
+
|
|
319
|
+
// TTS highlights (temporary)
|
|
320
|
+
highlightCoordinator.highlightTTSWord(textNode, start, end);
|
|
321
|
+
highlightCoordinator.highlightTTSSentence([range1, range2]);
|
|
322
|
+
highlightCoordinator.clearTTS();
|
|
323
|
+
|
|
324
|
+
// Annotation highlights (persistent)
|
|
325
|
+
const id = highlightCoordinator.addAnnotation(range, 'yellow');
|
|
326
|
+
highlightCoordinator.removeAnnotation(id);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### TTSService
|
|
330
|
+
|
|
331
|
+
Singleton text-to-speech service with QTI 3.0 accessibility catalog support.
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import {
|
|
335
|
+
TTSService,
|
|
336
|
+
BrowserTTSProvider,
|
|
337
|
+
AccessibilityCatalogResolver
|
|
338
|
+
} from '@pie-players/pie-assessment-toolkit';
|
|
339
|
+
|
|
340
|
+
const ttsService = new TTSService();
|
|
341
|
+
|
|
342
|
+
// Initialize with provider
|
|
343
|
+
await ttsService.initialize(new BrowserTTSProvider());
|
|
344
|
+
|
|
345
|
+
// Set up catalog resolver for SSML support
|
|
346
|
+
const catalogResolver = new AccessibilityCatalogResolver(
|
|
347
|
+
assessment.accessibilityCatalogs,
|
|
348
|
+
'en-US'
|
|
349
|
+
);
|
|
350
|
+
ttsService.setCatalogResolver(catalogResolver);
|
|
351
|
+
|
|
352
|
+
// Playback with catalog support
|
|
353
|
+
await ttsService.speak('Read this text', {
|
|
354
|
+
catalogId: 'prompt-001', // Uses pre-authored SSML if available
|
|
355
|
+
language: 'en-US'
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Plain text fallback (no catalog)
|
|
359
|
+
await ttsService.speak('Read this text');
|
|
360
|
+
|
|
361
|
+
// Controls
|
|
362
|
+
ttsService.pause();
|
|
363
|
+
ttsService.resume();
|
|
364
|
+
ttsService.stop();
|
|
365
|
+
|
|
366
|
+
// State
|
|
367
|
+
const isPlaying = ttsService.isPlaying();
|
|
368
|
+
|
|
369
|
+
// Dynamic settings updates (for preview/live changes)
|
|
370
|
+
await ttsService.updateSettings({
|
|
371
|
+
rate: 1.5,
|
|
372
|
+
pitch: 1.2,
|
|
373
|
+
voice: 'Matthew'
|
|
374
|
+
});
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Unified Settings UI**: A pre-built settings component is available in `section-demos/src/lib/components/AssessmentToolkitSettings.svelte` that provides a tabbed interface for configuring TTS, highlighting, and other toolkit features. See the component's README for integration details.
|
|
378
|
+
|
|
379
|
+
### AccessibilityCatalogResolver
|
|
380
|
+
|
|
381
|
+
Manages QTI 3.0 accessibility catalogs (SSML, sign language, braille, simplified language, etc.).
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
import { AccessibilityCatalogResolver } from '@pie-players/pie-assessment-toolkit';
|
|
385
|
+
|
|
386
|
+
// Initialize with assessment-level catalogs
|
|
387
|
+
const resolver = new AccessibilityCatalogResolver(
|
|
388
|
+
assessment.accessibilityCatalogs,
|
|
389
|
+
'en-US' // default language
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
// Add item-level catalogs (higher priority)
|
|
393
|
+
resolver.addItemCatalogs(item.accessibilityCatalogs);
|
|
394
|
+
|
|
395
|
+
// Get alternative representation
|
|
396
|
+
const alternative = resolver.getAlternative('prompt-001', {
|
|
397
|
+
type: 'spoken',
|
|
398
|
+
language: 'en-US',
|
|
399
|
+
useFallback: true
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
// Clear item catalogs when navigating away
|
|
403
|
+
resolver.clearItemCatalogs();
|
|
404
|
+
|
|
405
|
+
// Get all alternatives for an identifier
|
|
406
|
+
const alternatives = resolver.getAllAlternatives('prompt-001');
|
|
407
|
+
|
|
408
|
+
// Check availability
|
|
409
|
+
const hasSpoken = resolver.hasCatalog('prompt-001');
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### SSMLExtractor
|
|
413
|
+
|
|
414
|
+
Automatically extracts embedded `<speak>` tags from PIE content and generates QTI 3.0 accessibility catalogs.
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
import { SSMLExtractor } from '@pie-players/pie-assessment-toolkit';
|
|
418
|
+
|
|
419
|
+
const extractor = new SSMLExtractor();
|
|
420
|
+
|
|
421
|
+
// Extract from item config
|
|
422
|
+
const result = extractor.extractFromItemConfig(item.config);
|
|
423
|
+
|
|
424
|
+
// Result contains:
|
|
425
|
+
// - cleanedConfig: Config with SSML removed, catalog IDs added
|
|
426
|
+
// - catalogs: Generated accessibility catalogs
|
|
427
|
+
|
|
428
|
+
// Update item with cleaned config
|
|
429
|
+
item.config = result.cleanedConfig;
|
|
430
|
+
item.config.extractedCatalogs = result.catalogs;
|
|
431
|
+
|
|
432
|
+
// Register with catalog resolver
|
|
433
|
+
catalogResolver.addItemCatalogs(result.catalogs);
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Example Input:**
|
|
437
|
+
```typescript
|
|
438
|
+
{
|
|
439
|
+
prompt: `<div>
|
|
440
|
+
<speak>Solve <prosody rate="slow">x squared</prosody>.</speak>
|
|
441
|
+
<p>Solve x² = 0</p>
|
|
442
|
+
</div>`
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
**Example Output:**
|
|
447
|
+
```typescript
|
|
448
|
+
{
|
|
449
|
+
// Cleaned config
|
|
450
|
+
prompt: `<div data-catalog-id="auto-prompt-q1-0">
|
|
451
|
+
<p>Solve x² = 0</p>
|
|
452
|
+
</div>`,
|
|
453
|
+
|
|
454
|
+
// Generated catalogs
|
|
455
|
+
extractedCatalogs: [{
|
|
456
|
+
identifier: 'auto-prompt-q1-0',
|
|
457
|
+
cards: [{
|
|
458
|
+
catalog: 'spoken',
|
|
459
|
+
language: 'en-US',
|
|
460
|
+
content: '<speak>Solve <prosody rate="slow">x squared</prosody>.</speak>'
|
|
461
|
+
}]
|
|
462
|
+
}]
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
**Integration:** Used automatically by section player's ItemRenderer and PassageRenderer components.
|
|
467
|
+
|
|
468
|
+
### ThemeProvider
|
|
469
|
+
|
|
470
|
+
Accessibility theming.
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
const themeProvider = new ThemeProvider();
|
|
474
|
+
|
|
475
|
+
// Apply theme
|
|
476
|
+
themeProvider.applyTheme({
|
|
477
|
+
highContrast: true,
|
|
478
|
+
fontSize: 'large',
|
|
479
|
+
backgroundColor: '#000',
|
|
480
|
+
foregroundColor: '#fff'
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
// Quick settings
|
|
484
|
+
themeProvider.setHighContrast(true);
|
|
485
|
+
themeProvider.setFontSize('xlarge');
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### ToolConfigResolver
|
|
489
|
+
|
|
490
|
+
IEP/504 tool configuration.
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
const resolver = new ToolConfigResolver();
|
|
494
|
+
|
|
495
|
+
// Resolve single tool
|
|
496
|
+
const config = resolver.resolveTool('calculator', itemConfig, rosterConfig, studentProfile);
|
|
497
|
+
|
|
498
|
+
// Resolve all tools
|
|
499
|
+
const allTools = resolver.resolveAll({ itemConfig, rosterConfig, studentProfile });
|
|
500
|
+
|
|
501
|
+
// Helpers
|
|
502
|
+
const enabled = resolver.isToolEnabled('calculator', input);
|
|
503
|
+
const required = resolver.isToolRequired('calculator', input);
|
|
504
|
+
const enabledTools = resolver.getEnabledTools(input);
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## QTI 3.0 Support
|
|
508
|
+
|
|
509
|
+
The toolkit natively supports QTI 3.0 features for standards-compliant assessment delivery.
|
|
510
|
+
|
|
511
|
+
### Personal Needs Profile (PNP)
|
|
512
|
+
|
|
513
|
+
Student accommodations and IEP/504 support with automatic tool resolution:
|
|
514
|
+
|
|
515
|
+
```typescript
|
|
516
|
+
import { AssessmentPlayer, PNPToolResolver } from '@pie-players/pie-assessment-toolkit';
|
|
517
|
+
|
|
518
|
+
// QTI 3.0 assessment with PNP
|
|
519
|
+
const assessment = {
|
|
520
|
+
personalNeedsProfile: {
|
|
521
|
+
supports: ['textToSpeech', 'calculator'],
|
|
522
|
+
activateAtInit: ['textToSpeech']
|
|
523
|
+
},
|
|
524
|
+
settings: {
|
|
525
|
+
districtPolicy: {
|
|
526
|
+
blockedTools: [], // District blocks (absolute veto)
|
|
527
|
+
requiredTools: ['ruler'] // District requires
|
|
528
|
+
},
|
|
529
|
+
toolConfigs: {
|
|
530
|
+
calculator: {
|
|
531
|
+
type: 'scientific',
|
|
532
|
+
provider: 'desmos'
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// Simple initialization - tools automatically resolved
|
|
539
|
+
const player = new AssessmentPlayer({ assessment, loadItem });
|
|
540
|
+
|
|
541
|
+
// Or use PNPToolResolver directly
|
|
542
|
+
const resolver = new PNPToolResolver();
|
|
543
|
+
const tools = resolver.resolveTools(assessment, currentItemRef);
|
|
544
|
+
// Returns: [{ id: 'pie-tool-text-to-speech', enabled: true, ... }, ...]
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
**Standard PNP Support IDs:**
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
'textToSpeech' → 'pie-tool-text-to-speech'
|
|
551
|
+
'calculator' → 'pie-tool-calculator'
|
|
552
|
+
'ruler' → 'pie-tool-ruler'
|
|
553
|
+
'protractor' → 'pie-tool-protractor'
|
|
554
|
+
'highlighter' → 'pie-tool-annotation-toolbar'
|
|
555
|
+
'lineReader' → 'pie-tool-line-reader'
|
|
556
|
+
'magnifier' → 'pie-tool-magnifier'
|
|
557
|
+
'colorContrast' → 'pie-theme-contrast'
|
|
558
|
+
'answerMasking' → 'pie-tool-answer-eliminator'
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Context Declarations
|
|
562
|
+
|
|
563
|
+
Global variables shared across assessment items:
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
import { AssessmentPlayer, ContextVariableStore } from '@pie-players/pie-assessment-toolkit';
|
|
567
|
+
|
|
568
|
+
// Assessment with context declarations
|
|
569
|
+
const assessment = {
|
|
570
|
+
contextDeclarations: [
|
|
571
|
+
{
|
|
572
|
+
identifier: 'RANDOM_SEED',
|
|
573
|
+
baseType: 'integer',
|
|
574
|
+
cardinality: 'single',
|
|
575
|
+
defaultValue: 42
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
identifier: 'DIFFICULTY_LEVEL',
|
|
579
|
+
baseType: 'string',
|
|
580
|
+
cardinality: 'single',
|
|
581
|
+
defaultValue: 'medium'
|
|
582
|
+
}
|
|
583
|
+
]
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
// Use with AssessmentPlayer
|
|
587
|
+
const player = new AssessmentPlayer({ assessment, loadItem });
|
|
588
|
+
|
|
589
|
+
const seed = player.getContextVariable('RANDOM_SEED');
|
|
590
|
+
player.setContextVariable('DIFFICULTY_LEVEL', 'hard');
|
|
591
|
+
|
|
592
|
+
// Pass to PIE elements
|
|
593
|
+
const context = player.getContextVariables();
|
|
594
|
+
await renderItem(item, session, context);
|
|
595
|
+
|
|
596
|
+
// Or use ContextVariableStore directly
|
|
597
|
+
const store = new ContextVariableStore(assessment.contextDeclarations);
|
|
598
|
+
store.set('RANDOM_SEED', 12345);
|
|
599
|
+
const context = store.toObject();
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
**Use Cases:**
|
|
603
|
+
|
|
604
|
+
- Cross-item randomization (shared random seeds)
|
|
605
|
+
- Adaptive testing (difficulty adjustment based on performance)
|
|
606
|
+
- Shared configuration (currency symbols, measurement units)
|
|
607
|
+
- Item dependencies (later items react to earlier responses)
|
|
608
|
+
|
|
609
|
+
### QTI 3.0 Precedence Hierarchy
|
|
610
|
+
|
|
611
|
+
Tool resolution follows this precedence (highest to lowest):
|
|
612
|
+
|
|
613
|
+
```
|
|
614
|
+
1. District Block (absolute veto)
|
|
615
|
+
2. Test Administration Override
|
|
616
|
+
3. Item Restriction (per-item block)
|
|
617
|
+
4. Item Requirement (forces enable)
|
|
618
|
+
5. District Requirement
|
|
619
|
+
6. PNP Supports (student accommodations)
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
## Related Documentation
|
|
623
|
+
|
|
624
|
+
- [Architecture Overview](../../../docs/ARCHITECTURE.md) - Complete system architecture
|
|
625
|
+
- [Assessment Toolkit Architecture](../../../docs/tools-and-accomodations/assessment-player-architecture.md) - Toolkit design
|
|
626
|
+
- [Tools Architecture](../../../docs/tools-and-accomodations/tools-high-level-architecture.md) - Tool coordination
|