@vue-skuilder/db 0.1.1
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 +26 -0
- package/dist/core/index.d.mts +3 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +7906 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +7886 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/index-QMtzQI65.d.mts +734 -0
- package/dist/index-QMtzQI65.d.ts +734 -0
- package/dist/index.d.mts +133 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +8726 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8699 -0
- package/dist/index.mjs.map +1 -0
- package/eslint.config.mjs +20 -0
- package/package.json +47 -0
- package/src/core/bulkImport/cardProcessor.ts +165 -0
- package/src/core/bulkImport/index.ts +2 -0
- package/src/core/bulkImport/types.ts +27 -0
- package/src/core/index.ts +9 -0
- package/src/core/interfaces/adminDB.ts +27 -0
- package/src/core/interfaces/classroomDB.ts +75 -0
- package/src/core/interfaces/contentSource.ts +64 -0
- package/src/core/interfaces/courseDB.ts +139 -0
- package/src/core/interfaces/dataLayerProvider.ts +46 -0
- package/src/core/interfaces/index.ts +7 -0
- package/src/core/interfaces/navigationStrategyManager.ts +46 -0
- package/src/core/interfaces/userDB.ts +183 -0
- package/src/core/navigators/elo.ts +76 -0
- package/src/core/navigators/index.ts +57 -0
- package/src/core/readme.md +9 -0
- package/src/core/types/contentNavigationStrategy.ts +21 -0
- package/src/core/types/db.ts +7 -0
- package/src/core/types/types-legacy.ts +155 -0
- package/src/core/types/user.ts +70 -0
- package/src/core/util/index.ts +42 -0
- package/src/factory.ts +86 -0
- package/src/impl/pouch/PouchDataLayerProvider.ts +102 -0
- package/src/impl/pouch/adminDB.ts +91 -0
- package/src/impl/pouch/auth.ts +48 -0
- package/src/impl/pouch/classroomDB.ts +306 -0
- package/src/impl/pouch/clientCache.ts +19 -0
- package/src/impl/pouch/courseAPI.ts +245 -0
- package/src/impl/pouch/courseDB.ts +772 -0
- package/src/impl/pouch/courseLookupDB.ts +135 -0
- package/src/impl/pouch/index.ts +235 -0
- package/src/impl/pouch/pouchdb-setup.ts +16 -0
- package/src/impl/pouch/types.ts +7 -0
- package/src/impl/pouch/updateQueue.ts +89 -0
- package/src/impl/pouch/user-course-relDB.ts +73 -0
- package/src/impl/pouch/userDB.ts +1097 -0
- package/src/index.ts +8 -0
- package/src/study/SessionController.ts +401 -0
- package/src/study/SpacedRepetition.ts +128 -0
- package/src/study/getCardDataShape.ts +34 -0
- package/src/study/index.ts +2 -0
- package/src/util/Loggable.ts +11 -0
- package/src/util/index.ts +1 -0
- package/src/util/logger.ts +55 -0
- package/tsconfig.json +12 -0
- package/tsup.config.ts +17 -0
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
import { CourseConfig, ClassroomConfig, CourseElo, Evaluation, Answer, Status, SkuilderCourseData as SkuilderCourseData$1, DataShape, ParsedCard } from '@vue-skuilder/common';
|
|
2
|
+
import { Moment } from 'moment';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Admin functionality
|
|
6
|
+
*/
|
|
7
|
+
interface AdminDBInterface {
|
|
8
|
+
/**
|
|
9
|
+
* Get all users
|
|
10
|
+
*/
|
|
11
|
+
getUsers(): Promise<PouchDB.Core.Document<{}>[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Get all courses
|
|
14
|
+
*/
|
|
15
|
+
getCourses(): Promise<CourseConfig[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Remove a course
|
|
18
|
+
*/
|
|
19
|
+
removeCourse(id: string): Promise<PouchDB.Core.Response>;
|
|
20
|
+
/**
|
|
21
|
+
* Get all classrooms
|
|
22
|
+
*/
|
|
23
|
+
getClassrooms(): Promise<(ClassroomConfig & {
|
|
24
|
+
_id: string;
|
|
25
|
+
})[]>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface UserConfig {
|
|
29
|
+
darkMode: boolean;
|
|
30
|
+
likesConfetti: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface ActivityRecord {
|
|
33
|
+
timeStamp: number | string;
|
|
34
|
+
[key: string]: any;
|
|
35
|
+
}
|
|
36
|
+
interface CourseRegistration {
|
|
37
|
+
status?: 'active' | 'dropped' | 'maintenance-mode' | 'preview';
|
|
38
|
+
courseID: string;
|
|
39
|
+
admin: boolean;
|
|
40
|
+
moderator: boolean;
|
|
41
|
+
user: boolean;
|
|
42
|
+
settings?: {
|
|
43
|
+
[setting: string]: string | number | boolean;
|
|
44
|
+
};
|
|
45
|
+
elo: number | CourseElo;
|
|
46
|
+
}
|
|
47
|
+
interface StudyWeights {
|
|
48
|
+
[courseID: string]: number;
|
|
49
|
+
}
|
|
50
|
+
interface CourseRegistrationDoc {
|
|
51
|
+
courses: CourseRegistration[];
|
|
52
|
+
studyWeight: StudyWeights;
|
|
53
|
+
}
|
|
54
|
+
interface ScheduledCard {
|
|
55
|
+
_id: PouchDB.Core.DocumentId;
|
|
56
|
+
/**
|
|
57
|
+
* The docID of the card to be reviewed
|
|
58
|
+
*/
|
|
59
|
+
cardId: PouchDB.Core.DocumentId;
|
|
60
|
+
/**
|
|
61
|
+
* The ID of the course
|
|
62
|
+
*/
|
|
63
|
+
courseId: string;
|
|
64
|
+
/**
|
|
65
|
+
* The time at which the card becomes eligible for review.
|
|
66
|
+
*
|
|
67
|
+
* (Should probably be UTC adjusted so that performance is
|
|
68
|
+
* not wonky across time zones)
|
|
69
|
+
*/
|
|
70
|
+
reviewTime: Moment;
|
|
71
|
+
/**
|
|
72
|
+
* The time at which this scheduled event was created.
|
|
73
|
+
*/
|
|
74
|
+
scheduledAt: Moment;
|
|
75
|
+
/**
|
|
76
|
+
* Classifying whether this card is scheduled on behalf of a
|
|
77
|
+
* user-registered course or by as assigned content from a
|
|
78
|
+
* user-registered classroom
|
|
79
|
+
*/
|
|
80
|
+
scheduledFor: 'course' | 'classroom';
|
|
81
|
+
/**
|
|
82
|
+
* The ID of the course or classroom that requested this card
|
|
83
|
+
*/
|
|
84
|
+
schedulingAgentId: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
type StudySessionFailedItem = StudySessionFailedNewItem | StudySessionFailedReviewItem;
|
|
88
|
+
interface StudySessionFailedNewItem extends StudySessionItem {
|
|
89
|
+
status: 'failed-new';
|
|
90
|
+
}
|
|
91
|
+
interface StudySessionFailedReviewItem extends StudySessionReviewItem {
|
|
92
|
+
status: 'failed-review';
|
|
93
|
+
}
|
|
94
|
+
interface StudySessionNewItem extends StudySessionItem {
|
|
95
|
+
status: 'new';
|
|
96
|
+
}
|
|
97
|
+
interface StudySessionReviewItem extends StudySessionItem {
|
|
98
|
+
reviewID: string;
|
|
99
|
+
status: 'review' | 'failed-review';
|
|
100
|
+
}
|
|
101
|
+
declare function isReview(item: StudySessionItem): item is StudySessionReviewItem;
|
|
102
|
+
interface StudySessionItem {
|
|
103
|
+
status: 'new' | 'review' | 'failed-new' | 'failed-review';
|
|
104
|
+
qualifiedID: `${string}-${string}` | `${string}-${string}-${number}`;
|
|
105
|
+
cardID: string;
|
|
106
|
+
contentSourceType: 'course' | 'classroom';
|
|
107
|
+
contentSourceID: string;
|
|
108
|
+
courseID: string;
|
|
109
|
+
}
|
|
110
|
+
interface ContentSourceID {
|
|
111
|
+
type: 'course' | 'classroom';
|
|
112
|
+
id: string;
|
|
113
|
+
}
|
|
114
|
+
interface StudyContentSource {
|
|
115
|
+
getPendingReviews(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
|
|
116
|
+
getNewCards(n?: number): Promise<StudySessionNewItem[]>;
|
|
117
|
+
}
|
|
118
|
+
declare function getStudySource(source: ContentSourceID, user: UserDBInterface): Promise<StudyContentSource>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Classroom management
|
|
122
|
+
*/
|
|
123
|
+
interface ClassroomDBInterface {
|
|
124
|
+
/**
|
|
125
|
+
* Get classroom config
|
|
126
|
+
*/
|
|
127
|
+
getConfig(): ClassroomConfig;
|
|
128
|
+
/**
|
|
129
|
+
* Get assigned content
|
|
130
|
+
*/
|
|
131
|
+
getAssignedContent(): Promise<AssignedContent[]>;
|
|
132
|
+
}
|
|
133
|
+
interface TeacherClassroomDBInterface extends ClassroomDBInterface {
|
|
134
|
+
/**
|
|
135
|
+
* For teacher interfaces: assign content
|
|
136
|
+
*/
|
|
137
|
+
assignContent?(content: AssignedContent): Promise<boolean>;
|
|
138
|
+
/**
|
|
139
|
+
* For teacher interfaces: remove content
|
|
140
|
+
*/
|
|
141
|
+
removeContent?(content: AssignedContent): Promise<void>;
|
|
142
|
+
}
|
|
143
|
+
interface StudentClassroomDBInterface extends ClassroomDBInterface {
|
|
144
|
+
/**
|
|
145
|
+
* For student interfaces: get pending reviews
|
|
146
|
+
*/
|
|
147
|
+
getPendingReviews?(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
|
|
148
|
+
/**
|
|
149
|
+
* For student interfaces: get new cards
|
|
150
|
+
*/
|
|
151
|
+
getNewCards?(limit?: number): Promise<StudySessionNewItem[]>;
|
|
152
|
+
}
|
|
153
|
+
type AssignedContent = AssignedCourse | AssignedTag | AssignedCard;
|
|
154
|
+
interface AssignedTag extends ContentBase {
|
|
155
|
+
type: 'tag';
|
|
156
|
+
tagID: string;
|
|
157
|
+
}
|
|
158
|
+
interface AssignedCourse extends ContentBase {
|
|
159
|
+
type: 'course';
|
|
160
|
+
}
|
|
161
|
+
interface AssignedCard extends ContentBase {
|
|
162
|
+
type: 'card';
|
|
163
|
+
cardID: string;
|
|
164
|
+
}
|
|
165
|
+
interface ContentBase {
|
|
166
|
+
type: 'course' | 'tag' | 'card';
|
|
167
|
+
/**
|
|
168
|
+
* Username of the assigning teacher.
|
|
169
|
+
*/
|
|
170
|
+
assignedBy: string;
|
|
171
|
+
/**
|
|
172
|
+
* Date the content was assigned.
|
|
173
|
+
*/
|
|
174
|
+
assignedOn: moment.Moment;
|
|
175
|
+
/**
|
|
176
|
+
* A 'due' date for this assigned content, for scheduling content
|
|
177
|
+
* in advance. Content will not be actively pushed to students until
|
|
178
|
+
* this date.
|
|
179
|
+
*/
|
|
180
|
+
activeOn: moment.Moment;
|
|
181
|
+
courseID: string;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
declare const GuestUsername: string;
|
|
185
|
+
declare const log: (message: string) => void;
|
|
186
|
+
declare enum DocType {
|
|
187
|
+
DISPLAYABLE_DATA = "DISPLAYABLE_DATA",
|
|
188
|
+
CARD = "CARD",
|
|
189
|
+
DATASHAPE = "DATASHAPE",
|
|
190
|
+
QUESTIONTYPE = "QUESTION",
|
|
191
|
+
VIEW = "VIEW",
|
|
192
|
+
PEDAGOGY = "PEDAGOGY",
|
|
193
|
+
CARDRECORD = "CARDRECORD",
|
|
194
|
+
SCHEDULED_CARD = "SCHEDULED_CARD",
|
|
195
|
+
TAG = "TAG",
|
|
196
|
+
NAVIGATION_STRATEGY = "NAVIGATION_STRATEGY"
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Interface for all data on course content and pedagogy stored
|
|
200
|
+
* in the c/pouch database.
|
|
201
|
+
*/
|
|
202
|
+
interface SkuilderCourseData {
|
|
203
|
+
course: string;
|
|
204
|
+
docType: DocType;
|
|
205
|
+
}
|
|
206
|
+
interface Tag extends SkuilderCourseData {
|
|
207
|
+
docType: DocType.TAG;
|
|
208
|
+
name: string;
|
|
209
|
+
snippet: string;
|
|
210
|
+
wiki: string;
|
|
211
|
+
taggedCards: PouchDB.Core.DocumentId[];
|
|
212
|
+
}
|
|
213
|
+
interface TagStub {
|
|
214
|
+
name: string;
|
|
215
|
+
snippet: string;
|
|
216
|
+
count: number;
|
|
217
|
+
}
|
|
218
|
+
interface CardData extends SkuilderCourseData {
|
|
219
|
+
docType: DocType.CARD;
|
|
220
|
+
id_displayable_data: PouchDB.Core.DocumentId[];
|
|
221
|
+
id_view: PouchDB.Core.DocumentId;
|
|
222
|
+
elo: CourseElo;
|
|
223
|
+
}
|
|
224
|
+
/** A list of populated courses in the DB */
|
|
225
|
+
interface CourseListData extends PouchDB.Core.Response {
|
|
226
|
+
courses: string[];
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The data used to hydrate viewable components (questions, info, etc)
|
|
230
|
+
*/
|
|
231
|
+
interface DisplayableData extends SkuilderCourseData {
|
|
232
|
+
docType: DocType.DISPLAYABLE_DATA;
|
|
233
|
+
author?: string;
|
|
234
|
+
id_datashape: PouchDB.Core.DocumentId;
|
|
235
|
+
data: Field[];
|
|
236
|
+
_attachments?: {
|
|
237
|
+
[index: string]: PouchDB.Core.FullAttachment;
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
interface Field {
|
|
241
|
+
data: unknown;
|
|
242
|
+
name: string;
|
|
243
|
+
}
|
|
244
|
+
interface DataShapeData extends SkuilderCourseData {
|
|
245
|
+
docType: DocType.DATASHAPE;
|
|
246
|
+
_id: PouchDB.Core.DocumentId;
|
|
247
|
+
questionTypes: PouchDB.Core.DocumentId[];
|
|
248
|
+
}
|
|
249
|
+
interface QuestionData extends SkuilderCourseData {
|
|
250
|
+
docType: DocType.QUESTIONTYPE;
|
|
251
|
+
_id: PouchDB.Core.DocumentId;
|
|
252
|
+
viewList: string[];
|
|
253
|
+
dataShapeList: PouchDB.Core.DocumentId[];
|
|
254
|
+
}
|
|
255
|
+
declare const cardHistoryPrefix = "cardH";
|
|
256
|
+
interface CardHistory<T extends CardRecord> {
|
|
257
|
+
_id: PouchDB.Core.DocumentId;
|
|
258
|
+
/**
|
|
259
|
+
* The CouchDB id of the card
|
|
260
|
+
*/
|
|
261
|
+
cardID: PouchDB.Core.DocumentId;
|
|
262
|
+
/**
|
|
263
|
+
* The ID of the course
|
|
264
|
+
*/
|
|
265
|
+
courseID: string;
|
|
266
|
+
/**
|
|
267
|
+
* The to-date largest interval between successful
|
|
268
|
+
* card reviews. `0` indicates no successful reviews.
|
|
269
|
+
*/
|
|
270
|
+
bestInterval: number;
|
|
271
|
+
/**
|
|
272
|
+
* The number of times that a card has been
|
|
273
|
+
* failed in review
|
|
274
|
+
*/
|
|
275
|
+
lapses: number;
|
|
276
|
+
/**
|
|
277
|
+
* The number of consecutive successful impressions
|
|
278
|
+
* on this card
|
|
279
|
+
*/
|
|
280
|
+
streak: number;
|
|
281
|
+
records: T[];
|
|
282
|
+
}
|
|
283
|
+
interface CardRecord {
|
|
284
|
+
/**
|
|
285
|
+
* The CouchDB id of the card
|
|
286
|
+
*/
|
|
287
|
+
cardID: string;
|
|
288
|
+
/**
|
|
289
|
+
* The ID of the course
|
|
290
|
+
*/
|
|
291
|
+
courseID: string;
|
|
292
|
+
/**
|
|
293
|
+
* Number of milliseconds that the user spent before dismissing
|
|
294
|
+
* the card (ie, "I've read this" or "here is my answer")
|
|
295
|
+
*
|
|
296
|
+
* //TODO: this (sometimes?) wants to be replaced with a rich
|
|
297
|
+
* recording of user activity in working the question
|
|
298
|
+
*/
|
|
299
|
+
timeSpent: number;
|
|
300
|
+
/**
|
|
301
|
+
* The date-time that the card was rendered. timeStamp + timeSpent will give the
|
|
302
|
+
* time of user submission.
|
|
303
|
+
*/
|
|
304
|
+
timeStamp: Moment;
|
|
305
|
+
}
|
|
306
|
+
interface QuestionRecord extends CardRecord, Evaluation {
|
|
307
|
+
userAnswer: Answer;
|
|
308
|
+
/**
|
|
309
|
+
* The number of incorrect user submissions prededing this submisstion.
|
|
310
|
+
*
|
|
311
|
+
* eg, if a user is asked 7*6=__, submitting 46, 48, 42 will result in three
|
|
312
|
+
* records being created having 0, 1, and 2 as their recorded 'priorAttempts' values
|
|
313
|
+
*/
|
|
314
|
+
priorAttemps: number;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
interface DataLayerResult {
|
|
318
|
+
status: Status;
|
|
319
|
+
message: string;
|
|
320
|
+
id?: string;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
*
|
|
325
|
+
*/
|
|
326
|
+
interface ContentNavigationStrategyData extends SkuilderCourseData {
|
|
327
|
+
id: string;
|
|
328
|
+
docType: DocType.NAVIGATION_STRATEGY;
|
|
329
|
+
name: string;
|
|
330
|
+
description: string;
|
|
331
|
+
/**
|
|
332
|
+
The name of the class that implements the navigation strategy at runtime.
|
|
333
|
+
*/
|
|
334
|
+
implementingClass: string;
|
|
335
|
+
/**
|
|
336
|
+
A representation of the strategy's parameterization - to be deserialized
|
|
337
|
+
by the implementing class's constructor at runtime.
|
|
338
|
+
*/
|
|
339
|
+
serializedData: string;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* A NavigationStrategyManager is an entity which may contain multiple strategies.
|
|
344
|
+
*
|
|
345
|
+
* This interface defines strategy CRUD.
|
|
346
|
+
*/
|
|
347
|
+
interface NavigationStrategyManager {
|
|
348
|
+
/**
|
|
349
|
+
* Get the navigation strategy for a given course
|
|
350
|
+
* @returns The navigation strategy for the course
|
|
351
|
+
*/
|
|
352
|
+
getNavigationStrategy(id: string): Promise<ContentNavigationStrategyData>;
|
|
353
|
+
/**
|
|
354
|
+
* Get all available navigation strategies
|
|
355
|
+
* @returns An array of all available navigation strategies
|
|
356
|
+
*/
|
|
357
|
+
getAllNavigationStrategies(): Promise<ContentNavigationStrategyData[]>;
|
|
358
|
+
/**
|
|
359
|
+
* Add a new navigation strategy
|
|
360
|
+
* @param data The data for the new navigation strategy
|
|
361
|
+
* @returns A promise that resolves when the strategy has been added
|
|
362
|
+
*/
|
|
363
|
+
addNavigationStrategy(data: ContentNavigationStrategyData): Promise<void>;
|
|
364
|
+
/**
|
|
365
|
+
* Update an existing navigation strategy
|
|
366
|
+
* @param id The ID of the navigation strategy to update
|
|
367
|
+
* @param data The new data for the navigation strategy
|
|
368
|
+
* @returns A promise that resolves when the update is complete
|
|
369
|
+
*/
|
|
370
|
+
updateNavigationStrategy(id: string, data: ContentNavigationStrategyData): Promise<void>;
|
|
371
|
+
/**
|
|
372
|
+
* @returns A content navigation strategy suitable to the current context.
|
|
373
|
+
*/
|
|
374
|
+
surfaceNavigationStrategy(): Promise<ContentNavigationStrategyData>;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Course content and management
|
|
379
|
+
*/
|
|
380
|
+
interface CoursesDBInterface {
|
|
381
|
+
/**
|
|
382
|
+
* Get course config
|
|
383
|
+
*/
|
|
384
|
+
getCourseConfig(courseId: string): Promise<CourseConfig>;
|
|
385
|
+
/**
|
|
386
|
+
* Get a list of all courses
|
|
387
|
+
*/
|
|
388
|
+
getCourseList(): Promise<CourseConfig[]>;
|
|
389
|
+
disambiguateCourse(courseId: string, disambiguator: string): Promise<void>;
|
|
390
|
+
}
|
|
391
|
+
interface CourseInfo {
|
|
392
|
+
cardCount: number;
|
|
393
|
+
registeredUsers: number;
|
|
394
|
+
}
|
|
395
|
+
interface CourseDBInterface extends NavigationStrategyManager {
|
|
396
|
+
/**
|
|
397
|
+
* Get course config
|
|
398
|
+
*/
|
|
399
|
+
getCourseConfig(): Promise<CourseConfig>;
|
|
400
|
+
getCourseID(): string;
|
|
401
|
+
/**
|
|
402
|
+
* Set course config
|
|
403
|
+
*/
|
|
404
|
+
updateCourseConfig(cfg: CourseConfig): Promise<PouchDB.Core.Response>;
|
|
405
|
+
getCourseInfo(): Promise<CourseInfo>;
|
|
406
|
+
getCourseDoc<T extends SkuilderCourseData$1>(id: string, options?: PouchDB.Core.GetOptions): Promise<T>;
|
|
407
|
+
getCourseDocs<T extends SkuilderCourseData$1>(ids: string[], options?: PouchDB.Core.AllDocsOptions): Promise<PouchDB.Core.AllDocsWithKeysResponse<{} & T>>;
|
|
408
|
+
/**
|
|
409
|
+
* Get cards sorted by ELO rating
|
|
410
|
+
*/
|
|
411
|
+
getCardsByELO(elo: number, limit?: number): Promise<string[]>;
|
|
412
|
+
/**
|
|
413
|
+
* Get ELO data for specific cards
|
|
414
|
+
*/
|
|
415
|
+
getCardEloData(cardIds: string[]): Promise<CourseElo[]>;
|
|
416
|
+
/**
|
|
417
|
+
* Update card ELO rating
|
|
418
|
+
*/
|
|
419
|
+
updateCardElo(cardId: string, elo: CourseElo): Promise<PouchDB.Core.Response>;
|
|
420
|
+
/**
|
|
421
|
+
* Get new cards for study
|
|
422
|
+
*/
|
|
423
|
+
getNewCards(limit?: number): Promise<StudySessionNewItem[]>;
|
|
424
|
+
/**
|
|
425
|
+
* Get cards centered at a particular ELO rating
|
|
426
|
+
*/
|
|
427
|
+
getCardsCenteredAtELO(options: {
|
|
428
|
+
limit: number;
|
|
429
|
+
elo: 'user' | 'random' | number;
|
|
430
|
+
}, filter?: (id: string) => boolean): Promise<StudySessionItem[]>;
|
|
431
|
+
/**
|
|
432
|
+
* Get tags for a card
|
|
433
|
+
*/
|
|
434
|
+
getAppliedTags(cardId: string): Promise<PouchDB.Query.Response<TagStub>>;
|
|
435
|
+
/**
|
|
436
|
+
* Add a tag to a card
|
|
437
|
+
*/
|
|
438
|
+
addTagToCard(cardId: string, tagId: string, updateELO?: boolean): Promise<PouchDB.Core.Response>;
|
|
439
|
+
/**
|
|
440
|
+
* Remove a tag from a card
|
|
441
|
+
*/
|
|
442
|
+
removeTagFromCard(cardId: string, tagId: string): Promise<PouchDB.Core.Response>;
|
|
443
|
+
/**
|
|
444
|
+
* Create a new tag
|
|
445
|
+
*/
|
|
446
|
+
createTag(tagName: string): Promise<PouchDB.Core.Response>;
|
|
447
|
+
/**
|
|
448
|
+
* Get a tag by name
|
|
449
|
+
*/
|
|
450
|
+
getTag(tagName: string): Promise<Tag>;
|
|
451
|
+
/**
|
|
452
|
+
* Update a tag
|
|
453
|
+
*/
|
|
454
|
+
updateTag(tag: Tag): Promise<PouchDB.Core.Response>;
|
|
455
|
+
/**
|
|
456
|
+
* Get all tag stubs for a course
|
|
457
|
+
*/
|
|
458
|
+
getCourseTagStubs(): Promise<PouchDB.Core.AllDocsResponse<Tag>>;
|
|
459
|
+
/**
|
|
460
|
+
* Add a note to the course
|
|
461
|
+
*/
|
|
462
|
+
addNote(codeCourse: string, shape: DataShape, data: unknown, author: string, tags: string[], uploads?: {
|
|
463
|
+
[key: string]: PouchDB.Core.FullAttachment;
|
|
464
|
+
}, elo?: CourseElo): Promise<DataLayerResult>;
|
|
465
|
+
removeCard(cardId: string): Promise<PouchDB.Core.Response>;
|
|
466
|
+
getInexperiencedCards(): Promise<{
|
|
467
|
+
courseId: string;
|
|
468
|
+
cardId: string;
|
|
469
|
+
count: number;
|
|
470
|
+
elo: CourseElo;
|
|
471
|
+
}[]>;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
declare abstract class Loggable {
|
|
475
|
+
protected abstract readonly _className: string;
|
|
476
|
+
protected log(...args: unknown[]): void;
|
|
477
|
+
protected error(...args: unknown[]): void;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
type Update<T> = Partial<T> | ((x: T) => T);
|
|
481
|
+
|
|
482
|
+
interface DocumentUpdater {
|
|
483
|
+
update<T extends PouchDB.Core.Document<object>>(id: string, update: Update<T>): Promise<T>;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Returns the minimum number of seconds that should pass before a
|
|
487
|
+
* card is redisplayed for review / practice.
|
|
488
|
+
*
|
|
489
|
+
* @param cardHistory The user's history working with the given card
|
|
490
|
+
*/
|
|
491
|
+
declare function newInterval(user: DocumentUpdater, cardHistory: CardHistory<CardRecord>): number;
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* User data and authentication
|
|
495
|
+
*/
|
|
496
|
+
interface UserDBInterface extends DocumentUpdater {
|
|
497
|
+
/**
|
|
498
|
+
* Create a new user account
|
|
499
|
+
*/
|
|
500
|
+
createAccount(username: string, password: string): Promise<{
|
|
501
|
+
status: Status;
|
|
502
|
+
error: string;
|
|
503
|
+
}>;
|
|
504
|
+
/**
|
|
505
|
+
* Log in as a user
|
|
506
|
+
*/
|
|
507
|
+
login(username: string, password: string): Promise<{
|
|
508
|
+
ok: boolean;
|
|
509
|
+
name?: string;
|
|
510
|
+
roles?: string[];
|
|
511
|
+
}>;
|
|
512
|
+
/**
|
|
513
|
+
* Log out the current user
|
|
514
|
+
*/
|
|
515
|
+
logout(): Promise<{
|
|
516
|
+
ok: boolean;
|
|
517
|
+
}>;
|
|
518
|
+
getUsername(): string;
|
|
519
|
+
isLoggedIn(): boolean;
|
|
520
|
+
/**
|
|
521
|
+
* Get user configuration
|
|
522
|
+
*/
|
|
523
|
+
getConfig(): Promise<UserConfig>;
|
|
524
|
+
/**
|
|
525
|
+
* Update user configuration
|
|
526
|
+
*/
|
|
527
|
+
setConfig(config: Partial<UserConfig>): Promise<void>;
|
|
528
|
+
/**
|
|
529
|
+
* Record a user's interaction with a card
|
|
530
|
+
*/
|
|
531
|
+
putCardRecord<T extends CardRecord>(record: T): Promise<CardHistory<CardRecord>>;
|
|
532
|
+
/**
|
|
533
|
+
* Get cards that the user has seen
|
|
534
|
+
*/
|
|
535
|
+
getSeenCards(courseId?: string): Promise<string[]>;
|
|
536
|
+
/**
|
|
537
|
+
* Get cards that are actively scheduled for review
|
|
538
|
+
*/
|
|
539
|
+
getActiveCards(): Promise<string[]>;
|
|
540
|
+
/**
|
|
541
|
+
* Register user for a course
|
|
542
|
+
*/
|
|
543
|
+
registerForCourse(courseId: string, previewMode?: boolean): Promise<PouchDB.Core.Response>;
|
|
544
|
+
/**
|
|
545
|
+
* Drop a course registration
|
|
546
|
+
*/
|
|
547
|
+
dropCourse(courseId: string, dropStatus?: string): Promise<PouchDB.Core.Response>;
|
|
548
|
+
/**
|
|
549
|
+
* Get user's course registrations
|
|
550
|
+
*/
|
|
551
|
+
getCourseRegistrationsDoc(): Promise<CourseRegistrationDoc>;
|
|
552
|
+
/**
|
|
553
|
+
* Get the registration doc for a specific course.
|
|
554
|
+
* @param courseId
|
|
555
|
+
*/
|
|
556
|
+
getCourseRegDoc(courseId: string): Promise<CourseRegistration>;
|
|
557
|
+
/**
|
|
558
|
+
* Get user's active courses
|
|
559
|
+
*/
|
|
560
|
+
getActiveCourses(): Promise<CourseRegistration[]>;
|
|
561
|
+
/**
|
|
562
|
+
* Get user's pending reviews
|
|
563
|
+
*/
|
|
564
|
+
getPendingReviews(courseId?: string): Promise<ScheduledCard[]>;
|
|
565
|
+
getActivityRecords(): Promise<ActivityRecord[]>;
|
|
566
|
+
/**
|
|
567
|
+
* Schedule a card for review
|
|
568
|
+
*/
|
|
569
|
+
scheduleCardReview(review: {
|
|
570
|
+
user: string;
|
|
571
|
+
course_id: string;
|
|
572
|
+
card_id: string;
|
|
573
|
+
time: Moment;
|
|
574
|
+
scheduledFor: 'course' | 'classroom';
|
|
575
|
+
schedulingAgentId: string;
|
|
576
|
+
}): Promise<void>;
|
|
577
|
+
/**
|
|
578
|
+
* Remove a scheduled card review
|
|
579
|
+
*/
|
|
580
|
+
removeScheduledCardReview(reviewId: string): Promise<void>;
|
|
581
|
+
/**
|
|
582
|
+
* Register user for a classroom
|
|
583
|
+
*/
|
|
584
|
+
registerForClassroom(classId: string, registerAs: 'student' | 'teacher' | 'aide' | 'admin'): Promise<PouchDB.Core.Response>;
|
|
585
|
+
/**
|
|
586
|
+
* Drop user from classroom
|
|
587
|
+
*/
|
|
588
|
+
dropFromClassroom(classId: string): Promise<PouchDB.Core.Response>;
|
|
589
|
+
/**
|
|
590
|
+
* Get user's classroom registrations
|
|
591
|
+
*/
|
|
592
|
+
getUserClassrooms(): Promise<ClassroomRegistrationDoc>;
|
|
593
|
+
/**
|
|
594
|
+
* Get user's active classes
|
|
595
|
+
*/
|
|
596
|
+
getActiveClasses(): Promise<string[]>;
|
|
597
|
+
/**
|
|
598
|
+
* Update user's ELO rating for a course
|
|
599
|
+
*/
|
|
600
|
+
updateUserElo(courseId: string, elo: CourseElo): Promise<PouchDB.Core.Response>;
|
|
601
|
+
getCourseInterface(courseId: string): Promise<UsrCrsDataInterface>;
|
|
602
|
+
}
|
|
603
|
+
interface UserCourseSettings {
|
|
604
|
+
[setting: string]: string | number | boolean;
|
|
605
|
+
}
|
|
606
|
+
interface UserCourseSetting {
|
|
607
|
+
key: string;
|
|
608
|
+
value: string | number | boolean;
|
|
609
|
+
}
|
|
610
|
+
interface UsrCrsDataInterface {
|
|
611
|
+
getScheduledReviewCount(): Promise<number>;
|
|
612
|
+
getCourseSettings(): Promise<UserCourseSettings>;
|
|
613
|
+
updateCourseSettings(updates: UserCourseSetting[]): void;
|
|
614
|
+
}
|
|
615
|
+
type ClassroomRegistrationDesignation = 'student' | 'teacher' | 'aide' | 'admin';
|
|
616
|
+
interface ClassroomRegistration {
|
|
617
|
+
classID: string;
|
|
618
|
+
registeredAs: ClassroomRegistrationDesignation;
|
|
619
|
+
}
|
|
620
|
+
interface ClassroomRegistrationDoc {
|
|
621
|
+
registrations: ClassroomRegistration[];
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Main factory interface for data access
|
|
626
|
+
*/
|
|
627
|
+
interface DataLayerProvider {
|
|
628
|
+
/**
|
|
629
|
+
* Get the user database interface
|
|
630
|
+
*/
|
|
631
|
+
getUserDB(): UserDBInterface;
|
|
632
|
+
/**
|
|
633
|
+
* Get a course database interface
|
|
634
|
+
*/
|
|
635
|
+
getCourseDB(courseId: string): CourseDBInterface;
|
|
636
|
+
/**
|
|
637
|
+
* Get the courses-lookup interface
|
|
638
|
+
*/
|
|
639
|
+
getCoursesDB(): CoursesDBInterface;
|
|
640
|
+
/**
|
|
641
|
+
* Get a classroom database interface
|
|
642
|
+
*/
|
|
643
|
+
getClassroomDB(classId: string, type: 'student' | 'teacher'): Promise<ClassroomDBInterface>;
|
|
644
|
+
/**
|
|
645
|
+
* Get the admin database interface
|
|
646
|
+
*/
|
|
647
|
+
getAdminDB(): AdminDBInterface;
|
|
648
|
+
/**
|
|
649
|
+
* Initialize the data layer
|
|
650
|
+
*/
|
|
651
|
+
initialize(): Promise<void>;
|
|
652
|
+
/**
|
|
653
|
+
* Teardown the data layer
|
|
654
|
+
*/
|
|
655
|
+
teardown(): Promise<void>;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
declare function areQuestionRecords(h: CardHistory<CardRecord>): h is CardHistory<QuestionRecord>;
|
|
659
|
+
declare function isQuestionRecord(c: CardRecord): c is QuestionRecord;
|
|
660
|
+
declare function getCardHistoryID(courseID: string, cardID: string): PouchDB.Core.DocumentId;
|
|
661
|
+
declare function parseCardHistoryID(id: string): {
|
|
662
|
+
courseID: string;
|
|
663
|
+
cardID: string;
|
|
664
|
+
};
|
|
665
|
+
interface PouchDBError extends Error {
|
|
666
|
+
error?: string;
|
|
667
|
+
reason?: string;
|
|
668
|
+
}
|
|
669
|
+
declare function docIsDeleted(e: PouchDBError): boolean;
|
|
670
|
+
|
|
671
|
+
declare enum Navigators {
|
|
672
|
+
ELO = "elo"
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* A content-navigator provides runtime steering of study sessions.
|
|
676
|
+
*/
|
|
677
|
+
declare abstract class ContentNavigator implements StudyContentSource {
|
|
678
|
+
/**
|
|
679
|
+
*
|
|
680
|
+
* @param user
|
|
681
|
+
* @param strategyData
|
|
682
|
+
* @returns the runtime object used to steer a study session.
|
|
683
|
+
*/
|
|
684
|
+
static create(user: UserDBInterface, course: CourseDBInterface, strategyData: ContentNavigationStrategyData): Promise<ContentNavigator>;
|
|
685
|
+
abstract getPendingReviews(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
|
|
686
|
+
abstract getNewCards(n?: number): Promise<StudySessionNewItem[]>;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Interface representing the result of a bulk import operation for a single card
|
|
691
|
+
*/
|
|
692
|
+
interface ImportResult {
|
|
693
|
+
/** The original text input for the card */
|
|
694
|
+
originalText: string;
|
|
695
|
+
/** Status of the import operation */
|
|
696
|
+
status: 'success' | 'error';
|
|
697
|
+
/** Message describing the result or error */
|
|
698
|
+
message: string;
|
|
699
|
+
/** ID of the newly created card (only for success) */
|
|
700
|
+
cardId?: string;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Configuration for the bulk card processor
|
|
704
|
+
*/
|
|
705
|
+
interface BulkCardProcessorConfig {
|
|
706
|
+
/** The data shape to use for the cards */
|
|
707
|
+
dataShape: DataShape;
|
|
708
|
+
/** The course code used for adding notes */
|
|
709
|
+
courseCode: string;
|
|
710
|
+
/** The username of the current user */
|
|
711
|
+
userName: string;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Processes multiple cards from bulk text input
|
|
716
|
+
*
|
|
717
|
+
* @param parsedCards - Array of parsed cards to import
|
|
718
|
+
* @param courseDB - Course database interface
|
|
719
|
+
* @param config - Configuration for the card processor
|
|
720
|
+
* @returns Array of import results
|
|
721
|
+
*/
|
|
722
|
+
declare function importParsedCards(parsedCards: ParsedCard[], courseDB: CourseDBInterface, config: BulkCardProcessorConfig): Promise<ImportResult[]>;
|
|
723
|
+
/**
|
|
724
|
+
* Validates the configuration for bulk card processing
|
|
725
|
+
*
|
|
726
|
+
* @param config - Configuration to validate
|
|
727
|
+
* @returns Object with validation result and error message if any
|
|
728
|
+
*/
|
|
729
|
+
declare function validateProcessorConfig(config: Partial<BulkCardProcessorConfig>): {
|
|
730
|
+
isValid: boolean;
|
|
731
|
+
errorMessage?: string;
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
export { getCardHistoryID as $, type AdminDBInterface as A, type SkuilderCourseData as B, type CardRecord as C, type DataLayerProvider as D, type Tag as E, type TagStub as F, GuestUsername as G, type CardData as H, type CourseListData as I, type DisplayableData as J, type Field as K, Loggable as L, type DataShapeData as M, cardHistoryPrefix as N, type CardHistory as O, type QuestionRecord as P, type QuestionData as Q, type UserConfig as R, type StudySessionItem as S, type TeacherClassroomDBInterface as T, type UserDBInterface as U, type ActivityRecord as V, type CourseRegistration as W, type CourseRegistrationDoc as X, type ScheduledCard as Y, areQuestionRecords as Z, isQuestionRecord as _, type StudyContentSource as a, parseCardHistoryID as a0, docIsDeleted as a1, Navigators as a2, ContentNavigator as a3, importParsedCards as a4, validateProcessorConfig as a5, type ImportResult as a6, type BulkCardProcessorConfig as a7, type DocumentUpdater as a8, newInterval as a9, type ClassroomDBInterface as b, type StudentClassroomDBInterface as c, type AssignedContent as d, type AssignedTag as e, type AssignedCourse as f, type AssignedCard as g, type StudySessionFailedItem as h, type StudySessionFailedNewItem as i, type StudySessionFailedReviewItem as j, type StudySessionNewItem as k, type StudySessionReviewItem as l, isReview as m, type ContentSourceID as n, getStudySource as o, type CoursesDBInterface as p, type CourseInfo as q, type CourseDBInterface as r, type UserCourseSettings as s, type UserCourseSetting as t, type UsrCrsDataInterface as u, type ClassroomRegistrationDesignation as v, type ClassroomRegistration as w, type ClassroomRegistrationDoc as x, log as y, DocType as z };
|