@algebrakit/sdk 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -95
- package/dist/ApiClient.d.ts +26 -10
- package/dist/ApiClient.d.ts.map +1 -1
- package/dist/ApiClient.js +40 -51
- package/dist/ApiClient.js.map +1 -1
- package/dist/types/request/RequestTypes.d.ts +20 -1
- package/dist/types/request/RequestTypes.d.ts.map +1 -1
- package/dist/types/response/ResponseTypes.d.ts +1 -0
- package/dist/types/response/ResponseTypes.d.ts.map +1 -1
- package/dist/utils/apiErrorMessage.d.ts +6 -0
- package/dist/utils/apiErrorMessage.d.ts.map +1 -0
- package/dist/utils/apiErrorMessage.js +16 -0
- package/dist/utils/apiErrorMessage.js.map +1 -0
- package/dist/utils/errorHandler.d.ts +4 -5
- package/dist/utils/errorHandler.d.ts.map +1 -1
- package/dist/utils/errorHandler.js +19 -14
- package/dist/utils/errorHandler.js.map +1 -1
- package/package.json +16 -19
- package/dist/demo/config.js +0 -63
- package/dist/demo/demo.js +0 -373
- package/dist/src/ApiClient.js +0 -108
- package/dist/src/index.js +0 -18
- package/dist/src/types/ApiTypes.js +0 -23
- package/dist/src/types/exercise/AK_ExerciseTypes.js +0 -5
- package/dist/src/types/request/RequestTypes.js +0 -3
- package/dist/src/types/response/ResponseTypes.js +0 -2
- package/dist/src/types/shared/SharedTypes.js +0 -3
- package/dist/src/utils/errorHandler.js +0 -22
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.handleApiError = handleApiError;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const apiErrorMessage_1 = require("./apiErrorMessage");
|
|
4
9
|
/**
|
|
5
|
-
*
|
|
6
|
-
* @param error The
|
|
7
|
-
* @returns A
|
|
10
|
+
* Turns an error from an {@link ApiClient} call into a readable message.
|
|
11
|
+
* @param error The error thrown by an `ApiClient` method.
|
|
12
|
+
* @returns A message such as `API Error: 401 - Could not validate credentials: the provided api-key is not valid`.
|
|
8
13
|
*/
|
|
9
14
|
function handleApiError(error) {
|
|
10
|
-
if (error
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// Something happened in setting up the request
|
|
20
|
-
return `API Error: ${error.message}`;
|
|
15
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
16
|
+
if (error.response) {
|
|
17
|
+
// Server responded with a status code outside the 2xx range
|
|
18
|
+
return `API Error: ${error.response.status} - ${(0, apiErrorMessage_1.apiErrorMessage)(error.response.data)}`;
|
|
19
|
+
}
|
|
20
|
+
if (error.request) {
|
|
21
|
+
// Request was made but no response was received (network error or timeout)
|
|
22
|
+
return `API Error: No response received from the server (${error.message}).`;
|
|
23
|
+
}
|
|
21
24
|
}
|
|
25
|
+
// Something happened in setting up the request
|
|
26
|
+
return `API Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
22
27
|
}
|
|
23
28
|
//# sourceMappingURL=errorHandler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/utils/errorHandler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/utils/errorHandler.ts"],"names":[],"mappings":";;;;;AAQA,wCAaC;AArBD,kDAA0B;AAC1B,uDAAoD;AAEpD;;;;GAIG;AACH,SAAgB,cAAc,CAAC,KAAc;IAC3C,IAAI,eAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,4DAA4D;YAC5D,OAAO,cAAc,KAAK,CAAC,QAAQ,CAAC,MAAM,MAAM,IAAA,iCAAe,EAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACzF,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,2EAA2E;YAC3E,OAAO,oDAAoD,KAAK,CAAC,OAAO,IAAI,CAAC;QAC/E,CAAC;IACH,CAAC;IACD,+CAA+C;IAC/C,OAAO,cAAc,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AAChF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@algebrakit/sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Official
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Official Node.js and TypeScript SDK for the Algebrakit API: create exercise sessions, get scores and session info, lock sessions and validate exercises.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -18,33 +18,32 @@
|
|
|
18
18
|
],
|
|
19
19
|
"scripts": {
|
|
20
20
|
"build": "tsc",
|
|
21
|
-
"
|
|
22
|
-
"test": "
|
|
23
|
-
"
|
|
24
|
-
"demo": "
|
|
25
|
-
"demo:setup": "cd demo/cli && cp .env.example .env && echo '
|
|
26
|
-
"preplay-exercise": "npm run build",
|
|
27
|
-
"play-exercise": "ts-node demo/play-exercise/play-exercise.ts",
|
|
28
|
-
"play-exercise:setup": "cd demo/play-exercise && cp .env.example .env && echo 'Please edit demo/play-exercise/.env with your API key'"
|
|
21
|
+
"typecheck": "tsc -p tsconfig.check.json",
|
|
22
|
+
"test": "node --import tsx --test test/*.test.ts",
|
|
23
|
+
"prepublishOnly": "npm run typecheck && npm test && npm run build",
|
|
24
|
+
"demo": "tsx demo/cli/demo.ts",
|
|
25
|
+
"demo:setup": "cd demo/cli && cp .env.example .env && echo 'Now add your API key to demo/cli/.env'"
|
|
29
26
|
},
|
|
30
27
|
"keywords": [
|
|
31
28
|
"algebrakit",
|
|
32
29
|
"sdk",
|
|
30
|
+
"api-client",
|
|
33
31
|
"math",
|
|
34
32
|
"education",
|
|
33
|
+
"edtech",
|
|
35
34
|
"exercises",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
35
|
+
"typescript",
|
|
36
|
+
"nodejs"
|
|
38
37
|
],
|
|
39
38
|
"author": "Algebrakit",
|
|
40
39
|
"license": "MIT",
|
|
41
40
|
"repository": {
|
|
42
41
|
"type": "git",
|
|
43
|
-
"url": "git+https://github.com/algebrakit
|
|
42
|
+
"url": "git+https://github.com/algebrakit/sdk-typescript.git"
|
|
44
43
|
},
|
|
45
|
-
"homepage": "https://github.com/algebrakit
|
|
44
|
+
"homepage": "https://github.com/algebrakit/sdk-typescript#readme",
|
|
46
45
|
"bugs": {
|
|
47
|
-
"url": "https://github.com/algebrakit
|
|
46
|
+
"url": "https://github.com/algebrakit/sdk-typescript/issues"
|
|
48
47
|
},
|
|
49
48
|
"engines": {
|
|
50
49
|
"node": ">=18"
|
|
@@ -53,14 +52,12 @@
|
|
|
53
52
|
"access": "public"
|
|
54
53
|
},
|
|
55
54
|
"dependencies": {
|
|
56
|
-
"axios": "^1.
|
|
55
|
+
"axios": "^1.20.0"
|
|
57
56
|
},
|
|
58
57
|
"devDependencies": {
|
|
59
|
-
"@types/http-proxy": "^1.17.17",
|
|
60
58
|
"@types/node": "^22.15.17",
|
|
61
59
|
"dotenv": "^17.3.1",
|
|
62
|
-
"
|
|
63
|
-
"ts-node": "^10.9.2",
|
|
60
|
+
"tsx": "^4.23.15",
|
|
64
61
|
"typescript": "^5.8.3"
|
|
65
62
|
}
|
|
66
63
|
}
|
package/dist/demo/config.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.loadConfig = loadConfig;
|
|
37
|
-
const dotenv = __importStar(require("dotenv"));
|
|
38
|
-
const path = __importStar(require("path"));
|
|
39
|
-
// Load environment variables from .env file
|
|
40
|
-
dotenv.config({ path: path.join(__dirname, '.env') });
|
|
41
|
-
/**
|
|
42
|
-
* Loads and validates configuration from environment variables
|
|
43
|
-
*/
|
|
44
|
-
function loadConfig() {
|
|
45
|
-
const apiKey = process.env.ALGEBRAKIT_API_KEY;
|
|
46
|
-
const apiUrl = process.env.ALGEBRAKIT_API_URL || 'https://api.algebrakit.com';
|
|
47
|
-
// Validate configuration
|
|
48
|
-
if (!apiKey) {
|
|
49
|
-
console.error('\n❌ Error: ALGEBRAKIT_API_KEY is not set');
|
|
50
|
-
console.error('Please create a .env file in the demo directory with your API key.');
|
|
51
|
-
console.error('You can copy .env.example to .env and add your key.\n');
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
if (apiKey === 'your_api_key_here') {
|
|
55
|
-
console.error('\n❌ Error: Please replace the placeholder API key with your actual key');
|
|
56
|
-
console.error('Edit the .env file and add your real Algebrakit API key.\n');
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
apiKey,
|
|
61
|
-
apiUrl
|
|
62
|
-
};
|
|
63
|
-
}
|
package/dist/demo/demo.js
DELETED
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
const ApiClient_1 = require("../src/ApiClient");
|
|
13
|
-
const config_1 = require("./config");
|
|
14
|
-
// Test exercise ID as specified in requirements
|
|
15
|
-
const TEST_EXERCISE_ID = 'fa42e943-8213-41a6-8a91-8c22a929ffe9';
|
|
16
|
-
/**
|
|
17
|
-
* Displays penalties in a formatted way
|
|
18
|
-
*/
|
|
19
|
-
function displayPenalties(penalties, level) {
|
|
20
|
-
if (!penalties) {
|
|
21
|
-
console.log(` ${level} Penalties: None`);
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
console.log(` ${level} Penalties:`);
|
|
25
|
-
console.log(` - Hints Requested: ${penalties.hintsRequested || 0}`);
|
|
26
|
-
console.log(` - Math Errors: ${penalties.mathErrors || 0}`);
|
|
27
|
-
console.log(` - Marks Penalty: ${penalties.marksPenalty || 0}`);
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Step 1: Validate exercise
|
|
31
|
-
*/
|
|
32
|
-
function validateExercise(client) {
|
|
33
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
console.log('\nStep 1: Validating Exercise');
|
|
35
|
-
console.log(` Exercise ID: ${TEST_EXERCISE_ID}`);
|
|
36
|
-
try {
|
|
37
|
-
const request = {
|
|
38
|
-
exerciseId: TEST_EXERCISE_ID
|
|
39
|
-
};
|
|
40
|
-
const response = yield client.validateExercise(request);
|
|
41
|
-
console.log('Exercise validation successful');
|
|
42
|
-
console.log(` - Valid: ${response.valid}`);
|
|
43
|
-
console.log(` - Marks: ${response.marks || 'N/A'}`);
|
|
44
|
-
console.log(` - Random: ${response.random || false}`);
|
|
45
|
-
if (response.interactions) {
|
|
46
|
-
const interactionCount = Object.keys(response.interactions).length;
|
|
47
|
-
console.log(` - Interactions: ${interactionCount}`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
console.error(' ❌ Exercise validation failed:', error.message);
|
|
52
|
-
throw error;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Step 2: Create a new session
|
|
58
|
-
*/
|
|
59
|
-
function createSession(client) {
|
|
60
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
-
console.log('\nStep 2: Creating New Session');
|
|
62
|
-
console.log(` Exercise ID: ${TEST_EXERCISE_ID}`);
|
|
63
|
-
try {
|
|
64
|
-
const request = {
|
|
65
|
-
exercises: [
|
|
66
|
-
{
|
|
67
|
-
exerciseId: TEST_EXERCISE_ID,
|
|
68
|
-
version: 'latest'
|
|
69
|
-
}
|
|
70
|
-
],
|
|
71
|
-
apiVersion: 2
|
|
72
|
-
};
|
|
73
|
-
const response = yield client.createSession(request);
|
|
74
|
-
// Extract session ID from response
|
|
75
|
-
if (response && response.length > 0 && response[0].sessions && response[0].sessions.length > 0) {
|
|
76
|
-
const sessionId = response[0].sessions[0].sessionId;
|
|
77
|
-
console.log('Session created successfully');
|
|
78
|
-
console.log(` - Session ID: ${sessionId}`);
|
|
79
|
-
console.log(` - Success: ${response[0].success}`);
|
|
80
|
-
return sessionId;
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
throw new Error('No session ID returned in response');
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
console.error(' ❌ Session creation failed:', error.message);
|
|
88
|
-
throw error;
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Step 3: Lock and unlock the session
|
|
94
|
-
*/
|
|
95
|
-
function lockUnlockSession(client, sessionId) {
|
|
96
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
-
console.log('\nStep 3: Testing Session Lock/Unlock');
|
|
98
|
-
console.log(` Session ID: ${sessionId}`);
|
|
99
|
-
try {
|
|
100
|
-
// Lock the session
|
|
101
|
-
console.log(' Locking session...');
|
|
102
|
-
const lockRequest = {
|
|
103
|
-
action: 'LOCK',
|
|
104
|
-
sessionIds: [sessionId]
|
|
105
|
-
};
|
|
106
|
-
yield client.lockSession(lockRequest);
|
|
107
|
-
console.log(' Session locked successfully');
|
|
108
|
-
// Unlock the session
|
|
109
|
-
console.log(' Unlocking session...');
|
|
110
|
-
const unlockRequest = {
|
|
111
|
-
action: 'UNLOCK',
|
|
112
|
-
sessionIds: [sessionId]
|
|
113
|
-
};
|
|
114
|
-
yield client.lockSession(unlockRequest);
|
|
115
|
-
console.log(' Session unlocked successfully');
|
|
116
|
-
}
|
|
117
|
-
catch (error) {
|
|
118
|
-
console.error(' ❌ Lock/Unlock operation failed:', error.message);
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Step 4: Get session score with penalty information
|
|
125
|
-
*/
|
|
126
|
-
function getSessionScore(client, sessionId) {
|
|
127
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
-
console.log('\nStep 4: Getting Session Score with Penalties');
|
|
129
|
-
console.log(` Session ID: ${sessionId}`);
|
|
130
|
-
try {
|
|
131
|
-
const request = {
|
|
132
|
-
sessionId: sessionId,
|
|
133
|
-
lockSession: false
|
|
134
|
-
};
|
|
135
|
-
const response = yield client.getSessionScore(request);
|
|
136
|
-
console.log(' Session score retrieved successfully');
|
|
137
|
-
// Display exercise-level scoring with penalties
|
|
138
|
-
console.log('\n Exercise Level Scoring:');
|
|
139
|
-
console.log(` - Finished: ${response.scoring.finished}`);
|
|
140
|
-
console.log(` - Marks Total: ${response.scoring.marksTotal}`);
|
|
141
|
-
console.log(` - Marks Earned: ${response.scoring.marksEarned}`);
|
|
142
|
-
displayPenalties(response.scoring.penalties, 'Exercise');
|
|
143
|
-
// Display question-level scoring with penalties
|
|
144
|
-
if (response.questions && response.questions.length > 0) {
|
|
145
|
-
console.log('\n Question Level Scoring:');
|
|
146
|
-
response.questions.forEach((question, qIndex) => {
|
|
147
|
-
console.log(`\n Question ${qIndex + 1} (ID: ${question.id}):`);
|
|
148
|
-
console.log(` - Finished: ${question.scoring.finished}`);
|
|
149
|
-
console.log(` - Marks Total: ${question.scoring.marksTotal}`);
|
|
150
|
-
console.log(` - Marks Earned: ${question.scoring.marksEarned}`);
|
|
151
|
-
displayPenalties(question.scoring.penalties, 'Question');
|
|
152
|
-
// Display interaction-level scoring with penalties
|
|
153
|
-
if (question.interactions && question.interactions.length > 0) {
|
|
154
|
-
console.log(`\n 💡 Interactions for Question ${qIndex + 1}:`);
|
|
155
|
-
question.interactions.forEach((interaction, iIndex) => {
|
|
156
|
-
console.log(`\n Interaction ${iIndex + 1} (ID: ${interaction.id}):`);
|
|
157
|
-
console.log(` - Type: ${interaction.type}`);
|
|
158
|
-
console.log(` - Status: ${interaction.status}`);
|
|
159
|
-
console.log(` - Progress: ${interaction.progress}`);
|
|
160
|
-
console.log(` - Finished: ${interaction.scoring.finished}`);
|
|
161
|
-
console.log(` - Marks Total: ${interaction.scoring.marksTotal}`);
|
|
162
|
-
console.log(` - Marks Earned: ${interaction.scoring.marksEarned}`);
|
|
163
|
-
displayPenalties(interaction.scoring.penalties, 'Interaction');
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
// Verify penalty aggregation
|
|
169
|
-
console.log('\n Verifying Penalty Aggregation:');
|
|
170
|
-
verifyPenaltyAggregation(response);
|
|
171
|
-
}
|
|
172
|
-
catch (error) {
|
|
173
|
-
console.error(' ❌ Failed to get session score:', error.message);
|
|
174
|
-
throw error;
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Verify that penalties are correctly aggregated across levels
|
|
180
|
-
*/
|
|
181
|
-
function verifyPenaltyAggregation(response) {
|
|
182
|
-
var _a;
|
|
183
|
-
let totalHintsFromQuestions = 0;
|
|
184
|
-
let totalErrorsFromQuestions = 0;
|
|
185
|
-
let totalPenaltyFromQuestions = 0;
|
|
186
|
-
// Sum up penalties from all questions
|
|
187
|
-
(_a = response.questions) === null || _a === void 0 ? void 0 : _a.forEach(question => {
|
|
188
|
-
var _a;
|
|
189
|
-
if (question.scoring.penalties) {
|
|
190
|
-
totalHintsFromQuestions += question.scoring.penalties.hintsRequested || 0;
|
|
191
|
-
totalErrorsFromQuestions += question.scoring.penalties.mathErrors || 0;
|
|
192
|
-
totalPenaltyFromQuestions += question.scoring.penalties.marksPenalty || 0;
|
|
193
|
-
}
|
|
194
|
-
// Also verify question level aggregation from interactions
|
|
195
|
-
let questionHints = 0;
|
|
196
|
-
let questionErrors = 0;
|
|
197
|
-
let questionPenalty = 0;
|
|
198
|
-
(_a = question.interactions) === null || _a === void 0 ? void 0 : _a.forEach(interaction => {
|
|
199
|
-
if (interaction.scoring.penalties) {
|
|
200
|
-
questionHints += interaction.scoring.penalties.hintsRequested || 0;
|
|
201
|
-
questionErrors += interaction.scoring.penalties.mathErrors || 0;
|
|
202
|
-
questionPenalty += interaction.scoring.penalties.marksPenalty || 0;
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
// Verify question-level aggregation
|
|
206
|
-
const qPenalties = question.scoring.penalties;
|
|
207
|
-
if (qPenalties) {
|
|
208
|
-
const hintsMatch = (qPenalties.hintsRequested || 0) === questionHints;
|
|
209
|
-
const errorsMatch = (qPenalties.mathErrors || 0) === questionErrors;
|
|
210
|
-
const penaltyMatch = (qPenalties.marksPenalty || 0) === questionPenalty;
|
|
211
|
-
console.log(` Question ${question.id} aggregation: ${hintsMatch && errorsMatch && penaltyMatch ? '✅' : '❌'}`);
|
|
212
|
-
if (!hintsMatch)
|
|
213
|
-
console.log(` ⚠️ Hints mismatch: ${qPenalties.hintsRequested} vs ${questionHints}`);
|
|
214
|
-
if (!errorsMatch)
|
|
215
|
-
console.log(` ⚠️ Errors mismatch: ${qPenalties.mathErrors} vs ${questionErrors}`);
|
|
216
|
-
if (!penaltyMatch)
|
|
217
|
-
console.log(` ⚠️ Penalty mismatch: ${qPenalties.marksPenalty} vs ${questionPenalty}`);
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
// Verify exercise-level aggregation
|
|
221
|
-
const exercisePenalties = response.scoring.penalties;
|
|
222
|
-
if (exercisePenalties) {
|
|
223
|
-
const hintsMatch = (exercisePenalties.hintsRequested || 0) === totalHintsFromQuestions;
|
|
224
|
-
const errorsMatch = (exercisePenalties.mathErrors || 0) === totalErrorsFromQuestions;
|
|
225
|
-
const penaltyMatch = (exercisePenalties.marksPenalty || 0) === totalPenaltyFromQuestions;
|
|
226
|
-
console.log(` Exercise level aggregation: ${hintsMatch && errorsMatch && penaltyMatch ? '✅' : '❌'}`);
|
|
227
|
-
if (!hintsMatch)
|
|
228
|
-
console.log(` ⚠️ Hints mismatch: ${exercisePenalties.hintsRequested} vs ${totalHintsFromQuestions}`);
|
|
229
|
-
if (!errorsMatch)
|
|
230
|
-
console.log(` ⚠️ Errors mismatch: ${exercisePenalties.mathErrors} vs ${totalErrorsFromQuestions}`);
|
|
231
|
-
if (!penaltyMatch)
|
|
232
|
-
console.log(` ⚠️ Penalty mismatch: ${exercisePenalties.marksPenalty} vs ${totalPenaltyFromQuestions}`);
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
console.log(' ℹNo penalties at exercise level (might be a new session)');
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Step 5: Get detailed session information
|
|
240
|
-
*/
|
|
241
|
-
function getSessionInfo(client, sessionId) {
|
|
242
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
243
|
-
console.log('\n📄 Step 5: Getting Detailed Session Information');
|
|
244
|
-
console.log(` Session ID: ${sessionId}`);
|
|
245
|
-
try {
|
|
246
|
-
const request = {
|
|
247
|
-
sessionId: sessionId
|
|
248
|
-
};
|
|
249
|
-
const response = yield client.getSessionInfo(request);
|
|
250
|
-
console.log(' Session info retrieved successfully!');
|
|
251
|
-
if (response.elements && response.elements.length > 0) {
|
|
252
|
-
console.log(` - Elements: ${response.elements.length}`);
|
|
253
|
-
response.elements.forEach((element, index) => {
|
|
254
|
-
console.log(`\n Element ${index + 1}:`);
|
|
255
|
-
console.log(` - Type: ${element.type}`);
|
|
256
|
-
if (element.items) {
|
|
257
|
-
console.log(` - Items: ${element.items.length}`);
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
if (response.tagDescriptions) {
|
|
262
|
-
const tagCount = Object.keys(response.tagDescriptions).length;
|
|
263
|
-
console.log(`\n - Tag Descriptions: ${tagCount} tags`);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
catch (error) {
|
|
267
|
-
console.error(' ❌ Failed to get session info:', error.message);
|
|
268
|
-
throw error;
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Step 6: Create a session using an AK_Exercise specification
|
|
274
|
-
*/
|
|
275
|
-
function createSessionWithExerciseSpec(client) {
|
|
276
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
277
|
-
console.log('\nStep 6: Creating Session with AK_Exercise Spec');
|
|
278
|
-
// Define an exercise using the AK_Exercise format
|
|
279
|
-
const exerciseSpec = {
|
|
280
|
-
type: 'AK_Exercise',
|
|
281
|
-
version: 1,
|
|
282
|
-
studentProfile: 'uk_KS5',
|
|
283
|
-
questionMode: 'ALL_AT_ONCE',
|
|
284
|
-
symbols: [
|
|
285
|
-
{ name: 'x', type: 'VARIABLE' },
|
|
286
|
-
],
|
|
287
|
-
elements: [
|
|
288
|
-
{
|
|
289
|
-
blocks: [
|
|
290
|
-
{
|
|
291
|
-
type: 'CONTENT',
|
|
292
|
-
content: 'Simplify the following expression.',
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
type: 'INTERACTION',
|
|
296
|
-
interaction: {
|
|
297
|
-
type: 'MULTISTEP',
|
|
298
|
-
solutionPart: {
|
|
299
|
-
task: {
|
|
300
|
-
type: 'SIMPLIFY',
|
|
301
|
-
expression: '2x + 3x',
|
|
302
|
-
},
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
|
-
},
|
|
306
|
-
],
|
|
307
|
-
},
|
|
308
|
-
],
|
|
309
|
-
};
|
|
310
|
-
try {
|
|
311
|
-
// Validate the exercise spec first
|
|
312
|
-
const validateResponse = yield client.validateExercise({ exerciseSpec });
|
|
313
|
-
console.log(` Validation: valid=${validateResponse.valid}, marks=${validateResponse.marks}`);
|
|
314
|
-
// Create a session from the spec
|
|
315
|
-
const request = {
|
|
316
|
-
exercises: [{ exerciseSpec }],
|
|
317
|
-
apiVersion: 2,
|
|
318
|
-
};
|
|
319
|
-
const response = yield client.createSession(request);
|
|
320
|
-
if (response && response.length > 0 && response[0].sessions && response[0].sessions.length > 0) {
|
|
321
|
-
const sessionId = response[0].sessions[0].sessionId;
|
|
322
|
-
console.log(' Session created successfully from AK_Exercise spec');
|
|
323
|
-
console.log(` - Session ID: ${sessionId}`);
|
|
324
|
-
return sessionId;
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
throw new Error('No session ID returned in response');
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
catch (error) {
|
|
331
|
-
console.error(' Session creation from spec failed:', error.message);
|
|
332
|
-
throw error;
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Main demo function
|
|
338
|
-
*/
|
|
339
|
-
function runDemo() {
|
|
340
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
341
|
-
console.log('\nAlgebrakit TypeScript SDK Demo');
|
|
342
|
-
console.log('='.repeat(50));
|
|
343
|
-
// Load configuration
|
|
344
|
-
const config = (0, config_1.loadConfig)();
|
|
345
|
-
// Initialize API client
|
|
346
|
-
const client = new ApiClient_1.ApiClient(config.apiUrl, config.apiKey);
|
|
347
|
-
try {
|
|
348
|
-
// Run test scenario
|
|
349
|
-
yield validateExercise(client);
|
|
350
|
-
const sessionId = yield createSession(client);
|
|
351
|
-
yield lockUnlockSession(client, sessionId);
|
|
352
|
-
yield getSessionScore(client, sessionId);
|
|
353
|
-
yield getSessionInfo(client, sessionId);
|
|
354
|
-
// Demo: create session from AK_Exercise spec
|
|
355
|
-
yield createSessionWithExerciseSpec(client);
|
|
356
|
-
}
|
|
357
|
-
catch (error) {
|
|
358
|
-
console.error('\n❌ Demo failed with error:', error.message);
|
|
359
|
-
if (error.response) {
|
|
360
|
-
console.error(' Response status:', error.response.status);
|
|
361
|
-
console.error(' Response data:', JSON.stringify(error.response.data, null, 2));
|
|
362
|
-
}
|
|
363
|
-
process.exit(1);
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
// Handle errors gracefully
|
|
368
|
-
process.on('unhandledRejection', (error) => {
|
|
369
|
-
console.error('\n❌ Unhandled error:', error.message);
|
|
370
|
-
process.exit(1);
|
|
371
|
-
});
|
|
372
|
-
// Run the demo
|
|
373
|
-
runDemo();
|
package/dist/src/ApiClient.js
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.ApiClient = void 0;
|
|
16
|
-
const axios_1 = __importDefault(require("axios"));
|
|
17
|
-
/**
|
|
18
|
-
* ApiClient is a wrapper around Axios to interact with the Algebrakit Webservice API.
|
|
19
|
-
*/
|
|
20
|
-
class ApiClient {
|
|
21
|
-
/**
|
|
22
|
-
* Initialize the API client with a base URL and API key.
|
|
23
|
-
* @param baseUrl The base URL of the Algebrakit Webservice API.
|
|
24
|
-
* @param apiKey The API key for authentication.
|
|
25
|
-
*/
|
|
26
|
-
constructor(baseUrl, apiKey) {
|
|
27
|
-
this.baseUrl = baseUrl;
|
|
28
|
-
this.apiKey = apiKey;
|
|
29
|
-
this.axiosInstance = axios_1.default.create({
|
|
30
|
-
baseURL: baseUrl,
|
|
31
|
-
headers: {
|
|
32
|
-
'Content-Type': 'application/json',
|
|
33
|
-
'x-api-key': apiKey
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Create new exercise sessions.
|
|
39
|
-
* @param request The request payload for creating sessions.
|
|
40
|
-
* @returns The response containing session creation results.
|
|
41
|
-
*/
|
|
42
|
-
createSession(request) {
|
|
43
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
-
return this.axiosInstance.post('/session/create', request).then(r => r.data);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Retrieve results from exercise sessions.
|
|
49
|
-
* @param request The request payload for retrieving session scores.
|
|
50
|
-
* @returns The response containing session scores.
|
|
51
|
-
*/
|
|
52
|
-
getSessionScore(request) {
|
|
53
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
-
return this.axiosInstance.post('/session/score', request).then(r => r.data);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Lock or unlock exercise sessions.
|
|
59
|
-
* @param request The request payload for locking/unlocking sessions.
|
|
60
|
-
* @returns The response confirming the action.
|
|
61
|
-
*/
|
|
62
|
-
lockSession(request) {
|
|
63
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
return this.axiosInstance.post('/sessions/lock', request).then(r => r.data);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Retrieve detailed information about a session.
|
|
69
|
-
* @param request The request payload for retrieving session information.
|
|
70
|
-
* @returns The response containing session details.
|
|
71
|
-
*/
|
|
72
|
-
getSessionInfo(request) {
|
|
73
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
-
return this.axiosInstance.post('/session/info', request).then(r => r.data);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Retrieve existing sessions by their IDs.
|
|
79
|
-
* @param request The request payload containing session IDs.
|
|
80
|
-
* @returns The response containing session data for each ID.
|
|
81
|
-
*/
|
|
82
|
-
retrieveSession(request) {
|
|
83
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
-
return this.axiosInstance.post('/session/retrieve', request).then(r => r.data);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Validate an exercise definition or ID.
|
|
89
|
-
* @param request The request payload for exercise validation.
|
|
90
|
-
* @returns The response containing validation results and details.
|
|
91
|
-
*/
|
|
92
|
-
validateExercise(request) {
|
|
93
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
-
return this.axiosInstance.post('/exercise/validate', request).then(r => r.data);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Retrieve published information about an exercise (structure, versions, history).
|
|
99
|
-
* @param request The request payload containing the exercise ID.
|
|
100
|
-
* @returns The response containing published info about the exercise.
|
|
101
|
-
*/
|
|
102
|
-
getExercisePublishedInfo(request) {
|
|
103
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
-
return this.axiosInstance.post('/exercise/published-info', request).then(r => r.data);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
exports.ApiClient = ApiClient;
|