broker-core-sdk 1.0.0 → 1.0.1

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.cjs ADDED
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ACTION_TRIGGERS: () => ACTION_TRIGGERS,
24
+ ACTION_TYPES: () => ACTION_TYPES,
25
+ CONFIDENCE_LEVELS: () => CONFIDENCE_LEVELS,
26
+ ELEMENT_TYPES: () => ELEMENT_TYPES,
27
+ GAME_TYPES: () => GAME_TYPES,
28
+ SlideRenderer: () => slide_renderer_exports,
29
+ gameEngine: () => game_engine_exports,
30
+ learningEngine: () => learning_engine_exports
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+
34
+ // src/renderer/slide-renderer.ts
35
+ var slide_renderer_exports = {};
36
+ __export(slide_renderer_exports, {
37
+ calculatePercentPosition: () => calculatePercentPosition,
38
+ calculateRealPosition: () => calculateRealPosition
39
+ });
40
+ var calculatePercentPosition = (pixelPos, canvasSize) => ({
41
+ x: pixelPos.left / canvasSize.width * 100,
42
+ y: pixelPos.top / canvasSize.height * 100,
43
+ w: pixelPos.width / canvasSize.width * 100,
44
+ h: pixelPos.height / canvasSize.height * 100
45
+ });
46
+ var calculateRealPosition = (percentPos, screenSize) => ({
47
+ left: percentPos.x * screenSize.width / 100,
48
+ top: percentPos.y * screenSize.height / 100,
49
+ width: percentPos.w * screenSize.width / 100,
50
+ height: percentPos.h * screenSize.height / 100
51
+ });
52
+
53
+ // src/engines/learning-engine.ts
54
+ var learning_engine_exports = {};
55
+ __export(learning_engine_exports, {
56
+ calculateNextReview: () => calculateNextReview,
57
+ checkMastery: () => checkMastery
58
+ });
59
+
60
+ // src/types/models.ts
61
+ var CONFIDENCE_LEVELS = {
62
+ HIGH: "High",
63
+ MEDIUM: "Medium",
64
+ LOW: "Low"
65
+ };
66
+
67
+ // src/engines/learning-engine.ts
68
+ var calculateNextReview = (isCorrect, confidence) => {
69
+ if (!isCorrect) {
70
+ return 0;
71
+ }
72
+ if (confidence === CONFIDENCE_LEVELS.HIGH) {
73
+ return 7;
74
+ }
75
+ return 1;
76
+ };
77
+ var checkMastery = (streak, lastConfidence) => {
78
+ return streak >= 3 && lastConfidence === CONFIDENCE_LEVELS.HIGH;
79
+ };
80
+
81
+ // src/engines/game-engine.ts
82
+ var game_engine_exports = {};
83
+ __export(game_engine_exports, {
84
+ validateGameResult: () => validateGameResult
85
+ });
86
+
87
+ // src/types/elements.ts
88
+ var ELEMENT_TYPES = {
89
+ TEXT: "TEXT",
90
+ VIDEO: "VIDEO",
91
+ QUIZ: "QUIZ",
92
+ MATCHING: "MATCHING",
93
+ SORTING: "SORTING",
94
+ MEMORY_CARD: "MEMORY_CARD",
95
+ HOTSPOT: "HOTSPOT"
96
+ };
97
+ var GAME_TYPES = {
98
+ QUIZ: "QUIZ",
99
+ MATCHING: "MATCHING",
100
+ SORTING: "SORTING",
101
+ MEMORY_CARD: "MEMORY_CARD",
102
+ HOTSPOT: "HOTSPOT"
103
+ };
104
+
105
+ // src/engines/game-engine.ts
106
+ var validateGameResult = (type, userAnswer, correctData) => {
107
+ switch (type) {
108
+ case GAME_TYPES.QUIZ: {
109
+ const data = correctData;
110
+ return userAnswer === data.correctId;
111
+ }
112
+ case GAME_TYPES.SORTING: {
113
+ const data = correctData;
114
+ return JSON.stringify(userAnswer) === JSON.stringify(data.correctOrder);
115
+ }
116
+ case GAME_TYPES.MATCHING: {
117
+ const data = correctData;
118
+ const userSorted = [...userAnswer].sort();
119
+ const correctSorted = [...data.correctPairs].sort();
120
+ return JSON.stringify(userSorted) === JSON.stringify(correctSorted);
121
+ }
122
+ case GAME_TYPES.HOTSPOT: {
123
+ const data = correctData;
124
+ const { x, y } = userAnswer;
125
+ const zone = data.zones.find((z) => z.id === data.correctZoneId);
126
+ if (!zone) return false;
127
+ return x >= zone.xMin && x <= zone.xMax && y >= zone.yMin && y <= zone.yMax;
128
+ }
129
+ default:
130
+ return false;
131
+ }
132
+ };
133
+
134
+ // src/types/actions.ts
135
+ var ACTION_TRIGGERS = {
136
+ ON_CLICK: "ON_CLICK",
137
+ ON_DOUBLE_CLICK: "ON_DOUBLE_CLICK",
138
+ ON_HOVER: "ON_HOVER",
139
+ ON_ENTER_VIEWPORT: "ON_ENTER_VIEWPORT"
140
+ };
141
+ var ACTION_TYPES = {
142
+ NAVIGATE_SLIDE: "NAVIGATE_SLIDE",
143
+ TOGGLE_VISIBILITY: "TOGGLE_VISIBILITY",
144
+ PLAY_MEDIA: "PLAY_MEDIA",
145
+ EVALUATE_ANSWER: "EVALUATE_ANSWER"
146
+ };
147
+ // Annotate the CommonJS export names for ESM import in node:
148
+ 0 && (module.exports = {
149
+ ACTION_TRIGGERS,
150
+ ACTION_TYPES,
151
+ CONFIDENCE_LEVELS,
152
+ ELEMENT_TYPES,
153
+ GAME_TYPES,
154
+ SlideRenderer,
155
+ gameEngine,
156
+ learningEngine
157
+ });
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Chuyển đổi tọa độ từ Pixel sang % (Dùng cho Admin Builder)
3
+ * Canvas Builder & Percentage Positioning
4
+ */
5
+ declare const calculatePercentPosition: (pixelPos: {
6
+ left: number;
7
+ top: number;
8
+ width: number;
9
+ height: number;
10
+ }, canvasSize: {
11
+ width: number;
12
+ height: number;
13
+ }) => {
14
+ x: number;
15
+ y: number;
16
+ w: number;
17
+ h: number;
18
+ };
19
+ /**
20
+ * Chuyển đổi tọa độ từ % sang Pixel thực tế trên thiết bị.
21
+ * AC 1: Renderer phải tính toán vị trí dựa trên % từ JSON
22
+ */
23
+ declare const calculateRealPosition: (percentPos: {
24
+ x: number;
25
+ y: number;
26
+ w: number;
27
+ h: number;
28
+ }, screenSize: {
29
+ width: number;
30
+ height: number;
31
+ }) => {
32
+ left: number;
33
+ top: number;
34
+ width: number;
35
+ height: number;
36
+ };
37
+
38
+ declare const slideRenderer_calculatePercentPosition: typeof calculatePercentPosition;
39
+ declare const slideRenderer_calculateRealPosition: typeof calculateRealPosition;
40
+ declare namespace slideRenderer {
41
+ export { slideRenderer_calculatePercentPosition as calculatePercentPosition, slideRenderer_calculateRealPosition as calculateRealPosition };
42
+ }
43
+
44
+ /**
45
+ * Tập hợp các sự kiện (events) từ người dùng hoặc hệ thống
46
+ * dùng để kích hoạt một hành động (action) nào đó trên Slide.
47
+ */
48
+ declare const ACTION_TRIGGERS: {
49
+ readonly ON_CLICK: "ON_CLICK";
50
+ readonly ON_DOUBLE_CLICK: "ON_DOUBLE_CLICK";
51
+ readonly ON_HOVER: "ON_HOVER";
52
+ readonly ON_ENTER_VIEWPORT: "ON_ENTER_VIEWPORT";
53
+ };
54
+ type ActionTrigger = (typeof ACTION_TRIGGERS)[keyof typeof ACTION_TRIGGERS];
55
+ /**
56
+ * Danh sách các loại hành động (side-effects) mà hệ thống hỗ trợ thực thi.
57
+ * Ví dụ: Chuyển trang, ẩn hiện component, phát nhạc, hoặc nộp bài.
58
+ */
59
+ declare const ACTION_TYPES: {
60
+ readonly NAVIGATE_SLIDE: "NAVIGATE_SLIDE";
61
+ readonly TOGGLE_VISIBILITY: "TOGGLE_VISIBILITY";
62
+ readonly PLAY_MEDIA: "PLAY_MEDIA";
63
+ readonly EVALUATE_ANSWER: "EVALUATE_ANSWER";
64
+ };
65
+ type ActionType = (typeof ACTION_TYPES)[keyof typeof ACTION_TYPES];
66
+ /**
67
+ * Payload: Dữ liệu cấu hình cho hành động chuyển slide.
68
+ * - `targetSlideId`: ID của slide muốn nhảy tới (Dùng cho điều hướng tự do).
69
+ * - `direction`: Điều hướng tuần tự (Tiến/Lùi).
70
+ */
71
+ interface NavigatePayload {
72
+ targetSlideId?: string;
73
+ direction?: "NEXT" | "PREV";
74
+ }
75
+ /**
76
+ * Payload: Dữ liệu cấu hình cho hành động thay đổi trạng thái hiển thị của Element.
77
+ * - `targetElementId`: ID của phần tử bị tác động.
78
+ * - `action`: Trạng thái muốn áp dụng (Hiển thị / Ẩn / Đảo ngược trạng thái).
79
+ */
80
+ interface ToggleVisibilityPayload {
81
+ targetElementId: string;
82
+ action: "SHOW" | "HIDE" | "TOGGLE";
83
+ }
84
+ /**
85
+ * Payload: Dữ liệu cấu hình cho hành động chấm điểm và tính toán Spaced Repetition.
86
+ * - `targetElementId`: (Tùy chọn) ID của bài tập (Quiz, Matching,..) cần chấm. Nếu nút bấm nằm rời bên ngoài.
87
+ * - `conceptId`: (Tùy chọn) ID của kỹ năng/khái niệm để lưu tiến độ (mastery) cho học viên.
88
+ */
89
+ interface EvaluatePayload {
90
+ targetElementId?: string;
91
+ conceptId?: string;
92
+ }
93
+ /**
94
+ * Từ điển ánh xạ (Mapping Map) cực kỳ quan trọng.
95
+ * Định nghĩa chính xác ActionType nào thì phải xài chung với Payload Interface nào.
96
+ */
97
+ type ActionPayloadMap = {
98
+ [ACTION_TYPES.NAVIGATE_SLIDE]: NavigatePayload;
99
+ [ACTION_TYPES.TOGGLE_VISIBILITY]: ToggleVisibilityPayload;
100
+ [ACTION_TYPES.PLAY_MEDIA]: {
101
+ mediaUrl: string;
102
+ loop: boolean;
103
+ };
104
+ [ACTION_TYPES.EVALUATE_ANSWER]: EvaluatePayload;
105
+ };
106
+ /**
107
+ * Cấu trúc hoàn chỉnh của một Hành động gắn vào Element.
108
+ *
109
+ * @description Sử dụng pattern "Discriminated Union" của TypeScript:
110
+ * Khi dev set thuộc tính `type`, TypeScript sẽ tự động ép buộc `payload`
111
+ * phải chứa các trường dữ liệu tương ứng được định nghĩa trong `ActionPayloadMap`.
112
+ * Tránh tuyệt đối việc râu ông nọ cắm cằm bà kia (VD: type là NAVIGATE nhưng truyền mediaUrl).
113
+ */
114
+ type ElementAction = {
115
+ [K in ActionType]: {
116
+ trigger: ActionTrigger;
117
+ type: K;
118
+ payload: ActionPayloadMap[K];
119
+ };
120
+ }[ActionType];
121
+
122
+ /**
123
+ * Cấu trúc tọa độ cơ bản dựa trên tỷ lệ %.
124
+ */
125
+ interface Position {
126
+ x: number;
127
+ y: number;
128
+ w: number;
129
+ h: number;
130
+ }
131
+
132
+ interface TextData {
133
+ content: string;
134
+ }
135
+ interface VideoData {
136
+ src: string;
137
+ poster?: string;
138
+ autoPlay?: boolean;
139
+ muted?: boolean;
140
+ loop?: boolean;
141
+ controls?: boolean;
142
+ isLive?: boolean;
143
+ }
144
+ interface MultipleChoiceData {
145
+ question: string;
146
+ options: {
147
+ id: string;
148
+ content: string;
149
+ }[];
150
+ correctId: string;
151
+ }
152
+ interface SortingData {
153
+ items: {
154
+ id: string;
155
+ content: string;
156
+ }[];
157
+ correctOrder: string[];
158
+ }
159
+ interface MatchingData {
160
+ leftColumn: {
161
+ id: string;
162
+ content: string;
163
+ }[];
164
+ rightColumn: {
165
+ id: string;
166
+ content: string;
167
+ }[];
168
+ correctPairs: [string, string][];
169
+ }
170
+ interface HotspotData {
171
+ imageUri: string;
172
+ zones: {
173
+ id: string;
174
+ xMin: number;
175
+ yMin: number;
176
+ xMax: number;
177
+ yMax: number;
178
+ }[];
179
+ correctZoneId: string;
180
+ }
181
+ /**
182
+ * Map để liên kết các Game Type với dữ liệu tương ứng.
183
+ */
184
+ type GameDataMap = {
185
+ QUIZ: MultipleChoiceData;
186
+ SORTING: SortingData;
187
+ MATCHING: MatchingData;
188
+ HOTSPOT: HotspotData;
189
+ MEMORY_CARD: any;
190
+ };
191
+ /**
192
+ * Map tổng hợp giữa tất cả ElementType và cấu trúc data tương ứng.
193
+ */
194
+ type ElementDataMap = GameDataMap & {
195
+ TEXT: TextData;
196
+ VIDEO: VideoData;
197
+ };
198
+
199
+ /**
200
+ * Định nghĩa tất cả các loại phần tử có thể xuất hiện trong một Slide.
201
+ */
202
+ declare const ELEMENT_TYPES: {
203
+ readonly TEXT: "TEXT";
204
+ readonly VIDEO: "VIDEO";
205
+ readonly QUIZ: "QUIZ";
206
+ readonly MATCHING: "MATCHING";
207
+ readonly SORTING: "SORTING";
208
+ readonly MEMORY_CARD: "MEMORY_CARD";
209
+ readonly HOTSPOT: "HOTSPOT";
210
+ };
211
+ type ElementType = (typeof ELEMENT_TYPES)[keyof typeof ELEMENT_TYPES];
212
+ /**
213
+ * Định nghĩa các loại game (tập con của ELEMENT_TYPES).
214
+ */
215
+ declare const GAME_TYPES: {
216
+ readonly QUIZ: "QUIZ";
217
+ readonly MATCHING: "MATCHING";
218
+ readonly SORTING: "SORTING";
219
+ readonly MEMORY_CARD: "MEMORY_CARD";
220
+ readonly HOTSPOT: "HOTSPOT";
221
+ };
222
+ type GameType = Extract<ElementType, (typeof GAME_TYPES)[keyof typeof GAME_TYPES]>;
223
+ /**
224
+ * Định nghĩa style cho một phần tử.
225
+ */
226
+ interface ElementStyle {
227
+ backgroundColor?: string;
228
+ color?: string;
229
+ fontSize?: number;
230
+ fontFamily?: string;
231
+ fontWeight?: string | number;
232
+ textAlign?: "left" | "center" | "right" | "justify";
233
+ border?: string;
234
+ borderRadius?: number;
235
+ opacity?: number;
236
+ zIndex?: number;
237
+ [key: string]: any;
238
+ }
239
+ /**
240
+ * Định nghĩa các loại animation hỗ trợ
241
+ */
242
+ interface ElementAnimation {
243
+ type: "fade-in" | "slide-up" | "bounce" | "zoom-in";
244
+ duration: number;
245
+ delay: number;
246
+ repeat?: boolean;
247
+ }
248
+ /**
249
+ * Sử dụng Discriminated Union để đảm bảo type-safety cho thuộc tính 'data'.
250
+ */
251
+ type SlideElement = {
252
+ [K in keyof ElementDataMap]: {
253
+ id: string;
254
+ type: K;
255
+ position: Position;
256
+ style?: ElementStyle;
257
+ enterAnimation?: ElementAnimation;
258
+ exitAnimation?: ElementAnimation;
259
+ actions?: ElementAction[];
260
+ data: ElementDataMap[K];
261
+ groupId?: string;
262
+ };
263
+ }[keyof ElementDataMap];
264
+
265
+ interface SlideConfig {
266
+ aspectRatio: string;
267
+ theme: string;
268
+ }
269
+ interface Slide {
270
+ id: string;
271
+ tenant_id: string;
272
+ course_id: string;
273
+ order: number;
274
+ config?: SlideConfig;
275
+ elements: SlideElement[];
276
+ }
277
+ declare const CONFIDENCE_LEVELS: {
278
+ readonly HIGH: "High";
279
+ readonly MEDIUM: "Medium";
280
+ readonly LOW: "Low";
281
+ };
282
+ type ConfidenceLevel = typeof CONFIDENCE_LEVELS[keyof typeof CONFIDENCE_LEVELS];
283
+ interface ActionLog {
284
+ action_type: string;
285
+ timestamp: number;
286
+ duration: number;
287
+ result: {
288
+ is_correct: boolean;
289
+ confidence: ConfidenceLevel;
290
+ };
291
+ }
292
+ interface UserProgress {
293
+ user_id: string;
294
+ tenant_id: string;
295
+ concept_id: string;
296
+ streak: number;
297
+ is_mastered: boolean;
298
+ next_review_at: string;
299
+ last_sync_at: string;
300
+ }
301
+
302
+ /**
303
+ * Tính toán ngày review tiếp theo dựa trên kết quả và độ tự tin.
304
+ * - Đúng + Tự tin Cao: 7 ngày.
305
+ * - Đúng + Tự tin Vừa/Thấp: 1 ngày.
306
+ * - Sai: 0 ngày (ôn lại ngay).
307
+ */
308
+ declare const calculateNextReview: (isCorrect: boolean, confidence: ConfidenceLevel) => number;
309
+ /**
310
+ * Điều kiện Mastery (Thành thạo):
311
+ * Chuỗi đúng (streak) >= 3 và lần trả lời gần nhất có độ tự tin Cao.
312
+ */
313
+ declare const checkMastery: (streak: number, lastConfidence: ConfidenceLevel) => boolean;
314
+
315
+ declare const learningEngine_calculateNextReview: typeof calculateNextReview;
316
+ declare const learningEngine_checkMastery: typeof checkMastery;
317
+ declare namespace learningEngine {
318
+ export { learningEngine_calculateNextReview as calculateNextReview, learningEngine_checkMastery as checkMastery };
319
+ }
320
+
321
+ /**
322
+ * Validator nhận vào toàn bộ object cấu hình (GameDataMap[T]).
323
+ */
324
+ declare const validateGameResult: <T extends GameType>(type: T, userAnswer: any, correctData: GameDataMap[T]) => boolean;
325
+
326
+ declare const gameEngine_validateGameResult: typeof validateGameResult;
327
+ declare namespace gameEngine {
328
+ export { gameEngine_validateGameResult as validateGameResult };
329
+ }
330
+
331
+ export { ACTION_TRIGGERS, ACTION_TYPES, type ActionLog, type ActionPayloadMap, type ActionTrigger, type ActionType, CONFIDENCE_LEVELS, type ConfidenceLevel, ELEMENT_TYPES, type ElementAction, type ElementAnimation, type ElementDataMap, type ElementStyle, type ElementType, type EvaluatePayload, GAME_TYPES, type GameDataMap, type GameType, type HotspotData, type MatchingData, type MultipleChoiceData, type NavigatePayload, type Position, type Slide, type SlideConfig, type SlideElement, slideRenderer as SlideRenderer, type SortingData, type TextData, type ToggleVisibilityPayload, type UserProgress, type VideoData, gameEngine, learningEngine };