@playcademy/sdk 0.10.0 → 0.10.1-beta.2
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/index.d.ts +78 -3
- package/dist/index.js +71 -3
- package/dist/internal.d.ts +84 -5
- package/dist/internal.js +79 -3
- package/dist/server/edge.d.ts +5 -0
- package/dist/server/edge.js +27 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +27 -0
- package/dist/types.d.ts +80 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1145,9 +1145,7 @@ interface StartActivityResult {
|
|
|
1145
1145
|
|
|
1146
1146
|
/**
|
|
1147
1147
|
* A TimeBack enrollment for the current game session.
|
|
1148
|
-
* Alias for UserEnrollment without the optional gameId.
|
|
1149
|
-
* are available at `enrollment.enrollmentIds?.active` when supplied by the
|
|
1150
|
-
* platform.
|
|
1148
|
+
* Alias for UserEnrollment without the optional gameId.
|
|
1151
1149
|
*/
|
|
1152
1150
|
type TimebackEnrollment = Omit<UserEnrollment, 'gameId'>;
|
|
1153
1151
|
/**
|
|
@@ -1253,6 +1251,50 @@ interface TimebackUser extends TimebackUserContext {
|
|
|
1253
1251
|
* Call `xp.fetch()` to get XP from the server.
|
|
1254
1252
|
*/
|
|
1255
1253
|
xp: TimebackUserXp;
|
|
1254
|
+
/**
|
|
1255
|
+
* Mastery data for the current user.
|
|
1256
|
+
* Call `mastery.fetch()` to get mastery progress from the server.
|
|
1257
|
+
*/
|
|
1258
|
+
mastery: TimebackUserMastery;
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Mastery data access for the current user.
|
|
1262
|
+
* Results are cached for 5 seconds to avoid redundant network requests.
|
|
1263
|
+
*/
|
|
1264
|
+
interface TimebackUserMastery {
|
|
1265
|
+
/**
|
|
1266
|
+
* Fetch mastery data from the server.
|
|
1267
|
+
* Returns mastery for all courses in this game, or filter by grade/subject.
|
|
1268
|
+
* Results are cached for 5 seconds (use `force: true` to bypass).
|
|
1269
|
+
*
|
|
1270
|
+
* @param options - Query options
|
|
1271
|
+
* @param options.grade - Grade level to filter (must be used with subject)
|
|
1272
|
+
* @param options.subject - Subject to filter (must be used with grade)
|
|
1273
|
+
* @param options.include - Additional data to include: 'perCourse'
|
|
1274
|
+
* @param options.force - Bypass cache and fetch fresh data (default: false)
|
|
1275
|
+
* @returns Promise resolving to mastery data
|
|
1276
|
+
*
|
|
1277
|
+
* @example
|
|
1278
|
+
* ```typescript
|
|
1279
|
+
* // Get total mastery for all game courses
|
|
1280
|
+
* const mastery = await client.timeback.user.mastery.fetch()
|
|
1281
|
+
*
|
|
1282
|
+
* // Get mastery for a specific grade/subject
|
|
1283
|
+
* const mastery = await client.timeback.user.mastery.fetch({
|
|
1284
|
+
* grade: 3,
|
|
1285
|
+
* subject: 'Math'
|
|
1286
|
+
* })
|
|
1287
|
+
*
|
|
1288
|
+
* // Get mastery with per-course breakdown
|
|
1289
|
+
* const mastery = await client.timeback.user.mastery.fetch({
|
|
1290
|
+
* include: ['perCourse']
|
|
1291
|
+
* })
|
|
1292
|
+
*
|
|
1293
|
+
* // Force fresh data
|
|
1294
|
+
* const mastery = await client.timeback.user.mastery.fetch({ force: true })
|
|
1295
|
+
* ```
|
|
1296
|
+
*/
|
|
1297
|
+
fetch(options?: GetMasteryOptions): Promise<MasteryResponse>;
|
|
1256
1298
|
}
|
|
1257
1299
|
/**
|
|
1258
1300
|
* Options for querying student XP.
|
|
@@ -1267,6 +1309,19 @@ interface GetXpOptions {
|
|
|
1267
1309
|
/** Bypass cache and fetch fresh data (default: false) */
|
|
1268
1310
|
force?: boolean;
|
|
1269
1311
|
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Options for querying student mastery.
|
|
1314
|
+
*/
|
|
1315
|
+
interface GetMasteryOptions {
|
|
1316
|
+
/** Grade level to filter (must be used with subject) */
|
|
1317
|
+
grade?: TimebackGrade;
|
|
1318
|
+
/** Subject to filter (must be used with grade) */
|
|
1319
|
+
subject?: TimebackSubject;
|
|
1320
|
+
/** Additional data to include: 'perCourse' */
|
|
1321
|
+
include?: 'perCourse'[];
|
|
1322
|
+
/** Bypass cache and fetch fresh data (default: false) */
|
|
1323
|
+
force?: boolean;
|
|
1324
|
+
}
|
|
1270
1325
|
/**
|
|
1271
1326
|
* XP data for a single course.
|
|
1272
1327
|
*/
|
|
@@ -1285,6 +1340,26 @@ interface XpResponse {
|
|
|
1285
1340
|
todayXp?: number;
|
|
1286
1341
|
courses?: CourseXp[];
|
|
1287
1342
|
}
|
|
1343
|
+
/**
|
|
1344
|
+
* Mastery data for a single course.
|
|
1345
|
+
*/
|
|
1346
|
+
interface CourseMastery {
|
|
1347
|
+
grade: TimebackGrade;
|
|
1348
|
+
subject: TimebackSubject;
|
|
1349
|
+
title: string;
|
|
1350
|
+
masteredUnits: number;
|
|
1351
|
+
masterableUnits: number;
|
|
1352
|
+
pctComplete: number;
|
|
1353
|
+
isComplete: boolean;
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* Response from mastery query.
|
|
1357
|
+
*/
|
|
1358
|
+
interface MasteryResponse {
|
|
1359
|
+
totalMasteredUnits: number;
|
|
1360
|
+
totalMasterableUnits: number;
|
|
1361
|
+
courses?: CourseMastery[];
|
|
1362
|
+
}
|
|
1288
1363
|
|
|
1289
1364
|
/**
|
|
1290
1365
|
* Core client configuration and lifecycle types
|
package/dist/index.js
CHANGED
|
@@ -1145,9 +1145,21 @@ function isValidSubject(value) {
|
|
|
1145
1145
|
var TIMEBACK_ROUTES = {
|
|
1146
1146
|
END_ACTIVITY: "/integrations/timeback/end-activity",
|
|
1147
1147
|
GET_XP: "/integrations/timeback/xp",
|
|
1148
|
+
GET_MASTERY: "/integrations/timeback/mastery",
|
|
1148
1149
|
HEARTBEAT: "/integrations/timeback/heartbeat",
|
|
1149
1150
|
ADVANCE_COURSE: "/integrations/timeback/advance-course"
|
|
1150
1151
|
};
|
|
1152
|
+
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
1153
|
+
xp: 1,
|
|
1154
|
+
mastery: 0,
|
|
1155
|
+
score: 2
|
|
1156
|
+
};
|
|
1157
|
+
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
1158
|
+
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.xp,
|
|
1159
|
+
mastery: 0,
|
|
1160
|
+
time: 60,
|
|
1161
|
+
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
1162
|
+
};
|
|
1151
1163
|
// src/core/cache/ttl-cache.ts
|
|
1152
1164
|
function createTTLCache(options) {
|
|
1153
1165
|
const cache = new Map;
|
|
@@ -1705,6 +1717,9 @@ function createTimebackActivityTracker(client) {
|
|
|
1705
1717
|
const unreportedActiveMs = Math.max(0, activeTime - activity.totalPersistedActiveMs);
|
|
1706
1718
|
const unreportedPausedMs = Math.max(0, activity.pausedTime - activity.totalPersistedPausedMs);
|
|
1707
1719
|
const { correctQuestions, totalQuestions } = data;
|
|
1720
|
+
if (data.masteredUnits !== undefined && data.masteredUnitsAbsolute !== undefined) {
|
|
1721
|
+
throw new Error("Cannot provide both masteredUnits and masteredUnitsAbsolute — use one or the other");
|
|
1722
|
+
}
|
|
1708
1723
|
const request = {
|
|
1709
1724
|
runId: activity.runId,
|
|
1710
1725
|
resumeId: activity.resumeId,
|
|
@@ -1722,6 +1737,7 @@ function createTimebackActivityTracker(client) {
|
|
|
1722
1737
|
},
|
|
1723
1738
|
xpEarned: data.xpAwarded,
|
|
1724
1739
|
masteredUnits: data.masteredUnits,
|
|
1740
|
+
masteredUnitsAbsolute: data.masteredUnitsAbsolute,
|
|
1725
1741
|
extensions: data.extensions
|
|
1726
1742
|
};
|
|
1727
1743
|
try {
|
|
@@ -1780,6 +1796,10 @@ function createTimebackEngine(client) {
|
|
|
1780
1796
|
ttl: 5000,
|
|
1781
1797
|
keyPrefix: "game.timeback.xp"
|
|
1782
1798
|
});
|
|
1799
|
+
const masteryCache = createTTLCache({
|
|
1800
|
+
ttl: 5000,
|
|
1801
|
+
keyPrefix: "game.timeback.mastery"
|
|
1802
|
+
});
|
|
1783
1803
|
const enrollmentsCache = createTTLCache({
|
|
1784
1804
|
ttl: 5 * 60 * 1000,
|
|
1785
1805
|
keyPrefix: "game.timeback.enrollments"
|
|
@@ -1847,6 +1867,30 @@ function createTimebackEngine(client) {
|
|
|
1847
1867
|
return client["requestGameBackend"](endpoint, "GET");
|
|
1848
1868
|
}, { force: options.force });
|
|
1849
1869
|
}
|
|
1870
|
+
},
|
|
1871
|
+
mastery: {
|
|
1872
|
+
fetch: (options) => {
|
|
1873
|
+
const cacheKey = [
|
|
1874
|
+
options.grade ?? "",
|
|
1875
|
+
options.subject ?? "",
|
|
1876
|
+
options.include?.toSorted().join(",") ?? ""
|
|
1877
|
+
].join(":");
|
|
1878
|
+
return masteryCache.get(cacheKey, async () => {
|
|
1879
|
+
const params = new URLSearchParams;
|
|
1880
|
+
if (options.grade !== undefined) {
|
|
1881
|
+
params.set("grade", String(options.grade));
|
|
1882
|
+
}
|
|
1883
|
+
if (options.subject !== undefined) {
|
|
1884
|
+
params.set("subject", options.subject);
|
|
1885
|
+
}
|
|
1886
|
+
if (options.include?.length) {
|
|
1887
|
+
params.set("include", options.include.join(","));
|
|
1888
|
+
}
|
|
1889
|
+
const queryString = params.toString();
|
|
1890
|
+
const endpoint = `${TIMEBACK_ROUTES.GET_MASTERY}${queryString ? `?${queryString}` : ""}`;
|
|
1891
|
+
return client["requestGameBackend"](endpoint, "GET");
|
|
1892
|
+
}, { force: options.force });
|
|
1893
|
+
}
|
|
1850
1894
|
}
|
|
1851
1895
|
},
|
|
1852
1896
|
activity: {
|
|
@@ -1865,7 +1909,8 @@ function createTimebackEngine(client) {
|
|
|
1865
1909
|
}
|
|
1866
1910
|
|
|
1867
1911
|
// src/namespaces/game/timeback.ts
|
|
1868
|
-
var
|
|
1912
|
+
var VALID_XP_INCLUDE_OPTIONS = ["perCourse", "today"];
|
|
1913
|
+
var VALID_MASTERY_INCLUDE_OPTIONS = ["perCourse"];
|
|
1869
1914
|
function createTimebackNamespace(client) {
|
|
1870
1915
|
const engine = createTimebackEngine(client);
|
|
1871
1916
|
return {
|
|
@@ -1901,13 +1946,36 @@ function createTimebackNamespace(client) {
|
|
|
1901
1946
|
}
|
|
1902
1947
|
if (options.include?.length) {
|
|
1903
1948
|
for (const opt of options.include) {
|
|
1904
|
-
if (!
|
|
1905
|
-
throw new Error(`Invalid include option: ${opt}. Valid options: ${
|
|
1949
|
+
if (!VALID_XP_INCLUDE_OPTIONS.includes(opt)) {
|
|
1950
|
+
throw new Error(`Invalid include option: ${opt}. Valid options: ${VALID_XP_INCLUDE_OPTIONS.join(", ")}`);
|
|
1906
1951
|
}
|
|
1907
1952
|
}
|
|
1908
1953
|
}
|
|
1909
1954
|
return engine.user.xp.fetch(options);
|
|
1910
1955
|
}
|
|
1956
|
+
},
|
|
1957
|
+
mastery: {
|
|
1958
|
+
fetch: async (options = {}) => {
|
|
1959
|
+
const hasGrade = options.grade !== undefined;
|
|
1960
|
+
const hasSubject = options.subject !== undefined;
|
|
1961
|
+
if (hasGrade !== hasSubject) {
|
|
1962
|
+
throw new Error("Both grade and subject must be provided together");
|
|
1963
|
+
}
|
|
1964
|
+
if (hasGrade && !isValidGrade(options.grade)) {
|
|
1965
|
+
throw new Error(`Invalid grade: ${options.grade}. Valid grades: ${VALID_GRADES.join(", ")}`);
|
|
1966
|
+
}
|
|
1967
|
+
if (hasSubject && !isValidSubject(options.subject)) {
|
|
1968
|
+
throw new Error(`Invalid subject: ${options.subject}. Valid subjects: ${VALID_SUBJECTS.join(", ")}`);
|
|
1969
|
+
}
|
|
1970
|
+
if (options.include?.length) {
|
|
1971
|
+
for (const opt of options.include) {
|
|
1972
|
+
if (!VALID_MASTERY_INCLUDE_OPTIONS.includes(opt)) {
|
|
1973
|
+
throw new Error(`Invalid include option: ${opt}. Valid options: ${VALID_MASTERY_INCLUDE_OPTIONS.join(", ")}`);
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
return engine.user.mastery.fetch(options);
|
|
1978
|
+
}
|
|
1911
1979
|
}
|
|
1912
1980
|
};
|
|
1913
1981
|
},
|
package/dist/internal.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { TimebackGrade, TimebackSubject, TimebackCourseConfig, CourseConfig, Org
|
|
|
3
3
|
export { QtiTestQuestionRef, QtiTestQuestionsResponse } from '@playcademy/types/timeback';
|
|
4
4
|
import * as _playcademy_types from '@playcademy/types';
|
|
5
5
|
import { GameManifest } from '@playcademy/types';
|
|
6
|
-
export { AuthenticatedUser, DeveloperStatusEnumType, DeveloperStatusResponse, DeveloperStatusValue,
|
|
6
|
+
export { AuthenticatedUser, DeveloperStatusEnumType, DeveloperStatusResponse, DeveloperStatusValue, GameCourseMetrics, GameLeaderboardEntry, GameManifest, GameMetricComparisonKind, GameMetricComparisonMetric, GameMetricComparisonRow, GameMetricComparisonRowStatus, GameMetricsProxyResponse, GameMetricsResponse, GameMetricsUnsupportedReason, GamePlatform, GameRunMetrics, GameRunMetricsComparison, GameRunMetricsComparisonStatus, GameRunMetricsComparisonSummary, GameTimebackIntegration, GameType, GameUser, LeaderboardEntry, LeaderboardOptions, LeaderboardTimeframe, ManifestV1, ManifestV2, ManifestVersions, PopulateStudentResponse, UserEnrollment, UserInfo, UserOrganization, UserRank, UserRankResponse, UserRoleEnumType, UserScore, UserTimebackData } from '@playcademy/types';
|
|
7
7
|
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import { DomainValidationRecords } from '@playcademy/types/game';
|
|
@@ -999,9 +999,7 @@ interface StartActivityResult {
|
|
|
999
999
|
|
|
1000
1000
|
/**
|
|
1001
1001
|
* A TimeBack enrollment for the current game session.
|
|
1002
|
-
* Alias for UserEnrollment without the optional gameId.
|
|
1003
|
-
* are available at `enrollment.enrollmentIds?.active` when supplied by the
|
|
1004
|
-
* platform.
|
|
1002
|
+
* Alias for UserEnrollment without the optional gameId.
|
|
1005
1003
|
*/
|
|
1006
1004
|
type TimebackEnrollment = Omit<UserEnrollment, 'gameId'>;
|
|
1007
1005
|
/**
|
|
@@ -1107,6 +1105,50 @@ interface TimebackUser extends TimebackUserContext {
|
|
|
1107
1105
|
* Call `xp.fetch()` to get XP from the server.
|
|
1108
1106
|
*/
|
|
1109
1107
|
xp: TimebackUserXp;
|
|
1108
|
+
/**
|
|
1109
|
+
* Mastery data for the current user.
|
|
1110
|
+
* Call `mastery.fetch()` to get mastery progress from the server.
|
|
1111
|
+
*/
|
|
1112
|
+
mastery: TimebackUserMastery;
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Mastery data access for the current user.
|
|
1116
|
+
* Results are cached for 5 seconds to avoid redundant network requests.
|
|
1117
|
+
*/
|
|
1118
|
+
interface TimebackUserMastery {
|
|
1119
|
+
/**
|
|
1120
|
+
* Fetch mastery data from the server.
|
|
1121
|
+
* Returns mastery for all courses in this game, or filter by grade/subject.
|
|
1122
|
+
* Results are cached for 5 seconds (use `force: true` to bypass).
|
|
1123
|
+
*
|
|
1124
|
+
* @param options - Query options
|
|
1125
|
+
* @param options.grade - Grade level to filter (must be used with subject)
|
|
1126
|
+
* @param options.subject - Subject to filter (must be used with grade)
|
|
1127
|
+
* @param options.include - Additional data to include: 'perCourse'
|
|
1128
|
+
* @param options.force - Bypass cache and fetch fresh data (default: false)
|
|
1129
|
+
* @returns Promise resolving to mastery data
|
|
1130
|
+
*
|
|
1131
|
+
* @example
|
|
1132
|
+
* ```typescript
|
|
1133
|
+
* // Get total mastery for all game courses
|
|
1134
|
+
* const mastery = await client.timeback.user.mastery.fetch()
|
|
1135
|
+
*
|
|
1136
|
+
* // Get mastery for a specific grade/subject
|
|
1137
|
+
* const mastery = await client.timeback.user.mastery.fetch({
|
|
1138
|
+
* grade: 3,
|
|
1139
|
+
* subject: 'Math'
|
|
1140
|
+
* })
|
|
1141
|
+
*
|
|
1142
|
+
* // Get mastery with per-course breakdown
|
|
1143
|
+
* const mastery = await client.timeback.user.mastery.fetch({
|
|
1144
|
+
* include: ['perCourse']
|
|
1145
|
+
* })
|
|
1146
|
+
*
|
|
1147
|
+
* // Force fresh data
|
|
1148
|
+
* const mastery = await client.timeback.user.mastery.fetch({ force: true })
|
|
1149
|
+
* ```
|
|
1150
|
+
*/
|
|
1151
|
+
fetch(options?: GetMasteryOptions): Promise<MasteryResponse>;
|
|
1110
1152
|
}
|
|
1111
1153
|
/**
|
|
1112
1154
|
* Options for querying student XP.
|
|
@@ -1121,6 +1163,19 @@ interface GetXpOptions {
|
|
|
1121
1163
|
/** Bypass cache and fetch fresh data (default: false) */
|
|
1122
1164
|
force?: boolean;
|
|
1123
1165
|
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Options for querying student mastery.
|
|
1168
|
+
*/
|
|
1169
|
+
interface GetMasteryOptions {
|
|
1170
|
+
/** Grade level to filter (must be used with subject) */
|
|
1171
|
+
grade?: TimebackGrade;
|
|
1172
|
+
/** Subject to filter (must be used with grade) */
|
|
1173
|
+
subject?: TimebackSubject;
|
|
1174
|
+
/** Additional data to include: 'perCourse' */
|
|
1175
|
+
include?: 'perCourse'[];
|
|
1176
|
+
/** Bypass cache and fetch fresh data (default: false) */
|
|
1177
|
+
force?: boolean;
|
|
1178
|
+
}
|
|
1124
1179
|
/**
|
|
1125
1180
|
* XP data for a single course.
|
|
1126
1181
|
*/
|
|
@@ -1139,6 +1194,26 @@ interface XpResponse {
|
|
|
1139
1194
|
todayXp?: number;
|
|
1140
1195
|
courses?: CourseXp[];
|
|
1141
1196
|
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Mastery data for a single course.
|
|
1199
|
+
*/
|
|
1200
|
+
interface CourseMastery {
|
|
1201
|
+
grade: TimebackGrade;
|
|
1202
|
+
subject: TimebackSubject;
|
|
1203
|
+
title: string;
|
|
1204
|
+
masteredUnits: number;
|
|
1205
|
+
masterableUnits: number;
|
|
1206
|
+
pctComplete: number;
|
|
1207
|
+
isComplete: boolean;
|
|
1208
|
+
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Response from mastery query.
|
|
1211
|
+
*/
|
|
1212
|
+
interface MasteryResponse {
|
|
1213
|
+
totalMasteredUnits: number;
|
|
1214
|
+
totalMasterableUnits: number;
|
|
1215
|
+
courses?: CourseMastery[];
|
|
1216
|
+
}
|
|
1142
1217
|
|
|
1143
1218
|
/**
|
|
1144
1219
|
* Core client configuration and lifecycle types
|
|
@@ -2960,6 +3035,10 @@ declare class PlaycademyInternalClient extends PlaycademyBaseClient {
|
|
|
2960
3035
|
gameId: string;
|
|
2961
3036
|
courseId?: string;
|
|
2962
3037
|
}) => Promise<_playcademy_types.TimebackStudentOverviewResponse>;
|
|
3038
|
+
getGameMetrics: (timebackId: string, options: {
|
|
3039
|
+
gameId: string;
|
|
3040
|
+
runIds?: string[];
|
|
3041
|
+
}) => Promise<_playcademy_types.GameMetricsProxyResponse>;
|
|
2963
3042
|
getStudentActivity: (timebackId: string, courseId: string, options: {
|
|
2964
3043
|
gameId: string;
|
|
2965
3044
|
limit?: number;
|
|
@@ -3025,4 +3104,4 @@ declare class PlaycademyInternalClient extends PlaycademyBaseClient {
|
|
|
3025
3104
|
}
|
|
3026
3105
|
|
|
3027
3106
|
export { ApiError, MessageEvents, PlaycademyInternalClient as PlaycademyClient, PlaycademyError, PlaycademyInternalClient, extractApiErrorInfo, messaging };
|
|
3028
|
-
export type { ApiErrorCode, ApiErrorInfo, AssessmentBankStatus, AssessmentRow, AssessmentSummary, AuthCallbackPayload, AuthOptions, AuthProviderType, AuthResult, AuthServerMessage, AuthStateChangePayload, AuthStateUpdate, BetterAuthApiKey, BetterAuthApiKeyResponse, BetterAuthSignInResponse, BucketFile, ClientConfig, ClientEvents, CourseXp, DemoEndOptions, DemoEndPayload, DevUploadEvent, DevUploadHooks, ErrorResponseBody, EventListeners, ExternalGame, FetchedGame, Game, GameContextPayload, GameCustomHostname, GameInitUser, GameRow as GameRecord, GameTokenResponse, GetXpOptions, HostedGame, InitErrorPayload, InitPayload, KVKeyEntry, KVKeyMetadata, KVSeedEntry, KVStatsResponse, KeyEventPayload, LoginResponse, MessageEventMap, PlatformTimebackUser, PlatformTimebackUserContext, PlaycademyMode, PlaycademyServerClientConfig, PlaycademyServerClientState, ScoreSubmission, StartActivityOptions, StartActivityResult, TelemetryPayload, TimebackEnrollment, TimebackInitContext, TimebackOrganization, TimebackUser, TimebackUserContext, TimebackUserRefreshField, TimebackUserRefreshOptions, TimebackUserXp, TokenRefreshPayload, TokenType, UpsertGameMetadataInput, UserRow as User, XpResponse };
|
|
3107
|
+
export type { ApiErrorCode, ApiErrorInfo, AssessmentBankStatus, AssessmentRow, AssessmentSummary, AuthCallbackPayload, AuthOptions, AuthProviderType, AuthResult, AuthServerMessage, AuthStateChangePayload, AuthStateUpdate, BetterAuthApiKey, BetterAuthApiKeyResponse, BetterAuthSignInResponse, BucketFile, ClientConfig, ClientEvents, CourseMastery, CourseXp, DemoEndOptions, DemoEndPayload, DevUploadEvent, DevUploadHooks, ErrorResponseBody, EventListeners, ExternalGame, FetchedGame, Game, GameContextPayload, GameCustomHostname, GameInitUser, GameRow as GameRecord, GameTokenResponse, GetMasteryOptions, GetXpOptions, HostedGame, InitErrorPayload, InitPayload, KVKeyEntry, KVKeyMetadata, KVSeedEntry, KVStatsResponse, KeyEventPayload, LoginResponse, MasteryResponse, MessageEventMap, PlatformTimebackUser, PlatformTimebackUserContext, PlaycademyMode, PlaycademyServerClientConfig, PlaycademyServerClientState, ScoreSubmission, StartActivityOptions, StartActivityResult, TelemetryPayload, TimebackEnrollment, TimebackInitContext, TimebackOrganization, TimebackUser, TimebackUserContext, TimebackUserMastery, TimebackUserRefreshField, TimebackUserRefreshOptions, TimebackUserXp, TokenRefreshPayload, TokenType, UpsertGameMetadataInput, UserRow as User, XpResponse };
|
package/dist/internal.js
CHANGED
|
@@ -1145,9 +1145,21 @@ function isValidSubject(value) {
|
|
|
1145
1145
|
var TIMEBACK_ROUTES = {
|
|
1146
1146
|
END_ACTIVITY: "/integrations/timeback/end-activity",
|
|
1147
1147
|
GET_XP: "/integrations/timeback/xp",
|
|
1148
|
+
GET_MASTERY: "/integrations/timeback/mastery",
|
|
1148
1149
|
HEARTBEAT: "/integrations/timeback/heartbeat",
|
|
1149
1150
|
ADVANCE_COURSE: "/integrations/timeback/advance-course"
|
|
1150
1151
|
};
|
|
1152
|
+
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
1153
|
+
xp: 1,
|
|
1154
|
+
mastery: 0,
|
|
1155
|
+
score: 2
|
|
1156
|
+
};
|
|
1157
|
+
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
1158
|
+
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.xp,
|
|
1159
|
+
mastery: 0,
|
|
1160
|
+
time: 60,
|
|
1161
|
+
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
1162
|
+
};
|
|
1151
1163
|
// src/core/cache/ttl-cache.ts
|
|
1152
1164
|
function createTTLCache(options) {
|
|
1153
1165
|
const cache = new Map;
|
|
@@ -1705,6 +1717,9 @@ function createTimebackActivityTracker(client) {
|
|
|
1705
1717
|
const unreportedActiveMs = Math.max(0, activeTime - activity.totalPersistedActiveMs);
|
|
1706
1718
|
const unreportedPausedMs = Math.max(0, activity.pausedTime - activity.totalPersistedPausedMs);
|
|
1707
1719
|
const { correctQuestions, totalQuestions } = data;
|
|
1720
|
+
if (data.masteredUnits !== undefined && data.masteredUnitsAbsolute !== undefined) {
|
|
1721
|
+
throw new Error("Cannot provide both masteredUnits and masteredUnitsAbsolute — use one or the other");
|
|
1722
|
+
}
|
|
1708
1723
|
const request = {
|
|
1709
1724
|
runId: activity.runId,
|
|
1710
1725
|
resumeId: activity.resumeId,
|
|
@@ -1722,6 +1737,7 @@ function createTimebackActivityTracker(client) {
|
|
|
1722
1737
|
},
|
|
1723
1738
|
xpEarned: data.xpAwarded,
|
|
1724
1739
|
masteredUnits: data.masteredUnits,
|
|
1740
|
+
masteredUnitsAbsolute: data.masteredUnitsAbsolute,
|
|
1725
1741
|
extensions: data.extensions
|
|
1726
1742
|
};
|
|
1727
1743
|
try {
|
|
@@ -1780,6 +1796,10 @@ function createTimebackEngine(client) {
|
|
|
1780
1796
|
ttl: 5000,
|
|
1781
1797
|
keyPrefix: "game.timeback.xp"
|
|
1782
1798
|
});
|
|
1799
|
+
const masteryCache = createTTLCache({
|
|
1800
|
+
ttl: 5000,
|
|
1801
|
+
keyPrefix: "game.timeback.mastery"
|
|
1802
|
+
});
|
|
1783
1803
|
const enrollmentsCache = createTTLCache({
|
|
1784
1804
|
ttl: 5 * 60 * 1000,
|
|
1785
1805
|
keyPrefix: "game.timeback.enrollments"
|
|
@@ -1847,6 +1867,30 @@ function createTimebackEngine(client) {
|
|
|
1847
1867
|
return client["requestGameBackend"](endpoint, "GET");
|
|
1848
1868
|
}, { force: options.force });
|
|
1849
1869
|
}
|
|
1870
|
+
},
|
|
1871
|
+
mastery: {
|
|
1872
|
+
fetch: (options) => {
|
|
1873
|
+
const cacheKey = [
|
|
1874
|
+
options.grade ?? "",
|
|
1875
|
+
options.subject ?? "",
|
|
1876
|
+
options.include?.toSorted().join(",") ?? ""
|
|
1877
|
+
].join(":");
|
|
1878
|
+
return masteryCache.get(cacheKey, async () => {
|
|
1879
|
+
const params = new URLSearchParams;
|
|
1880
|
+
if (options.grade !== undefined) {
|
|
1881
|
+
params.set("grade", String(options.grade));
|
|
1882
|
+
}
|
|
1883
|
+
if (options.subject !== undefined) {
|
|
1884
|
+
params.set("subject", options.subject);
|
|
1885
|
+
}
|
|
1886
|
+
if (options.include?.length) {
|
|
1887
|
+
params.set("include", options.include.join(","));
|
|
1888
|
+
}
|
|
1889
|
+
const queryString = params.toString();
|
|
1890
|
+
const endpoint = `${TIMEBACK_ROUTES.GET_MASTERY}${queryString ? `?${queryString}` : ""}`;
|
|
1891
|
+
return client["requestGameBackend"](endpoint, "GET");
|
|
1892
|
+
}, { force: options.force });
|
|
1893
|
+
}
|
|
1850
1894
|
}
|
|
1851
1895
|
},
|
|
1852
1896
|
activity: {
|
|
@@ -1865,7 +1909,8 @@ function createTimebackEngine(client) {
|
|
|
1865
1909
|
}
|
|
1866
1910
|
|
|
1867
1911
|
// src/namespaces/game/timeback.ts
|
|
1868
|
-
var
|
|
1912
|
+
var VALID_XP_INCLUDE_OPTIONS = ["perCourse", "today"];
|
|
1913
|
+
var VALID_MASTERY_INCLUDE_OPTIONS = ["perCourse"];
|
|
1869
1914
|
function createTimebackNamespace(client) {
|
|
1870
1915
|
const engine = createTimebackEngine(client);
|
|
1871
1916
|
return {
|
|
@@ -1901,13 +1946,36 @@ function createTimebackNamespace(client) {
|
|
|
1901
1946
|
}
|
|
1902
1947
|
if (options.include?.length) {
|
|
1903
1948
|
for (const opt of options.include) {
|
|
1904
|
-
if (!
|
|
1905
|
-
throw new Error(`Invalid include option: ${opt}. Valid options: ${
|
|
1949
|
+
if (!VALID_XP_INCLUDE_OPTIONS.includes(opt)) {
|
|
1950
|
+
throw new Error(`Invalid include option: ${opt}. Valid options: ${VALID_XP_INCLUDE_OPTIONS.join(", ")}`);
|
|
1906
1951
|
}
|
|
1907
1952
|
}
|
|
1908
1953
|
}
|
|
1909
1954
|
return engine.user.xp.fetch(options);
|
|
1910
1955
|
}
|
|
1956
|
+
},
|
|
1957
|
+
mastery: {
|
|
1958
|
+
fetch: async (options = {}) => {
|
|
1959
|
+
const hasGrade = options.grade !== undefined;
|
|
1960
|
+
const hasSubject = options.subject !== undefined;
|
|
1961
|
+
if (hasGrade !== hasSubject) {
|
|
1962
|
+
throw new Error("Both grade and subject must be provided together");
|
|
1963
|
+
}
|
|
1964
|
+
if (hasGrade && !isValidGrade(options.grade)) {
|
|
1965
|
+
throw new Error(`Invalid grade: ${options.grade}. Valid grades: ${VALID_GRADES.join(", ")}`);
|
|
1966
|
+
}
|
|
1967
|
+
if (hasSubject && !isValidSubject(options.subject)) {
|
|
1968
|
+
throw new Error(`Invalid subject: ${options.subject}. Valid subjects: ${VALID_SUBJECTS.join(", ")}`);
|
|
1969
|
+
}
|
|
1970
|
+
if (options.include?.length) {
|
|
1971
|
+
for (const opt of options.include) {
|
|
1972
|
+
if (!VALID_MASTERY_INCLUDE_OPTIONS.includes(opt)) {
|
|
1973
|
+
throw new Error(`Invalid include option: ${opt}. Valid options: ${VALID_MASTERY_INCLUDE_OPTIONS.join(", ")}`);
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
return engine.user.mastery.fetch(options);
|
|
1978
|
+
}
|
|
1911
1979
|
}
|
|
1912
1980
|
};
|
|
1913
1981
|
},
|
|
@@ -2577,6 +2645,14 @@ function createTimebackNamespace2(client) {
|
|
|
2577
2645
|
}
|
|
2578
2646
|
return client["request"](`/timeback/student-overview/${timebackId}?${params}`, "GET");
|
|
2579
2647
|
},
|
|
2648
|
+
getGameMetrics: (timebackId, options) => {
|
|
2649
|
+
const params = new URLSearchParams;
|
|
2650
|
+
for (const runId of options.runIds ?? []) {
|
|
2651
|
+
params.append("runId", runId);
|
|
2652
|
+
}
|
|
2653
|
+
const query = params.toString();
|
|
2654
|
+
return client["request"](`/timeback/game-metrics/${options.gameId}/${timebackId}${query ? `?${query}` : ""}`, "GET");
|
|
2655
|
+
},
|
|
2580
2656
|
getStudentActivity: (timebackId, courseId, options) => {
|
|
2581
2657
|
const params = new URLSearchParams({ gameId: options.gameId });
|
|
2582
2658
|
if (options.limit !== undefined) {
|
package/dist/server/edge.d.ts
CHANGED
|
@@ -298,6 +298,11 @@ declare class PlaycademyClient {
|
|
|
298
298
|
subject?: string;
|
|
299
299
|
include?: ('perCourse' | 'today')[];
|
|
300
300
|
}) => Promise<_playcademy_types.StudentXpResponse>;
|
|
301
|
+
getStudentMastery: (studentId: string, options?: {
|
|
302
|
+
grade?: number;
|
|
303
|
+
subject?: string;
|
|
304
|
+
include?: 'perCourse'[];
|
|
305
|
+
}) => Promise<_playcademy_types.StudentMasteryResponse>;
|
|
301
306
|
};
|
|
302
307
|
}
|
|
303
308
|
|
package/dist/server/edge.js
CHANGED
|
@@ -83,6 +83,33 @@ function createTimebackNamespace(client) {
|
|
|
83
83
|
const queryString = params.toString();
|
|
84
84
|
const endpoint = `/api/timeback/student-xp/${studentId}?${queryString}`;
|
|
85
85
|
return client["request"](endpoint, "GET");
|
|
86
|
+
},
|
|
87
|
+
getStudentMastery: async (studentId, options) => {
|
|
88
|
+
const hasGrade = options?.grade !== undefined;
|
|
89
|
+
const hasSubject = options?.subject !== undefined;
|
|
90
|
+
if (hasGrade !== hasSubject) {
|
|
91
|
+
throw new Error("Both grade and subject must be provided together");
|
|
92
|
+
}
|
|
93
|
+
if (hasGrade && !isValidGrade(options.grade)) {
|
|
94
|
+
throw new Error(`Invalid grade: ${options.grade}. Valid grades: ${VALID_GRADES.join(", ")}`);
|
|
95
|
+
}
|
|
96
|
+
if (hasSubject && !isValidSubject(options.subject)) {
|
|
97
|
+
throw new Error(`Invalid subject: ${options.subject}. Valid subjects: ${VALID_SUBJECTS.join(", ")}`);
|
|
98
|
+
}
|
|
99
|
+
const params = new URLSearchParams;
|
|
100
|
+
params.set("gameId", client.gameId);
|
|
101
|
+
if (options?.grade !== undefined) {
|
|
102
|
+
params.set("grade", String(options.grade));
|
|
103
|
+
}
|
|
104
|
+
if (options?.subject) {
|
|
105
|
+
params.set("subject", options.subject);
|
|
106
|
+
}
|
|
107
|
+
if (options?.include?.length) {
|
|
108
|
+
params.set("include", options.include.join(","));
|
|
109
|
+
}
|
|
110
|
+
const queryString = params.toString();
|
|
111
|
+
const endpoint = `/api/timeback/student-mastery/${studentId}?${queryString}`;
|
|
112
|
+
return client["request"](endpoint, "GET");
|
|
86
113
|
}
|
|
87
114
|
};
|
|
88
115
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -298,6 +298,11 @@ declare class PlaycademyClient$1 {
|
|
|
298
298
|
subject?: string;
|
|
299
299
|
include?: ('perCourse' | 'today')[];
|
|
300
300
|
}) => Promise<_playcademy_types.StudentXpResponse>;
|
|
301
|
+
getStudentMastery: (studentId: string, options?: {
|
|
302
|
+
grade?: number;
|
|
303
|
+
subject?: string;
|
|
304
|
+
include?: 'perCourse'[];
|
|
305
|
+
}) => Promise<_playcademy_types.StudentMasteryResponse>;
|
|
301
306
|
};
|
|
302
307
|
}
|
|
303
308
|
|
package/dist/server.js
CHANGED
|
@@ -272,6 +272,33 @@ function createTimebackNamespace(client) {
|
|
|
272
272
|
const queryString = params.toString();
|
|
273
273
|
const endpoint = `/api/timeback/student-xp/${studentId}?${queryString}`;
|
|
274
274
|
return client["request"](endpoint, "GET");
|
|
275
|
+
},
|
|
276
|
+
getStudentMastery: async (studentId, options) => {
|
|
277
|
+
const hasGrade = options?.grade !== undefined;
|
|
278
|
+
const hasSubject = options?.subject !== undefined;
|
|
279
|
+
if (hasGrade !== hasSubject) {
|
|
280
|
+
throw new Error("Both grade and subject must be provided together");
|
|
281
|
+
}
|
|
282
|
+
if (hasGrade && !isValidGrade(options.grade)) {
|
|
283
|
+
throw new Error(`Invalid grade: ${options.grade}. Valid grades: ${VALID_GRADES.join(", ")}`);
|
|
284
|
+
}
|
|
285
|
+
if (hasSubject && !isValidSubject(options.subject)) {
|
|
286
|
+
throw new Error(`Invalid subject: ${options.subject}. Valid subjects: ${VALID_SUBJECTS.join(", ")}`);
|
|
287
|
+
}
|
|
288
|
+
const params = new URLSearchParams;
|
|
289
|
+
params.set("gameId", client.gameId);
|
|
290
|
+
if (options?.grade !== undefined) {
|
|
291
|
+
params.set("grade", String(options.grade));
|
|
292
|
+
}
|
|
293
|
+
if (options?.subject) {
|
|
294
|
+
params.set("subject", options.subject);
|
|
295
|
+
}
|
|
296
|
+
if (options?.include?.length) {
|
|
297
|
+
params.set("include", options.include.join(","));
|
|
298
|
+
}
|
|
299
|
+
const queryString = params.toString();
|
|
300
|
+
const endpoint = `/api/timeback/student-mastery/${studentId}?${queryString}`;
|
|
301
|
+
return client["request"](endpoint, "GET");
|
|
275
302
|
}
|
|
276
303
|
};
|
|
277
304
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _playcademy_types from '@playcademy/types';
|
|
2
2
|
import { GameManifest } from '@playcademy/types';
|
|
3
|
-
export { AuthenticatedUser, DeveloperStatusEnumType, DeveloperStatusResponse, DeveloperStatusValue,
|
|
3
|
+
export { AuthenticatedUser, DeveloperStatusEnumType, DeveloperStatusResponse, DeveloperStatusValue, GameCourseMetrics, GameLeaderboardEntry, GameManifest, GameMetricComparisonKind, GameMetricComparisonMetric, GameMetricComparisonRow, GameMetricComparisonRowStatus, GameMetricsProxyResponse, GameMetricsResponse, GameMetricsUnsupportedReason, GamePlatform, GameRunMetrics, GameRunMetricsComparison, GameRunMetricsComparisonStatus, GameRunMetricsComparisonSummary, GameTimebackIntegration, GameType, GameUser, LeaderboardEntry, LeaderboardOptions, LeaderboardTimeframe, ManifestV1, ManifestV2, ManifestVersions, PopulateStudentResponse, UserEnrollment, UserInfo, UserOrganization, UserRank, UserRankResponse, UserRoleEnumType, UserScore, UserTimebackData } from '@playcademy/types';
|
|
4
4
|
import { TimebackCourseConfig, CourseConfig, OrganizationConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig, TimebackGrade, TimebackSubject } from '@playcademy/types/timeback';
|
|
5
5
|
export { QtiTestQuestionRef, QtiTestQuestionsResponse } from '@playcademy/types/timeback';
|
|
6
6
|
import { TimebackUserRole, UserEnrollment, UserOrganization, UserInfo } from '@playcademy/types/user';
|
|
@@ -1502,9 +1502,7 @@ interface StartActivityResult {
|
|
|
1502
1502
|
|
|
1503
1503
|
/**
|
|
1504
1504
|
* A TimeBack enrollment for the current game session.
|
|
1505
|
-
* Alias for UserEnrollment without the optional gameId.
|
|
1506
|
-
* are available at `enrollment.enrollmentIds?.active` when supplied by the
|
|
1507
|
-
* platform.
|
|
1505
|
+
* Alias for UserEnrollment without the optional gameId.
|
|
1508
1506
|
*/
|
|
1509
1507
|
type TimebackEnrollment = Omit<UserEnrollment, 'gameId'>;
|
|
1510
1508
|
/**
|
|
@@ -1610,6 +1608,50 @@ interface TimebackUser extends TimebackUserContext {
|
|
|
1610
1608
|
* Call `xp.fetch()` to get XP from the server.
|
|
1611
1609
|
*/
|
|
1612
1610
|
xp: TimebackUserXp;
|
|
1611
|
+
/**
|
|
1612
|
+
* Mastery data for the current user.
|
|
1613
|
+
* Call `mastery.fetch()` to get mastery progress from the server.
|
|
1614
|
+
*/
|
|
1615
|
+
mastery: TimebackUserMastery;
|
|
1616
|
+
}
|
|
1617
|
+
/**
|
|
1618
|
+
* Mastery data access for the current user.
|
|
1619
|
+
* Results are cached for 5 seconds to avoid redundant network requests.
|
|
1620
|
+
*/
|
|
1621
|
+
interface TimebackUserMastery {
|
|
1622
|
+
/**
|
|
1623
|
+
* Fetch mastery data from the server.
|
|
1624
|
+
* Returns mastery for all courses in this game, or filter by grade/subject.
|
|
1625
|
+
* Results are cached for 5 seconds (use `force: true` to bypass).
|
|
1626
|
+
*
|
|
1627
|
+
* @param options - Query options
|
|
1628
|
+
* @param options.grade - Grade level to filter (must be used with subject)
|
|
1629
|
+
* @param options.subject - Subject to filter (must be used with grade)
|
|
1630
|
+
* @param options.include - Additional data to include: 'perCourse'
|
|
1631
|
+
* @param options.force - Bypass cache and fetch fresh data (default: false)
|
|
1632
|
+
* @returns Promise resolving to mastery data
|
|
1633
|
+
*
|
|
1634
|
+
* @example
|
|
1635
|
+
* ```typescript
|
|
1636
|
+
* // Get total mastery for all game courses
|
|
1637
|
+
* const mastery = await client.timeback.user.mastery.fetch()
|
|
1638
|
+
*
|
|
1639
|
+
* // Get mastery for a specific grade/subject
|
|
1640
|
+
* const mastery = await client.timeback.user.mastery.fetch({
|
|
1641
|
+
* grade: 3,
|
|
1642
|
+
* subject: 'Math'
|
|
1643
|
+
* })
|
|
1644
|
+
*
|
|
1645
|
+
* // Get mastery with per-course breakdown
|
|
1646
|
+
* const mastery = await client.timeback.user.mastery.fetch({
|
|
1647
|
+
* include: ['perCourse']
|
|
1648
|
+
* })
|
|
1649
|
+
*
|
|
1650
|
+
* // Force fresh data
|
|
1651
|
+
* const mastery = await client.timeback.user.mastery.fetch({ force: true })
|
|
1652
|
+
* ```
|
|
1653
|
+
*/
|
|
1654
|
+
fetch(options?: GetMasteryOptions): Promise<MasteryResponse>;
|
|
1613
1655
|
}
|
|
1614
1656
|
/**
|
|
1615
1657
|
* Options for querying student XP.
|
|
@@ -1624,6 +1666,19 @@ interface GetXpOptions {
|
|
|
1624
1666
|
/** Bypass cache and fetch fresh data (default: false) */
|
|
1625
1667
|
force?: boolean;
|
|
1626
1668
|
}
|
|
1669
|
+
/**
|
|
1670
|
+
* Options for querying student mastery.
|
|
1671
|
+
*/
|
|
1672
|
+
interface GetMasteryOptions {
|
|
1673
|
+
/** Grade level to filter (must be used with subject) */
|
|
1674
|
+
grade?: TimebackGrade;
|
|
1675
|
+
/** Subject to filter (must be used with grade) */
|
|
1676
|
+
subject?: TimebackSubject;
|
|
1677
|
+
/** Additional data to include: 'perCourse' */
|
|
1678
|
+
include?: 'perCourse'[];
|
|
1679
|
+
/** Bypass cache and fetch fresh data (default: false) */
|
|
1680
|
+
force?: boolean;
|
|
1681
|
+
}
|
|
1627
1682
|
/**
|
|
1628
1683
|
* XP data for a single course.
|
|
1629
1684
|
*/
|
|
@@ -1642,6 +1697,26 @@ interface XpResponse {
|
|
|
1642
1697
|
todayXp?: number;
|
|
1643
1698
|
courses?: CourseXp[];
|
|
1644
1699
|
}
|
|
1700
|
+
/**
|
|
1701
|
+
* Mastery data for a single course.
|
|
1702
|
+
*/
|
|
1703
|
+
interface CourseMastery {
|
|
1704
|
+
grade: TimebackGrade;
|
|
1705
|
+
subject: TimebackSubject;
|
|
1706
|
+
title: string;
|
|
1707
|
+
masteredUnits: number;
|
|
1708
|
+
masterableUnits: number;
|
|
1709
|
+
pctComplete: number;
|
|
1710
|
+
isComplete: boolean;
|
|
1711
|
+
}
|
|
1712
|
+
/**
|
|
1713
|
+
* Response from mastery query.
|
|
1714
|
+
*/
|
|
1715
|
+
interface MasteryResponse {
|
|
1716
|
+
totalMasteredUnits: number;
|
|
1717
|
+
totalMasterableUnits: number;
|
|
1718
|
+
courses?: CourseMastery[];
|
|
1719
|
+
}
|
|
1645
1720
|
|
|
1646
1721
|
/**
|
|
1647
1722
|
* Core client configuration and lifecycle types
|
|
@@ -2067,4 +2142,4 @@ interface AssessmentBankStatus {
|
|
|
2067
2142
|
}
|
|
2068
2143
|
|
|
2069
2144
|
export { PlaycademyClient };
|
|
2070
|
-
export type { AssessmentBankStatus, AssessmentRow, AssessmentSummary, AuthCallbackPayload, AuthOptions, AuthProviderType, AuthResult, AuthServerMessage, AuthStateChangePayload, AuthStateUpdate, BetterAuthApiKey, BetterAuthApiKeyResponse, BetterAuthSignInResponse, BucketFile, ClientConfig, ClientEvents, CourseXp, DemoEndOptions, DemoEndPayload, DevUploadEvent, DevUploadHooks, EventListeners, ExternalGame, FetchedGame, Game, GameContextPayload, GameCustomHostname, GameInitUser, GameRow as GameRecord, GameTokenResponse, GetXpOptions, HostedGame, InitErrorPayload, InitPayload, KVKeyEntry, KVKeyMetadata, KVSeedEntry, KVStatsResponse, KeyEventPayload, LoginResponse, PlatformTimebackUser, PlatformTimebackUserContext, PlaycademyMode, PlaycademyServerClientConfig, PlaycademyServerClientState, ScoreSubmission, StartActivityOptions, StartActivityResult, TelemetryPayload, TimebackEnrollment, TimebackInitContext, TimebackOrganization, TimebackUser, TimebackUserContext, TimebackUserRefreshField, TimebackUserRefreshOptions, TimebackUserXp, TokenRefreshPayload, TokenType, UpsertGameMetadataInput, UserRow as User, XpResponse };
|
|
2145
|
+
export type { AssessmentBankStatus, AssessmentRow, AssessmentSummary, AuthCallbackPayload, AuthOptions, AuthProviderType, AuthResult, AuthServerMessage, AuthStateChangePayload, AuthStateUpdate, BetterAuthApiKey, BetterAuthApiKeyResponse, BetterAuthSignInResponse, BucketFile, ClientConfig, ClientEvents, CourseMastery, CourseXp, DemoEndOptions, DemoEndPayload, DevUploadEvent, DevUploadHooks, EventListeners, ExternalGame, FetchedGame, Game, GameContextPayload, GameCustomHostname, GameInitUser, GameRow as GameRecord, GameTokenResponse, GetMasteryOptions, GetXpOptions, HostedGame, InitErrorPayload, InitPayload, KVKeyEntry, KVKeyMetadata, KVSeedEntry, KVStatsResponse, KeyEventPayload, LoginResponse, MasteryResponse, PlatformTimebackUser, PlatformTimebackUserContext, PlaycademyMode, PlaycademyServerClientConfig, PlaycademyServerClientState, ScoreSubmission, StartActivityOptions, StartActivityResult, TelemetryPayload, TimebackEnrollment, TimebackInitContext, TimebackOrganization, TimebackUser, TimebackUserContext, TimebackUserMastery, TimebackUserRefreshField, TimebackUserRefreshOptions, TimebackUserXp, TokenRefreshPayload, TokenType, UpsertGameMetadataInput, UserRow as User, XpResponse };
|