@vue-skuilder/db 0.1.11 → 0.1.12
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/dist/core/index.d.mts +7 -6
- package/dist/core/index.d.ts +7 -6
- package/dist/core/index.js +146 -37
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +146 -37
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-VieuAAkV.d.mts → dataLayerProvider-BiP3kWix.d.mts} +1 -1
- package/dist/{dataLayerProvider-juuqUHOP.d.ts → dataLayerProvider-DSdeyRT3.d.ts} +1 -1
- package/dist/impl/couch/index.d.mts +3 -3
- package/dist/impl/couch/index.d.ts +3 -3
- package/dist/impl/couch/index.js +146 -37
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +146 -37
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.mts +14 -6
- package/dist/impl/static/index.d.ts +14 -6
- package/dist/impl/static/index.js +147 -39
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +147 -39
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/{index-DZyxHCcf.d.mts → index-Bmll7Xse.d.mts} +1 -1
- package/dist/{index-CWY6yhkV.d.ts → index-CD8BZz2k.d.ts} +1 -1
- package/dist/index.d.mts +119 -24
- package/dist/index.d.ts +119 -24
- package/dist/index.js +785 -261
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +789 -265
- package/dist/index.mjs.map +1 -1
- package/dist/{types-DtoI27Xh.d.ts → types-CewsN87z.d.ts} +1 -1
- package/dist/{types-Che4wTwA.d.mts → types-Dbp5DaRR.d.mts} +1 -1
- package/dist/{types-legacy-B8ahaCbj.d.mts → types-legacy-6ettoclI.d.mts} +13 -2
- package/dist/{types-legacy-B8ahaCbj.d.ts → types-legacy-6ettoclI.d.ts} +13 -2
- package/dist/{userDB-DJ8HMw83.d.mts → userDB-C4yyAnpp.d.mts} +3 -3
- package/dist/{userDB-B7zTQ123.d.ts → userDB-CD6s6ZCp.d.ts} +3 -3
- package/dist/util/packer/index.d.mts +3 -3
- package/dist/util/packer/index.d.ts +3 -3
- package/package.json +3 -3
- package/src/core/navigators/hardcodedOrder.ts +64 -0
- package/src/core/navigators/index.ts +1 -0
- package/src/core/types/contentNavigationStrategy.ts +2 -1
- package/src/core/types/types-legacy.ts +2 -2
- package/src/impl/common/BaseUserDB.ts +15 -11
- package/src/impl/couch/courseDB.ts +74 -27
- package/src/impl/couch/updateQueue.ts +8 -3
- package/src/impl/static/StaticDataLayerProvider.ts +57 -17
- package/src/impl/static/courseDB.ts +17 -12
- package/src/impl/static/coursesDB.ts +10 -6
- package/src/study/ItemQueue.ts +58 -0
- package/src/study/SessionController.ts +132 -178
- package/src/study/services/CardHydrationService.ts +153 -0
- package/src/study/services/EloService.ts +85 -0
- package/src/study/services/ResponseProcessor.ts +224 -0
- package/src/study/services/SrsService.ts +44 -0
package/dist/core/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { i as StudyContentSource, U as UserDBInterface, C as CourseDBInterface, e as ContentNavigationStrategyData, f as StudySessionReviewItem, g as ScheduledCard, S as StudySessionNewItem } from '../userDB-
|
|
2
|
-
export {
|
|
3
|
-
export { D as DataLayerProvider } from '../dataLayerProvider-
|
|
4
|
-
import {
|
|
5
|
-
export {
|
|
1
|
+
import { i as StudyContentSource, U as UserDBInterface, C as CourseDBInterface, e as ContentNavigationStrategyData, f as StudySessionReviewItem, g as ScheduledCard, S as StudySessionNewItem } from '../userDB-C4yyAnpp.mjs';
|
|
2
|
+
export { H as ActivityRecord, A as AdminDBInterface, u as AssignedCard, h as AssignedContent, t as AssignedCourse, s as AssignedTag, c as ClassroomDBInterface, E as ClassroomRegistration, B as ClassroomRegistrationDesignation, F as ClassroomRegistrationDoc, p as ContentSourceID, d as CourseInfo, I as CourseRegistration, r as CourseRegistrationDoc, b as CoursesDBInterface, j as StudentClassroomDBInterface, l as StudySessionFailedItem, m as StudySessionFailedNewItem, n as StudySessionFailedReviewItem, k as StudySessionItem, T as TeacherClassroomDBInterface, G as UserConfig, y as UserCourseSetting, x as UserCourseSettings, w as UserDBAuthenticator, a as UserDBReader, v as UserDBWriter, z as UsrCrsDataInterface, q as getStudySource, o as isReview } from '../userDB-C4yyAnpp.mjs';
|
|
3
|
+
export { D as DataLayerProvider } from '../dataLayerProvider-BiP3kWix.mjs';
|
|
4
|
+
import { C as CardHistory, c as CardRecord, i as QuestionRecord } from '../types-legacy-6ettoclI.mjs';
|
|
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, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-6ettoclI.mjs';
|
|
6
6
|
import { DataShape, ParsedCard } from '@vue-skuilder/common';
|
|
7
7
|
import 'moment';
|
|
8
8
|
|
|
@@ -26,7 +26,8 @@ interface PouchDBError extends Error {
|
|
|
26
26
|
declare function docIsDeleted(e: PouchDBError): boolean;
|
|
27
27
|
|
|
28
28
|
declare enum Navigators {
|
|
29
|
-
ELO = "elo"
|
|
29
|
+
ELO = "elo",
|
|
30
|
+
HARDCODED = "hardcodedOrder"
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
33
|
* A content-navigator provides runtime steering of study sessions.
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { i as StudyContentSource, U as UserDBInterface, C as CourseDBInterface, e as ContentNavigationStrategyData, f as StudySessionReviewItem, g as ScheduledCard, S as StudySessionNewItem } from '../userDB-
|
|
2
|
-
export {
|
|
3
|
-
export { D as DataLayerProvider } from '../dataLayerProvider-
|
|
4
|
-
import {
|
|
5
|
-
export {
|
|
1
|
+
import { i as StudyContentSource, U as UserDBInterface, C as CourseDBInterface, e as ContentNavigationStrategyData, f as StudySessionReviewItem, g as ScheduledCard, S as StudySessionNewItem } from '../userDB-CD6s6ZCp.js';
|
|
2
|
+
export { H as ActivityRecord, A as AdminDBInterface, u as AssignedCard, h as AssignedContent, t as AssignedCourse, s as AssignedTag, c as ClassroomDBInterface, E as ClassroomRegistration, B as ClassroomRegistrationDesignation, F as ClassroomRegistrationDoc, p as ContentSourceID, d as CourseInfo, I as CourseRegistration, r as CourseRegistrationDoc, b as CoursesDBInterface, j as StudentClassroomDBInterface, l as StudySessionFailedItem, m as StudySessionFailedNewItem, n as StudySessionFailedReviewItem, k as StudySessionItem, T as TeacherClassroomDBInterface, G as UserConfig, y as UserCourseSetting, x as UserCourseSettings, w as UserDBAuthenticator, a as UserDBReader, v as UserDBWriter, z as UsrCrsDataInterface, q as getStudySource, o as isReview } from '../userDB-CD6s6ZCp.js';
|
|
3
|
+
export { D as DataLayerProvider } from '../dataLayerProvider-DSdeyRT3.js';
|
|
4
|
+
import { C as CardHistory, c as CardRecord, i as QuestionRecord } from '../types-legacy-6ettoclI.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, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-6ettoclI.js';
|
|
6
6
|
import { DataShape, ParsedCard } from '@vue-skuilder/common';
|
|
7
7
|
import 'moment';
|
|
8
8
|
|
|
@@ -26,7 +26,8 @@ interface PouchDBError extends Error {
|
|
|
26
26
|
declare function docIsDeleted(e: PouchDBError): boolean;
|
|
27
27
|
|
|
28
28
|
declare enum Navigators {
|
|
29
|
-
ELO = "elo"
|
|
29
|
+
ELO = "elo",
|
|
30
|
+
HARDCODED = "hardcodedOrder"
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
33
|
* A content-navigator provides runtime steering of study sessions.
|
package/dist/core/index.js
CHANGED
|
@@ -343,7 +343,9 @@ var init_updateQueue = __esm({
|
|
|
343
343
|
async applyUpdates(id) {
|
|
344
344
|
logger.debug(`Applying updates on doc: ${id}`);
|
|
345
345
|
if (this.inprogressUpdates[id]) {
|
|
346
|
-
|
|
346
|
+
while (this.inprogressUpdates[id]) {
|
|
347
|
+
await new Promise((resolve) => setTimeout(resolve, Math.random() * 50));
|
|
348
|
+
}
|
|
347
349
|
return this.applyUpdates(id);
|
|
348
350
|
} else {
|
|
349
351
|
if (this.pendingUpdates[id] && this.pendingUpdates[id].length > 0) {
|
|
@@ -379,6 +381,9 @@ var init_updateQueue = __esm({
|
|
|
379
381
|
if (e.name === "conflict" && i < MAX_RETRIES - 1) {
|
|
380
382
|
logger.warn(`Conflict on update for doc ${id}, retry #${i + 1}`);
|
|
381
383
|
await new Promise((res) => setTimeout(res, 50 * Math.random()));
|
|
384
|
+
} else if (e.name === "not_found" && i === 0) {
|
|
385
|
+
logger.warn(`Update failed for ${id} - does not exist. Throwing to caller.`);
|
|
386
|
+
throw e;
|
|
382
387
|
} else {
|
|
383
388
|
delete this.inprogressUpdates[id];
|
|
384
389
|
if (this.pendingUpdates[id]) {
|
|
@@ -744,12 +749,74 @@ var init_elo = __esm({
|
|
|
744
749
|
}
|
|
745
750
|
});
|
|
746
751
|
|
|
752
|
+
// src/core/navigators/hardcodedOrder.ts
|
|
753
|
+
var hardcodedOrder_exports = {};
|
|
754
|
+
__export(hardcodedOrder_exports, {
|
|
755
|
+
default: () => HardcodedOrderNavigator
|
|
756
|
+
});
|
|
757
|
+
var HardcodedOrderNavigator;
|
|
758
|
+
var init_hardcodedOrder = __esm({
|
|
759
|
+
"src/core/navigators/hardcodedOrder.ts"() {
|
|
760
|
+
"use strict";
|
|
761
|
+
init_navigators();
|
|
762
|
+
init_logger();
|
|
763
|
+
HardcodedOrderNavigator = class extends ContentNavigator {
|
|
764
|
+
orderedCardIds = [];
|
|
765
|
+
user;
|
|
766
|
+
course;
|
|
767
|
+
constructor(user, course, strategyData) {
|
|
768
|
+
super();
|
|
769
|
+
this.user = user;
|
|
770
|
+
this.course = course;
|
|
771
|
+
if (strategyData.serializedData) {
|
|
772
|
+
try {
|
|
773
|
+
this.orderedCardIds = JSON.parse(strategyData.serializedData);
|
|
774
|
+
} catch (e) {
|
|
775
|
+
logger.error("Failed to parse serializedData for HardcodedOrderNavigator", e);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
async getPendingReviews() {
|
|
780
|
+
const reviews = await this.user.getPendingReviews(this.course.getCourseID());
|
|
781
|
+
return reviews.map((r) => {
|
|
782
|
+
return {
|
|
783
|
+
...r,
|
|
784
|
+
contentSourceType: "course",
|
|
785
|
+
contentSourceID: this.course.getCourseID(),
|
|
786
|
+
cardID: r.cardId,
|
|
787
|
+
courseID: r.courseId,
|
|
788
|
+
reviewID: r._id,
|
|
789
|
+
status: "review"
|
|
790
|
+
};
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
async getNewCards(limit = 99) {
|
|
794
|
+
const activeCardIds = (await this.user.getActiveCards()).map((c) => c.cardID);
|
|
795
|
+
const newCardIds = this.orderedCardIds.filter(
|
|
796
|
+
(cardId) => !activeCardIds.includes(cardId)
|
|
797
|
+
);
|
|
798
|
+
const cardsToReturn = newCardIds.slice(0, limit);
|
|
799
|
+
return cardsToReturn.map((cardId) => {
|
|
800
|
+
return {
|
|
801
|
+
cardID: cardId,
|
|
802
|
+
courseID: this.course.getCourseID(),
|
|
803
|
+
contentSourceType: "course",
|
|
804
|
+
contentSourceID: this.course.getCourseID(),
|
|
805
|
+
status: "new"
|
|
806
|
+
};
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
|
|
747
813
|
// import("./**/*") in src/core/navigators/index.ts
|
|
748
814
|
var globImport;
|
|
749
815
|
var init_ = __esm({
|
|
750
816
|
'import("./**/*") in src/core/navigators/index.ts'() {
|
|
751
817
|
globImport = __glob({
|
|
752
818
|
"./elo.ts": () => Promise.resolve().then(() => (init_elo(), elo_exports)),
|
|
819
|
+
"./hardcodedOrder.ts": () => Promise.resolve().then(() => (init_hardcodedOrder(), hardcodedOrder_exports)),
|
|
753
820
|
"./index.ts": () => Promise.resolve().then(() => (init_navigators(), navigators_exports))
|
|
754
821
|
});
|
|
755
822
|
}
|
|
@@ -769,6 +836,7 @@ var init_navigators = __esm({
|
|
|
769
836
|
init_();
|
|
770
837
|
Navigators = /* @__PURE__ */ ((Navigators2) => {
|
|
771
838
|
Navigators2["ELO"] = "elo";
|
|
839
|
+
Navigators2["HARDCODED"] = "hardcodedOrder";
|
|
772
840
|
return Navigators2;
|
|
773
841
|
})(Navigators || {});
|
|
774
842
|
ContentNavigator = class {
|
|
@@ -993,6 +1061,23 @@ var init_courseDB = __esm({
|
|
|
993
1061
|
if (!doc.docType || !(doc.docType === "CARD" /* CARD */)) {
|
|
994
1062
|
throw new Error(`failed to remove ${id} from course ${this.id}. id does not point to a card`);
|
|
995
1063
|
}
|
|
1064
|
+
try {
|
|
1065
|
+
const appliedTags = await this.getAppliedTags(id);
|
|
1066
|
+
const results = await Promise.allSettled(
|
|
1067
|
+
appliedTags.rows.map(async (tagRow) => {
|
|
1068
|
+
const tagId = tagRow.id;
|
|
1069
|
+
await this.removeTagFromCard(id, tagId);
|
|
1070
|
+
})
|
|
1071
|
+
);
|
|
1072
|
+
results.forEach((result, index) => {
|
|
1073
|
+
if (result.status === "rejected") {
|
|
1074
|
+
const tagId = appliedTags.rows[index].id;
|
|
1075
|
+
logger.error(`Failed to remove card ${id} from tag ${tagId}: ${result.reason}`);
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
1078
|
+
} catch (error) {
|
|
1079
|
+
logger.error(`Error removing card ${id} from tags: ${error}`);
|
|
1080
|
+
}
|
|
996
1081
|
return this.db.remove(doc);
|
|
997
1082
|
}
|
|
998
1083
|
async getCardDisplayableDataIDs(id) {
|
|
@@ -1176,23 +1261,9 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1176
1261
|
////////////////////////////////////
|
|
1177
1262
|
getNavigationStrategy(id) {
|
|
1178
1263
|
logger.debug(`[courseDB] Getting navigation strategy: ${id}`);
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
name: "ELO",
|
|
1183
|
-
description: "ELO-based navigation strategy for ordering content by difficulty",
|
|
1184
|
-
implementingClass: "elo" /* ELO */,
|
|
1185
|
-
course: this.id,
|
|
1186
|
-
serializedData: ""
|
|
1187
|
-
// serde is a noop for ELO navigator.
|
|
1188
|
-
};
|
|
1189
|
-
return Promise.resolve(strategy);
|
|
1190
|
-
}
|
|
1191
|
-
getAllNavigationStrategies() {
|
|
1192
|
-
logger.debug("[courseDB] Returning hard-coded navigation strategies");
|
|
1193
|
-
const strategies = [
|
|
1194
|
-
{
|
|
1195
|
-
id: "ELO",
|
|
1264
|
+
if (id == "") {
|
|
1265
|
+
const strategy = {
|
|
1266
|
+
_id: "NAVIGATION_STRATEGY-ELO",
|
|
1196
1267
|
docType: "NAVIGATION_STRATEGY" /* NAVIGATION_STRATEGY */,
|
|
1197
1268
|
name: "ELO",
|
|
1198
1269
|
description: "ELO-based navigation strategy for ordering content by difficulty",
|
|
@@ -1200,14 +1271,25 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1200
1271
|
course: this.id,
|
|
1201
1272
|
serializedData: ""
|
|
1202
1273
|
// serde is a noop for ELO navigator.
|
|
1203
|
-
}
|
|
1204
|
-
|
|
1205
|
-
|
|
1274
|
+
};
|
|
1275
|
+
return Promise.resolve(strategy);
|
|
1276
|
+
} else {
|
|
1277
|
+
return this.db.get(id);
|
|
1278
|
+
}
|
|
1206
1279
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1280
|
+
async getAllNavigationStrategies() {
|
|
1281
|
+
const prefix = DocTypePrefixes["NAVIGATION_STRATEGY" /* NAVIGATION_STRATEGY */];
|
|
1282
|
+
const result = await this.db.allDocs({
|
|
1283
|
+
startkey: prefix,
|
|
1284
|
+
endkey: `${prefix}\uFFF0`,
|
|
1285
|
+
include_docs: true
|
|
1286
|
+
});
|
|
1287
|
+
return result.rows.map((row) => row.doc);
|
|
1288
|
+
}
|
|
1289
|
+
async addNavigationStrategy(data) {
|
|
1290
|
+
logger.debug(`[courseDB] Adding navigation strategy: ${data._id}`);
|
|
1291
|
+
return this.db.put(data).then(() => {
|
|
1292
|
+
});
|
|
1211
1293
|
}
|
|
1212
1294
|
updateNavigationStrategy(id, data) {
|
|
1213
1295
|
logger.debug(`[courseDB] Updating navigation strategy: ${id}`);
|
|
@@ -1215,9 +1297,32 @@ ${above.rows.map((r) => ` ${r.id}-${r.key}
|
|
|
1215
1297
|
return Promise.resolve();
|
|
1216
1298
|
}
|
|
1217
1299
|
async surfaceNavigationStrategy() {
|
|
1300
|
+
try {
|
|
1301
|
+
const config = await this.getCourseConfig();
|
|
1302
|
+
if (config.defaultNavigationStrategyId) {
|
|
1303
|
+
try {
|
|
1304
|
+
const strategy = await this.getNavigationStrategy(config.defaultNavigationStrategyId);
|
|
1305
|
+
if (strategy) {
|
|
1306
|
+
logger.debug(`Surfacing strategy ${strategy.name} from course config`);
|
|
1307
|
+
return strategy;
|
|
1308
|
+
}
|
|
1309
|
+
} catch (e) {
|
|
1310
|
+
logger.warn(
|
|
1311
|
+
// @ts-expect-error tmp: defaultNavigationStrategyId property does not yet exist
|
|
1312
|
+
`Failed to load strategy '${config.defaultNavigationStrategyId}' specified in course config. Falling back to ELO.`,
|
|
1313
|
+
e
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
} catch (e) {
|
|
1318
|
+
logger.warn(
|
|
1319
|
+
"Could not retrieve course config to determine navigation strategy. Falling back to ELO.",
|
|
1320
|
+
e
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1218
1323
|
logger.warn(`Returning hard-coded default ELO navigator`);
|
|
1219
1324
|
const ret = {
|
|
1220
|
-
|
|
1325
|
+
_id: "NAVIGATION_STRATEGY-ELO",
|
|
1221
1326
|
docType: "NAVIGATION_STRATEGY" /* NAVIGATION_STRATEGY */,
|
|
1222
1327
|
name: "ELO",
|
|
1223
1328
|
description: "ELO-based navigation strategy",
|
|
@@ -2339,17 +2444,21 @@ Currently logged-in as ${this._username}.`
|
|
|
2339
2444
|
} catch (e) {
|
|
2340
2445
|
const reason = e;
|
|
2341
2446
|
if (reason.status === 404) {
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2447
|
+
try {
|
|
2448
|
+
const initCardHistory = {
|
|
2449
|
+
_id: cardHistoryID,
|
|
2450
|
+
cardID: record.cardID,
|
|
2451
|
+
courseID: record.courseID,
|
|
2452
|
+
records: [record],
|
|
2453
|
+
lapses: 0,
|
|
2454
|
+
streak: 0,
|
|
2455
|
+
bestInterval: 0
|
|
2456
|
+
};
|
|
2457
|
+
const putResult = await this.writeDB.put(initCardHistory);
|
|
2458
|
+
return { ...initCardHistory, _rev: putResult.rev };
|
|
2459
|
+
} catch (creationError) {
|
|
2460
|
+
throw new Error(`Failed to create CardHistory for ${cardHistoryID}. Reason: ${creationError}`);
|
|
2461
|
+
}
|
|
2353
2462
|
} else {
|
|
2354
2463
|
throw new Error(`putCardRecord failed because of:
|
|
2355
2464
|
name:${reason.name}
|