@vue-skuilder/db 0.1.18 → 0.1.21
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/CLAUDE.md +2 -2
- package/dist/{classroomDB-BgfrVb8d.d.ts → contentSource-BP9hznNV.d.ts} +220 -197
- package/dist/{classroomDB-CTOenngH.d.cts → contentSource-DsJadoBU.d.cts} +220 -197
- package/dist/core/index.d.cts +80 -6
- package/dist/core/index.d.ts +80 -6
- package/dist/core/index.js +735 -1560
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +708 -1539
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-D6PoCwS6.d.cts → dataLayerProvider-CHYrQ5pB.d.cts} +1 -1
- package/dist/{dataLayerProvider-CZxC9GtB.d.ts → dataLayerProvider-MDTxXq2l.d.ts} +1 -1
- package/dist/impl/couch/index.d.cts +8 -23
- package/dist/impl/couch/index.d.ts +8 -23
- package/dist/impl/couch/index.js +723 -1578
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +692 -1552
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.cts +25 -8
- package/dist/impl/static/index.d.ts +25 -8
- package/dist/impl/static/index.js +700 -1400
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +688 -1393
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/{index-D-Fa4Smt.d.cts → index-B_j6u5E4.d.cts} +1 -1
- package/dist/{index-CD8BZz2k.d.ts → index-Dj0SEgk3.d.ts} +1 -1
- package/dist/index.d.cts +71 -63
- package/dist/index.d.ts +71 -63
- package/dist/index.js +1162 -1996
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1124 -1955
- package/dist/index.mjs.map +1 -1
- package/dist/pouch/index.js +3 -0
- package/dist/pouch/index.js.map +1 -1
- package/dist/pouch/index.mjs +3 -0
- package/dist/pouch/index.mjs.map +1 -1
- package/dist/{types-CzPDLAK6.d.cts → types-Bn0itutr.d.cts} +1 -1
- package/dist/{types-CewsN87z.d.ts → types-DQaXnuoc.d.ts} +1 -1
- package/dist/{types-legacy-6ettoclI.d.cts → types-legacy-DDY4N-Uq.d.cts} +3 -1
- package/dist/{types-legacy-6ettoclI.d.ts → types-legacy-DDY4N-Uq.d.ts} +3 -1
- package/dist/util/packer/index.d.cts +3 -3
- package/dist/util/packer/index.d.ts +3 -3
- package/docs/navigators-architecture.md +115 -17
- package/package.json +4 -4
- package/src/core/index.ts +1 -0
- package/src/core/interfaces/classroomDB.ts +5 -13
- package/src/core/interfaces/contentSource.ts +6 -66
- package/src/core/interfaces/courseDB.ts +15 -7
- package/src/core/interfaces/userDB.ts +32 -0
- package/src/core/navigators/Pipeline.ts +136 -52
- package/src/core/navigators/PipelineAssembler.ts +1 -1
- package/src/core/navigators/defaults.ts +84 -0
- package/src/core/navigators/{hierarchyDefinition.ts → filters/hierarchyDefinition.ts} +15 -29
- package/src/core/navigators/filters/index.ts +3 -0
- package/src/core/navigators/filters/inferredPreferenceStub.ts +107 -0
- package/src/core/navigators/{interferenceMitigator.ts → filters/interferenceMitigator.ts} +11 -37
- package/src/core/navigators/{relativePriority.ts → filters/relativePriority.ts} +12 -38
- package/src/core/navigators/filters/userGoalStub.ts +136 -0
- package/src/core/navigators/filters/userTagPreference.ts +217 -0
- package/src/core/navigators/{CompositeGenerator.ts → generators/CompositeGenerator.ts} +15 -64
- package/src/core/navigators/{elo.ts → generators/elo.ts} +13 -63
- package/src/core/navigators/{srs.ts → generators/srs.ts} +11 -40
- package/src/core/navigators/generators/types.ts +1 -1
- package/src/core/navigators/index.ts +95 -91
- package/src/core/types/strategyState.ts +84 -0
- package/src/core/types/types-legacy.ts +2 -0
- package/src/impl/common/BaseUserDB.ts +74 -7
- package/src/impl/couch/adminDB.ts +1 -2
- package/src/impl/couch/classroomDB.ts +100 -103
- package/src/impl/couch/courseDB.ts +35 -91
- package/src/impl/couch/pouchdb-setup.ts +7 -0
- package/src/impl/static/StaticDataUnpacker.ts +50 -1
- package/src/impl/static/courseDB.ts +87 -37
- package/src/study/SessionController.ts +122 -202
- package/src/study/SourceMixer.ts +65 -0
- package/src/study/TagFilteredContentSource.ts +49 -92
- package/src/study/index.ts +1 -0
- package/src/study/services/CardHydrationService.ts +165 -81
- package/src/util/dataDirectory.ts +1 -1
- package/src/util/index.ts +0 -1
- package/tests/core/navigators/CompositeGenerator.test.ts +44 -168
- package/tests/core/navigators/Pipeline.test.ts +6 -72
- package/tests/core/navigators/PipelineAssembler.test.ts +8 -58
- package/tests/core/navigators/navigators.test.ts +118 -151
- package/docs/todo-pipeline-optimization.md +0 -117
- package/docs/todo-strategy-state-storage.md +0 -278
- package/src/core/navigators/hardcodedOrder.ts +0 -163
- package/src/util/tuiLogger.ts +0 -139
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PackerConfig, a as PackedCourseData, S as StaticCourseManifest } from './types-
|
|
1
|
+
import { P as PackerConfig, a as PackedCourseData, S as StaticCourseManifest } from './types-Bn0itutr.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Abstraction for file system operations needed by the migrator.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PackerConfig, a as PackedCourseData, S as StaticCourseManifest } from './types-
|
|
1
|
+
import { P as PackerConfig, a as PackedCourseData, S as StaticCourseManifest } from './types-DQaXnuoc.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Abstraction for file system operations needed by the migrator.
|
package/dist/index.d.cts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { U as UserDBInterface, s as CourseRegistrationDoc,
|
|
2
|
-
export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard,
|
|
3
|
-
import { D as DataLayerProvider } from './dataLayerProvider-
|
|
4
|
-
import { C as CardHistory, c as CardRecord } from './types-legacy-
|
|
5
|
-
export { d as CardData, e as CourseListData, g as DataShapeData, f as DisplayableData, D as DocType, b as DocTypePrefixes, F as Field, G as GuestUsername, Q as QualifiedCardID, h as QuestionData, i as QuestionRecord, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from './types-legacy-
|
|
1
|
+
import { U as UserDBInterface, s as CourseRegistrationDoc, S as StudySessionItem, W as WeightedCard, h as StudyContentSource } from './contentSource-DsJadoBU.cjs';
|
|
2
|
+
export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, G as ClassroomRegistrationDoc, f as ContentNavigator, q as ContentSourceID, C as CourseDBInterface, d as CourseInfo, K as CourseRegistration, b as CoursesDBInterface, V as DocumentUpdater, O as NavigatorRole, P as NavigatorRoles, N as Navigators, j as ScheduledCard, H as SessionTrackingData, L as StrategyContribution, i as StudentClassroomDBInterface, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, n as StudySessionNewItem, o as StudySessionReviewItem, T as TeacherClassroomDBInterface, I as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, M as getCardOrigin, r as getStudySource, R as isFilter, Q as isGenerator, p as isReview, X as newInterval } from './contentSource-DsJadoBU.cjs';
|
|
3
|
+
import { D as DataLayerProvider } from './dataLayerProvider-CHYrQ5pB.cjs';
|
|
4
|
+
import { C as CardHistory, c as CardRecord } from './types-legacy-DDY4N-Uq.cjs';
|
|
5
|
+
export { d as CardData, e as CourseListData, g as DataShapeData, f as DisplayableData, D as DocType, b as DocTypePrefixes, F as Field, G as GuestUsername, Q as QualifiedCardID, h as QuestionData, i as QuestionRecord, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from './types-legacy-DDY4N-Uq.cjs';
|
|
6
6
|
import { Loggable } from './core/index.cjs';
|
|
7
|
-
export { BulkCardProcessorConfig, CardFilter, CardFilterFactory, CardGenerator, CardGeneratorFactory, FilterContext, GeneratorContext, ImportResult, areQuestionRecords, docIsDeleted, getCardHistoryID, importParsedCards, isQuestionRecord, parseCardHistoryID, validateProcessorConfig } from './core/index.cjs';
|
|
7
|
+
export { BulkCardProcessorConfig, CardFilter, CardFilterFactory, CardGenerator, CardGeneratorFactory, FilterContext, GeneratorContext, ImportResult, StrategyStateDoc, StrategyStateId, areQuestionRecords, buildStrategyStateId, docIsDeleted, getCardHistoryID, importParsedCards, isQuestionRecord, parseCardHistoryID, validateProcessorConfig } from './core/index.cjs';
|
|
8
8
|
import { TagFilter } from '@vue-skuilder/common';
|
|
9
|
-
import { S as StaticCourseManifest } from './types-
|
|
10
|
-
export { A as AttachmentData, C as ChunkMetadata, D as DesignDocument, I as IndexMetadata, a as PackedCourseData, P as PackerConfig } from './types-
|
|
11
|
-
import { F as FileSystemAdapter } from './index-
|
|
12
|
-
export { C as CouchDBToStaticPacker, a as FileStats, b as FileSystemError } from './index-
|
|
9
|
+
import { S as StaticCourseManifest } from './types-Bn0itutr.cjs';
|
|
10
|
+
export { A as AttachmentData, C as ChunkMetadata, D as DesignDocument, I as IndexMetadata, a as PackedCourseData, P as PackerConfig } from './types-Bn0itutr.cjs';
|
|
11
|
+
import { F as FileSystemAdapter } from './index-B_j6u5E4.cjs';
|
|
12
|
+
export { C as CouchDBToStaticPacker, a as FileStats, b as FileSystemError } from './index-B_j6u5E4.cjs';
|
|
13
13
|
import 'moment';
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -242,30 +242,47 @@ declare function getDbPath(dbName: string): string;
|
|
|
242
242
|
declare function initializeDataDirectory(): Promise<void>;
|
|
243
243
|
|
|
244
244
|
/**
|
|
245
|
-
*
|
|
245
|
+
* Represents a batch of content fetched from a single StudyContentSource.
|
|
246
246
|
*/
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
declare function getLogFilePath(): string | null;
|
|
252
|
-
/**
|
|
253
|
-
* Show user-facing message (always visible in TUI)
|
|
254
|
-
*/
|
|
255
|
-
declare function showUserMessage(message: string): void;
|
|
247
|
+
interface SourceBatch {
|
|
248
|
+
sourceIndex: number;
|
|
249
|
+
weighted: WeightedCard[];
|
|
250
|
+
}
|
|
256
251
|
/**
|
|
257
|
-
*
|
|
252
|
+
* Strategy interface for mixing content from multiple sources into a unified
|
|
253
|
+
* set of weighted candidates.
|
|
254
|
+
*
|
|
255
|
+
* Different implementations can provide different balancing strategies:
|
|
256
|
+
* - QuotaRoundRobinMixer: Equal representation per source
|
|
257
|
+
* - MinMaxNormalizingMixer: Score normalization then global sort
|
|
258
|
+
* - PercentileBucketMixer: Bucketed round-robin
|
|
259
|
+
* etc.
|
|
258
260
|
*/
|
|
259
|
-
|
|
261
|
+
interface SourceMixer {
|
|
262
|
+
/**
|
|
263
|
+
* Mix weighted cards from multiple sources into a unified, ordered list.
|
|
264
|
+
*
|
|
265
|
+
* @param batches - Content batches from each source
|
|
266
|
+
* @param limit - Target number of cards to return
|
|
267
|
+
* @returns Mixed and ordered weighted cards
|
|
268
|
+
*/
|
|
269
|
+
mix(batches: SourceBatch[], limit: number): WeightedCard[];
|
|
270
|
+
}
|
|
260
271
|
/**
|
|
261
|
-
*
|
|
272
|
+
* Simple quota-based mixer: allocates equal representation to each source,
|
|
273
|
+
* taking the top-N cards by score from each.
|
|
274
|
+
*
|
|
275
|
+
* Guarantees balanced representation across sources regardless of absolute
|
|
276
|
+
* score differences. A low-scoring source gets the same quota as a high-scoring
|
|
277
|
+
* source.
|
|
278
|
+
*
|
|
279
|
+
* This is the KISS approach - simple, predictable, and fair in terms of
|
|
280
|
+
* source representation (though not necessarily optimal in terms of absolute
|
|
281
|
+
* card quality).
|
|
262
282
|
*/
|
|
263
|
-
declare
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
warn: (message: string, ...args: any[]) => void;
|
|
267
|
-
error: (message: string, ...args: any[]) => void;
|
|
268
|
-
};
|
|
283
|
+
declare class QuotaRoundRobinMixer implements SourceMixer {
|
|
284
|
+
mix(batches: SourceBatch[], limit: number): WeightedCard[];
|
|
285
|
+
}
|
|
269
286
|
|
|
270
287
|
interface StudySessionRecord {
|
|
271
288
|
card: {
|
|
@@ -294,6 +311,7 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
294
311
|
private srsService;
|
|
295
312
|
private eloService;
|
|
296
313
|
private hydrationService;
|
|
314
|
+
private mixer;
|
|
297
315
|
private sources;
|
|
298
316
|
private _sessionRecord;
|
|
299
317
|
set sessionRecord(r: StudySessionRecord[]);
|
|
@@ -309,9 +327,13 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
309
327
|
get detailedReport(): string;
|
|
310
328
|
private _intervalHandle;
|
|
311
329
|
/**
|
|
312
|
-
*
|
|
330
|
+
* @param sources - Array of content sources to mix for the session
|
|
331
|
+
* @param time - Session duration in seconds
|
|
332
|
+
* @param dataLayer - Data layer provider
|
|
333
|
+
* @param getViewComponent - Function to resolve view components
|
|
334
|
+
* @param mixer - Optional source mixer strategy (defaults to QuotaRoundRobinMixer)
|
|
313
335
|
*/
|
|
314
|
-
constructor(sources: StudyContentSource[], time: number, dataLayer: DataLayerProvider, getViewComponent: (viewId: string) => TView);
|
|
336
|
+
constructor(sources: StudyContentSource[], time: number, dataLayer: DataLayerProvider, getViewComponent: (viewId: string) => TView, mixer?: SourceMixer);
|
|
315
337
|
private tick;
|
|
316
338
|
/**
|
|
317
339
|
* Returns a rough, erring toward conservative, guess at
|
|
@@ -369,34 +391,29 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
369
391
|
};
|
|
370
392
|
hydratedCache: {
|
|
371
393
|
count: number;
|
|
372
|
-
|
|
373
|
-
items: any[];
|
|
394
|
+
cardIds: string[];
|
|
374
395
|
};
|
|
375
396
|
};
|
|
376
397
|
/**
|
|
377
|
-
* Fetch content using the
|
|
378
|
-
*
|
|
379
|
-
* This method uses getWeightedCards() to get scored candidates, then uses the
|
|
380
|
-
* scores to determine ordering. For reviews, we still need the full ScheduledCard
|
|
381
|
-
* data from getPendingReviews(), so we fetch both and use scores for ordering.
|
|
398
|
+
* Fetch content using the getWeightedCards API and mix across sources.
|
|
382
399
|
*
|
|
383
|
-
*
|
|
384
|
-
* 1.
|
|
385
|
-
* 2.
|
|
386
|
-
* 3.
|
|
387
|
-
* 4.
|
|
400
|
+
* This method:
|
|
401
|
+
* 1. Fetches weighted cards from each source
|
|
402
|
+
* 2. Fetches full review data (we need ScheduledCard fields for queue)
|
|
403
|
+
* 3. Uses SourceMixer to balance content across sources
|
|
404
|
+
* 4. Populates review and new card queues with mixed results
|
|
388
405
|
*/
|
|
389
406
|
private getWeightedContent;
|
|
390
407
|
/**
|
|
391
|
-
*
|
|
392
|
-
*
|
|
408
|
+
* Returns items that should be pre-hydrated.
|
|
409
|
+
* Deterministic: top N items from each queue to ensure coverage.
|
|
410
|
+
* Failed queue items will typically already be hydrated (from initial render).
|
|
393
411
|
*/
|
|
394
|
-
private
|
|
412
|
+
private _getItemsToHydrate;
|
|
395
413
|
/**
|
|
396
|
-
*
|
|
397
|
-
*
|
|
414
|
+
* Selects the next item to present to the user.
|
|
415
|
+
* Nondeterministic: uses probability to balance between queues based on session state.
|
|
398
416
|
*/
|
|
399
|
-
private getNewCards;
|
|
400
417
|
private _selectNextItemToHydrate;
|
|
401
418
|
nextCard(action?: SessionAction): Promise<HydratedCard<TView> | null>;
|
|
402
419
|
/**
|
|
@@ -414,9 +431,8 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
414
431
|
*/
|
|
415
432
|
submitResponse(cardRecord: CardRecord, cardHistory: Promise<CardHistory<CardRecord>>, courseRegistrationDoc: CourseRegistrationDoc, currentCard: StudySessionRecord, courseId: string, cardId: string, maxAttemptsPerView: number, maxSessionViews: number, sessionViews: number): Promise<ResponseResult>;
|
|
416
433
|
private dismissCurrentCard;
|
|
417
|
-
private hasAvailableCards;
|
|
418
434
|
/**
|
|
419
|
-
*
|
|
435
|
+
* Remove an item from its source queue after consumption by nextCard().
|
|
420
436
|
*/
|
|
421
437
|
private removeItemFromQueue;
|
|
422
438
|
}
|
|
@@ -445,20 +461,12 @@ declare class TagFilteredContentSource implements StudyContentSource {
|
|
|
445
461
|
* - Cards in `exclude` tags are removed from the result
|
|
446
462
|
*/
|
|
447
463
|
private resolveFilteredCardIds;
|
|
448
|
-
/**
|
|
449
|
-
* Gets new cards that match the tag filter and are not already active for the user.
|
|
450
|
-
*/
|
|
451
|
-
getNewCards(limit?: number): Promise<StudySessionNewItem[]>;
|
|
452
|
-
/**
|
|
453
|
-
* Gets pending reviews, filtered to only include cards that match the tag filter.
|
|
454
|
-
*/
|
|
455
|
-
getPendingReviews(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
|
|
456
464
|
/**
|
|
457
465
|
* Get cards with suitability scores for presentation.
|
|
458
466
|
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
467
|
+
* Filters cards by tag inclusion/exclusion and assigns score=1.0 to all.
|
|
468
|
+
* TagFilteredContentSource does not currently support pluggable navigation
|
|
469
|
+
* strategies - it returns flat-scored candidates.
|
|
462
470
|
*
|
|
463
471
|
* @param limit - Maximum number of cards to return
|
|
464
472
|
* @returns Cards sorted by score descending (all scores = 1.0)
|
|
@@ -577,4 +585,4 @@ interface CouchDbUserDoc extends PouchDB.Authentication.User {
|
|
|
577
585
|
entitlements: UserEntitlements;
|
|
578
586
|
}
|
|
579
587
|
|
|
580
|
-
export { type AggregatedDocument, type AttachmentUploadResult, CardHistory, CardRecord, type CouchDbUserDoc, CourseLookup, CourseRegistrationDoc, DEFAULT_MIGRATION_OPTIONS, type DataLayerConfig, DataLayerProvider, type DocumentCounts, ENV, type Entitlement, FileSystemAdapter, Loggable, type MigrationOptions, type MigrationResult, NOT_SET, type ResponseResult, type RestoreProgress,
|
|
588
|
+
export { type AggregatedDocument, type AttachmentUploadResult, CardHistory, CardRecord, type CouchDbUserDoc, CourseLookup, CourseRegistrationDoc, DEFAULT_MIGRATION_OPTIONS, type DataLayerConfig, DataLayerProvider, type DocumentCounts, ENV, type Entitlement, FileSystemAdapter, Loggable, type MigrationOptions, type MigrationResult, NOT_SET, QuotaRoundRobinMixer, type ResponseResult, type RestoreProgress, type SessionAction, SessionController, type SourceBatch, type SourceMixer, StaticCourseManifest, type StaticCourseValidation, StaticToCouchDBMigrator, StudyContentSource, StudySessionItem, type StudySessionRecord, TagFilteredContentSource, type UserAccountStatus, UserDBInterface, type UserEntitlements, type ValidationIssue, type ValidationResult, WeightedCard, _resetDataLayer, ensureAppDataDirectory, getAppDataDirectory, getDataLayer, getDbPath, initializeDataDirectory, initializeDataLayer, validateMigration, validateStaticCourse };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { U as UserDBInterface, s as CourseRegistrationDoc,
|
|
2
|
-
export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard,
|
|
3
|
-
import { D as DataLayerProvider } from './dataLayerProvider-
|
|
4
|
-
import { C as CardHistory, c as CardRecord } from './types-legacy-
|
|
5
|
-
export { d as CardData, e as CourseListData, g as DataShapeData, f as DisplayableData, D as DocType, b as DocTypePrefixes, F as Field, G as GuestUsername, Q as QualifiedCardID, h as QuestionData, i as QuestionRecord, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from './types-legacy-
|
|
1
|
+
import { U as UserDBInterface, s as CourseRegistrationDoc, S as StudySessionItem, W as WeightedCard, h as StudyContentSource } from './contentSource-BP9hznNV.js';
|
|
2
|
+
export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, G as ClassroomRegistrationDoc, f as ContentNavigator, q as ContentSourceID, C as CourseDBInterface, d as CourseInfo, K as CourseRegistration, b as CoursesDBInterface, V as DocumentUpdater, O as NavigatorRole, P as NavigatorRoles, N as Navigators, j as ScheduledCard, H as SessionTrackingData, L as StrategyContribution, i as StudentClassroomDBInterface, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, n as StudySessionNewItem, o as StudySessionReviewItem, T as TeacherClassroomDBInterface, I as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, M as getCardOrigin, r as getStudySource, R as isFilter, Q as isGenerator, p as isReview, X as newInterval } from './contentSource-BP9hznNV.js';
|
|
3
|
+
import { D as DataLayerProvider } from './dataLayerProvider-MDTxXq2l.js';
|
|
4
|
+
import { C as CardHistory, c as CardRecord } from './types-legacy-DDY4N-Uq.js';
|
|
5
|
+
export { d as CardData, e as CourseListData, g as DataShapeData, f as DisplayableData, D as DocType, b as DocTypePrefixes, F as Field, G as GuestUsername, Q as QualifiedCardID, h as QuestionData, i as QuestionRecord, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from './types-legacy-DDY4N-Uq.js';
|
|
6
6
|
import { Loggable } from './core/index.js';
|
|
7
|
-
export { BulkCardProcessorConfig, CardFilter, CardFilterFactory, CardGenerator, CardGeneratorFactory, FilterContext, GeneratorContext, ImportResult, areQuestionRecords, docIsDeleted, getCardHistoryID, importParsedCards, isQuestionRecord, parseCardHistoryID, validateProcessorConfig } from './core/index.js';
|
|
7
|
+
export { BulkCardProcessorConfig, CardFilter, CardFilterFactory, CardGenerator, CardGeneratorFactory, FilterContext, GeneratorContext, ImportResult, StrategyStateDoc, StrategyStateId, areQuestionRecords, buildStrategyStateId, docIsDeleted, getCardHistoryID, importParsedCards, isQuestionRecord, parseCardHistoryID, validateProcessorConfig } from './core/index.js';
|
|
8
8
|
import { TagFilter } from '@vue-skuilder/common';
|
|
9
|
-
import { S as StaticCourseManifest } from './types-
|
|
10
|
-
export { A as AttachmentData, C as ChunkMetadata, D as DesignDocument, I as IndexMetadata, a as PackedCourseData, P as PackerConfig } from './types-
|
|
11
|
-
import { F as FileSystemAdapter } from './index-
|
|
12
|
-
export { C as CouchDBToStaticPacker, a as FileStats, b as FileSystemError } from './index-
|
|
9
|
+
import { S as StaticCourseManifest } from './types-DQaXnuoc.js';
|
|
10
|
+
export { A as AttachmentData, C as ChunkMetadata, D as DesignDocument, I as IndexMetadata, a as PackedCourseData, P as PackerConfig } from './types-DQaXnuoc.js';
|
|
11
|
+
import { F as FileSystemAdapter } from './index-Dj0SEgk3.js';
|
|
12
|
+
export { C as CouchDBToStaticPacker, a as FileStats, b as FileSystemError } from './index-Dj0SEgk3.js';
|
|
13
13
|
import 'moment';
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -242,30 +242,47 @@ declare function getDbPath(dbName: string): string;
|
|
|
242
242
|
declare function initializeDataDirectory(): Promise<void>;
|
|
243
243
|
|
|
244
244
|
/**
|
|
245
|
-
*
|
|
245
|
+
* Represents a batch of content fetched from a single StudyContentSource.
|
|
246
246
|
*/
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
declare function getLogFilePath(): string | null;
|
|
252
|
-
/**
|
|
253
|
-
* Show user-facing message (always visible in TUI)
|
|
254
|
-
*/
|
|
255
|
-
declare function showUserMessage(message: string): void;
|
|
247
|
+
interface SourceBatch {
|
|
248
|
+
sourceIndex: number;
|
|
249
|
+
weighted: WeightedCard[];
|
|
250
|
+
}
|
|
256
251
|
/**
|
|
257
|
-
*
|
|
252
|
+
* Strategy interface for mixing content from multiple sources into a unified
|
|
253
|
+
* set of weighted candidates.
|
|
254
|
+
*
|
|
255
|
+
* Different implementations can provide different balancing strategies:
|
|
256
|
+
* - QuotaRoundRobinMixer: Equal representation per source
|
|
257
|
+
* - MinMaxNormalizingMixer: Score normalization then global sort
|
|
258
|
+
* - PercentileBucketMixer: Bucketed round-robin
|
|
259
|
+
* etc.
|
|
258
260
|
*/
|
|
259
|
-
|
|
261
|
+
interface SourceMixer {
|
|
262
|
+
/**
|
|
263
|
+
* Mix weighted cards from multiple sources into a unified, ordered list.
|
|
264
|
+
*
|
|
265
|
+
* @param batches - Content batches from each source
|
|
266
|
+
* @param limit - Target number of cards to return
|
|
267
|
+
* @returns Mixed and ordered weighted cards
|
|
268
|
+
*/
|
|
269
|
+
mix(batches: SourceBatch[], limit: number): WeightedCard[];
|
|
270
|
+
}
|
|
260
271
|
/**
|
|
261
|
-
*
|
|
272
|
+
* Simple quota-based mixer: allocates equal representation to each source,
|
|
273
|
+
* taking the top-N cards by score from each.
|
|
274
|
+
*
|
|
275
|
+
* Guarantees balanced representation across sources regardless of absolute
|
|
276
|
+
* score differences. A low-scoring source gets the same quota as a high-scoring
|
|
277
|
+
* source.
|
|
278
|
+
*
|
|
279
|
+
* This is the KISS approach - simple, predictable, and fair in terms of
|
|
280
|
+
* source representation (though not necessarily optimal in terms of absolute
|
|
281
|
+
* card quality).
|
|
262
282
|
*/
|
|
263
|
-
declare
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
warn: (message: string, ...args: any[]) => void;
|
|
267
|
-
error: (message: string, ...args: any[]) => void;
|
|
268
|
-
};
|
|
283
|
+
declare class QuotaRoundRobinMixer implements SourceMixer {
|
|
284
|
+
mix(batches: SourceBatch[], limit: number): WeightedCard[];
|
|
285
|
+
}
|
|
269
286
|
|
|
270
287
|
interface StudySessionRecord {
|
|
271
288
|
card: {
|
|
@@ -294,6 +311,7 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
294
311
|
private srsService;
|
|
295
312
|
private eloService;
|
|
296
313
|
private hydrationService;
|
|
314
|
+
private mixer;
|
|
297
315
|
private sources;
|
|
298
316
|
private _sessionRecord;
|
|
299
317
|
set sessionRecord(r: StudySessionRecord[]);
|
|
@@ -309,9 +327,13 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
309
327
|
get detailedReport(): string;
|
|
310
328
|
private _intervalHandle;
|
|
311
329
|
/**
|
|
312
|
-
*
|
|
330
|
+
* @param sources - Array of content sources to mix for the session
|
|
331
|
+
* @param time - Session duration in seconds
|
|
332
|
+
* @param dataLayer - Data layer provider
|
|
333
|
+
* @param getViewComponent - Function to resolve view components
|
|
334
|
+
* @param mixer - Optional source mixer strategy (defaults to QuotaRoundRobinMixer)
|
|
313
335
|
*/
|
|
314
|
-
constructor(sources: StudyContentSource[], time: number, dataLayer: DataLayerProvider, getViewComponent: (viewId: string) => TView);
|
|
336
|
+
constructor(sources: StudyContentSource[], time: number, dataLayer: DataLayerProvider, getViewComponent: (viewId: string) => TView, mixer?: SourceMixer);
|
|
315
337
|
private tick;
|
|
316
338
|
/**
|
|
317
339
|
* Returns a rough, erring toward conservative, guess at
|
|
@@ -369,34 +391,29 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
369
391
|
};
|
|
370
392
|
hydratedCache: {
|
|
371
393
|
count: number;
|
|
372
|
-
|
|
373
|
-
items: any[];
|
|
394
|
+
cardIds: string[];
|
|
374
395
|
};
|
|
375
396
|
};
|
|
376
397
|
/**
|
|
377
|
-
* Fetch content using the
|
|
378
|
-
*
|
|
379
|
-
* This method uses getWeightedCards() to get scored candidates, then uses the
|
|
380
|
-
* scores to determine ordering. For reviews, we still need the full ScheduledCard
|
|
381
|
-
* data from getPendingReviews(), so we fetch both and use scores for ordering.
|
|
398
|
+
* Fetch content using the getWeightedCards API and mix across sources.
|
|
382
399
|
*
|
|
383
|
-
*
|
|
384
|
-
* 1.
|
|
385
|
-
* 2.
|
|
386
|
-
* 3.
|
|
387
|
-
* 4.
|
|
400
|
+
* This method:
|
|
401
|
+
* 1. Fetches weighted cards from each source
|
|
402
|
+
* 2. Fetches full review data (we need ScheduledCard fields for queue)
|
|
403
|
+
* 3. Uses SourceMixer to balance content across sources
|
|
404
|
+
* 4. Populates review and new card queues with mixed results
|
|
388
405
|
*/
|
|
389
406
|
private getWeightedContent;
|
|
390
407
|
/**
|
|
391
|
-
*
|
|
392
|
-
*
|
|
408
|
+
* Returns items that should be pre-hydrated.
|
|
409
|
+
* Deterministic: top N items from each queue to ensure coverage.
|
|
410
|
+
* Failed queue items will typically already be hydrated (from initial render).
|
|
393
411
|
*/
|
|
394
|
-
private
|
|
412
|
+
private _getItemsToHydrate;
|
|
395
413
|
/**
|
|
396
|
-
*
|
|
397
|
-
*
|
|
414
|
+
* Selects the next item to present to the user.
|
|
415
|
+
* Nondeterministic: uses probability to balance between queues based on session state.
|
|
398
416
|
*/
|
|
399
|
-
private getNewCards;
|
|
400
417
|
private _selectNextItemToHydrate;
|
|
401
418
|
nextCard(action?: SessionAction): Promise<HydratedCard<TView> | null>;
|
|
402
419
|
/**
|
|
@@ -414,9 +431,8 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
414
431
|
*/
|
|
415
432
|
submitResponse(cardRecord: CardRecord, cardHistory: Promise<CardHistory<CardRecord>>, courseRegistrationDoc: CourseRegistrationDoc, currentCard: StudySessionRecord, courseId: string, cardId: string, maxAttemptsPerView: number, maxSessionViews: number, sessionViews: number): Promise<ResponseResult>;
|
|
416
433
|
private dismissCurrentCard;
|
|
417
|
-
private hasAvailableCards;
|
|
418
434
|
/**
|
|
419
|
-
*
|
|
435
|
+
* Remove an item from its source queue after consumption by nextCard().
|
|
420
436
|
*/
|
|
421
437
|
private removeItemFromQueue;
|
|
422
438
|
}
|
|
@@ -445,20 +461,12 @@ declare class TagFilteredContentSource implements StudyContentSource {
|
|
|
445
461
|
* - Cards in `exclude` tags are removed from the result
|
|
446
462
|
*/
|
|
447
463
|
private resolveFilteredCardIds;
|
|
448
|
-
/**
|
|
449
|
-
* Gets new cards that match the tag filter and are not already active for the user.
|
|
450
|
-
*/
|
|
451
|
-
getNewCards(limit?: number): Promise<StudySessionNewItem[]>;
|
|
452
|
-
/**
|
|
453
|
-
* Gets pending reviews, filtered to only include cards that match the tag filter.
|
|
454
|
-
*/
|
|
455
|
-
getPendingReviews(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
|
|
456
464
|
/**
|
|
457
465
|
* Get cards with suitability scores for presentation.
|
|
458
466
|
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
467
|
+
* Filters cards by tag inclusion/exclusion and assigns score=1.0 to all.
|
|
468
|
+
* TagFilteredContentSource does not currently support pluggable navigation
|
|
469
|
+
* strategies - it returns flat-scored candidates.
|
|
462
470
|
*
|
|
463
471
|
* @param limit - Maximum number of cards to return
|
|
464
472
|
* @returns Cards sorted by score descending (all scores = 1.0)
|
|
@@ -577,4 +585,4 @@ interface CouchDbUserDoc extends PouchDB.Authentication.User {
|
|
|
577
585
|
entitlements: UserEntitlements;
|
|
578
586
|
}
|
|
579
587
|
|
|
580
|
-
export { type AggregatedDocument, type AttachmentUploadResult, CardHistory, CardRecord, type CouchDbUserDoc, CourseLookup, CourseRegistrationDoc, DEFAULT_MIGRATION_OPTIONS, type DataLayerConfig, DataLayerProvider, type DocumentCounts, ENV, type Entitlement, FileSystemAdapter, Loggable, type MigrationOptions, type MigrationResult, NOT_SET, type ResponseResult, type RestoreProgress,
|
|
588
|
+
export { type AggregatedDocument, type AttachmentUploadResult, CardHistory, CardRecord, type CouchDbUserDoc, CourseLookup, CourseRegistrationDoc, DEFAULT_MIGRATION_OPTIONS, type DataLayerConfig, DataLayerProvider, type DocumentCounts, ENV, type Entitlement, FileSystemAdapter, Loggable, type MigrationOptions, type MigrationResult, NOT_SET, QuotaRoundRobinMixer, type ResponseResult, type RestoreProgress, type SessionAction, SessionController, type SourceBatch, type SourceMixer, StaticCourseManifest, type StaticCourseValidation, StaticToCouchDBMigrator, StudyContentSource, StudySessionItem, type StudySessionRecord, TagFilteredContentSource, type UserAccountStatus, UserDBInterface, type UserEntitlements, type ValidationIssue, type ValidationResult, WeightedCard, _resetDataLayer, ensureAppDataDirectory, getAppDataDirectory, getDataLayer, getDbPath, initializeDataDirectory, initializeDataLayer, validateMigration, validateStaticCourse };
|