broker-core-sdk 1.0.0 → 1.0.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.cjs +157 -0
- package/dist/index.d.cts +331 -0
- package/dist/index.d.ts +331 -0
- package/dist/index.js +129 -0
- package/package.json +4 -1
- package/docs/codebase/.codebase-scan.txt +0 -230
- package/docs/codebase/ARCHITECTURE.md +0 -37
- package/docs/codebase/CONCERNS.md +0 -19
- package/docs/codebase/CONVENTIONS.md +0 -22
- package/docs/codebase/INTEGRATIONS.md +0 -12
- package/docs/codebase/STACK.md +0 -47
- package/docs/codebase/STRUCTURE.md +0 -41
- package/docs/codebase/TESTING.md +0 -22
- package/src/engines/game-engine.ts +0 -44
- package/src/engines/learning-engine.ts +0 -35
- package/src/index.ts +0 -5
- package/src/renderer/slide-renderer.ts +0 -27
- package/src/sync/action-manager.ts +0 -23
- package/src/types/actions.ts +0 -83
- package/src/types/common.ts +0 -9
- package/src/types/data.ts +0 -71
- package/src/types/elements.ts +0 -77
- package/src/types/index.ts +0 -5
- package/src/types/models.ts +0 -47
- package/tsconfig.json +0 -44
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
## Core Sections (Required)
|
|
4
|
-
|
|
5
|
-
### 1) Architectural Style
|
|
6
|
-
|
|
7
|
-
- Primary style: Library / SDK (Functional Programming)
|
|
8
|
-
- Why this classification: Stated in `README.md` that it is designed with Functional Programming and Tree-shaking.
|
|
9
|
-
- Primary constraints: Must be framework agnostic (Vanilla TS), no Magic Strings, must use strict Discriminated Union types.
|
|
10
|
-
|
|
11
|
-
### 2) System Flow
|
|
12
|
-
|
|
13
|
-
```text
|
|
14
|
-
[Consumer App] -> [Core SDK Export (src/index.ts)] -> [Pure Function Engine (e.g. game-engine.ts)] -> [Result]
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
### 3) Layer/Module Responsibilities
|
|
18
|
-
|
|
19
|
-
| Layer or module | Owns | Must not own | Evidence |
|
|
20
|
-
|-----------------|------|--------------|----------|
|
|
21
|
-
| `src/engines` | Algorithmic logic (Spaced Repetition, Game Checks) | State management, UI | `README.md` |
|
|
22
|
-
| `src/types` | Data definitions and Constants | Implementations | `README.md` |
|
|
23
|
-
|
|
24
|
-
### 4) Reused Patterns
|
|
25
|
-
|
|
26
|
-
| Pattern | Where found | Why it exists |
|
|
27
|
-
|---------|-------------|---------------|
|
|
28
|
-
| Discriminated Union | `src/types/elements.ts` (`SlideElement`) | To map structures automatically and ensure Type-safety across the ecosystem. |
|
|
29
|
-
|
|
30
|
-
### 5) Known Architectural Risks
|
|
31
|
-
|
|
32
|
-
- [TODO] Expanding types might require significant refactoring across the `ElementDataMap`.
|
|
33
|
-
|
|
34
|
-
### 6) Evidence
|
|
35
|
-
|
|
36
|
-
- `README.md`
|
|
37
|
-
- `src/index.ts`
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# Concerns and Technical Debt
|
|
2
|
-
|
|
3
|
-
## Core Sections (Required)
|
|
4
|
-
|
|
5
|
-
### 1) Technical Debt & TODOs
|
|
6
|
-
|
|
7
|
-
- NONE detected in code comments.
|
|
8
|
-
|
|
9
|
-
### 2) High-Churn Areas
|
|
10
|
-
|
|
11
|
-
- `README.md` (4 commits)
|
|
12
|
-
- `src/types/slide-element.ts` (4 commits) - Indicates high activity around the core element types.
|
|
13
|
-
- `src/engines/game-engine.ts` (3 commits)
|
|
14
|
-
- `src/engines/learning-engine.ts` (3 commits)
|
|
15
|
-
- `src/types/index.ts` (3 commits)
|
|
16
|
-
|
|
17
|
-
### 3) Evidence
|
|
18
|
-
|
|
19
|
-
- Scan output
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Coding Standards and Conventions
|
|
2
|
-
|
|
3
|
-
## Core Sections (Required)
|
|
4
|
-
|
|
5
|
-
### 1) Naming Conventions
|
|
6
|
-
|
|
7
|
-
- Files: kebab-case (e.g., `slide-renderer.ts`, `learning-engine.ts`)
|
|
8
|
-
- Variables/Functions: camelCase
|
|
9
|
-
- Constants: UPPER_SNAKE_CASE (e.g., `ELEMENT_TYPES`, `CONFIDENCE_LEVELS`)
|
|
10
|
-
- Types/Interfaces: PascalCase
|
|
11
|
-
|
|
12
|
-
### 2) Coding Rules
|
|
13
|
-
|
|
14
|
-
- **No Magic Strings**: Always define constants in `src/types/elements.ts` or `src/types/models.ts`. (from `README.md`)
|
|
15
|
-
- **Consolidate Data**: When adding new element types, define the data interface in `data.ts` and add to `ElementDataMap`. (from `README.md`)
|
|
16
|
-
- **Strict Discriminated Unions**: Do not use `any` for the `data` field in `SlideElement`. (from `README.md`)
|
|
17
|
-
- **Framework Agnostic**: Code must be Vanilla TS without React/Node-specific dependencies. (from `README.md`)
|
|
18
|
-
|
|
19
|
-
### 3) Evidence
|
|
20
|
-
|
|
21
|
-
- `README.md`
|
|
22
|
-
- Scan output
|
package/docs/codebase/STACK.md
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# Technology Stack
|
|
2
|
-
|
|
3
|
-
## Core Sections (Required)
|
|
4
|
-
|
|
5
|
-
### 1) Runtime Summary
|
|
6
|
-
|
|
7
|
-
| Area | Value | Evidence |
|
|
8
|
-
|------|-------|----------|
|
|
9
|
-
| Primary language | TypeScript | `package.json`, `tsconfig.json` |
|
|
10
|
-
| Runtime + version | Node.js / Browser (Library) | `package.json` |
|
|
11
|
-
| Package manager | npm | `package-lock.json` |
|
|
12
|
-
| Module/build system | tsup | `package.json` (`scripts.build`) |
|
|
13
|
-
|
|
14
|
-
### 2) Production Frameworks and Dependencies
|
|
15
|
-
|
|
16
|
-
List only high-impact production dependencies (frameworks, data, transport, auth).
|
|
17
|
-
|
|
18
|
-
| Dependency | Version | Role in system | Evidence |
|
|
19
|
-
|------------|---------|----------------|----------|
|
|
20
|
-
| None | N/A | Zero-dependency SDK | `package.json` (no `dependencies`) |
|
|
21
|
-
|
|
22
|
-
### 3) Development Toolchain
|
|
23
|
-
|
|
24
|
-
| Tool | Purpose | Evidence |
|
|
25
|
-
|------|---------|----------|
|
|
26
|
-
| `typescript` | Type checking | `package.json` |
|
|
27
|
-
| `tsup` | Module bundler (CJS/ESM) | `package.json` |
|
|
28
|
-
| `vitest` | Unit testing | `package.json` |
|
|
29
|
-
|
|
30
|
-
### 4) Key Commands
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm install
|
|
34
|
-
npm run build
|
|
35
|
-
npm test
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### 5) Environment and Config
|
|
39
|
-
|
|
40
|
-
- Config sources: `tsconfig.json`
|
|
41
|
-
- Required env vars: None detected.
|
|
42
|
-
- Deployment/runtime constraints: Deployed as an npm package via workspace or separate install, exports ESM and CommonJS. Framework-agnostic.
|
|
43
|
-
|
|
44
|
-
### 6) Evidence
|
|
45
|
-
|
|
46
|
-
- `package.json`
|
|
47
|
-
- `tsconfig.json`
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# Codebase Structure
|
|
2
|
-
|
|
3
|
-
## Core Sections (Required)
|
|
4
|
-
|
|
5
|
-
### 1) Top-Level Map
|
|
6
|
-
|
|
7
|
-
List only meaningful top-level directories and files.
|
|
8
|
-
|
|
9
|
-
| Path | Purpose | Evidence |
|
|
10
|
-
|------|---------|----------|
|
|
11
|
-
| `src/` | Source code root | Scan output |
|
|
12
|
-
| `src/types/` | Data definitions, Discriminated Unions, and models | `README.md`, Scan output |
|
|
13
|
-
| `src/engines/` | Core logic for game evaluation and spaced repetition | `README.md`, Scan output |
|
|
14
|
-
| `src/renderer/` | Slide rendering and calculation math | `README.md`, Scan output |
|
|
15
|
-
| `src/sync/` | Action manager handling | Scan output |
|
|
16
|
-
| `tests/` | Unit test files | Scan output |
|
|
17
|
-
|
|
18
|
-
### 2) Entry Points
|
|
19
|
-
|
|
20
|
-
- Main runtime entry: `src/index.ts`
|
|
21
|
-
- Secondary entry points (worker/cli/jobs): NONE
|
|
22
|
-
- How entry is selected (script/config): Configured in `package.json` (`main`, `module`, `types`, `exports` fields).
|
|
23
|
-
|
|
24
|
-
### 3) Module Boundaries
|
|
25
|
-
|
|
26
|
-
| Boundary | What belongs here | What must not be here |
|
|
27
|
-
|----------|-------------------|------------------------|
|
|
28
|
-
| `src/types/` | Interfaces, types, and constants | Business logic, algorithms |
|
|
29
|
-
| `src/engines/` | Pure functions for logic (Game Engine, Learning Engine) | UI rendering code, specific framework APIs |
|
|
30
|
-
|
|
31
|
-
### 4) Naming and Organization Rules
|
|
32
|
-
|
|
33
|
-
- File naming pattern: kebab-case (e.g., `game-engine.ts`, `slide-renderer.ts`)
|
|
34
|
-
- Directory organization pattern: domain-based (`engines`, `types`, `renderer`)
|
|
35
|
-
- Import aliasing or path conventions: Relative imports within the SDK, exported centrally via `src/index.ts`.
|
|
36
|
-
|
|
37
|
-
### 5) Evidence
|
|
38
|
-
|
|
39
|
-
- `docs/codebase/.codebase-scan.txt`
|
|
40
|
-
- `package.json`
|
|
41
|
-
- `README.md`
|
package/docs/codebase/TESTING.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Testing
|
|
2
|
-
|
|
3
|
-
## Core Sections (Required)
|
|
4
|
-
|
|
5
|
-
### 1) Testing Frameworks
|
|
6
|
-
|
|
7
|
-
- Test Runner: `vitest`
|
|
8
|
-
|
|
9
|
-
### 2) Test Organization
|
|
10
|
-
|
|
11
|
-
- Location: Tests are colocated in the `tests/` directory at the project root (e.g., `tests/game-engine.test.ts`).
|
|
12
|
-
|
|
13
|
-
### 3) Key Commands
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npm test
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### 4) Evidence
|
|
20
|
-
|
|
21
|
-
- `package.json`
|
|
22
|
-
- Scan output
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { GameDataMap } from "../types/data.js";
|
|
2
|
-
import { GAME_TYPES, type GameType } from "../types/elements.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Validator nhận vào toàn bộ object cấu hình (GameDataMap[T]).
|
|
6
|
-
*/
|
|
7
|
-
export const validateGameResult = <T extends GameType>(
|
|
8
|
-
type: T,
|
|
9
|
-
userAnswer: any,
|
|
10
|
-
correctData: GameDataMap[T], // Nhận cả object data thay vì chỉ string
|
|
11
|
-
): boolean => {
|
|
12
|
-
switch (type) {
|
|
13
|
-
case GAME_TYPES.QUIZ: {
|
|
14
|
-
// Ép kiểu về MultipleChoiceData để truy cập correctId
|
|
15
|
-
const data = correctData as GameDataMap[typeof GAME_TYPES.QUIZ];
|
|
16
|
-
return userAnswer === data.correctId;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
case GAME_TYPES.SORTING: {
|
|
20
|
-
const data = correctData as GameDataMap[typeof GAME_TYPES.SORTING];
|
|
21
|
-
return JSON.stringify(userAnswer) === JSON.stringify(data.correctOrder);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
case GAME_TYPES.MATCHING: {
|
|
25
|
-
const data = correctData as GameDataMap[typeof GAME_TYPES.MATCHING];
|
|
26
|
-
const userSorted = [...userAnswer].sort();
|
|
27
|
-
const correctSorted = [...data.correctPairs].sort();
|
|
28
|
-
return JSON.stringify(userSorted) === JSON.stringify(correctSorted);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
case GAME_TYPES.HOTSPOT: {
|
|
32
|
-
const data = correctData as GameDataMap[typeof GAME_TYPES.HOTSPOT];
|
|
33
|
-
const { x, y } = userAnswer;
|
|
34
|
-
const zone = data.zones.find((z) => z.id === data.correctZoneId);
|
|
35
|
-
if (!zone) return false;
|
|
36
|
-
return (
|
|
37
|
-
x >= zone.xMin && x <= zone.xMax && y >= zone.yMin && y <= zone.yMax
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
default:
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { CONFIDENCE_LEVELS } from "../types/models.js";
|
|
2
|
-
import type { ConfidenceLevel } from "../types/models.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Tính toán ngày review tiếp theo dựa trên kết quả và độ tự tin.
|
|
6
|
-
* - Đúng + Tự tin Cao: 7 ngày.
|
|
7
|
-
* - Đúng + Tự tin Vừa/Thấp: 1 ngày.
|
|
8
|
-
* - Sai: 0 ngày (ôn lại ngay).
|
|
9
|
-
*/
|
|
10
|
-
export const calculateNextReview = (
|
|
11
|
-
isCorrect: boolean,
|
|
12
|
-
confidence: ConfidenceLevel,
|
|
13
|
-
): number => {
|
|
14
|
-
if (!isCorrect) {
|
|
15
|
-
return 0; // Ôn lại ngay lập tức
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (confidence === CONFIDENCE_LEVELS.HIGH) {
|
|
19
|
-
return 7; // Giãn cách 7 ngày cho câu trả lời tự tin
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Trường hợp Medium hoặc Low: Chỉ giãn cách 1 ngày
|
|
23
|
-
return 1;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Điều kiện Mastery (Thành thạo):
|
|
28
|
-
* Chuỗi đúng (streak) >= 3 và lần trả lời gần nhất có độ tự tin Cao.
|
|
29
|
-
*/
|
|
30
|
-
export const checkMastery = (
|
|
31
|
-
streak: number,
|
|
32
|
-
lastConfidence: ConfidenceLevel,
|
|
33
|
-
): boolean => {
|
|
34
|
-
return streak >= 3 && lastConfidence === CONFIDENCE_LEVELS.HIGH;
|
|
35
|
-
};
|
package/src/index.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import * as SlideRenderer from "./renderer/slide-renderer.js";
|
|
2
|
-
import * as learningEngine from "./engines/learning-engine.js";
|
|
3
|
-
import * as gameEngine from "./engines/game-engine.js";
|
|
4
|
-
export * from "./types/index.js";
|
|
5
|
-
export { SlideRenderer, learningEngine, gameEngine };
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chuyển đổi tọa độ từ Pixel sang % (Dùng cho Admin Builder)
|
|
3
|
-
* Canvas Builder & Percentage Positioning
|
|
4
|
-
*/
|
|
5
|
-
export const calculatePercentPosition = (
|
|
6
|
-
pixelPos: { left: number; top: number; width: number; height: number },
|
|
7
|
-
canvasSize: { width: number; height: number },
|
|
8
|
-
) => ({
|
|
9
|
-
x: (pixelPos.left / canvasSize.width) * 100,
|
|
10
|
-
y: (pixelPos.top / canvasSize.height) * 100,
|
|
11
|
-
w: (pixelPos.width / canvasSize.width) * 100,
|
|
12
|
-
h: (pixelPos.height / canvasSize.height) * 100,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Chuyển đổi tọa độ từ % sang Pixel thực tế trên thiết bị.
|
|
17
|
-
* AC 1: Renderer phải tính toán vị trí dựa trên % từ JSON
|
|
18
|
-
*/
|
|
19
|
-
export const calculateRealPosition = (
|
|
20
|
-
percentPos: { x: number; y: number; w: number; h: number },
|
|
21
|
-
screenSize: { width: number; height: number },
|
|
22
|
-
) => ({
|
|
23
|
-
left: (percentPos.x * screenSize.width) / 100,
|
|
24
|
-
top: (percentPos.y * screenSize.height) / 100,
|
|
25
|
-
width: (percentPos.w * screenSize.width) / 100,
|
|
26
|
-
height: (percentPos.h * screenSize.height) / 100,
|
|
27
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { ActionLog } from "../index.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Quản lý hàng đợi hành động để đồng bộ Offline.
|
|
5
|
-
* Cơ chế Action Log (Tránh mất dữ liệu)
|
|
6
|
-
*/
|
|
7
|
-
export const filterActionsToSync = (
|
|
8
|
-
localActions: ActionLog[],
|
|
9
|
-
lastSyncAtServer: number,
|
|
10
|
-
): ActionLog[] => {
|
|
11
|
-
// AC 1: Chỉ gửi lên Server những hành động có timestamp lớn hơn thời điểm đồng bộ cuối
|
|
12
|
-
return localActions.filter((action) => action.timestamp > lastSyncAtServer);
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Xử lý xung đột theo quy tắc Last Sync Wins.
|
|
17
|
-
*/
|
|
18
|
-
export const resolveSyncConflict = (
|
|
19
|
-
localTimestamp: number,
|
|
20
|
-
serverTimestamp: number,
|
|
21
|
-
): boolean => {
|
|
22
|
-
return localTimestamp > serverTimestamp;
|
|
23
|
-
};
|
package/src/types/actions.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tập hợp các sự kiện (events) từ người dùng hoặc hệ thống
|
|
3
|
-
* dùng để kích hoạt một hành động (action) nào đó trên Slide.
|
|
4
|
-
*/
|
|
5
|
-
export const ACTION_TRIGGERS = {
|
|
6
|
-
ON_CLICK: "ON_CLICK",
|
|
7
|
-
ON_DOUBLE_CLICK: "ON_DOUBLE_CLICK",
|
|
8
|
-
ON_HOVER: "ON_HOVER",
|
|
9
|
-
ON_ENTER_VIEWPORT: "ON_ENTER_VIEWPORT",
|
|
10
|
-
} as const;
|
|
11
|
-
|
|
12
|
-
export type ActionTrigger =
|
|
13
|
-
(typeof ACTION_TRIGGERS)[keyof typeof ACTION_TRIGGERS];
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Danh sách các loại hành động (side-effects) mà hệ thống hỗ trợ thực thi.
|
|
17
|
-
* Ví dụ: Chuyển trang, ẩn hiện component, phát nhạc, hoặc nộp bài.
|
|
18
|
-
*/
|
|
19
|
-
export const ACTION_TYPES = {
|
|
20
|
-
NAVIGATE_SLIDE: "NAVIGATE_SLIDE",
|
|
21
|
-
TOGGLE_VISIBILITY: "TOGGLE_VISIBILITY",
|
|
22
|
-
PLAY_MEDIA: "PLAY_MEDIA",
|
|
23
|
-
EVALUATE_ANSWER: "EVALUATE_ANSWER",
|
|
24
|
-
} as const;
|
|
25
|
-
|
|
26
|
-
export type ActionType = (typeof ACTION_TYPES)[keyof typeof ACTION_TYPES];
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Payload: Dữ liệu cấu hình cho hành động chuyển slide.
|
|
30
|
-
* - `targetSlideId`: ID của slide muốn nhảy tới (Dùng cho điều hướng tự do).
|
|
31
|
-
* - `direction`: Điều hướng tuần tự (Tiến/Lùi).
|
|
32
|
-
*/
|
|
33
|
-
export interface NavigatePayload {
|
|
34
|
-
targetSlideId?: string;
|
|
35
|
-
direction?: "NEXT" | "PREV";
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Payload: Dữ liệu cấu hình cho hành động thay đổi trạng thái hiển thị của Element.
|
|
40
|
-
* - `targetElementId`: ID của phần tử bị tác động.
|
|
41
|
-
* - `action`: Trạng thái muốn áp dụng (Hiển thị / Ẩn / Đảo ngược trạng thái).
|
|
42
|
-
*/
|
|
43
|
-
export interface ToggleVisibilityPayload {
|
|
44
|
-
targetElementId: string;
|
|
45
|
-
action: "SHOW" | "HIDE" | "TOGGLE";
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Payload: Dữ liệu cấu hình cho hành động chấm điểm và tính toán Spaced Repetition.
|
|
50
|
-
* - `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.
|
|
51
|
-
* - `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.
|
|
52
|
-
*/
|
|
53
|
-
export interface EvaluatePayload {
|
|
54
|
-
targetElementId?: string;
|
|
55
|
-
conceptId?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Từ điển ánh xạ (Mapping Map) cực kỳ quan trọng.
|
|
60
|
-
* Định nghĩa chính xác ActionType nào thì phải xài chung với Payload Interface nào.
|
|
61
|
-
*/
|
|
62
|
-
export type ActionPayloadMap = {
|
|
63
|
-
[ACTION_TYPES.NAVIGATE_SLIDE]: NavigatePayload;
|
|
64
|
-
[ACTION_TYPES.TOGGLE_VISIBILITY]: ToggleVisibilityPayload;
|
|
65
|
-
[ACTION_TYPES.PLAY_MEDIA]: { mediaUrl: string; loop: boolean };
|
|
66
|
-
[ACTION_TYPES.EVALUATE_ANSWER]: EvaluatePayload;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Cấu trúc hoàn chỉnh của một Hành động gắn vào Element.
|
|
71
|
-
*
|
|
72
|
-
* @description Sử dụng pattern "Discriminated Union" của TypeScript:
|
|
73
|
-
* Khi dev set thuộc tính `type`, TypeScript sẽ tự động ép buộc `payload`
|
|
74
|
-
* phải chứa các trường dữ liệu tương ứng được định nghĩa trong `ActionPayloadMap`.
|
|
75
|
-
* 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).
|
|
76
|
-
*/
|
|
77
|
-
export type ElementAction = {
|
|
78
|
-
[K in ActionType]: {
|
|
79
|
-
trigger: ActionTrigger;
|
|
80
|
-
type: K;
|
|
81
|
-
payload: ActionPayloadMap[K];
|
|
82
|
-
};
|
|
83
|
-
}[ActionType];
|
package/src/types/common.ts
DELETED
package/src/types/data.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
// --- Standard Element Data ---
|
|
2
|
-
|
|
3
|
-
export interface TextData {
|
|
4
|
-
content: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface VideoData {
|
|
8
|
-
src: string;
|
|
9
|
-
poster?: string;
|
|
10
|
-
autoPlay?: boolean;
|
|
11
|
-
muted?: boolean;
|
|
12
|
-
loop?: boolean;
|
|
13
|
-
controls?: boolean;
|
|
14
|
-
isLive?: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// --- Game Element Data ---
|
|
18
|
-
|
|
19
|
-
// 1. Multiple Choice: Chọn 1 đáp án đúng
|
|
20
|
-
export interface MultipleChoiceData {
|
|
21
|
-
question: string;
|
|
22
|
-
options: { id: string; content: string }[];
|
|
23
|
-
correctId: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// 2. Sorting: Sắp xếp theo thứ tự mảng
|
|
27
|
-
export interface SortingData {
|
|
28
|
-
items: { id: string; content: string }[];
|
|
29
|
-
correctOrder: string[]; // Mảng chứa các ID theo thứ tự đúng
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// 3. Matching: Nối cặp A - B
|
|
33
|
-
export interface MatchingData {
|
|
34
|
-
leftColumn: { id: string; content: string }[];
|
|
35
|
-
rightColumn: { id: string; content: string }[];
|
|
36
|
-
correctPairs: [string, string][]; // Mảng các cặp [id_trái, id_phải]
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// 4. Hotspot: Click vào vùng ảnh
|
|
40
|
-
export interface HotspotData {
|
|
41
|
-
imageUri: string;
|
|
42
|
-
zones: {
|
|
43
|
-
id: string;
|
|
44
|
-
xMin: number;
|
|
45
|
-
yMin: number; // Đơn vị %
|
|
46
|
-
xMax: number;
|
|
47
|
-
yMax: number;
|
|
48
|
-
}[];
|
|
49
|
-
correctZoneId: string;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// --- Data Maps ---
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Map để liên kết các Game Type với dữ liệu tương ứng.
|
|
56
|
-
*/
|
|
57
|
-
export type GameDataMap = {
|
|
58
|
-
QUIZ: MultipleChoiceData;
|
|
59
|
-
SORTING: SortingData;
|
|
60
|
-
MATCHING: MatchingData;
|
|
61
|
-
HOTSPOT: HotspotData;
|
|
62
|
-
MEMORY_CARD: any; // Có thể mở rộng thêm sau
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Map tổng hợp giữa tất cả ElementType và cấu trúc data tương ứng.
|
|
67
|
-
*/
|
|
68
|
-
export type ElementDataMap = GameDataMap & {
|
|
69
|
-
TEXT: TextData;
|
|
70
|
-
VIDEO: VideoData;
|
|
71
|
-
};
|
package/src/types/elements.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import type { ElementAction } from "./actions.js";
|
|
2
|
-
import type { Position } from "./common.js";
|
|
3
|
-
import type { ElementDataMap } from "./data.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Định nghĩa tất cả các loại phần tử có thể xuất hiện trong một Slide.
|
|
7
|
-
*/
|
|
8
|
-
export const ELEMENT_TYPES = {
|
|
9
|
-
TEXT: "TEXT",
|
|
10
|
-
VIDEO: "VIDEO",
|
|
11
|
-
QUIZ: "QUIZ",
|
|
12
|
-
MATCHING: "MATCHING",
|
|
13
|
-
SORTING: "SORTING",
|
|
14
|
-
MEMORY_CARD: "MEMORY_CARD",
|
|
15
|
-
HOTSPOT: "HOTSPOT",
|
|
16
|
-
} as const;
|
|
17
|
-
|
|
18
|
-
export type ElementType = (typeof ELEMENT_TYPES)[keyof typeof ELEMENT_TYPES];
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Định nghĩa các loại game (tập con của ELEMENT_TYPES).
|
|
22
|
-
*/
|
|
23
|
-
export const GAME_TYPES = {
|
|
24
|
-
QUIZ: "QUIZ",
|
|
25
|
-
MATCHING: "MATCHING",
|
|
26
|
-
SORTING: "SORTING",
|
|
27
|
-
MEMORY_CARD: "MEMORY_CARD",
|
|
28
|
-
HOTSPOT: "HOTSPOT",
|
|
29
|
-
} as const;
|
|
30
|
-
|
|
31
|
-
export type GameType = Extract<
|
|
32
|
-
ElementType,
|
|
33
|
-
(typeof GAME_TYPES)[keyof typeof GAME_TYPES]
|
|
34
|
-
>;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Định nghĩa style cho một phần tử.
|
|
38
|
-
*/
|
|
39
|
-
export interface ElementStyle {
|
|
40
|
-
backgroundColor?: string;
|
|
41
|
-
color?: string;
|
|
42
|
-
fontSize?: number;
|
|
43
|
-
fontFamily?: string;
|
|
44
|
-
fontWeight?: string | number;
|
|
45
|
-
textAlign?: "left" | "center" | "right" | "justify";
|
|
46
|
-
border?: string;
|
|
47
|
-
borderRadius?: number;
|
|
48
|
-
opacity?: number;
|
|
49
|
-
zIndex?: number;
|
|
50
|
-
[key: string]: any; // Allow other CSS properties
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Định nghĩa các loại animation hỗ trợ
|
|
54
|
-
*/
|
|
55
|
-
export interface ElementAnimation {
|
|
56
|
-
type: "fade-in" | "slide-up" | "bounce" | "zoom-in";
|
|
57
|
-
duration: number; // Tính bằng ms
|
|
58
|
-
delay: number; // Độ trễ trước khi chạy (ms)
|
|
59
|
-
repeat?: boolean;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Sử dụng Discriminated Union để đảm bảo type-safety cho thuộc tính 'data'.
|
|
64
|
-
*/
|
|
65
|
-
export type SlideElement = {
|
|
66
|
-
[K in keyof ElementDataMap]: {
|
|
67
|
-
id: string;
|
|
68
|
-
type: K;
|
|
69
|
-
position: Position;
|
|
70
|
-
style?: ElementStyle;
|
|
71
|
-
enterAnimation?: ElementAnimation;
|
|
72
|
-
exitAnimation?: ElementAnimation;
|
|
73
|
-
actions?: ElementAction[];
|
|
74
|
-
data: ElementDataMap[K];
|
|
75
|
-
groupId?: string;
|
|
76
|
-
};
|
|
77
|
-
}[keyof ElementDataMap];
|
package/src/types/index.ts
DELETED
package/src/types/models.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { SlideElement } from "./elements.js";
|
|
2
|
-
|
|
3
|
-
// --- Slide Models ---
|
|
4
|
-
|
|
5
|
-
export interface SlideConfig {
|
|
6
|
-
aspectRatio: string;
|
|
7
|
-
theme: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface Slide {
|
|
11
|
-
id: string;
|
|
12
|
-
tenant_id: string;
|
|
13
|
-
course_id: string;
|
|
14
|
-
order: number;
|
|
15
|
-
config?: SlideConfig;
|
|
16
|
-
elements: SlideElement[];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// --- Tracking & Progress Models ---
|
|
20
|
-
|
|
21
|
-
export const CONFIDENCE_LEVELS = {
|
|
22
|
-
HIGH: "High",
|
|
23
|
-
MEDIUM: "Medium",
|
|
24
|
-
LOW: "Low",
|
|
25
|
-
} as const;
|
|
26
|
-
|
|
27
|
-
export type ConfidenceLevel = typeof CONFIDENCE_LEVELS[keyof typeof CONFIDENCE_LEVELS];
|
|
28
|
-
|
|
29
|
-
export interface ActionLog {
|
|
30
|
-
action_type: string;
|
|
31
|
-
timestamp: number;
|
|
32
|
-
duration: number;
|
|
33
|
-
result: {
|
|
34
|
-
is_correct: boolean;
|
|
35
|
-
confidence: ConfidenceLevel;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface UserProgress {
|
|
40
|
-
user_id: string;
|
|
41
|
-
tenant_id: string;
|
|
42
|
-
concept_id: string;
|
|
43
|
-
streak: number; // Số lần đúng liên tiếp
|
|
44
|
-
is_mastered: boolean;
|
|
45
|
-
next_review_at: string; // ISODate string
|
|
46
|
-
last_sync_at: string; // ISODate string
|
|
47
|
-
}
|