@playcademy/vite-plugin 0.3.3-beta.1 → 0.3.3-beta.3
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/hooks/shell-sdk.d.ts +12 -0
- package/dist/index.js +312 -36
- package/package.json +5 -4
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Virtual module for the dev shell's SDK import
|
|
3
|
+
*
|
|
4
|
+
* The dev shell (shell.html) needs MessageEvents and messaging from
|
|
5
|
+
* @playcademy/sdk. Rather than loading the SDK from a remote CDN via
|
|
6
|
+
* an importmap, we serve a virtual module that re-exports the needed
|
|
7
|
+
* symbols. Vite resolves @playcademy/sdk through normal node resolution,
|
|
8
|
+
* so the shell always uses the locally installed SDK — whether that's a
|
|
9
|
+
* workspace link or an npm-installed version.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveShellSdkId(id: string): string | undefined;
|
|
12
|
+
export declare function loadShellSdk(id: string): string | undefined;
|
package/dist/index.js
CHANGED
|
@@ -23746,7 +23746,7 @@ import path from "node:path";
|
|
|
23746
23746
|
// package.json
|
|
23747
23747
|
var package_default = {
|
|
23748
23748
|
name: "@playcademy/vite-plugin",
|
|
23749
|
-
version: "0.3.3-beta.
|
|
23749
|
+
version: "0.3.3-beta.3",
|
|
23750
23750
|
type: "module",
|
|
23751
23751
|
exports: {
|
|
23752
23752
|
".": {
|
|
@@ -23779,6 +23779,7 @@ var package_default = {
|
|
|
23779
23779
|
"@types/bun": "1.3.5"
|
|
23780
23780
|
},
|
|
23781
23781
|
peerDependencies: {
|
|
23782
|
+
"@playcademy/sdk": ">=0.10.0",
|
|
23782
23783
|
typescript: "^5",
|
|
23783
23784
|
vite: "^5 || ^6"
|
|
23784
23785
|
}
|
|
@@ -24339,6 +24340,8 @@ var TIMEBACK_COURSE_DEFAULTS;
|
|
|
24339
24340
|
var TIMEBACK_RESOURCE_DEFAULTS;
|
|
24340
24341
|
var TIMEBACK_COMPONENT_DEFAULTS;
|
|
24341
24342
|
var TIMEBACK_COMPONENT_RESOURCE_DEFAULTS;
|
|
24343
|
+
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES;
|
|
24344
|
+
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE;
|
|
24342
24345
|
var init_timeback2 = __esm(() => {
|
|
24343
24346
|
TIMEBACK_ROUTES = {
|
|
24344
24347
|
END_ACTIVITY: "/integrations/timeback/end-activity",
|
|
@@ -24383,6 +24386,17 @@ var init_timeback2 = __esm(() => {
|
|
|
24383
24386
|
sortOrder: 1,
|
|
24384
24387
|
lessonType: "quiz"
|
|
24385
24388
|
};
|
|
24389
|
+
TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
24390
|
+
xp: 1,
|
|
24391
|
+
mastery: 0,
|
|
24392
|
+
score: 2
|
|
24393
|
+
};
|
|
24394
|
+
TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
24395
|
+
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.xp,
|
|
24396
|
+
mastery: 0,
|
|
24397
|
+
time: 60,
|
|
24398
|
+
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
24399
|
+
};
|
|
24386
24400
|
});
|
|
24387
24401
|
var WORKER_NAMING;
|
|
24388
24402
|
var SECRETS_PREFIX = "secrets_";
|
|
@@ -25177,7 +25191,7 @@ var package_default2;
|
|
|
25177
25191
|
var init_package = __esm(() => {
|
|
25178
25192
|
package_default2 = {
|
|
25179
25193
|
name: "@playcademy/sandbox",
|
|
25180
|
-
version: "0.4.1-beta.
|
|
25194
|
+
version: "0.4.1-beta.3",
|
|
25181
25195
|
description: "Local development server for Playcademy game development",
|
|
25182
25196
|
type: "module",
|
|
25183
25197
|
exports: {
|
|
@@ -53873,7 +53887,7 @@ var CourseGoalsSchema;
|
|
|
53873
53887
|
var UpdateGameTimebackIntegrationRequestSchema;
|
|
53874
53888
|
var TimebackActivityDataSchema;
|
|
53875
53889
|
var EndActivityRequestSchema;
|
|
53876
|
-
var
|
|
53890
|
+
var GameRunMetricsSchema;
|
|
53877
53891
|
var GameCourseMetricsSchema;
|
|
53878
53892
|
var GameMetricsResponseSchema;
|
|
53879
53893
|
var AdvanceCourseRequestSchema;
|
|
@@ -53972,22 +53986,22 @@ var init_schemas4 = __esm(() => {
|
|
|
53972
53986
|
message: "Cannot provide both masteredUnits and masteredUnitsAbsolute",
|
|
53973
53987
|
path: ["masteredUnitsAbsolute"]
|
|
53974
53988
|
});
|
|
53975
|
-
|
|
53989
|
+
GameRunMetricsSchema = exports_external.object({
|
|
53990
|
+
runId: exports_external.string().uuid(),
|
|
53976
53991
|
activityId: exports_external.string().min(1),
|
|
53977
53992
|
activityName: exports_external.string().optional(),
|
|
53978
|
-
totalXp: exports_external.number().nonnegative(),
|
|
53979
|
-
masteredUnits: exports_external.number().int().nonnegative(),
|
|
53980
|
-
activeTimeSeconds: exports_external.number().nonnegative(),
|
|
53981
|
-
|
|
53982
|
-
lastCompletedAt: exports_external.string().datetime().optional()
|
|
53993
|
+
totalXp: exports_external.number().nonnegative().optional(),
|
|
53994
|
+
masteredUnits: exports_external.number().int().nonnegative().optional(),
|
|
53995
|
+
activeTimeSeconds: exports_external.number().nonnegative().optional(),
|
|
53996
|
+
score: exports_external.number().min(0).max(100).optional()
|
|
53983
53997
|
});
|
|
53984
53998
|
GameCourseMetricsSchema = exports_external.object({
|
|
53985
53999
|
grade: TimebackGradeSchema,
|
|
53986
54000
|
subject: TimebackSubjectSchema,
|
|
53987
|
-
totalXp: exports_external.number().nonnegative(),
|
|
53988
|
-
masteredUnits: exports_external.number().int().nonnegative(),
|
|
53989
|
-
activeTimeSeconds: exports_external.number().nonnegative(),
|
|
53990
|
-
activities: exports_external.array(
|
|
54001
|
+
totalXp: exports_external.number().nonnegative().optional(),
|
|
54002
|
+
masteredUnits: exports_external.number().int().nonnegative().optional(),
|
|
54003
|
+
activeTimeSeconds: exports_external.number().nonnegative().optional(),
|
|
54004
|
+
activities: exports_external.array(GameRunMetricsSchema).optional()
|
|
53991
54005
|
});
|
|
53992
54006
|
GameMetricsResponseSchema = exports_external.object({
|
|
53993
54007
|
studentId: exports_external.string().min(1),
|
|
@@ -54257,6 +54271,122 @@ function compareEnrollmentsByRecency(a, b) {
|
|
|
54257
54271
|
var init_timeback_admin_util = __esm(() => {
|
|
54258
54272
|
init_errors();
|
|
54259
54273
|
});
|
|
54274
|
+
function createMetricRow(definition) {
|
|
54275
|
+
const { gameValue, kind, metric, timebackValue, tolerance } = definition;
|
|
54276
|
+
if (timebackValue === undefined && gameValue === undefined) {
|
|
54277
|
+
return null;
|
|
54278
|
+
}
|
|
54279
|
+
if (gameValue === undefined) {
|
|
54280
|
+
return {
|
|
54281
|
+
metric,
|
|
54282
|
+
kind,
|
|
54283
|
+
status: "not_reported_by_game",
|
|
54284
|
+
...timebackValue !== undefined ? { timebackValue } : {}
|
|
54285
|
+
};
|
|
54286
|
+
}
|
|
54287
|
+
if (timebackValue === undefined) {
|
|
54288
|
+
return {
|
|
54289
|
+
metric,
|
|
54290
|
+
kind,
|
|
54291
|
+
status: "not_recorded_by_timeback",
|
|
54292
|
+
gameValue
|
|
54293
|
+
};
|
|
54294
|
+
}
|
|
54295
|
+
const delta = gameValue - timebackValue;
|
|
54296
|
+
const isDiscrepant = tolerance === 0 ? delta !== 0 : Math.abs(delta) >= tolerance;
|
|
54297
|
+
return {
|
|
54298
|
+
metric,
|
|
54299
|
+
kind,
|
|
54300
|
+
status: isDiscrepant ? "discrepant" : "matched",
|
|
54301
|
+
timebackValue,
|
|
54302
|
+
gameValue,
|
|
54303
|
+
delta
|
|
54304
|
+
};
|
|
54305
|
+
}
|
|
54306
|
+
function createRunComparison(activity, gameRun) {
|
|
54307
|
+
const runId = activity.runId ?? "";
|
|
54308
|
+
if (!gameRun) {
|
|
54309
|
+
return {
|
|
54310
|
+
runId,
|
|
54311
|
+
status: "not_reported",
|
|
54312
|
+
discrepancyCount: 0,
|
|
54313
|
+
rows: []
|
|
54314
|
+
};
|
|
54315
|
+
}
|
|
54316
|
+
const rows = [
|
|
54317
|
+
createMetricRow({
|
|
54318
|
+
metric: "xp",
|
|
54319
|
+
kind: "number",
|
|
54320
|
+
timebackValue: activity.xpDelta,
|
|
54321
|
+
gameValue: gameRun.totalXp,
|
|
54322
|
+
tolerance: TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE.xp
|
|
54323
|
+
}),
|
|
54324
|
+
createMetricRow({
|
|
54325
|
+
metric: "mastery",
|
|
54326
|
+
kind: "number",
|
|
54327
|
+
timebackValue: activity.masteredUnitsDelta,
|
|
54328
|
+
gameValue: gameRun.masteredUnits,
|
|
54329
|
+
tolerance: TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE.mastery
|
|
54330
|
+
}),
|
|
54331
|
+
createMetricRow({
|
|
54332
|
+
metric: "time",
|
|
54333
|
+
kind: "time",
|
|
54334
|
+
timebackValue: activity.timeDeltaSeconds,
|
|
54335
|
+
gameValue: gameRun.activeTimeSeconds,
|
|
54336
|
+
tolerance: TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE.time
|
|
54337
|
+
}),
|
|
54338
|
+
createMetricRow({
|
|
54339
|
+
metric: "score",
|
|
54340
|
+
kind: "percent",
|
|
54341
|
+
timebackValue: activity.score,
|
|
54342
|
+
gameValue: gameRun.score,
|
|
54343
|
+
tolerance: TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE.score
|
|
54344
|
+
})
|
|
54345
|
+
].filter((row) => row !== null);
|
|
54346
|
+
const discrepancyCount = rows.filter((row) => row.status === "discrepant").length;
|
|
54347
|
+
return {
|
|
54348
|
+
runId,
|
|
54349
|
+
status: discrepancyCount > 0 ? "discrepant" : "matched",
|
|
54350
|
+
discrepancyCount,
|
|
54351
|
+
rows
|
|
54352
|
+
};
|
|
54353
|
+
}
|
|
54354
|
+
function summarizeGameRunMetricsComparison(comparison) {
|
|
54355
|
+
return {
|
|
54356
|
+
runId: comparison.runId,
|
|
54357
|
+
status: comparison.status,
|
|
54358
|
+
discrepancyCount: comparison.discrepancyCount,
|
|
54359
|
+
...comparison.reason ? { reason: comparison.reason } : {}
|
|
54360
|
+
};
|
|
54361
|
+
}
|
|
54362
|
+
function buildGameRunMetricComparisons(activities, course, response) {
|
|
54363
|
+
const activitiesWithRunIds = activities.filter((activity) => typeof activity.runId === "string" && activity.runId.length > 0);
|
|
54364
|
+
const comparisons = new Map;
|
|
54365
|
+
if (activitiesWithRunIds.length === 0) {
|
|
54366
|
+
return comparisons;
|
|
54367
|
+
}
|
|
54368
|
+
if (!response.supported) {
|
|
54369
|
+
for (const activity of activitiesWithRunIds) {
|
|
54370
|
+
comparisons.set(activity.runId, {
|
|
54371
|
+
runId: activity.runId,
|
|
54372
|
+
status: "unavailable",
|
|
54373
|
+
discrepancyCount: 0,
|
|
54374
|
+
reason: response.reason,
|
|
54375
|
+
rows: []
|
|
54376
|
+
});
|
|
54377
|
+
}
|
|
54378
|
+
return comparisons;
|
|
54379
|
+
}
|
|
54380
|
+
const gameCourseMetrics = response.metrics.courses.find((gameCourse) => gameCourse.grade === course.grade && gameCourse.subject === course.subject);
|
|
54381
|
+
const gameRunsById = new Map(gameCourseMetrics?.activities?.map((gameRun) => [gameRun.runId.toLowerCase(), gameRun]));
|
|
54382
|
+
for (const activity of activitiesWithRunIds) {
|
|
54383
|
+
comparisons.set(activity.runId, createRunComparison(activity, gameRunsById.get(activity.runId.toLowerCase())));
|
|
54384
|
+
}
|
|
54385
|
+
return comparisons;
|
|
54386
|
+
}
|
|
54387
|
+
var init_timeback_game_metrics_comparison_util = __esm(() => {
|
|
54388
|
+
init_src();
|
|
54389
|
+
});
|
|
54260
54390
|
async function upsertMasteryCompletionEntry(params) {
|
|
54261
54391
|
const { client, courseId, studentId, appName, action } = params;
|
|
54262
54392
|
const ids = deriveSourcedIds(courseId);
|
|
@@ -54643,6 +54773,8 @@ class TimebackAdminService {
|
|
|
54643
54773
|
static ANALYTICS_CONCURRENCY = 8;
|
|
54644
54774
|
static MASTERABLE_UNITS_CONCURRENCY = 4;
|
|
54645
54775
|
static GAME_METRICS_FETCH_TIMEOUT_MS = 1e4;
|
|
54776
|
+
static GAME_METRICS_LIST_FETCH_TIMEOUT_MS = 3000;
|
|
54777
|
+
static GAME_METRICS_RUN_IDS_PER_REQUEST = 50;
|
|
54646
54778
|
constructor(deps) {
|
|
54647
54779
|
this.deps = deps;
|
|
54648
54780
|
}
|
|
@@ -54652,13 +54784,42 @@ class TimebackAdminService {
|
|
|
54652
54784
|
}
|
|
54653
54785
|
return this.deps.config.localGameUrls[slug2] ?? deployedUrl;
|
|
54654
54786
|
}
|
|
54655
|
-
static resolveGameMetricsUrl(baseUrl) {
|
|
54787
|
+
static resolveGameMetricsUrl(baseUrl, runIds) {
|
|
54656
54788
|
try {
|
|
54657
|
-
|
|
54789
|
+
const url2 = new URL("/__playcademy/metrics", baseUrl);
|
|
54790
|
+
for (const runId of runIds ?? []) {
|
|
54791
|
+
url2.searchParams.append("runId", runId);
|
|
54792
|
+
}
|
|
54793
|
+
return url2;
|
|
54658
54794
|
} catch {
|
|
54659
54795
|
return null;
|
|
54660
54796
|
}
|
|
54661
54797
|
}
|
|
54798
|
+
static normalizeRunIds(runIds, limit = Number.POSITIVE_INFINITY) {
|
|
54799
|
+
const normalized = [];
|
|
54800
|
+
const seen = new Set;
|
|
54801
|
+
for (const runId of runIds ?? []) {
|
|
54802
|
+
const value = runId.trim().toLowerCase();
|
|
54803
|
+
if (isValidUUID(value) && !seen.has(value)) {
|
|
54804
|
+
seen.add(value);
|
|
54805
|
+
normalized.push(value);
|
|
54806
|
+
if (normalized.length >= limit) {
|
|
54807
|
+
break;
|
|
54808
|
+
}
|
|
54809
|
+
}
|
|
54810
|
+
}
|
|
54811
|
+
return normalized;
|
|
54812
|
+
}
|
|
54813
|
+
static chunkRunIds(runIds) {
|
|
54814
|
+
const chunks = [];
|
|
54815
|
+
for (let index2 = 0;index2 < runIds.length; index2 += this.GAME_METRICS_RUN_IDS_PER_REQUEST) {
|
|
54816
|
+
chunks.push(runIds.slice(index2, index2 + this.GAME_METRICS_RUN_IDS_PER_REQUEST));
|
|
54817
|
+
}
|
|
54818
|
+
return chunks;
|
|
54819
|
+
}
|
|
54820
|
+
static isAbortError(error) {
|
|
54821
|
+
return error instanceof Error && error.name === "AbortError";
|
|
54822
|
+
}
|
|
54662
54823
|
static roundXpToTenths(value) {
|
|
54663
54824
|
const rounded = Math.round(value * TimebackAdminService.XP_PRECISION_FACTOR) / TimebackAdminService.XP_PRECISION_FACTOR;
|
|
54664
54825
|
return Object.is(rounded, -0) ? 0 : rounded;
|
|
@@ -54819,6 +54980,56 @@ class TimebackAdminService {
|
|
|
54819
54980
|
const remediationItems = events.map((event) => mapCaliperEventToRemediationActivity(event, relevantCourseIds)).filter((item) => Boolean(item));
|
|
54820
54981
|
return [...groupedGameplayItems, ...remediationItems].toSorted((a, b) => b.occurredAt.localeCompare(a.occurredAt));
|
|
54821
54982
|
}
|
|
54983
|
+
async getGameMetricComparisonsForActivities(user, options) {
|
|
54984
|
+
const runIds = TimebackAdminService.normalizeRunIds(options.activities.map((activity) => activity.runId).filter((runId) => Boolean(runId)));
|
|
54985
|
+
if (runIds.length === 0) {
|
|
54986
|
+
return new Map;
|
|
54987
|
+
}
|
|
54988
|
+
const activitiesByRunId = new Map(options.activities.filter((activity) => typeof activity.runId === "string" && activity.runId.length > 0).map((activity) => [activity.runId.toLowerCase(), activity]));
|
|
54989
|
+
const comparisons = new Map;
|
|
54990
|
+
await Promise.all(TimebackAdminService.chunkRunIds(runIds).map(async (chunk) => {
|
|
54991
|
+
const activities = [];
|
|
54992
|
+
for (const runId of chunk) {
|
|
54993
|
+
const activity = activitiesByRunId.get(runId);
|
|
54994
|
+
if (activity) {
|
|
54995
|
+
activities.push(activity);
|
|
54996
|
+
}
|
|
54997
|
+
}
|
|
54998
|
+
if (activities.length === 0) {
|
|
54999
|
+
return;
|
|
55000
|
+
}
|
|
55001
|
+
let response;
|
|
55002
|
+
try {
|
|
55003
|
+
response = await this.getGameMetrics(options.gameId, options.studentId, user, {
|
|
55004
|
+
runIds: chunk,
|
|
55005
|
+
timeoutMs: options.timeoutMs
|
|
55006
|
+
});
|
|
55007
|
+
} catch (error) {
|
|
55008
|
+
response = {
|
|
55009
|
+
supported: false,
|
|
55010
|
+
reason: "fetch_failed",
|
|
55011
|
+
details: error instanceof Error ? error.message : String(error)
|
|
55012
|
+
};
|
|
55013
|
+
}
|
|
55014
|
+
for (const [runId, comparison] of buildGameRunMetricComparisons(activities, options.course, response)) {
|
|
55015
|
+
comparisons.set(runId, comparison);
|
|
55016
|
+
}
|
|
55017
|
+
}));
|
|
55018
|
+
return comparisons;
|
|
55019
|
+
}
|
|
55020
|
+
async attachGameMetricSummariesToActivities(user, options) {
|
|
55021
|
+
const comparisons = await this.getGameMetricComparisonsForActivities(user, options);
|
|
55022
|
+
if (comparisons.size === 0) {
|
|
55023
|
+
return [...options.activities];
|
|
55024
|
+
}
|
|
55025
|
+
return options.activities.map((activity) => {
|
|
55026
|
+
const comparison = activity.runId ? comparisons.get(activity.runId) : undefined;
|
|
55027
|
+
return comparison ? {
|
|
55028
|
+
...activity,
|
|
55029
|
+
gameMetricsComparison: summarizeGameRunMetricsComparison(comparison)
|
|
55030
|
+
} : activity;
|
|
55031
|
+
});
|
|
55032
|
+
}
|
|
54822
55033
|
async getStudentEnrollmentsByCourseId(client, studentId, courseIds, options) {
|
|
54823
55034
|
const enrollments = new Map;
|
|
54824
55035
|
const allEnrollments = new Map;
|
|
@@ -54978,7 +55189,7 @@ class TimebackAdminService {
|
|
|
54978
55189
|
});
|
|
54979
55190
|
return { gameId, courseId, students: deduped };
|
|
54980
55191
|
}
|
|
54981
|
-
async getGameMetrics(gameId, timebackId, user) {
|
|
55192
|
+
async getGameMetrics(gameId, timebackId, user, options) {
|
|
54982
55193
|
const client = this.requireClient();
|
|
54983
55194
|
await this.deps.validateGameManagementAccess(user, gameId);
|
|
54984
55195
|
const [targetUser, integrations, game2, deployment] = await Promise.all([
|
|
@@ -55013,7 +55224,8 @@ class TimebackAdminService {
|
|
|
55013
55224
|
if (!metricsBaseUrl) {
|
|
55014
55225
|
return { supported: false, reason: "no_active_deployment" };
|
|
55015
55226
|
}
|
|
55016
|
-
const
|
|
55227
|
+
const runIds = TimebackAdminService.normalizeRunIds(options?.runIds, TimebackAdminService.GAME_METRICS_RUN_IDS_PER_REQUEST);
|
|
55228
|
+
const metricsUrl = TimebackAdminService.resolveGameMetricsUrl(metricsBaseUrl, runIds);
|
|
55017
55229
|
if (!metricsUrl) {
|
|
55018
55230
|
return {
|
|
55019
55231
|
supported: false,
|
|
@@ -55023,7 +55235,7 @@ class TimebackAdminService {
|
|
|
55023
55235
|
}
|
|
55024
55236
|
const token = await this.deps.mintPlatformServiceToken(gameId, targetUser.id);
|
|
55025
55237
|
const controller = new AbortController;
|
|
55026
|
-
const timeout = setTimeout(() => controller.abort(), TimebackAdminService.GAME_METRICS_FETCH_TIMEOUT_MS);
|
|
55238
|
+
const timeout = setTimeout(() => controller.abort(), options?.timeoutMs ?? TimebackAdminService.GAME_METRICS_FETCH_TIMEOUT_MS);
|
|
55027
55239
|
let response;
|
|
55028
55240
|
try {
|
|
55029
55241
|
response = await fetch(metricsUrl, {
|
|
@@ -55035,10 +55247,19 @@ class TimebackAdminService {
|
|
|
55035
55247
|
signal: controller.signal
|
|
55036
55248
|
});
|
|
55037
55249
|
} catch (error) {
|
|
55250
|
+
const timedOut = TimebackAdminService.isAbortError(error);
|
|
55251
|
+
let details;
|
|
55252
|
+
if (timedOut) {
|
|
55253
|
+
details = "Game metrics request timed out";
|
|
55254
|
+
} else if (error instanceof Error) {
|
|
55255
|
+
details = error.message;
|
|
55256
|
+
} else {
|
|
55257
|
+
details = String(error);
|
|
55258
|
+
}
|
|
55038
55259
|
return {
|
|
55039
55260
|
supported: false,
|
|
55040
|
-
reason: "fetch_failed",
|
|
55041
|
-
details
|
|
55261
|
+
reason: timedOut ? "timeout" : "fetch_failed",
|
|
55262
|
+
details
|
|
55042
55263
|
};
|
|
55043
55264
|
} finally {
|
|
55044
55265
|
clearTimeout(timeout);
|
|
@@ -55142,7 +55363,14 @@ class TimebackAdminService {
|
|
|
55142
55363
|
const allActivities = await this.listRecentActivityForStudent(client, studentId, gameSource, relevantCourseIds, fetchLimit);
|
|
55143
55364
|
const activities = allActivities.slice(safeOffset, safeOffset + safeLimit);
|
|
55144
55365
|
const hasMore = allActivities.length > safeOffset + safeLimit;
|
|
55145
|
-
|
|
55366
|
+
const activitiesWithGameMetrics = await this.attachGameMetricSummariesToActivities(user, {
|
|
55367
|
+
gameId,
|
|
55368
|
+
studentId,
|
|
55369
|
+
course: { grade: integration.grade, subject: integration.subject },
|
|
55370
|
+
activities,
|
|
55371
|
+
timeoutMs: TimebackAdminService.GAME_METRICS_LIST_FETCH_TIMEOUT_MS
|
|
55372
|
+
});
|
|
55373
|
+
return { activities: activitiesWithGameMetrics, hasMore };
|
|
55146
55374
|
}
|
|
55147
55375
|
async getActivityDetail(user, options) {
|
|
55148
55376
|
const { gameId, studentId, courseId, activityId, runId } = options;
|
|
@@ -55178,7 +55406,22 @@ class TimebackAdminService {
|
|
|
55178
55406
|
if (!activity) {
|
|
55179
55407
|
throw new NotFoundError("Activity", activityId);
|
|
55180
55408
|
}
|
|
55181
|
-
|
|
55409
|
+
const comparisons = await this.getGameMetricComparisonsForActivities(user, {
|
|
55410
|
+
gameId,
|
|
55411
|
+
studentId,
|
|
55412
|
+
course: { grade: integration.grade, subject: integration.subject },
|
|
55413
|
+
activities: [activity]
|
|
55414
|
+
});
|
|
55415
|
+
const gameMetricsComparison = activity.runId ? comparisons.get(activity.runId) : undefined;
|
|
55416
|
+
const activityWithGameMetrics = gameMetricsComparison ? {
|
|
55417
|
+
...activity,
|
|
55418
|
+
gameMetricsComparison: summarizeGameRunMetricsComparison(gameMetricsComparison)
|
|
55419
|
+
} : activity;
|
|
55420
|
+
return {
|
|
55421
|
+
activity: activityWithGameMetrics,
|
|
55422
|
+
rawEvents: matchedEvents,
|
|
55423
|
+
...gameMetricsComparison ? { gameMetricsComparison } : {}
|
|
55424
|
+
};
|
|
55182
55425
|
}
|
|
55183
55426
|
async grantManualXp(data, user) {
|
|
55184
55427
|
const { client, sensorUrl, appName, actor } = await this.resolveAdminMutationContext(data.gameId, data.courseId, user, data.studentId);
|
|
@@ -55466,6 +55709,7 @@ var init_timeback_admin_service = __esm(() => {
|
|
|
55466
55709
|
init_errors();
|
|
55467
55710
|
init_timeback_admin_metrics_util();
|
|
55468
55711
|
init_timeback_admin_util();
|
|
55712
|
+
init_timeback_game_metrics_comparison_util();
|
|
55469
55713
|
init_timeback_mastery_completion_util();
|
|
55470
55714
|
init_timeback_util();
|
|
55471
55715
|
logger17 = log.scope("TimebackAdminService");
|
|
@@ -120916,15 +121160,19 @@ var init_timeback_controller = __esm(() => {
|
|
|
120916
121160
|
getGameMetrics = requireGameManagementAccess(async (ctx) => {
|
|
120917
121161
|
const gameId = ctx.params.gameId;
|
|
120918
121162
|
const timebackId = ctx.params.timebackId;
|
|
121163
|
+
const runIds = [
|
|
121164
|
+
...new Set(ctx.url.searchParams.getAll("runId").map((runId) => runId.trim().toLowerCase()).filter(isValidUUID))
|
|
121165
|
+
];
|
|
120919
121166
|
if (!gameId || !timebackId) {
|
|
120920
121167
|
throw ApiError.badRequest("Missing gameId or timebackId path parameter");
|
|
120921
121168
|
}
|
|
120922
121169
|
logger45.debug("Getting game metrics", {
|
|
120923
121170
|
requesterId: ctx.user.id,
|
|
120924
121171
|
gameId,
|
|
120925
|
-
timebackId
|
|
121172
|
+
timebackId,
|
|
121173
|
+
runIds
|
|
120926
121174
|
});
|
|
120927
|
-
return ctx.services.timebackAdmin.getGameMetrics(gameId, timebackId, ctx.user);
|
|
121175
|
+
return ctx.services.timebackAdmin.getGameMetrics(gameId, timebackId, ctx.user, { runIds });
|
|
120928
121176
|
});
|
|
120929
121177
|
getStudentActivity = requireGameManagementAccess(async (ctx) => {
|
|
120930
121178
|
const timebackId = ctx.params.timebackId;
|
|
@@ -122767,6 +123015,17 @@ var POSTHOG_CONFIG = {
|
|
|
122767
123015
|
var TIMEBACK_ORG_SOURCED_ID2 = "PLAYCADEMY";
|
|
122768
123016
|
var TIMEBACK_ORG_NAME2 = "Playcademy Studios";
|
|
122769
123017
|
var TIMEBACK_ORG_TYPE2 = "department";
|
|
123018
|
+
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES2 = {
|
|
123019
|
+
xp: 1,
|
|
123020
|
+
mastery: 0,
|
|
123021
|
+
score: 2
|
|
123022
|
+
};
|
|
123023
|
+
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE2 = {
|
|
123024
|
+
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES2.xp,
|
|
123025
|
+
mastery: 0,
|
|
123026
|
+
time: 60,
|
|
123027
|
+
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES2.score
|
|
123028
|
+
};
|
|
122770
123029
|
// src/lib/sandbox/timeback.ts
|
|
122771
123030
|
function detectTimebackOptions() {
|
|
122772
123031
|
if (process.env.TIMEBACK_LOCAL === "true") {
|
|
@@ -122983,6 +123242,8 @@ var TIMEBACK_COURSE_DEFAULTS2;
|
|
|
122983
123242
|
var TIMEBACK_RESOURCE_DEFAULTS2;
|
|
122984
123243
|
var TIMEBACK_COMPONENT_DEFAULTS2;
|
|
122985
123244
|
var TIMEBACK_COMPONENT_RESOURCE_DEFAULTS2;
|
|
123245
|
+
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES3;
|
|
123246
|
+
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE3;
|
|
122986
123247
|
var init_timeback7 = __esm8(() => {
|
|
122987
123248
|
TIMEBACK_ROUTES2 = {
|
|
122988
123249
|
END_ACTIVITY: "/integrations/timeback/end-activity",
|
|
@@ -123027,6 +123288,17 @@ var init_timeback7 = __esm8(() => {
|
|
|
123027
123288
|
sortOrder: 1,
|
|
123028
123289
|
lessonType: "quiz"
|
|
123029
123290
|
};
|
|
123291
|
+
TIMEBACK_GAME_METRIC_DECIMAL_PLACES3 = {
|
|
123292
|
+
xp: 1,
|
|
123293
|
+
mastery: 0,
|
|
123294
|
+
score: 2
|
|
123295
|
+
};
|
|
123296
|
+
TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE3 = {
|
|
123297
|
+
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES3.xp,
|
|
123298
|
+
mastery: 0,
|
|
123299
|
+
time: 60,
|
|
123300
|
+
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES3.score
|
|
123301
|
+
};
|
|
123030
123302
|
});
|
|
123031
123303
|
var WORKER_NAMING2;
|
|
123032
123304
|
var init_cloudflare2 = __esm8(() => {
|
|
@@ -123199,14 +123471,6 @@ var shell_default = `<!doctype html>
|
|
|
123199
123471
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
123200
123472
|
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet" />
|
|
123201
123473
|
<script type="module" src="/@vite/client"></script>
|
|
123202
|
-
<script type="importmap">
|
|
123203
|
-
{
|
|
123204
|
-
"imports": {
|
|
123205
|
-
"@playcademy/sdk": "https://esm.sh/@playcademy/sdk@latest",
|
|
123206
|
-
"@playcademy/sdk-fallback": "https://cdn.playcademy.net/sdk/latest/index.js"
|
|
123207
|
-
}
|
|
123208
|
-
}
|
|
123209
|
-
</script>
|
|
123210
123474
|
<style>
|
|
123211
123475
|
* {
|
|
123212
123476
|
margin: 0;
|
|
@@ -123252,10 +123516,7 @@ var shell_default = `<!doctype html>
|
|
|
123252
123516
|
<iframe id="frame" class="hidden"></iframe>
|
|
123253
123517
|
|
|
123254
123518
|
<script type="module">
|
|
123255
|
-
const { MessageEvents, messaging } = await
|
|
123256
|
-
import('@playcademy/sdk'),
|
|
123257
|
-
import('@playcademy/sdk-fallback'),
|
|
123258
|
-
])
|
|
123519
|
+
const { MessageEvents, messaging } = await import('/@playcademy/shell-sdk')
|
|
123259
123520
|
|
|
123260
123521
|
const CONFIG = {
|
|
123261
123522
|
sandboxUrl: '{{SANDBOX_URL}}',
|
|
@@ -123873,6 +124134,19 @@ async function configureServerHook(server, context) {
|
|
|
123873
124134
|
}
|
|
123874
124135
|
}
|
|
123875
124136
|
|
|
124137
|
+
// src/hooks/shell-sdk.ts
|
|
124138
|
+
var SHELL_SDK_ID = "/@playcademy/shell-sdk";
|
|
124139
|
+
function resolveShellSdkId(id) {
|
|
124140
|
+
if (id === SHELL_SDK_ID) {
|
|
124141
|
+
return SHELL_SDK_ID;
|
|
124142
|
+
}
|
|
124143
|
+
}
|
|
124144
|
+
function loadShellSdk(id) {
|
|
124145
|
+
if (id === SHELL_SDK_ID) {
|
|
124146
|
+
return `export { MessageEvents, messaging } from '@playcademy/sdk'`;
|
|
124147
|
+
}
|
|
124148
|
+
}
|
|
124149
|
+
|
|
123876
124150
|
// src/hooks/transform-index-html.ts
|
|
123877
124151
|
var SERVER_TIMING_PATCH = '!function(){function p(P){var o=P.prototype.toJSON;if(o){P.prototype.toJSON=function(){var r=o.call(this);delete r.serverTiming;return r}}}if(typeof PerformanceResourceTiming!=="undefined")p(PerformanceResourceTiming);if(typeof PerformanceNavigationTiming!=="undefined")p(PerformanceNavigationTiming)}();';
|
|
123878
124152
|
var POSTHOG_LOADER = '!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug getPageViewId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);';
|
|
@@ -123963,6 +124237,8 @@ function playcademy(options = {}) {
|
|
|
123963
124237
|
config: (userConfig) => configHook(userConfig, context),
|
|
123964
124238
|
configResolved: (resolvedConfig) => configResolvedHook(resolvedConfig, context),
|
|
123965
124239
|
configureServer: (server) => configureServerHook(server, context),
|
|
124240
|
+
resolveId: (id) => resolveShellSdkId(id),
|
|
124241
|
+
load: (id) => loadShellSdk(id),
|
|
123966
124242
|
transformIndexHtml: () => transformIndexHtmlHook(context),
|
|
123967
124243
|
writeBundle: () => writeBundleHook(context),
|
|
123968
124244
|
closeBundle: () => closeBundleHook(context)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playcademy/vite-plugin",
|
|
3
|
-
"version": "0.3.3-beta.
|
|
3
|
+
"version": "0.3.3-beta.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -19,20 +19,21 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"archiver": "^7.0.1",
|
|
21
21
|
"picocolors": "^1.1.1",
|
|
22
|
-
"playcademy": "0.
|
|
22
|
+
"playcademy": "0.23.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@electric-sql/pglite": "^0.3.16",
|
|
26
26
|
"@inquirer/prompts": "^7.8.6",
|
|
27
27
|
"@playcademy/constants": "0.0.1",
|
|
28
|
-
"@playcademy/sandbox": "0.4.
|
|
29
|
-
"@playcademy/sdk": "0.
|
|
28
|
+
"@playcademy/sandbox": "0.4.1",
|
|
29
|
+
"@playcademy/sdk": "0.11.0",
|
|
30
30
|
"@playcademy/types": "0.0.1",
|
|
31
31
|
"@playcademy/utils": "0.0.1",
|
|
32
32
|
"@types/archiver": "^6.0.3",
|
|
33
33
|
"@types/bun": "1.3.5"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
+
"@playcademy/sdk": ">=0.10.0",
|
|
36
37
|
"typescript": "^5",
|
|
37
38
|
"vite": "^5 || ^6"
|
|
38
39
|
}
|