@tinyweb_dev/oe-exam-sdk 0.1.26 → 0.1.28
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 +79 -5
- package/dist/components/exams/ExamPreviewDialog.d.ts +7 -6
- package/dist/components/exams/ExamPreviewDialog.js +1 -1
- package/dist/components/exams/index.d.ts +0 -1
- package/dist/components/exams/take/components/QuestionRenderer.js +1 -1
- package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.js +1 -1
- package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.js +1 -1
- package/dist/components/exams/take/exam-taking.utils.d.ts +0 -13
- package/dist/components/exams/take/exam-taking.utils.js +1 -1
- package/dist/components/exams/take/utils/answer-transformers.js +1 -1
- package/dist/components/exams/take/utils/question-transformers.d.ts +7 -17
- package/dist/components/exams/take/utils/question-transformers.js +1 -1
- package/dist/components/questions/_shared/config/question-types.config.js +1 -1
- package/dist/components/questions/_shared/types/choose-the-correct-answer-group.type.d.ts +36 -0
- package/dist/components/questions/_shared/types/cross-out-word-group.type.d.ts +40 -0
- package/dist/components/questions/_shared/types/index.d.ts +1 -0
- package/dist/components/questions/_shared/types/index.js +1 -1
- package/dist/components/questions/_shared/types/true-false-group.type.d.ts +31 -0
- package/dist/components/questions/_shared/types/true-false-group.type.js +1 -0
- package/dist/components/questions/_shared/types/word-fill-structured-form.type.d.ts +11 -17
- package/dist/components/questions/creator/question-type-registry.js +1 -1
- package/dist/components/questions/index.d.ts +0 -1
- package/dist/components/questions/index.js +1 -1
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.d.ts +2 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.d.ts +2 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupCreator.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/index.d.ts +3 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/index.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.d.ts +4 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/map-choose-the-correct-answer-group-data.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/register.d.ts +2 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/register.js +1 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/transform.d.ts +2 -0
- package/dist/components/questions/types/choose-the-correct-answer-group/transform.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/index.d.ts +5 -0
- package/dist/components/questions/types/cross-out-word-group/index.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.d.ts +6 -0
- package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/register.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/register.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/transform.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/transform.js +1 -0
- package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.d.ts +2 -0
- package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +1 -0
- package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.d.ts +2 -0
- package/dist/components/questions/types/true-false-group/TrueFalseGroupCreator.js +1 -0
- package/dist/components/questions/types/true-false-group/index.d.ts +5 -0
- package/dist/components/questions/types/true-false-group/index.js +1 -0
- package/dist/components/questions/types/true-false-group/map-true-false-group-data.d.ts +4 -0
- package/dist/components/questions/types/true-false-group/map-true-false-group-data.js +1 -0
- package/dist/components/questions/types/true-false-group/register.d.ts +2 -0
- package/dist/components/questions/types/true-false-group/register.js +1 -0
- package/dist/components/questions/types/true-false-group/transform.d.ts +2 -0
- package/dist/components/questions/types/true-false-group/transform.js +1 -0
- package/dist/components/questions/types/word-fill-structured-form/index.d.ts +1 -0
- package/dist/components/questions/types/word-fill-structured-form/index.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/map-wfsf-question-data.d.ts +7 -0
- package/dist/components/questions/types/word-fill-structured-form/map-wfsf-question-data.js +1 -0
- package/dist/components/questions/types/word-fill-structured-form/register.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/transform.js +1 -1
- package/dist/components/questions/viewer/ChooseTheCorrectAnswerGroupViewer.d.ts +8 -0
- package/dist/components/questions/viewer/ChooseTheCorrectAnswerGroupViewer.js +1 -0
- package/dist/components/questions/viewer/CrossOutWordGroupViewer.d.ts +7 -0
- package/dist/components/questions/viewer/CrossOutWordGroupViewer.js +1 -0
- package/dist/components/questions/viewer/QuestionViewer.js +1 -1
- package/dist/components/questions/viewer/SpontaneousQaGroupViewer.d.ts +4 -0
- package/dist/components/questions/viewer/SpontaneousQaGroupViewer.js +1 -0
- package/dist/components/questions/viewer/TrueFalseGroupViewer.d.ts +8 -0
- package/dist/components/questions/viewer/TrueFalseGroupViewer.js +1 -0
- package/dist/components/questions/viewer/WordFillStructuredFormViewer.d.ts +9 -0
- package/dist/components/questions/viewer/WordFillStructuredFormViewer.js +1 -0
- package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.d.ts +4 -0
- package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.js +1 -0
- package/dist/components/questions/viewer/index.d.ts +6 -0
- package/dist/components/questions/viewer/index.js +1 -1
- package/dist/components/results/renderers/review-question-body-dedicated.js +1 -1
- package/dist/components/results/review-data.js +1 -1
- package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +1 -1
- package/dist/mcp/config.d.ts +12 -0
- package/dist/mcp/config.js +1 -0
- package/dist/mcp/http-client.d.ts +6 -0
- package/dist/mcp/http-client.js +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/tools/_helpers.d.ts +4 -0
- package/dist/mcp/tools/_helpers.js +1 -0
- package/dist/mcp/tools/exams.d.ts +2 -0
- package/dist/mcp/tools/exams.js +1 -0
- package/dist/mcp/tools/index.d.ts +2 -0
- package/dist/mcp/tools/index.js +1 -0
- package/dist/mcp/tools/results.d.ts +2 -0
- package/dist/mcp/tools/results.js +1 -0
- package/dist/shared/constants/question-skills.js +1 -1
- package/dist/shared/lib/i18n/messages/en/admin.d.ts +4 -11
- package/dist/shared/lib/i18n/messages/en/admin.js +1 -1
- package/dist/shared/lib/i18n/messages/en.d.ts +4 -11
- package/dist/shared/lib/i18n/messages/vi/admin.d.ts +4 -11
- package/dist/shared/lib/i18n/messages/vi/admin.js +1 -1
- package/dist/shared/lib/i18n/messages/vi.d.ts +4 -11
- package/dist/shared/lib/utils/question-reverse-transform.js +1 -1
- package/dist/shared/lib/utils/question-transform.js +1 -1
- package/dist/shared/types/common.types.d.ts +1 -1
- package/dist/shared/types/questions/choose-the-correct-answer-group.d.ts +41 -0
- package/dist/shared/types/questions/choose-the-correct-answer-group.js +1 -0
- package/dist/shared/types/questions/cross-out-word-group.d.ts +41 -0
- package/dist/shared/types/questions/cross-out-word-group.js +1 -0
- package/dist/shared/types/questions/index.d.ts +2 -0
- package/dist/shared/types/questions/index.js +1 -1
- package/package.json +166 -169
- package/dist/components/exams/ExamPreviewPartContent.d.ts +0 -18
- package/dist/components/exams/ExamPreviewPartContent.js +0 -1
- package/dist/components/exams/ExamPreviewSidebar.d.ts +0 -17
- package/dist/components/exams/ExamPreviewSidebar.js +0 -1
- package/dist/components/exams/exam-preview.types.d.ts +0 -34
- package/dist/components/exams/exam-preview.types.js +0 -1
- package/dist/components/questions/_shared/utils/parseFillBlankStem.d.ts +0 -30
- package/dist/components/questions/_shared/utils/parseFillBlankStem.js +0 -1
- package/dist/components/questions/question-bank/EditQuestionBankDialog.d.ts +0 -2
- package/dist/components/questions/question-bank/EditQuestionBankDialog.js +0 -1
- package/dist/components/questions/question-bank/QuestionEditorRenderer.d.ts +0 -23
- package/dist/components/questions/question-bank/QuestionEditorRenderer.js +0 -1
- package/dist/components/questions/question-bank/difficulty.d.ts +0 -15
- package/dist/components/questions/question-bank/difficulty.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/choice-adapters.d.ts +0 -5
- package/dist/components/questions/question-bank/editor-adapters/choice-adapters.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/index.d.ts +0 -5
- package/dist/components/questions/question-bank/editor-adapters/index.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/media-adapters.d.ts +0 -6
- package/dist/components/questions/question-bank/editor-adapters/media-adapters.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/types.d.ts +0 -1
- package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.d.ts +0 -8
- package/dist/components/questions/question-bank/editor-adapters/unsupported-fallback.js +0 -1
- package/dist/components/questions/question-bank/editor-adapters/writing-adapters.d.ts +0 -5
- package/dist/components/questions/question-bank/editor-adapters/writing-adapters.js +0 -1
- package/dist/components/questions/question-bank/index.d.ts +0 -4
- package/dist/components/questions/question-bank/index.js +0 -1
- package/dist/components/questions/question-bank/types.d.ts +0 -59
- /package/dist/components/questions/{question-bank/editor-adapters/types.js → _shared/types/choose-the-correct-answer-group.type.js} +0 -0
- /package/dist/components/questions/{question-bank/types.js → _shared/types/cross-out-word-group.type.js} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @tinyweb_dev/oe-exam-sdk
|
|
2
2
|
|
|
3
|
-
SDK tái sử dụng cho hệ thống OE Exam: màn tạo đề, quản lý câu hỏi, làm bài, xem kết
|
|
3
|
+
SDK tái sử dụng cho hệ thống OE Exam: màn tạo đề, quản lý câu hỏi, làm bài, xem kết quả, theme giao diện và MCP tools.
|
|
4
4
|
|
|
5
5
|
## Cài đặt
|
|
6
6
|
|
|
@@ -88,9 +88,10 @@ export function ResultReviewPage({ attemptId, token, router }) {
|
|
|
88
88
|
## Entry points
|
|
89
89
|
|
|
90
90
|
```txt
|
|
91
|
-
@tinyweb_dev/oe-exam-sdk # export tổng hợp
|
|
91
|
+
@tinyweb_dev/oe-exam-sdk # export tổng hợp browser-safe (UI + API)
|
|
92
92
|
@tinyweb_dev/oe-exam-sdk/api # API adapters, constants, types
|
|
93
93
|
@tinyweb_dev/oe-exam-sdk/shared # shared constants/types/helpers
|
|
94
|
+
@tinyweb_dev/oe-exam-sdk/mcp # MCP server ONLY (Node/stdio) — không re-export từ root
|
|
94
95
|
@tinyweb_dev/oe-exam-sdk/components # shared UI components
|
|
95
96
|
@tinyweb_dev/oe-exam-sdk/components/exams # màn tạo đề / câu hỏi / làm bài / vào phòng
|
|
96
97
|
@tinyweb_dev/oe-exam-sdk/components/exams/entry # màn vào phòng (entry) + state machine
|
|
@@ -100,6 +101,8 @@ export function ResultReviewPage({ attemptId, token, router }) {
|
|
|
100
101
|
@tinyweb_dev/oe-exam-sdk/components/results # màn xem chi tiết kết quả
|
|
101
102
|
```
|
|
102
103
|
|
|
104
|
+
> **MCP:** import từ subpath `@tinyweb_dev/oe-exam-sdk/mcp` (CLI/bin `oe-exam-mcp`). Root barrel **không** export MCP để tránh kéo `node:fs` vào client Next.js (`UnhandledSchemeError`).
|
|
105
|
+
|
|
103
106
|
## API adapters
|
|
104
107
|
|
|
105
108
|
SDK không fix cứng API client. Host app có thể truyền adapter riêng qua prop `api`, hoặc dùng adapter mặc định:
|
|
@@ -237,16 +240,16 @@ Các report shell, renderer, transform helper, polling/status helper và result-
|
|
|
237
240
|
|
|
238
241
|
## MCP server
|
|
239
242
|
|
|
240
|
-
|
|
243
|
+
SDK expose bin:
|
|
241
244
|
|
|
242
245
|
```bash
|
|
243
|
-
|
|
246
|
+
oe-exam-mcp
|
|
244
247
|
```
|
|
245
248
|
|
|
246
249
|
Chạy bằng PAT/API token. Nếu token có dạng `oeexam_...`, MCP tự gửi qua `X-API-Key`; token khác sẽ gửi qua `Authorization: Bearer`.
|
|
247
250
|
|
|
248
251
|
```bash
|
|
249
|
-
OE_API_URL=http://localhost:3000 OE_API_TOKEN=... npx
|
|
252
|
+
OE_API_URL=http://localhost:3000 OE_API_TOKEN=... npx oe-exam-mcp
|
|
250
253
|
```
|
|
251
254
|
|
|
252
255
|
Tools hiện có:
|
|
@@ -328,12 +331,83 @@ import {
|
|
|
328
331
|
- Các tích hợp host-system nên đi qua props/API adapter.
|
|
329
332
|
- Upload file trong component mặc định dùng `blob:` URL cục bộ; API upload thật nên truyền từ host app khi cần.
|
|
330
333
|
|
|
334
|
+
## Dev local với host Next.js (không build tay mỗi lần sửa)
|
|
335
|
+
|
|
336
|
+
SDK **không** export thẳng `src/` vì source dùng path alias `@/` / `@oe/exam` (được `tsc-alias` rewrite lúc build). Host app luôn resolve `exports` → `dist/`.
|
|
337
|
+
|
|
338
|
+
Để sửa SDK và host nhận ngay:
|
|
339
|
+
|
|
340
|
+
### 1) Link package vào host
|
|
341
|
+
|
|
342
|
+
**Yarn (oe-school/frontend — đã cấu hình):**
|
|
343
|
+
|
|
344
|
+
```json
|
|
345
|
+
// frontend/package.json
|
|
346
|
+
"@tinyweb_dev/oe-exam-sdk": "portal:../../oe-exam/sdk"
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
cd oe-school/frontend
|
|
351
|
+
yarn install
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**npm (host khác):**
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
cd oe-exam/sdk && npm link
|
|
358
|
+
cd /path/to/host-nextjs && npm link @tinyweb_dev/oe-exam-sdk
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### 2) Transpile package trong host Next.js
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
// next.config.ts
|
|
365
|
+
const nextConfig = {
|
|
366
|
+
transpilePackages: ['@tinyweb_dev/oe-exam-sdk'],
|
|
367
|
+
};
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
(`oe-school/frontend` đã có sẵn trong `transpilePackages`.)
|
|
371
|
+
|
|
372
|
+
### 3) Chạy watch build SDK (bắt buộc — cập nhật `dist/`)
|
|
373
|
+
|
|
374
|
+
Terminal 1 — SDK:
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
cd oe-exam/sdk
|
|
378
|
+
npm run dev
|
|
379
|
+
# initial build:ts (không minify) + tsc --watch
|
|
380
|
+
# → tsc-alias + check-aliases sau mỗi lần emit thành công + copy assets
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Terminal 2 — host:
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
cd oe-school/frontend # hoặc host Next.js khác
|
|
387
|
+
yarn dev # / npm run dev
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Luồng:
|
|
391
|
+
|
|
392
|
+
```txt
|
|
393
|
+
SDK src/** → npm run dev (watch) → dist/**
|
|
394
|
+
↑ portal/npm link symlink
|
|
395
|
+
host node_modules/@tinyweb_dev/oe-exam-sdk
|
|
396
|
+
→ Next transpilePackages + HMR
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Không cần: `npm pack` / publish / reinstall version mới mỗi lần sửa.
|
|
400
|
+
|
|
401
|
+
> Publish production vẫn dùng `npm run build` (có minify). `npm run dev` chỉ cho local.
|
|
402
|
+
|
|
331
403
|
## Kiểm tra local
|
|
332
404
|
|
|
333
405
|
Trong repo này:
|
|
334
406
|
|
|
335
407
|
```bash
|
|
336
408
|
npm --prefix sdk run build
|
|
409
|
+
# hoặc watch khi dev host:
|
|
410
|
+
npm --prefix sdk run dev
|
|
337
411
|
```
|
|
338
412
|
|
|
339
413
|
Nếu chạy app dev:
|
|
@@ -10,10 +10,11 @@ export interface ExamPreviewDialogProps {
|
|
|
10
10
|
title?: string;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Read-only popup that previews an exam by id
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* Read-only popup that previews an exam (đề) by id: the layout mirrors the
|
|
14
|
+
* exam taking experience (left sidebar with exam info + progress + question
|
|
15
|
+
* navigation, right pane showing one question at a time) but creates NO attempt
|
|
16
|
+
* — exam + questions are fetched through {@link ExamQuestionsSdkApi}, so it
|
|
17
|
+
* matches exactly how the đề looks. Each question renders via {@link QuestionViewer}
|
|
18
|
+
* in review mode (correct answers highlighted).
|
|
18
19
|
*/
|
|
19
|
-
export declare function ExamPreviewDialog({ open, onOpenChange, examId, api, title
|
|
20
|
+
export declare function ExamPreviewDialog({ open, onOpenChange, examId, api, title }: ExamPreviewDialogProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useEffect as r,useMemo as a,useRef as n,useState as o}from"react";import{Eye as i}from"lucide-react";import{Button as l}from"../../components/ui/button";import{Dialog as s,DialogContent as m,DialogHeader as c,DialogTitle as u}from"../../components/ui/dialog";import{useT as p}from"../../shared/lib/i18n";import{ExamPreviewPartContent as d}from"./ExamPreviewPartContent";import{ExamPreviewSidebar as x}from"./ExamPreviewSidebar";import{buildOrderedParts as h,getQuestionNumber as f,getQuestionPoints as g,groupQuestionsByPart as P,sumQuestionPoints as v,unwrapApiData as w}from"./exam-preview.types";export function ExamPreviewDialog({open:N,onOpenChange:y,examId:b,api:E,title:T}){const j=p(),[q,C]=o(null),[D,I]=o([]),[Q,O]=o(0),[R,k]=o(!1),[B,G]=o(!1),[S,z]=o(null),[A,F]=o(0),H=n(null);r(()=>{if(!N||!b)return;let e=!1;return G(!0),z(null),O(0),(async()=>{try{const t=w(await E.getExam(b)),r=E.getQuestions?w(await E.getQuestions(b)):[];if(e)return;const a=[...r].sort((e,t)=>f(e)-f(t));C(t),I(a)}catch{e||z(j("admin.exams.preview.loadError"))}finally{e||G(!1)}})(),()=>{e=!0}},[N,b,A,E,j]),r(()=>{N||(C(null),I([]),O(0),k(!1),z(null))},[N]);const J=a(()=>h(q?.template?.parts??[],D),[q,D]),K=a(()=>P(D,J),[D,J]);r(()=>{0!==K.length?Q>K.length-1&&O(K.length-1):0!==Q&&O(0)},[Q,K.length]);const L=q?.name??T??"",M=q?.template?.totalTime??q?.duration??0,U=v(D),V=K[Q]??null,W=V?.questions??[],X=K.length,Y=X>0?(Q+1)/X*100:0,Z=V?.partName??"",$=W.reduce((e,t)=>e+g(t),0),_=()=>{H.current?.scrollTo({top:0,behavior:"smooth"})};return e(s,{open:N,onOpenChange:y,children:t(m,{className:"max-h-[95vh] max-w-7xl overflow-y-auto",children:[e(c,{children:t(u,{className:"flex items-center gap-2",children:[e(i,{className:"h-5 w-5 text-blue-600"}),j("admin.exams.preview.title",{name:L})]})}),t("div",{className:"flex h-[80vh] flex-col gap-4 sm:flex-row",children:[e(x,{examName:L,duration:M,totalPoints:U,questions:D,questionsByPart:K,currentPart:V,currentPartIndex:Q,totalParts:X,progress:Y,loading:B,showPartsDetail:R,onTogglePartsDetail:()=>k(e=>!e),onGoToPart:e=>{e<0||e>=X||(O(e),_())}}),e(d,{loading:B,error:S,questions:D,currentPart:V,currentPartQuestions:W,currentPartIndex:Q,totalParts:X,partDisplayName:Z,partTotalPoints:$,contentRef:H,onRetry:()=>F(e=>e+1),onPreviousPart:()=>{Q>0&&(O(Q-1),_())},onNextPart:()=>{Q<X-1&&(O(Q+1),_())}})]}),e("div",{className:"border-t pt-4",children:t("div",{className:"flex items-center justify-between",children:[e("div",{className:"text-sm text-gray-600",children:j("admin.exams.preview.footerNote")}),e(l,{variant:"outline",onClick:()=>y(!1),className:"border-gray-300",children:j("admin.exams.preview.close")})]})})]})})}
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useEffect as a,useMemo as n,useRef as i,useState as s}from"react";import{ArrowLeft as r,ArrowRight as l,Eye as d,Loader2 as m}from"lucide-react";import{Badge as c}from"../../components/ui/badge";import{Button as o}from"../../components/ui/button";import{Card as p,CardContent as x,CardHeader as u,CardTitle as h}from"../../components/ui/card";import{Dialog as g,DialogContent as f,DialogHeader as N,DialogTitle as v}from"../../components/ui/dialog";import{Progress as b}from"../../components/ui/progress";import{useT as y}from"../../shared/lib/i18n";import{QuestionViewer as w}from"../questions/viewer/QuestionViewer";function j(e){return e&&"object"==typeof e&&"data"in e?e.data:e}function I(e){switch(e?.toUpperCase()){case"EASY":return"bg-green-100 text-green-800";case"MEDIUM":return"bg-orange-100 text-orange-800";case"HARD":return"bg-red-100 text-red-800";default:return"bg-gray-100 text-gray-800"}}export function ExamPreviewDialog({open:q,onOpenChange:S,examId:C,api:Q,title:k}){const E=y(),[P,z]=s(null),[A,M]=s([]),[$,D]=s(0),[T,O]=s("all"),[R,U]=s(!1),[H,V]=s(!1),[Y,B]=s(null),[F,G]=s(0),J=i(null);a(()=>{if(!q||!C)return;let e=!1;return V(!0),B(null),D(0),O("all"),(async()=>{try{const t=j(await Q.getExam(C)),a=Q.getQuestions?j(await Q.getQuestions(C)):[];if(e)return;const n=[...a].sort((e,t)=>(e.questionNumber??0)-(t.questionNumber??0));z(t),M(n)}catch{e||B(E("admin.exams.preview.loadError"))}finally{e||V(!1)}})(),()=>{e=!0}},[q,C,F,Q,E]),a(()=>{q||(z(null),M([]),D(0),O("all"),U(!1),B(null))},[q]);const K=n(()=>{const e=(P?.template?.parts??[]).map(e=>({id:e.id,name:e.name||e.title})),t=new Set(e.map(e=>e.id));for(const a of A){const n=a.partId??"";n&&!t.has(n)&&(t.add(n),e.push({id:n}))}return e},[P,A]),L=e=>{const t=K.findIndex(t=>t.id===(e??""));return t>=0?t+1:1},W=n(()=>{const e=new Map;for(const t of A){const a=t.partId??"";if(!e.has(a)){const t=K.findIndex(e=>e.id===a),n=t>=0?t+1:1;e.set(a,{partId:a,partNo:n,partName:K[t]?.name||`Part ${n}`,questions:[]})}e.get(a).questions.push(t)}return Array.from(e.values()).sort((e,t)=>e.partNo-t.partNo)},[A,K]),X=P?.name??k??"",Z=P?.template?.totalTime??P?.duration??0,_=function(e){return e.reduce((e,t)=>e+(Number(t.points)||0),0)}(A),ee=A[$],te=A.length>0?($+1)/A.length*100:0,ae=e=>{D(e),J.current?.scrollTo({top:0,behavior:"smooth"})},ne="all"===T?A:A.filter(e=>L(e.partId)===T);return e(g,{open:q,onOpenChange:S,children:t(f,{className:"max-h-[95vh] max-w-7xl overflow-y-auto",children:[e(N,{children:t(v,{className:"flex items-center gap-2",children:[e(d,{className:"h-5 w-5 text-blue-600"}),E("admin.exams.preview.title",{name:X})]})}),t("div",{className:"flex h-[80vh] flex-col gap-4 sm:flex-row",children:[e("div",{className:"w-full overflow-y-auto border-b border-gray-200 sm:w-80 sm:border-b-0 sm:border-r",children:t("div",{className:"space-y-4 p-4",children:[t(p,{children:[e(u,{className:"pb-3",children:e(h,{className:"text-base",children:E("admin.exams.preview.examInfo")})}),t(x,{className:"space-y-3",children:[t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:E("admin.exams.preview.duration")}),e("span",{className:"text-sm font-medium",children:E("admin.exams.view.minutes",{count:String(Z)})})]}),t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:E("admin.exams.preview.questionCount")}),e("span",{className:"text-sm font-medium",children:H?"...":E("admin.exams.preview.questions",{count:String(A.length)})})]}),t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm text-gray-600",children:E("admin.exams.preview.totalPoints")}),e("span",{className:"text-sm font-medium",children:E("admin.exams.preview.points",{count:String(_)})})]})]})]}),!H&&A.length>0&&e(p,{children:e(x,{className:"p-4",children:t("div",{className:"space-y-2",children:[t("div",{className:"flex justify-between text-sm",children:[e("span",{children:E("admin.exams.preview.progress")}),t("span",{className:"font-medium",children:[$+1,"/",A.length]})]}),e(b,{value:te,className:"h-2"})]})})}),H?e("div",{className:"flex items-center justify-center py-4",children:t("div",{className:"flex items-center gap-2 text-gray-500",children:[e(m,{className:"h-4 w-4 animate-spin"}),e("span",{className:"text-sm",children:E("admin.exams.preview.loading")})]})}):A.length>0&&t("div",{className:"space-y-3",children:[e("h4",{className:"text-sm font-medium text-gray-700",children:E("admin.exams.preview.questionNavigation")}),t("div",{className:"flex flex-wrap gap-2",children:[e(o,{variant:"all"===T?"default":"outline",size:"sm",onClick:()=>O("all"),className:"h-8 px-3 text-xs font-medium",children:E("admin.exams.preview.all")}),W.map(e=>t(o,{variant:T===e.partNo?"default":"outline",size:"sm",onClick:()=>{O(e.partNo);const t=e.questions[0];if(t){const e=A.findIndex(e=>e.id===t.id);-1!==e&&ae(e)}},className:"h-8 px-3 text-xs font-medium",children:["P",e.partNo]},e.partId||`part-${e.partNo}`))]}),e("div",{className:"rounded bg-gray-50 p-2 text-xs",children:e("span",{className:"font-medium",children:"all"===T?E("admin.exams.preview.allQuestions",{count:String(A.length)}):E("admin.exams.preview.partQuestions",{part:String(T),count:String(W.find(e=>e.partNo===T)?.questions.length??0)})})}),e("div",{className:"rounded-lg bg-gray-50 p-3",children:e("div",{className:"grid max-h-64 grid-cols-6 gap-2 overflow-y-auto pr-2",children:ne.map(t=>{const a=A.findIndex(e=>e.id===t.id);return e(o,{variant:"ghost",size:"sm",onClick:()=>ae(a),className:"h-8 w-full p-0 text-xs font-medium transition-all duration-200 "+(a===$?"border-2 border-blue-500 bg-blue-500 text-white hover:bg-blue-600":"border border-gray-300 bg-white hover:bg-gray-100"),children:t.questionNumber},t.id)})})})]}),!H&&A.length>0&&t("div",{children:[t("div",{className:"mb-2 flex items-center justify-between",children:[e("h4",{className:"text-sm font-medium text-gray-700",children:X}),e(o,{variant:"ghost",size:"sm",onClick:()=>U(e=>!e),className:"h-6 px-2 text-xs text-gray-600 hover:text-gray-900",children:E(R?"admin.exams.preview.collapse":"admin.exams.preview.detail")})]}),e("div",{className:"rounded-lg bg-gray-50 p-3",children:t("div",{className:"flex items-center justify-between",children:[t("div",{children:[t("span",{className:"text-sm font-medium text-gray-900",children:["Total: ",E("admin.exams.preview.questions",{count:String(A.length)})]}),e("div",{className:"mt-1 flex gap-3",children:t("span",{className:"text-xs text-gray-600",children:[W.length," part(s)"]})})]}),e("div",{className:"text-xs text-gray-500",children:E("admin.exams.view.minutes",{count:String(Z)})})]})}),R&&e("div",{className:"mt-3 space-y-2",children:W.map(a=>{const n=L(ee?.partId)===a.partNo;return e("div",{className:"cursor-pointer rounded-lg border-2 p-3 transition-all duration-200 "+(n?"border-blue-400 bg-blue-50 shadow-md":"border-gray-200 bg-white hover:border-gray-300"),onClick:()=>{const e=a.questions[0];if(e){const t=A.findIndex(t=>t.id===e.id);-1!==t&&(ae(t),O(a.partNo))}},children:t("div",{className:"flex items-center justify-between",children:[e("span",{className:"text-sm font-medium "+(n?"text-blue-900":"text-gray-900"),children:a.partName}),e(c,{variant:"secondary",className:"text-xs "+(n?"bg-blue-200 text-blue-800":"bg-gray-100 text-gray-700"),children:E("admin.exams.preview.questions",{count:String(a.questions.length)})})]})},a.partId||`part-${a.partNo}`)})})]})]})}),e("div",{className:"flex-1 overflow-y-auto",children:t("div",{className:"flex h-full flex-col",children:[t("div",{className:"flex items-center justify-between border-b pb-4",children:[t("div",{children:[e("h3",{className:"text-lg font-semibold",children:H?e("span",{className:"text-gray-400",children:E("admin.exams.preview.loading")}):A.length>0?E("admin.exams.preview.questionIndex",{index:String($+1),total:String(A.length)}):E("admin.exams.preview.noQuestions")}),ee&&e("div",{className:"mt-1 inline-flex items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-3 py-1.5",children:e("span",{className:"text-sm font-semibold text-blue-700",children:(e=>{const t=K.findIndex(t=>t.id===(e??""));return K[t]?.name||`Part ${t>=0?t+1:1}`})(ee.partId)})})]}),ee&&t("div",{className:"flex items-center gap-2",children:[e(c,{variant:"outline",children:E("admin.exams.preview.points",{count:String(Number(ee.points)||1)})}),e(c,{className:I(ee.difficulty),children:ee.difficulty??"N/A"})]})]}),e("div",{ref:J,className:"flex-1 overflow-y-auto py-4",children:H?t("div",{className:"flex flex-col items-center justify-center space-y-4 py-12",children:[e(m,{className:"h-8 w-8 animate-spin text-blue-500"}),e("p",{className:"text-gray-600",children:E("admin.exams.preview.loadingQuestions")})]}):Y?e("div",{className:"flex flex-col items-center justify-center space-y-4 py-12",children:t("div",{className:"rounded-lg border border-red-200 bg-red-50 p-6 text-center",children:[e("p",{className:"font-medium text-red-800",children:Y}),e(o,{variant:"outline",onClick:()=>G(e=>e+1),className:"mt-4",children:E("admin.exams.preview.retry")})]})}):0===A.length?e("div",{className:"flex flex-col items-center justify-center space-y-4 py-12",children:e("div",{className:"rounded-lg border border-yellow-200 bg-yellow-50 p-6 text-center",children:e("p",{className:"font-medium text-yellow-800",children:E("admin.exams.preview.examNoQuestions")})})}):ee?e(w,{question:ee,isReviewMode:!0}):null}),!H&&A.length>0&&t("div",{className:"mt-auto flex items-center justify-between border-t border-gray-200 bg-gray-50 px-4 py-3",children:[t(o,{variant:"outline",onClick:()=>{$>0&&ae($-1)},disabled:0===$,className:"flex h-9 items-center gap-2 px-3 text-sm",children:[e(r,{className:"h-4 w-4"}),e("span",{className:"hidden sm:inline",children:E("admin.exams.preview.prevQuestion")}),e("span",{className:"sm:hidden",children:E("admin.exams.preview.prev")})]}),t("div",{className:"text-sm text-gray-600",children:[$+1," / ",A.length]}),t(o,{variant:"outline",onClick:()=>{$<A.length-1&&ae($+1)},disabled:$===A.length-1,className:"flex h-9 items-center gap-2 px-3 text-sm",children:[e("span",{className:"hidden sm:inline",children:E("admin.exams.preview.nextQuestion")}),e("span",{className:"sm:hidden",children:E("admin.exams.preview.next")}),e(l,{className:"h-4 w-4"})]})]})]})})]}),e("div",{className:"border-t pt-4",children:t("div",{className:"flex items-center justify-between",children:[e("div",{className:"text-sm text-gray-600",children:E("admin.exams.preview.footerNote")}),e(o,{variant:"outline",onClick:()=>S(!1),className:"border-gray-300",children:E("admin.exams.preview.close")})]})})]})})}
|
|
@@ -32,5 +32,4 @@ export { EXAM_DIFFICULTY, ExamViewDialog } from './ExamViewDialog';
|
|
|
32
32
|
export type { ExamDifficulty, ExamViewDialogExam, ExamViewDialogProps } from './ExamViewDialog';
|
|
33
33
|
export { ExamPreviewDialog } from './ExamPreviewDialog';
|
|
34
34
|
export type { ExamPreviewDialogProps } from './ExamPreviewDialog';
|
|
35
|
-
export type { PreviewQuestion, QuestionsByPart } from './exam-preview.types';
|
|
36
35
|
export { QuestionStatus, clearQuestionStatuses, getQuestionStatus, initializeQuestionStatusesFromAPI, setQuestionStatus } from './exam-question-status';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as n}from"react/jsx-runtime";import{MoversListenAndWriteRenderer as t,MoversChooseBestAnswerRenderer as s,MoversChooseAdjectiveRenderer as i,MoversWritingRenderer as r,MoversColoringRenderer as o,MoversPictureChooseRenderer as a,MoversPictureFillBlankChooseRenderer as u,MoversReadingPassageRenderer as c,MoversLabelThePictureRenderer as m,MoversFillWordHintRenderer as l,MoversGridFillRenderer as
|
|
1
|
+
"use client";import{jsx as e,jsxs as n}from"react/jsx-runtime";import{MoversListenAndWriteRenderer as t,MoversChooseBestAnswerRenderer as s,MoversChooseAdjectiveRenderer as i,MoversWritingRenderer as r,MoversColoringRenderer as o,MoversPictureChooseRenderer as a,MoversPictureFillBlankChooseRenderer as u,MoversReadingPassageRenderer as c,MoversLabelThePictureRenderer as m,MoversFillWordHintRenderer as l,MoversGridFillRenderer as p,MoversTrueFalseRenderer as g,MoversAnswerTheQuestionRenderer as _,MoversWriteSentencesRenderer as N,MoversWordOrderingRenderer as E,MoversWordFillParagraphRenderer as C,MoversMatchByWritingAnswerRenderer as d,MoversWordFillStructuredFormRenderer as A}from"./question-renderers";import{SpeakingQuestionRenderer as R}from"./speaking/renderers";import{transformFillInBlank as w,transformWriteCorrectVerbForm as I,transformChooseCorrectAnswer as T,transformChooseTheCorrectAnswerGroup as h,transformChooseCorrectAdjective as S,transformWriteShortLetter as O,transformColorObjects as U,transformPictureChoose as q,transformPictureFillBlankChoose as M,transformReadingPassage as b,transformLabelPicture as L,transformFillWordHint as x,transformGridFill as v,transformAnswerTheQuestion as D,transformTrueFalse as f,transformWordOrdering as P,transformWordFillParagraph as W,transformMatchByWritingAnswer as G,transformWriteSentences as H,transformWordFillStructuredForm as B}from"../utils/question-transformers";import{normalizeColoringAssignments as K}from"../utils/coloring-assignments";export function QuestionRenderer({part:Q,answers:F,onAnswerChange:k,isReviewMode:j=!1,onExit:y,onPartComplete:V,onPartBack:J,speakingTheme:Y,initialQuestionIndex:X,skipTeacherVideo:z,onTeacherIntroPlayed:Z,currentQuestionIndex:$}){const{partNo:ee,questionType:ne,questions:te}=Q,se=te.filter(e=>!e.is_example).length,ie=e=>{if(void 0!==$&&$>=0){if(e.length>0&&"isExample"in e[0]){const n=e.filter(e=>e.isExample),t=e.filter(e=>!e.isExample);if($<t.length)return 0===$&&n.length>0?[...n,t[$]]:[t[$]]}else if($<e.length)return[e[$]]}return e};switch(ne){case"FILL_IN_BLANK":{const n=w(te);return e(t,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,title:n.title,imageUrl:n.groupImageUrl||n.imageUrl,audioUrl:n.audioUrl||Q.audioUrl,exampleText:n.exampleText,exampleHighlight:n.exampleHighlight,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j,showHints:n.showHints,groupContent:n.groupContent,groupTitle:n.groupTitle})}case"WRITE_CORRECT_VERB_FORM":{const n=I(te);return e(t,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,title:n.title,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"CHOOSE_THE_CORRECT_ANSWER":{const n=T(te);return e(s,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,imageUrl:n.groupImageUrl,groupTitle:n.groupTitle,groupContent:n.groupContent,articles:n.articles,audioUrl:n.audioUrl||Q.audioUrl,example:n.example,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"CHOOSE_THE_CORRECT_ANSWER_GROUP":{const n=h(te);return e(s,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,example:n.example,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"CHOOSE_CORRECT_ADJECTIVE":{const n=S(te);return e(i,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"WRITE_A_SHORT_LETTER":{const n=te[0],t=O(n),s=F[n.id]||"";return e(r,{partNumber:ee,partName:Q.name,instruction:Q.instructions,prompt:t.prompt,requirements:t.requirements,minWords:t.minWords,maxWords:t.maxWords,answer:s,onAnswerChange:e=>k(n.id,e),isReviewMode:j,guideImages:t.guideImages})}case"READ_AND_COLOR_OBJECTS":{const n=U(te),t=new Set(n.regions.map(e=>e.id)),s=Object.fromEntries(Object.entries(F).filter(([e])=>t.has(e))),i=K(s,n.hintItems);return e(o,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,instructions:n.instructions,imageUrl:n.imageUrl,audioUrl:n.audioUrl||Q.audioUrl,hintItems:n.hintItems,regions:n.regions,assignments:i,onAssignmentChange:(e,t)=>{if(t){const s=n.hintItems.find(e=>e.id===t);if(s&&s.color)return void k(e,s.color)}k(e,t)},isReviewMode:j})}case"LOOK_PICTURE_CHOOSE_CORRECT_ANSWER":{const n=q(te);return e(a,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,subQuestions:n.subQuestions,answers:F,onAnswerChange:k,isReviewMode:j})}case"LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER":{const n=M(te);return e(u,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,subQuestions:n.subQuestions,answers:F,onAnswerChange:k,isReviewMode:j})}case"READ_PASSAGE_AND_ANSWER_QUESTIONS":{const n=b(te);return e(c,{partNumber:ee,partName:Q.name,questionCount:n.questions.length,instruction:Q.instructions||n.instruction,passageTitle:n.passageTitle,passage:n.passage,passageImageUrl:n.passageImageUrl,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"LABEL_THE_PICTURE":{const n=L(te);return e(m,{partNumber:ee,partName:Q.name,questionCount:n.labels.length,instruction:Q.instructions||n.instruction,imageUrl:n.imageUrl,wordBank:n.wordBank,labels:n.labels,answers:F,onAnswerChange:k,isReviewMode:j})}case"LOOK_PICTURE_FILL_WORD_HINT":{const n=x(te);return e(l,{partNumber:ee,partName:Q.name,questionCount:n.subQuestions.length,instruction:Q.instructions||n.instruction,hintLetters:n.hintLetters,subQuestions:n.subQuestions,answers:F,onAnswerChange:k,isReviewMode:j})}case"FILL_MISSING_WORDS_IN_GRID":{const n=v(te);return e(p,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,grid:n.grid,rows:n.rows,columns:n.columns,cellAnswers:{},answers:F,onAnswerChange:k,isReviewMode:j,disabledCells:n.disabledCells})}case"IMAGE_OBJECT_MATCHING":{const n=U(te),t=new Set(n.regions.map(e=>e.id)),s=Object.fromEntries(Object.entries(F).filter(([e])=>t.has(e))),i=K(s,n.hintItems);return e(o,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,instructions:n.instructions,imageUrl:n.imageUrl,audioUrl:n.audioUrl||Q.audioUrl,hintItems:n.hintItems,regions:n.regions,assignments:i,onAssignmentChange:(e,t)=>{if(t){const s=n.hintItems.find(e=>e.id===t);if(s&&s.color)return void k(e,s.color)}k(e,t)},isReviewMode:j})}case"ANSWER_THE_QUESTION":{const n=D(te);return e(_,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,imageUrl:n.imageUrl,audioUrl:Q.audioUrl,title:n.title,groupContent:n.groupContent,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"TRUE_FALSE":{const n=f(te);return e(g,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,imageUrl:n.imageUrl,groupContent:n.groupContent,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"WORD_ORDERING":{const n=P(te);return e(E,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"WORD_FILL_PARAGRAPH":{const n=W(te),t=n.wordBank.filter(e=>e.isExample).length,s=n.paragraph.match(/\{\d+\}/g),i=s?s.length:0,r=Math.max(1,i-t);let o=Q.instructions||n.instruction;return o=o.replace(/\{FROM\}/gi,"1").replace(/\{TO\}/gi,String(r)),e(C,{partNumber:ee,partName:Q.name,questionCount:se,instruction:o,questionId:n.questionId,paragraph:n.paragraph,title:n.title,imageUrl:n.imageUrl,wordBank:n.wordBank,viewMode:n.viewMode,answers:F,onAnswerChange:k,exampleAnswer:n.exampleAnswer,isReviewMode:j,emailFrom:n.emailFrom,emailTo:n.emailTo})}case"MATCH_BY_WRITING_ANSWER":{const n=G(te);return e(d,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,audioUrl:Q.audioUrl,options:n.options,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j,viewMode:n.viewMode,groupImageUrl:n.groupImageUrl})}case"WORD_FILL_STRUCTURED_FORM":{const n=B(te);return e(A,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,audioUrl:n.audioUrl||Q.audioUrl,groupTitle:n.groupTitle,groupContent:n.groupContent,groupImageUrl:n.groupImageUrl,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"WRITE_SENTENCES":{const n=H(te);return e(N,{partNumber:ee,partName:Q.name,questionCount:se,instruction:Q.instructions||n.instruction,imageUrl:n.imageUrl,title:n.title,groupContent:n.groupContent,questions:ie(n.questions),answers:F,onAnswerChange:k,isReviewMode:j})}case"LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE":case"LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP":case"LISTEN_AND_DRAG_OBJECTS_INTO_SCENE":case"LISTEN_AND_SPEAK_ANSWER":case"LISTEN_AND_SPEAK_COMPARE_IMAGES":case"LISTEN_AND_SPEAK_WITH_STORY_IMAGES":case"LISTEN_AND_SPEAK_IMAGE_GROUP":case"LISTEN_AND_SPEAK_ODD_ONE_OUT":case"LISTEN_AND_SPEAK_QUESTION_LIST":case"LISTEN_AND_SPEAK_INFO_EXCHANGE":case"SPEAKING_DESCRIBE_IMAGE":case"READ_DISPLAYED_CONTENT":case"SPONTANEOUS_QA":case"SPEAKING_CONVERSATION":case"GN_SPEAKING_INTERVIEW":case"SPEAKING_CUE_CARD":return e(R,{part:Q,answers:F,onAnswerChange:k,isReviewMode:j,onExit:y,onPartComplete:V,onPartBack:J,speakingTheme:Y,initialQuestionIndex:X,skipTeacherVideo:z,onTeacherIntroPlayed:Z,currentQuestionIndex:$});default:return e("div",{className:"flex h-full items-center justify-center",children:n("div",{className:"text-center",children:[e("p",{className:"text-lg font-semibold text-red-500",children:"Unsupported question type"}),e("p",{className:"mt-2 text-gray-500",children:ne})]})})}}
|
package/dist/components/exams/take/components/question-renderers/MoversListenAndWriteRenderer.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as r}from"react/jsx-runtime";import{
|
|
1
|
+
import{jsx as e,jsxs as r}from"react/jsx-runtime";import{Fragment as t}from"react";import{ResolvedImage as l}from"../../../../../components/common/ResolvedImage";import a from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import s from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";import o from"../../../../../components/themes/cambridge-yle/CambridgeYleAudioPlayer";import n from"../../../../../components/themes/cambridge-yle/CambridgeYleExampleText";function i(l){return l.split("\n").map((l,a)=>r(t,{children:[a>0?e("br",{}):null,l]},a))}export function MoversListenAndWriteRenderer({partNumber:t,partName:d,questionCount:m,instruction:c,imageUrl:b,audioUrl:x,title:p,exampleText:u,exampleHighlight:h,questions:g,answers:f,onAnswerChange:w,isReviewMode:N=!1,showHints:v=!1,groupContent:y,groupTitle:C}){const A=!!(x||b||y||u);return r("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar relative",children:[r("div",{className:"flex flex-col gap-2 sm:gap-3 p-3 sm:px-6 sm:pt-4",children:[e(a,{partNumber:t,questionCount:m,partName:d,isReviewMode:N}),e(s,{instruction:c,hasExample:!!u,isReviewMode:N})]}),A&&r("div",{className:"flex flex-col gap-2 sm:gap-3 p-3 sm:px-6 sm:pt-0 sticky top-0 z-20 bg-white/95 backdrop-blur pb-2 shadow-sm border-b border-gray-100",children:[x&&e(o,{audioSrc:x,compact:!0}),r("div",{className:"max-h-[35vh] overflow-y-auto custom-scrollbar pr-2 flex flex-col gap-3",children:[b&&e("div",{className:"flex items-center justify-center",children:e(l,{src:b,alt:"Shared illustration",className:"max-h-[200px] rounded-lg object-contain shadow-md"})}),y&&r("div",{className:"rounded-lg bg-amber-50 p-3 text-sm leading-relaxed text-gray-700 shadow-inner",children:[C&&e("h3",{className:"mb-2 font-semibold text-gray-800",children:C}),y]})]}),u&&e(n,{text:u,highlightedWord:h||""})]}),r("div",{className:"flex flex-col gap-4 p-3 sm:gap-6 sm:pb-6 sm:px-6",children:[p&&e("h2",{className:"text-center text-3xl font-bold uppercase text-coral-500",children:p}),e("div",{className:"flex flex-col gap-6 sm:gap-8",children:g.map(t=>{const a=t.isExample||!1,s=N||a,n=a&&t.correctAnswer?t.correctAnswer:f[t.id]||"",d=(f[t.id]||"").trim().toLowerCase(),m=(t.correctAnswer||"").trim().toLowerCase(),c=!!d,b=N&&!a&&c&&d===m,x=N&&!a&&c&&d!==m;return r("div",{id:`question-${t.id}`,className:"flex flex-col gap-4 rounded-2xl border p-4 sm:p-6 transition-all duration-200 hover:shadow-md "+(a?"border-amber-300 bg-amber-50/60 shadow-xs":"border-slate-200/80 bg-white shadow-xs hover:border-blue-300"),children:[r("div",{className:"flex items-center justify-between border-b border-slate-100 pb-3",children:[r("div",{className:"flex items-center gap-2",children:[e("span",{className:"inline-flex items-center justify-center rounded-full px-3.5 py-1 text-sm font-bold text-white shadow-xs "+(a?"bg-amber-500":N?b?"bg-emerald-500":x?"bg-rose-500":"bg-[#001590]":"bg-[#001590]"),children:a?"Ví dụ":`${t.questionNumber}.`}),a&&e("span",{className:"rounded-md bg-amber-100 px-2 py-0.5 text-xs font-semibold text-amber-700",children:"Example"})]}),N&&!a&&e("div",{children:e("span",b?{className:"inline-flex items-center gap-1 rounded-full bg-emerald-50 px-2.5 py-0.5 text-xs font-semibold text-emerald-700 border border-emerald-200",children:"✓ Đúng"}:x?{className:"inline-flex items-center gap-1 rounded-full bg-rose-50 px-2.5 py-0.5 text-xs font-semibold text-rose-700 border border-rose-200",children:"✕ Chưa đúng"}:{className:"inline-flex items-center gap-1 rounded-full bg-slate-100 px-2.5 py-0.5 text-xs font-medium text-slate-600",children:"Chưa trả lời"})})]}),t.audioUrl&&e("div",{className:"w-full my-1",children:e(o,{audioSrc:t.audioUrl,compact:!0,dense:!0})}),t.imageUrl&&e("div",{className:"flex items-center justify-center rounded-xl bg-slate-50/80 p-3 border border-slate-100 max-w-md mx-auto w-full",children:e(l,{src:t.imageUrl,alt:`Question ${t.questionNumber} illustration`,className:"max-h-[200px] sm:max-h-[220px] w-auto rounded-lg object-contain drop-shadow-xs"})}),r("div",{className:"text-base sm:text-lg leading-relaxed text-slate-800 pt-1",children:[t.textBefore&&e("span",{className:"font-medium",children:i(t.textBefore)}),e("span",{className:"mx-1 inline-block w-[7.5rem] max-w-[40%] min-w-[5.5rem] align-baseline sm:w-[8.5rem]",children:e("input",{type:"text",value:n,onChange:e=>w(t.id,e.target.value),disabled:s,placeholder:a?"":"...",className:`w-full rounded-md border-2 px-2 py-1 text-center text-sm font-semibold outline-none transition-all sm:text-base ${a?"border-amber-300 bg-amber-100/50 text-amber-800 disabled:opacity-100":N?b?"border-emerald-400 bg-emerald-50 text-emerald-800":"border-rose-400 bg-rose-50 text-rose-800":"border-blue-200 bg-blue-50/30 text-blue-900 focus:border-blue-500 focus:bg-white focus:ring-4 focus:ring-blue-100"} ${s?"disabled:cursor-not-allowed disabled:opacity-75":""}`})}),t.textAfter&&e("span",{className:"font-medium",children:i(t.textAfter)}),t.verbHint&&r("span",{className:"ml-1 italic text-slate-500 font-normal",children:["(",t.verbHint,")"]})]}),v&&t.hints&&t.hints.length>0&&!N&&r("div",{className:"flex flex-wrap items-center gap-2 pt-2 border-t border-slate-100",children:[e("span",{className:"text-xs font-medium text-slate-500",children:"Gợi ý:"}),t.hints.map((r,l)=>e("button",{type:"button",onClick:()=>w(t.id,r),className:"rounded-full border border-blue-200 bg-blue-50 px-3 py-1 text-xs font-semibold text-blue-700 shadow-2xs transition-all hover:bg-blue-600 hover:text-white hover:border-blue-600 active:scale-95",children:r},l))]}),N&&!a&&t.correctAnswer&&e("div",{className:"mt-1 rounded-lg bg-emerald-50/80 p-2.5 text-sm border border-emerald-200/80",children:r("span",{className:"font-semibold text-emerald-800",children:["Đáp án đúng: ",e("span",{className:"font-bold underline",children:t.correctAnswer})]})})]},t.id)})})]})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import{useRef as t,useEffect as n,useMemo as a,useCallback as s,memo as l}from"react";import{ResolvedImage as i}from"../../../../../components/common/ResolvedImage";import o from"../../../../../components/themes/cambridge-yle/CambridgeYlePartBanner";import d from"../../../../../components/themes/cambridge-yle/CambridgeYleInstructionBanner";import c from"../../../../../components/themes/cambridge-yle/CambridgeYleAudioPlayer";import{cn as m}from"../../../../../shared/lib/utils";function u(e,r){const t=e.trim();return r?t:t.toLowerCase()}const p={},b=l(function({question:s,initialAnswers:l,onBlankChange:o,isReviewMode:d}){const c=t(null),p=t(o);p.current=o;const b=t(!1),g=t(l),x=a(()=>s.content.replace(/\{([\w\d]+)\}/g,(e,r)=>`\n <span class="structured-blank-wrapper" data-blank-wrapper="${r}">\n <input type="text" data-blank-key="${r}" placeholder="" class="structured-blank-input" />\n <span class="structured-blank-hint" data-blank-hint="${r}"></span>\n </span>\n `),[s.content]);return n(()=>{const e=c.current;if(!e)return;b.current||(e.innerHTML=x,b.current=!0);const r=e.querySelectorAll("input.structured-blank-input"),t=[];return r.forEach(r=>{const n=r.getAttribute("data-blank-key")||"",a=e.querySelector(`[data-blank-wrapper="${n}"]`),l=e.querySelector(`[data-blank-hint="${n}"]`),i=g.current[n]||"",o=s.answers[n]||"",c=i.trim().length>0,b=c&&u(i,s.caseSensitive)===u(o,s.caseSensitive),x=d&&!b&&o.trim().length>0;r.value=x?`${c?i:"(trống)"} → ${o}`:i,r.disabled=d,r.className=m("structured-blank-input inline-block min-w-[90px] max-w-[200px] rounded-t border-b-2 bg-slate-50/40 px-2 py-0.5 text-sm font-semibold outline-none transition-all align-baseline hover:bg-slate-100/60 focus:bg-teal-50/60 focus:ring-0",d?b?"border-emerald-500 bg-emerald-50 text-emerald-800 font-bold":c?"border-rose-500 bg-rose-50 text-rose-800 font-bold":"border-amber-500 bg-amber-50 text-amber-800 font-bold":"border-slate-400 text-slate-800 focus:border-teal-600"),a&&(a.className=m("structured-blank-wrapper inline-flex items-baseline align-baseline mx-1 my-0.5",d&&"mx-1 my-0.5")),l&&(l.textContent="",l.className="structured-blank-hint hidden");const h=e=>{const r=e.target;p.current(n,r.value)};r.addEventListener("input",h),t.push({el:r,handler:h})}),()=>{t.forEach(({el:e,handler:r})=>{e.removeEventListener("input",r)})}},[x,d]),r("div",{className:"space-y-3",children:[s.title&&e("h3",{className:"text-base font-semibold text-gray-800",children:s.title}),s.imageUrl&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-gray-200",children:e(i,{src:s.imageUrl,alt:s.title||"Question image",className:"max-h-48 w-auto object-contain"})})}),e("div",{ref:c,className:"structured-form-content rounded-lg border border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50 p-4 text-sm leading-relaxed text-gray-800 [&_.structured-blank-wrapper]:inline-flex [&_.structured-blank-wrapper]:align-baseline [&_.structured-blank-wrapper]:items-baseline [&_.structured-blank-hint]:max-w-[180px]"}),d&&r("div",{className:"space-y-2 rounded-lg border border-slate-200 bg-slate-50 p-3",children:[r("div",{className:"flex flex-wrap gap-2 text-[11px] font-medium",children:[r("span",{className:"inline-flex items-center gap-1 rounded-full bg-green-100 px-2 py-1 text-green-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-green-500"}),"Đúng"]}),r("span",{className:"inline-flex items-center gap-1 rounded-full bg-red-100 px-2 py-1 text-red-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-red-500"}),"Sai"]}),r("span",{className:"inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-1 text-amber-700",children:[e("span",{className:"h-2 w-2 rounded-full bg-amber-500"}),"Chưa trả lời"]})]}),r("div",{children:[e("span",{className:"text-[10px] font-medium uppercase tracking-wider text-slate-500",children:"Đáp án đúng"}),e("div",{className:"mt-1 flex flex-wrap gap-1.5",children:Object.entries(s.answers).map(([e,t])=>r("span",{className:"rounded border border-green-300 bg-green-100 px-2 py-0.5 text-xs font-semibold text-green-800",children:[e,": ",t]},e))})]})]})]})});export function MoversWordFillStructuredFormRenderer({partNumber:n,partName:l,questionCount:m,instruction:u,audioUrl:g,groupTitle:x,groupContent:h,groupImageUrl:f,questions:w,answers:v,onAnswerChange:N,isReviewMode:y=!1}){const k=t(v);k.current=v;const C=t(N);C.current=N;const q=s((e,r,t)=>{const n=k.current[e]||{};C.current(e,{...n,[r]:t})},[]),j=a(()=>{const e={};return w.forEach(r=>{e[r.id]=(e,t)=>q(r.id,e,t)}),e},[w,q]);return r("div",{className:"flex flex-col h-full gap-4 sm:gap-6 overflow-y-auto custom-scrollbar",children:[r("div",{className:"flex flex-col gap-4 p-3 sm:px-6 sm:pt-2",children:[e(o,{partNumber:n,questionCount:m,partName:l,isReviewMode:y}),e(d,{instruction:u,isReviewMode:y}),x&&e("h2",{className:"text-center text-xl font-bold uppercase text-coral-500",children:x}),g&&e(c,{audioSrc:g,compact:!0}),f&&e("div",{className:"flex items-center justify-center",children:e(i,{src:f,alt:x||"Group image",className:"max-h-[300px] rounded-lg object-contain shadow-md"})}),h&&e("div",{className:"article-content rounded-lg bg-amber-50 p-4 text-sm leading-relaxed text-gray-700 max-h-[500px] overflow-y-auto pr-2 custom-scrollbar",dangerouslySetInnerHTML:{__html:h}})]}),w.length>0&&e("div",{className:"px-3 sm:px-6",children:e("hr",{className:"border-t border-slate-200/60 my-1"})}),e("div",{className:"grid grid-cols-1 gap-4 sm:gap-5 p-3 sm:px-6 sm:pb-6",children:w.map(t=>r("div",{id:`question-${t.id}`,className:"rounded-xl border border-gray-200 bg-white p-4 shadow-sm transition-all hover:border-indigo-200 hover:shadow-md",children:[e("div",{className:"mb-2 flex items-center gap-2",children:e("span",{className:"flex h-7 w-7 items-center justify-center rounded-full bg-gradient-to-br from-indigo-500 to-violet-600 text-xs font-bold text-white shadow-sm",children:t.questionNumber})}),e(b,{question:t,initialAnswers:v[t.id]||p,onBlankChange:j[t.id],isReviewMode:y})]},t.id))})]})}
|
|
@@ -11,13 +11,6 @@ export interface TemplateSection {
|
|
|
11
11
|
viewMode?: string;
|
|
12
12
|
wordBankConfig?: string[];
|
|
13
13
|
}
|
|
14
|
-
export type WfsfBlankStyle = 'letter' | 'word' | 'phrase';
|
|
15
|
-
export type WfsfWordBankEntry = {
|
|
16
|
-
options: string[];
|
|
17
|
-
} | {
|
|
18
|
-
word: string;
|
|
19
|
-
isExample?: boolean;
|
|
20
|
-
} | null;
|
|
21
14
|
export interface WordFillStructuredFormQuestion {
|
|
22
15
|
id: string;
|
|
23
16
|
content: string;
|
|
@@ -27,9 +20,6 @@ export interface WordFillStructuredFormQuestion {
|
|
|
27
20
|
caseSensitive?: boolean;
|
|
28
21
|
imageUrl?: string;
|
|
29
22
|
questionNumber?: number;
|
|
30
|
-
blankStyle?: WfsfBlankStyle;
|
|
31
|
-
viewMode?: string;
|
|
32
|
-
wordBank?: WfsfWordBankEntry[];
|
|
33
23
|
}
|
|
34
24
|
export interface ExamTakingPart {
|
|
35
25
|
id: string;
|
|
@@ -120,8 +110,6 @@ export declare function transformWordFillStructuredForm(questions: ExamTakingQue
|
|
|
120
110
|
groupContent: string;
|
|
121
111
|
groupImageUrl: string;
|
|
122
112
|
questions: {
|
|
123
|
-
wordBank?: WfsfWordBankEntry[];
|
|
124
|
-
viewMode?: string;
|
|
125
113
|
id: string;
|
|
126
114
|
title: string;
|
|
127
115
|
content: string;
|
|
@@ -129,6 +117,5 @@ export declare function transformWordFillStructuredForm(questions: ExamTakingQue
|
|
|
129
117
|
caseSensitive: boolean;
|
|
130
118
|
imageUrl: string;
|
|
131
119
|
questionNumber: number;
|
|
132
|
-
blankStyle: WfsfBlankStyle;
|
|
133
120
|
}[];
|
|
134
121
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function unwrap(t){return function(t){return"object"==typeof t&&null!==t&&"data"in t}(t)?t.data:t}export function unwrapAttempt(t){return"attempt"in t?t.attempt:t}export function groupQuestions(t){const n=t.examTemplate?.parts??[],e=new Map;for(const n of t.questions){const t=n.part_id??String(n.part_no??"default");e.set(t,[...e.get(t)??[],n])}return Array.from(e.entries()).map(([t,e])=>{const r=n.find(n=>String(n.id)===t);return{id:t,name:r?.name??`Part ${e[0]?.part_no??t}`,template:r,partId:t,partNo:e[0]?.part_no,instructions:r?.instructions,audioUrl:r?.audioUrl,questionType:r?.questionType??e[0]?.question_type,isGroup:r?.isGroup,group:r?.group,sections:r?.sections,viewMode:"string"==typeof r?.group?.viewMode?r.group.viewMode:void 0,startIndex:r?.startIndex,endIndex:r?.endIndex,questions:e.sort((t,n)=>t.question_number-n.question_number)}})}export function transformAnswerTheQuestion(t){return{instruction:n(t[0]?.content,"instruction"),imageUrl:n(t[0]?.content,"imageUrl"),title:n(t[0]?.content,"title"),groupContent:n(t[0]?.content,"groupContent"),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),prefixText:n(t.content,"prefixText"),suffixText:n(t.content,"suffixText"),exampleAnswer:n(t.content,"exampleAnswer"),suggestedAnswers:r(t.content,"suggestedAnswers"),isExample:Boolean(t.is_example)}))}}export function transformMatchByWritingAnswer(t){return{instruction:n(t[0]?.content,"instruction"),groupImageUrl:n(t[0]?.content,"groupImageUrl"),options:o(t[0]?.content,"options").map(t=>({answer:String(t.answer??t.value??""),text:String(t.text??t.label??""),content:String(t.content??t.text??t.label??""),imageUrl:"string"==typeof t.imageUrl?t.imageUrl:void 0})),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),exampleAnswer:n(t.content,"exampleAnswer"),isExample:Boolean(t.is_example)}))}}export function transformWordFillParagraph(t){const e=t[0];return{questionId:e?.id??"",paragraph:n(e?.content,"paragraph")||n(e?.content,"text"),title:n(e?.content,"title"),imageUrl:n(e?.content,"imageUrl"),wordBank:o(e?.content,"wordBank").map(t=>({word:String(t.word??t.text??""),isExample:Boolean(t.isExample)})),viewMode:n(e?.content,"viewMode"),instruction:n(e?.content,"instruction")}}export function transformWriteShortLetter(o){if(!o)return{prompt:"",requirements:[],minWords:void 0,maxWords:void 0,guideImages:[]};const i=t(o.content),s=t(i.instructions),
|
|
1
|
+
export function unwrap(t){return function(t){return"object"==typeof t&&null!==t&&"data"in t}(t)?t.data:t}export function unwrapAttempt(t){return"attempt"in t?t.attempt:t}export function groupQuestions(t){const n=t.examTemplate?.parts??[],e=new Map;for(const n of t.questions){const t=n.part_id??String(n.part_no??"default");e.set(t,[...e.get(t)??[],n])}return Array.from(e.entries()).map(([t,e])=>{const r=n.find(n=>String(n.id)===t);return{id:t,name:r?.name??`Part ${e[0]?.part_no??t}`,template:r,partId:t,partNo:e[0]?.part_no,instructions:r?.instructions,audioUrl:r?.audioUrl,questionType:r?.questionType??e[0]?.question_type,isGroup:r?.isGroup,group:r?.group,sections:r?.sections,viewMode:"string"==typeof r?.group?.viewMode?r.group.viewMode:void 0,startIndex:r?.startIndex,endIndex:r?.endIndex,questions:e.sort((t,n)=>t.question_number-n.question_number)}})}export function transformAnswerTheQuestion(t){return{instruction:n(t[0]?.content,"instruction"),imageUrl:n(t[0]?.content,"imageUrl"),title:n(t[0]?.content,"title"),groupContent:n(t[0]?.content,"groupContent"),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),prefixText:n(t.content,"prefixText"),suffixText:n(t.content,"suffixText"),exampleAnswer:n(t.content,"exampleAnswer"),suggestedAnswers:r(t.content,"suggestedAnswers"),isExample:Boolean(t.is_example)}))}}export function transformMatchByWritingAnswer(t){return{instruction:n(t[0]?.content,"instruction"),groupImageUrl:n(t[0]?.content,"groupImageUrl"),options:o(t[0]?.content,"options").map(t=>({answer:String(t.answer??t.value??""),text:String(t.text??t.label??""),content:String(t.content??t.text??t.label??""),imageUrl:"string"==typeof t.imageUrl?t.imageUrl:void 0})),questions:t.map(t=>({id:t.id,questionNumber:t.question_number,question:n(t.content,"question")||n(t.content,"text"),imageUrl:n(t.content,"imageUrl"),exampleAnswer:n(t.content,"exampleAnswer"),isExample:Boolean(t.is_example)}))}}export function transformWordFillParagraph(t){const e=t[0];return{questionId:e?.id??"",paragraph:n(e?.content,"paragraph")||n(e?.content,"text"),title:n(e?.content,"title"),imageUrl:n(e?.content,"imageUrl"),wordBank:o(e?.content,"wordBank").map(t=>({word:String(t.word??t.text??""),isExample:Boolean(t.isExample)})),viewMode:n(e?.content,"viewMode"),instruction:n(e?.content,"instruction")}}export function transformWriteShortLetter(o){if(!o)return{prompt:"",requirements:[],minWords:void 0,maxWords:void 0,guideImages:[]};const i=t(o.content),s=t(i.instructions),u="string"==typeof s.mainInstruction?s.mainInstruction:"",a=Array.isArray(i.informations)?i.informations.filter(t=>"string"==typeof t):[],c=r(o.content,"guideImages"),p=e(o.content,"minWords"),m=e(o.content,"maxWords");if(u||a.length)return{prompt:u,requirements:a,minWords:p,maxWords:m,guideImages:c};return{prompt:(Array.isArray(i.contexts)?i.contexts:[]).map(t).filter(t=>"text"===t.type&&"string"==typeof t.text).map(t=>String(t.text)).join("\n")||n(o.content,"prompt")||n(o.content,"question"),requirements:r(o.content,"requirements"),minWords:p,maxWords:m,guideImages:c}}export function transformWordFillStructuredForm(e){return{instruction:n(e[0]?.content,"instruction"),groupTitle:n(e[0]?.content,"groupTitle"),groupContent:n(e[0]?.content,"groupContent"),groupImageUrl:n(e[0]?.content,"groupImageUrl"),questions:e.map(e=>({id:e.id,title:n(e.content,"title"),content:n(e.content,"content")||n(e.content,"html")||n(e.content,"text"),answers:i(e.content,"answers"),caseSensitive:Boolean(t(e.content).caseSensitive),imageUrl:n(e.content,"imageUrl"),questionNumber:e.question_number}))}}function t(t){return"object"==typeof t&&null!==t?t:{}}function n(n,e){const r=t(n)[e];return"string"==typeof r?r:""}function e(n,e){const r=t(n)[e];return"number"==typeof r?r:void 0}function r(n,e){const r=t(n)[e];return Array.isArray(r)?r.filter(t=>"string"==typeof t):[]}function o(n,e){const r=t(n)[e];return Array.isArray(r)?r.map(t):[]}function i(n,e){const r=t(n)[e],o=t(r);return Object.fromEntries(Object.entries(o).map(([t,n])=>[t,String(n??"")]))}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function n(n){const t=n.match(/-opt-(\d+)$/);return t?parseInt(t[1],10):0}function t(n){return"string"==typeof n&&n.includes("-opt-")}function e(n){return Array.isArray(n)&&n.every(n=>t(n))}function s(n){return"object"==typeof n&&null!==n&&!Array.isArray(n)&&t(n.optionId)}function o(n){return n.startsWith("sq-")||n.includes("-sq-")||n.includes("-blank-")}function r(n){return/^\d+-\d+$/.test(n)}function i(n){return n.startsWith("label-")}function u(n){return n.startsWith("region-")}function f(n,t){for(const
|
|
1
|
+
function n(n){const t=n.match(/-opt-(\d+)$/);return t?parseInt(t[1],10):0}function t(n){return"string"==typeof n&&n.includes("-opt-")}function e(n){return Array.isArray(n)&&n.every(n=>t(n))}function s(n){return"object"==typeof n&&null!==n&&!Array.isArray(n)&&t(n.optionId)}function o(n){return n.startsWith("sq-")||n.includes("-sq-")||n.includes("-blank-")||n.includes("-item-")}function r(n){return/^\d+-\d+$/.test(n)}function i(n){return n.startsWith("label-")}function u(n){return n.startsWith("region-")}function f(n,t){for(const e of t){if("READ_PASSAGE_AND_ANSWER_QUESTIONS"===e.questionType&&e.questions.length>0)return{parentId:e.questions[0].id,questionType:e.questionType};if("CHOOSE_THE_CORRECT_ANSWER_GROUP"===e.questionType){const t=e.questions.find(t=>n.startsWith(`${t.id}-item-`));if(t)return{parentId:t.id,questionType:e.questionType}}}return null}function a(n){for(const t of n)if("FILL_MISSING_WORDS_IN_GRID"===t.questionType&&t.questions.length>0)return{parentId:t.questions[0].id,questionType:t.questionType};return null}function c(n){for(const t of n)if("LABEL_THE_PICTURE"===t.questionType&&t.questions.length>0)return{parentId:t.questions[0].id,questionType:t.questionType};return null}function p(n,t){for(const e of t)if(("READ_AND_COLOR_OBJECTS"===e.questionType||"IMAGE_OBJECT_MATCHING"===e.questionType)&&e.questions.length>0){const t=e.questions[0],s=t.content;if((s?.regions||s?.regionNodes||[]).some(t=>t.id===n))return{parentId:t.id,questionType:e.questionType}}return null}function d(n,t){for(const e of t)if("LOOK_PICTURE_FILL_WORD_HINT"===e.questionType)for(const t of e.questions){if(n.startsWith(`${t.id}-blank-`))return{parentId:t.id,questionType:e.questionType};const s=t.content;if(s?.subQuestions?.some(t=>t.id===n))return{parentId:t.id,questionType:e.questionType}}return null}function q(n,t){for(const e of t)for(const t of e.questions)if(t.id===n)return e.questionType;return null}function I(n,t){return"number"==typeof n||"string"==typeof n?{answer:n}:Array.isArray(n)?"WORD_FILL_PARAGRAPH"===t?{answers:n}:{answer:n}:"object"==typeof n&&null!==n?n:{answer:n}}export function transformAnswersForSubmission(l,y){const T=[],_=new Map,h=new Map,A=new Map,w=new Map,g=new Set;for(const n of y)for(const t of n.questions)"SPEAKING"===t.question_skill_type&&g.add(t.id);for(const[m,O]of Object.entries(l)){if(null==O||""===O)continue;if(g.has(m)&&"string"==typeof O)continue;if(r(m)){const n=a(y);n&&(h.has(n.parentId)||h.set(n.parentId,{}),h.get(n.parentId)[m]=String(O));continue}if(i(m)){const n=c(y);n&&(A.has(n.parentId)||A.set(n.parentId,{}),A.get(n.parentId)[m]=String(O));continue}if(u(m)){const n=p(m,y);n&&(w.has(n.parentId)||w.set(n.parentId,{}),w.get(n.parentId)[m]=String(O));continue}if(o(m)){let e=f(m,y);if(e||(e=d(m,y)),e){_.has(e.parentId)||_.set(e.parentId,{});const s=t(O)?n(O):O;_.get(e.parentId)[m]=s}continue}const l=q(m,y);let S;S=t(O)?I(n(O),l):e(O)?I(O.map(t=>n(t)),l):s(O)?I(n(O.optionId),l):I(O,l),T.push({questionId:m,answer:S})}for(const[n,t]of _){if(Object.keys(t).some(n=>n.includes("-item-"))){const e=y.flatMap(n=>n.questions).find(t=>t.id===n),s=Array.isArray(e?.content?.items)?e.content.items.length:0,o=Array.from({length:s},(e,s)=>{const o=t[`${n}-item-${s}`];return"string"==typeof o?o:""});T.push({questionId:n,answer:{answer:o}});continue}if(Object.keys(t).some(n=>n.includes("-blank-"))){const e=Object.entries(t).sort(([n],[t])=>{const e=n.match(/-blank-(\d+)$/),s=t.match(/-blank-(\d+)$/);return(e?parseInt(e[1],10):0)-(s?parseInt(s[1],10):0)}).map(([,n])=>n).join(", ");T.push({questionId:n,answer:{answer:e}})}else T.push({questionId:n,answer:{subAnswers:t}})}for(const[n,t]of h)T.push({questionId:n,answer:{answers:t}});for(const[n,t]of A)T.push({questionId:n,answer:{answers:t}});for(const[n,t]of w)T.push({questionId:n,answer:{answers:t}});return T}export function getValidQuestionIds(n){const t=new Set;for(const e of n)for(const n of e.questions)t.add(n.id);return t}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Each transformer handles specific question type data structure.
|
|
6
6
|
*/
|
|
7
7
|
import type { FillBlankQuestion, ChooseBestAnswerQuestion, PictureChooseSubQuestion, PictureFillBlankSubQuestion, ReadingPassageQuestion, LabelThePictureLabel, FillWordHintSubQuestion, ColoringHintItem, ColoringRegion } from '../types';
|
|
8
|
-
export type QuestionType = 'FILL_IN_BLANK' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_CORRECT_ADJECTIVE' | 'WRITE_A_SHORT_LETTER' | 'READ_AND_COLOR_OBJECTS' | 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER' | 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'LABEL_THE_PICTURE' | 'LOOK_PICTURE_FILL_WORD_HINT' | 'FILL_MISSING_WORDS_IN_GRID' | 'IMAGE_OBJECT_MATCHING' | 'ANSWER_THE_QUESTION' | 'TRUE_FALSE' | 'WORD_ORDERING' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'WRITE_SENTENCES' | 'WORD_FILL_STRUCTURED_FORM' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPEAKING_CONVERSATION' | 'GN_SPEAKING_INTERVIEW' | 'SPEAKING_CUE_CARD';
|
|
8
|
+
export type QuestionType = 'FILL_IN_BLANK' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_THE_CORRECT_ANSWER_GROUP' | 'CHOOSE_CORRECT_ADJECTIVE' | 'WRITE_A_SHORT_LETTER' | 'READ_AND_COLOR_OBJECTS' | 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER' | 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'LABEL_THE_PICTURE' | 'LOOK_PICTURE_FILL_WORD_HINT' | 'FILL_MISSING_WORDS_IN_GRID' | 'IMAGE_OBJECT_MATCHING' | 'ANSWER_THE_QUESTION' | 'TRUE_FALSE' | 'WORD_ORDERING' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'WRITE_SENTENCES' | 'WORD_FILL_STRUCTURED_FORM' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPEAKING_CONVERSATION' | 'GN_SPEAKING_INTERVIEW' | 'SPEAKING_CUE_CARD';
|
|
9
9
|
export interface ApiQuestion {
|
|
10
10
|
id: string;
|
|
11
11
|
content: any;
|
|
@@ -140,9 +140,7 @@ export declare function transformWriteCorrectVerbForm(questions: ApiQuestion[]):
|
|
|
140
140
|
title: string;
|
|
141
141
|
instruction: string;
|
|
142
142
|
};
|
|
143
|
-
export declare function transformChooseCorrectAnswer(questions: ApiQuestion[]
|
|
144
|
-
shuffleOptions?: boolean;
|
|
145
|
-
}): {
|
|
143
|
+
export declare function transformChooseCorrectAnswer(questions: ApiQuestion[]): {
|
|
146
144
|
questions: ChooseBestAnswerQuestion[];
|
|
147
145
|
example?: import('../types').ChooseBestAnswerExample;
|
|
148
146
|
imageUrl?: string;
|
|
@@ -157,6 +155,11 @@ export declare function transformChooseCorrectAnswer(questions: ApiQuestion[], o
|
|
|
157
155
|
audioUrl?: string;
|
|
158
156
|
instruction: string;
|
|
159
157
|
};
|
|
158
|
+
export declare function transformChooseTheCorrectAnswerGroup(questions: ApiQuestion[]): {
|
|
159
|
+
questions: ChooseBestAnswerQuestion[];
|
|
160
|
+
example?: import('../types').ChooseBestAnswerExample;
|
|
161
|
+
instruction: string;
|
|
162
|
+
};
|
|
160
163
|
export interface ChooseAdjectiveOption {
|
|
161
164
|
id: string;
|
|
162
165
|
label: string;
|
|
@@ -315,13 +318,6 @@ export declare function transformWriteSentences(questions: ApiQuestion[]): {
|
|
|
315
318
|
title?: string;
|
|
316
319
|
groupContent?: string;
|
|
317
320
|
};
|
|
318
|
-
export type WfsfBlankStyle = 'letter' | 'word' | 'phrase';
|
|
319
|
-
export type WfsfWordBankEntry = {
|
|
320
|
-
options: string[];
|
|
321
|
-
} | {
|
|
322
|
-
word: string;
|
|
323
|
-
isExample?: boolean;
|
|
324
|
-
} | null;
|
|
325
321
|
export interface WordFillStructuredFormQuestion {
|
|
326
322
|
id: string;
|
|
327
323
|
questionNumber: number;
|
|
@@ -330,12 +326,6 @@ export interface WordFillStructuredFormQuestion {
|
|
|
330
326
|
content: string;
|
|
331
327
|
answers: Record<string, string>;
|
|
332
328
|
caseSensitive: boolean;
|
|
333
|
-
/** letter = square boxes; word / phrase = underline width */
|
|
334
|
-
blankStyle: WfsfBlankStyle;
|
|
335
|
-
/** WITH_OPTIONS when choice-inline options present (plan 0024). */
|
|
336
|
-
viewMode?: string;
|
|
337
|
-
/** Index i ↔ blank key "i" (or order of {n} appearance). */
|
|
338
|
-
wordBank?: WfsfWordBankEntry[];
|
|
339
329
|
}
|
|
340
330
|
export declare function transformWordFillStructuredForm(questions: ApiQuestion[]): {
|
|
341
331
|
questions: WordFillStructuredFormQuestion[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function groupQuestionsByPart(t,e){const n=new Map,o=new Map;for(const e of t){const t=o.get(e.part_id)||[];t.push(e),o.set(e.part_id,t)}for(const[t,r]of o.entries()){const o=[...r].sort((t,e)=>t.question_number-e.question_number),i=o[0];if(!i)continue;const s=e?.find(e=>String(e.id)===String(t)),a=void 0!==s?.id?Number(s.id):void 0,u=s?.name?.match(/\d+/),l=u?parseInt(u[0],10):i.part_no,c=s?.group,m=Boolean(s?.isGroup)&&"DOCUMENT"===c?.type,p=s?.sections??[],d=new Set(p.map(t=>t.questionType).filter(Boolean)),g=p.length>1&&d.size>1;if(m||g){const e=`${t}_part`;n.set(e,{partId:t,partNo:l,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:!0,group:c,sections:s?.sections,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}if(!s?.sections?.length){const e=`${t}_part`;n.set(e,{partId:t,partNo:l,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:s?.isGroup,optionMode:s?.optionMode,optionCount:s?.optionCount,viewMode:s?.viewMode,defaultValue:s?.defaultValue,multipleAnswers:s?.multipleAnswers,questionConfig:s?.questionConfig,wordBankConfig:s?.wordBankConfig,group:s?.group,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}for(const[e,r]of s.sections.entries()){const i=o.filter(t=>{const e=t.question_number-1;return e>=r.startIndex&&e<=r.endIndex});if(!i.length)continue;const u=`${t}_section_${e}`,c=Boolean(r.isGroup||r.group?.type);n.set(u,{partId:t,partNo:l,questionType:r.questionType||i[0].question_type,questions:i,name:s.name,instructions:r.instructions||r.name||s.instructions,audioUrl:s.audioUrl,templateOrder:a,category:s.category,points:s.points,sectionId:r.sectionId,isGroup:c,optionMode:r.optionMode,optionCount:r.optionCount,viewMode:r.viewMode,defaultValue:r.defaultValue,multipleAnswers:r.multipleAnswers,questionConfig:r.questionConfig,wordBankConfig:r.wordBankConfig,group:r.group,startIndex:r.startIndex,endIndex:r.endIndex})}}return Array.from(n.values()).sort((t,e)=>{const n=void 0===t.templateOrder||isNaN(t.templateOrder)?1/0:t.templateOrder,o=void 0===e.templateOrder||isNaN(e.templateOrder)?1/0:e.templateOrder;return n!==o?n-o:(t.questions[0]?.question_number||0)-(e.questions[0]?.question_number||0)})}export function transformFillInBlank(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload,r=[],i=t=>t.replace(/\*\*/g,"");for(const e of t){const t=e.content,n=e.is_example||!1,o=t.question||t.blanks?.[0]?.text||"";if([...o.matchAll(/\{(\d+)\}/g)].length>1){const s=o.split("\n").filter(t=>t.trim());for(const o of s){const s=o.match(/\{(\d+)\}/);if(!s)continue;const a=parseInt(s[1],10),u=o.split(/\{\d+\}/),l=i(u[0]?.trim()||""),c=i(u[1]?.trim()||"");r.push({id:`${e.id}-blank-${a}`,questionNumber:e.question_number,textBefore:l,textAfter:c,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[a]:void 0})}}else{const s=o.match(/^(.*?)\{0\}(.*)$/),a=i(s?s[1].trim():o),u=i(s?s[2].trim():"");r.push({id:e.id,questionNumber:e.question_number,textBefore:a,textAfter:u,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[0]:void 0})}}return{questions:r,title:n?.title||o?.title||"",imageUrl:o?n?.imageUrl:void 0,audioUrl:n?.audioUrl,exampleText:n?.exampleText,exampleHighlight:n?.exampleHighlight,instruction:n?.instruction||"LISTEN AND WRITE",showHints:n?.showHints,groupContent:o?.content||o?.groupContent,groupTitle:o?.title,groupImageUrl:o?.mainImageUrl||o?.imageUrl}}export function transformWriteCorrectVerbForm(t){const e=t[0],n=e?.content;return{questions:t.map(t=>{const e=t.content,n=e.sentence||"",o=n.match(/^(.*?)\{0\}(.*)$/),r=o?o[1].trim():n,i=o?o[2].trim():"";return{id:t.id,questionNumber:t.question_number,textBefore:r,textAfter:i,verbHint:e.verbHint}}),title:"WRITE THE CORRECT VERB FORM",instruction:n?.instruction||"Write the correct form of the verb in parentheses."}}function t(t,e){const n=[...t];let o=function(t){let e=0;for(let n=0;n<t.length;n++)e=(e<<5)-e+t.charCodeAt(n),e|=0;return Math.abs(e)}(e);for(let t=n.length-1;t>0;t--){o=1664525*o+1013904223&2147483647;const e=o%(t+1);[n[t],n[e]]=[n[e],n[t]]}return n}const e=["A","B","C","D","E","F"];export function transformChooseCorrectAnswer(n,o){const r=o?.shuffleOptions??!0,i=n[0]?.content,s=n[0]?.questionGroup?.payload,a=n.find(t=>t.is_example),u=n.filter(t=>!t.is_example);let l;if(a){const t=a.content,n=(t.options||[]).map((t,n)=>{const o="object"==typeof t&&null!==t,r=o&&t.id?String(t.id):`${a.id}-opt-${n}`,i=o?t.text??t.content??"":String(t),s=o?t.imageUrl:void 0;return{id:r,label:e[n]||String(n+1),text:i,...s?{imageUrl:s}:{}}}),o=a.correct_answer?.answer??a.correct_answer?.optionId;let r="";if("string"==typeof o&&o){const t=n.find(t=>t.id===o);r=t?t.id:o}else"number"==typeof o&&o>=0&&o<n.length&&(r=n[o]?.id||"");l={questionNumber:a.question_number,questionText:t.question||"",options:n,correctOptionId:r||n[0]?.id||"",optionType:t.optionType||"text",imageUrl:t.imageUrl,audioUrl:t.audioUrl}}const c=u.map(n=>{const o=n.content,i=o.optionType||"text",s=(o.options||[]).map((t,o)=>{const r="object"==typeof t&&null!==t,i=r&&t.id?String(t.id):`${n.id}-opt-${o}`,s=r?t.text??t.content??"":String(t),a=r?t.imageUrl:void 0;return{id:i,label:e[o]||String(o+1),text:s,...a?{imageUrl:a}:{}}}),a=n.correct_answer?.answer??n.correct_answer?.optionId??n.correct_answer?.optionIds,u=t=>{if(null==t)return;const e=String(t),n=s.find(t=>t.id===e);if(n)return n.id;const o=e.match(/-opt-(\d+)$/);if(o){const t=parseInt(o[1],10);if(t>=0&&t<s.length)return s[t]?.id}if("number"==typeof t&&t>=0&&t<s.length)return s[t]?.id;const r=parseInt(e,10);return!isNaN(r)&&r>=0&&r<s.length&&!e.startsWith("opt-")?s[r]?.id:e};let l=[];if(Array.isArray(a))l=a.map(u).filter(t=>Boolean(t));else{const t=u(a);t&&(l=[t])}const c=r?t(s,n.id).map((t,n)=>({...t,label:e[n]||String(n+1)})):s;return{id:n.id,questionNumber:n.question_number,questionText:o.question||"",options:c,correctOptionId:l[0],correctOptionIds:l,imageUrl:o.imageUrl,audioUrl:o.audioUrl,optionType:i,multipleAnswers:Boolean(o.multipleAnswers||Array.isArray(a)),explanation:n.explanation}}),m=c.some(t=>!!t.audioUrl?.trim())||!!l?.audioUrl?.trim();return{questions:c,example:l,imageUrl:i?.imageUrl,groupImageUrl:s?.mainImageUrl||s?.imageUrl,groupTitle:s?.title,groupContent:s?.content,articles:s?.articles,audioUrl:m?void 0:i?.audioUrl,instruction:i?.instruction||"CHOOSE THE CORRECT ANSWER"}}export function transformChooseCorrectAdjective(t){return{questions:t.map(t=>{const n=t.content,o=n.sentence||"",r=o.match(/^(.*?)\{0\}(.*)$/),i=r?r[1]:o,s=r?r[2]:"";return{id:t.id,questionNumber:t.question_number,sentenceBefore:i,sentenceAfter:s,options:(n.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:n}))}}),instruction:"CHOOSE THE CORRECT ADJECTIVE"}}export function transformWriteShortLetter(t){const e=t.content;if(e.instructions?.mainInstruction||e.informations?.length)return{prompt:e.instructions?.mainInstruction||"",requirements:e.informations,minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages};return{prompt:e.contexts?.filter(t=>"text"===t.type).map(t=>t.text).join("\n")||"",minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages}}export function transformColorObjects(t){const e=t[0],n=e?.content,o=n?.colorNodes?.map(t=>({id:t.id,color:t.color,label:t.label}))||n?.hintItems||[],r=n?.regionNodes?.map(t=>({id:t.id,x:t.x,y:t.y,width:t.width,height:t.height,correctHintId:t.linkedColorNodeId}))||n?.regions||[],i=n?.instructions;return{instruction:(i&&i.length>0?i.join(" "):n?.instruction)||"READ AND COLOR THE OBJECTS",instructions:i,imageUrl:n?.backgroundImageUrl||n?.imageUrl||"",audioUrl:n?.audioUrl,hintItems:o,regions:r}}export function transformPictureChoose(t){const n=t[0]?.content;return{subQuestions:t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,imageUrl:n.imageUrl||"",questionText:n.questionText,options:(n.options||[]).map((n,o)=>({id:n.id||`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE AND CHOOSE THE CORRECT ANSWER"}}export function transformPictureFillBlankChoose(t){const n=t[0]?.content;return{subQuestions:t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,imageUrl:n.imageUrl||"",question:n.question||"",options:(n.options||[]).map((n,o)=>({id:n.id||`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE, FILL IN THE BLANK AND CHOOSE THE ANSWER"}}export function transformReadingPassage(t){if(function(t){const e=t[0];if(!e)return!1;const n=e.content;return void 0!==n?.question&&!n?.questions&&void 0!==e.questionGroup?.payload?.passage}(t)){const n=t[0],o=n.questionGroup?.payload||{},r=t.map(t=>{const n=t.content;return{id:t.id,questionNumber:t.question_number,questionText:n?.question||"",options:(n?.options||[]).map((n,o)=>({id:`${t.id}-opt-${o}`,label:e[o]||String(o+1),text:"string"==typeof n?n:String(n)}))}});return{passage:o.passage||"",passageTitle:o.passageTitle,passageImageUrl:o.passageImageUrl||o.mainImageUrl,instruction:o.instructions||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}const n=t[0],o=n?.content,r=o?.questions?.map((t,o)=>({id:t.id||`${n.id}-sq-${o}`,questionNumber:o+1,questionText:t.question,options:(t.options||[]).map((o,r)=>({id:`${t.id||n.id}-opt-${r}`,label:e[r]||String(r+1),text:o}))}))||[];return{passage:o?.passage||"",passageTitle:o?.passageTitle,passageImageUrl:o?.passageImageUrl||o?.mainImageUrl,instruction:o?.instructions?.mainInstruction||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}export function transformLabelPicture(t){const e=t[0],n=e?.content;return{imageUrl:n?.imageUrl||"",wordBank:n?.wordBank||[],labels:n?.labels?.map(t=>({id:t.id,number:t.number,isPreFilled:t.isPreFilled||!1,correctAnswer:t.correctAnswer}))||[],instruction:n?.instruction||"LABEL THE PICTURE"}}function n(t){return t&&"string"==typeof t.word&&!t.subQuestions}export function transformFillWordHint(t){const e=t[0],o=e?.content;if(t.length>1&&t.every(t=>n(t.content))){const n=e.questionGroup?.payload?.hintLetters||[];return{subQuestions:t.map(t=>{const e=t.content,n=e.word.replace(/\{\d+\}/,"_");return{id:t.id,questionNumber:t.question_number,imageUrl:e.imageUrl||"",word:n}}),hintLetters:n,instruction:o?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}if(n(o)){const t=o,n=e.questionGroup?.payload?.hintLetters||[];return{subQuestions:function(t){const e=[],n=t.split(",").map(t=>t.trim());for(const t of n){let n;const o=/\{(\d+)\}/g;for(;null!==(n=o.exec(t));){const o=parseInt(n[1],10),r=t.replace(n[0],"_");e.push({index:o,displayWord:r})}}return e.sort((t,e)=>t.index-e.index),e}(t.word).map(n=>({id:`${e.id}-blank-${n.index}`,questionNumber:e.question_number,imageUrl:t.imageUrl||"",word:n.displayWord,blankIndex:n.index})),hintLetters:n,instruction:t.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}const r=o;return{subQuestions:r?.subQuestions?.map((t,n)=>({id:t.id,questionNumber:e.question_number+n,imageUrl:t.imageUrl||"",word:t.word||""}))||[],hintLetters:r?.hintLetters||e.questionGroup?.payload?.hintLetters||[],instruction:r?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}export function transformGridFill(t){const e=t[0],n=e?.content;return{grid:n?.grid||[],rows:n?.rows||0,columns:n?.columns||0,instruction:n?.instruction||"FILL IN THE MISSING WORDS",disabledCells:n?.disabledCells||[]}}export function transformAnswerTheQuestion(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:(e.question||"").replace(/\{\d+\}/g,"______"),imageUrl:e.imageUrl,prefixText:e.prefixText,suffixText:e.suffixText,suggestedAnswers:e.suggestedAnswers,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0}}),instruction:"ANSWER THE QUESTION",imageUrl:n?.mainImageUrl||n?.imageUrl||o?.imageUrl,title:o?.title,groupContent:n?.groupContent||o?.groupContent}}export function transformTrueFalse(t){const e=t[0]?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=n&&"boolean"==typeof t.correct_answer?.answer?t.correct_answer.answer:void 0;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleCorrectAnswer:o}}),instruction:"READ AND CHOOSE TRUE OR FALSE",imageUrl:e?.mainImageUrl||e?.imageUrl,groupContent:e?.content||e?.groupContent}}export function transformWordOrdering(t){return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=Array.isArray(t.correct_answer?.answer)?t.correct_answer.answer:Array.isArray(e.answer)?e.answer:void 0;return{id:t.id,questionNumber:t.question_number,words:e.words||[],imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?o:void 0}}),instruction:"ARRANGE THE LETTERS TO MAKE A WORD"}}export function transformWordFillParagraph(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content,r=o?.title||n?.title||t.find(t=>t.content?.title)?.content?.title,i=o?.wordBank||[],s=i.map(t=>"string"==typeof t?{word:t}:t),a=o?.viewMode,u=void 0!==o?.wordBank?.[0]?.options;let l;l="EMAIL"===a?"EMAIL":a||!o?.emailFrom&&!o?.emailTo?"DEFAULT"===a?"DEFAULT":"WITH_OPTIONS"===a||u?"WITH_OPTIONS":a||0!==i.length?"WITH_WORD_BANK":"DEFAULT":"EMAIL";const c=o?.emailFrom||o?.metadata?.emailFrom,m=o?.emailTo||o?.metadata?.emailTo;return{questionId:e?.id||"",paragraph:o?.paragraph||"",title:r,imageUrl:o?.imageUrl,wordBank:s,viewMode:l,instruction:"READ AND FILL IN THE BLANKS",exampleAnswer:o?.exampleAnswer,emailFrom:c,emailTo:m}}export function transformMatchByWritingAnswer(t){const e=t[0]?.questionGroup?.payload,n=t.some(t=>!!t.content?.askerName),o=t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0,askerName:e.askerName,answererName:e.answererName}}),r=e?.options?.map(t=>({answer:t.answer,imageUrl:t.imageUrl||"",content:t.content||""}))||[],i=n?t[0]?.content:void 0;return{questions:o,options:r,instruction:"LOOK AND WRITE THE ANSWER",viewMode:n?"CONVERSATION":"DEFAULT",groupImageUrl:e?.groupImageUrl||"",askerName:i?.askerName,answererName:i?.answererName}}export function transformWriteSentences(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload;return{questions:t.map(t=>({id:t.id,questionNumber:t.question_number})),instruction:n?.instruction||"WRITE SENTENCES ABOUT THE PICTURE",imageUrl:o?.mainImageUrl||o?.imageUrl||n?.imageUrl,title:n?.title,groupContent:o?.groupContent||n?.groupContent}}function o(t){const e=String(t||"").toLowerCase();return"letter"===e||"box"===e?"letter":"phrase"===e||"sentence"===e?"phrase":"word"}export function transformWordFillStructuredForm(t){const e=t[0],n=e?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.correct_answer||{};let r=e?.content||"";const i=e?.blocks;!r&&i?.length&&(r=i.map(t=>(t.heading?`<h3>${t.heading}</h3>`:"")+(t.content||"")).join(""));const s=function(t){if(!Array.isArray(t)||0===t.length)return;const e=t.map(t=>{if(null==t)return null;if("object"!=typeof t||Array.isArray(t))return null;const e=t;if(Array.isArray(e.options)){const t=e.options.map(t=>String(t??"").trim()).filter(t=>t.length>0);return t.length>=2?{options:t}:null}const n=String(e.word??"").trim();return n?e.isExample?{word:n,isExample:!0}:{word:n}:null});return e.some(t=>null!=t)?e:void 0}(e?.wordBank),a=Boolean(s?.some(t=>null!=t&&"options"in t&&Array.isArray(t.options))),u=Boolean(s?.some(t=>null!=t&&"word"in t&&t.word)),l=e?.viewMode||(a?"WITH_OPTIONS":u?"WITH_WORD_BANK":void 0);return{id:t.id,questionNumber:t.question_number,title:e?.title||"",imageUrl:e?.imageUrl,content:r,answers:n?.answers||{},caseSensitive:n?.caseSensitive??e?.caseSensitive??!1,blankStyle:o(e?.blankStyle),...l?{viewMode:l}:{},...s?{wordBank:s}:{}}}),instruction:n?.instructions||"COMPLETE THE FORM BELOW",groupTitle:n?.title,groupContent:n?.content,groupImageUrl:n?.imageUrl,audioUrl:e?.audio_url||n?.audioUrl}}export function transformListenChooseObjects(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload||{};return{audioUrl:n?.audioUrl||"",backgroundImageUrl:o.backgroundImageUrl||"",objectNodes:o.objectNodes||[],correctObjectId:e?.correctAnswer?.objectId||e?.correct_answer?.objectId||"",isBackup:n?.isBackup||!1,instruction:"LISTEN AND CHOOSE THE CORRECT OBJECT"}}export function transformListenSpeakAnswer(t){return{questions:t.map(t=>{const e=t.content,n=t.questionGroup?.payload||{};return{id:t.id,questionNumber:t.question_number,audioUrl:e?.audioUrl||"",arrowNode:e?.arrowNode,backgroundImageUrl:n.backgroundImageUrl||n.imageUrl||"",isBackup:e?.isBackup||!1}}),instruction:"LISTEN AND SPEAK YOUR ANSWER"}}
|
|
1
|
+
export function groupQuestionsByPart(t,e){const n=new Map,o=new Map;for(const e of t){const t=o.get(e.part_id)||[];t.push(e),o.set(e.part_id,t)}for(const[t,r]of o.entries()){const o=[...r].sort((t,e)=>t.question_number-e.question_number),i=o[0];if(!i)continue;const s=e?.find(e=>String(e.id)===String(t)),a=void 0!==s?.id?Number(s.id):void 0,u=s?.name?.match(/\d+/),c=u?parseInt(u[0],10):i.part_no,l=s?.group,m=Boolean(s?.isGroup)&&"DOCUMENT"===l?.type,p=s?.sections??[],d=new Set(p.map(t=>t.questionType).filter(Boolean)),g=p.length>1&&d.size>1;if(m||g){const e=`${t}_part`;n.set(e,{partId:t,partNo:c,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:!0,group:l,sections:s?.sections,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}if(!s?.sections?.length){const e=`${t}_part`;n.set(e,{partId:t,partNo:c,questionType:i.question_type,questions:o,name:s?.name,instructions:s?.instructions,audioUrl:s?.audioUrl,templateOrder:a,category:s?.category,points:s?.points,isGroup:s?.isGroup,optionMode:s?.optionMode,optionCount:s?.optionCount,viewMode:s?.viewMode,defaultValue:s?.defaultValue,multipleAnswers:s?.multipleAnswers,questionConfig:s?.questionConfig,wordBankConfig:s?.wordBankConfig,group:s?.group,startIndex:s?.startIndex,endIndex:s?.endIndex});continue}for(const[e,r]of s.sections.entries()){const i=o.filter(t=>{const e=t.question_number-1;return e>=r.startIndex&&e<=r.endIndex});if(!i.length)continue;const u=`${t}_section_${e}`,l=Boolean(r.isGroup||r.group?.type);n.set(u,{partId:t,partNo:c,questionType:r.questionType||i[0].question_type,questions:i,name:s.name,instructions:r.instructions||r.name||s.instructions,audioUrl:s.audioUrl,templateOrder:a,category:s.category,points:s.points,sectionId:r.sectionId,isGroup:l,optionMode:r.optionMode,optionCount:r.optionCount,viewMode:r.viewMode,defaultValue:r.defaultValue,multipleAnswers:r.multipleAnswers,questionConfig:r.questionConfig,wordBankConfig:r.wordBankConfig,group:r.group,startIndex:r.startIndex,endIndex:r.endIndex})}}return Array.from(n.values()).sort((t,e)=>{const n=void 0===t.templateOrder||isNaN(t.templateOrder)?1/0:t.templateOrder,o=void 0===e.templateOrder||isNaN(e.templateOrder)?1/0:e.templateOrder;return n!==o?n-o:(t.questions[0]?.question_number||0)-(e.questions[0]?.question_number||0)})}export function transformFillInBlank(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload,r=[];for(const e of t){const t=e.content,n=e.is_example||!1,o=t.question||t.blanks?.[0]?.text||"";if([...o.matchAll(/\{(\d+)\}/g)].length>1){const i=o.split("\n").filter(t=>t.trim());for(const o of i){const i=o.match(/\{(\d+)\}/);if(!i)continue;const s=parseInt(i[1],10),a=o.split(/\{\d+\}/),u=a[0]?.trim()||"",c=a[1]?.trim()||"";r.push({id:`${e.id}-blank-${s}`,questionNumber:e.question_number,textBefore:u,textAfter:c,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[s]:void 0})}}else{const i=o.match(/^([\s\S]*?)\{0\}([\s\S]*)$/),s=i?i[1].trim():o,a=i?i[2].trim():"";r.push({id:e.id,questionNumber:e.question_number,textBefore:s,textAfter:a,imageUrl:t.imageUrl,hints:t.hints,isExample:n,correctAnswer:n?e.correct_answer?.answers?.[0]:void 0})}}return{questions:r,title:n?.title||o?.title||"",imageUrl:o?n?.imageUrl:void 0,audioUrl:n?.audioUrl,exampleText:n?.exampleText,exampleHighlight:n?.exampleHighlight,instruction:n?.instruction||"LISTEN AND WRITE",showHints:n?.showHints,groupContent:o?.content||o?.groupContent,groupTitle:o?.title,groupImageUrl:o?.mainImageUrl||o?.imageUrl}}export function transformWriteCorrectVerbForm(t){const e=t[0],n=e?.content;return{questions:t.map(t=>{const e=t.content,n=e.sentence||"",o=n.match(/^([\s\S]*?)\{0\}([\s\S]*)$/),r=o?o[1].trim():n,i=o?o[2].trim():"";return{id:t.id,questionNumber:t.question_number,textBefore:r,textAfter:i,verbHint:e.verbHint}}),title:"WRITE THE CORRECT VERB FORM",instruction:n?.instruction||"Write the correct form of the verb in parentheses."}}const t=["A","B","C","D","E","F"];export function transformChooseCorrectAnswer(e){const n=e[0]?.content,o=e[0]?.questionGroup?.payload,r=e.find(t=>t.is_example),i=e.filter(t=>!t.is_example);let s;if(r){const e=r.content,n=(e.options||[]).map((e,n)=>{const o="object"==typeof e&&null!==e,i=o&&e.id?String(e.id):`${r.id}-opt-${n}`,s=o?e.text??e.content??"":String(e),a=o?e.imageUrl:void 0;return{id:i,label:t[n]||String(n+1),text:s,...a?{imageUrl:a}:{}}}),o=r.correct_answer?.answer??r.correct_answer?.optionId;let i="";if("string"==typeof o&&o){const t=n.find(t=>t.id===o);i=t?t.id:o}else"number"==typeof o&&o>=0&&o<n.length&&(i=n[o]?.id||"");s={questionNumber:r.question_number,questionText:e.question||"",options:n,correctOptionId:i||n[0]?.id||"",optionType:e.optionType||"text",imageUrl:e.imageUrl,audioUrl:e.audioUrl}}const a=i.map(e=>{const n=e.content,o=n.optionType||"text",r=(n.options||[]).map((n,o)=>{const r="object"==typeof n&&null!==n,i=r&&n.id?String(n.id):`${e.id}-opt-${o}`,s=r?n.text??n.content??"":String(n),a=r?n.imageUrl:void 0;return{id:i,label:t[o]||String(o+1),text:s,...a?{imageUrl:a}:{}}}),i=e.correct_answer?.answer??e.correct_answer?.optionId??e.correct_answer?.optionIds,s=t=>{if(null==t)return;const e=String(t),n=r.find(t=>t.id===e);if(n)return n.id;const o=e.match(/-opt-(\d+)$/);if(o){const t=parseInt(o[1],10);if(t>=0&&t<r.length)return r[t]?.id}if("number"==typeof t&&t>=0&&t<r.length)return r[t]?.id;const i=parseInt(e,10);return!isNaN(i)&&i>=0&&i<r.length&&!e.startsWith("opt-")?r[i]?.id:e};let a=[];if(Array.isArray(i))a=i.map(s).filter(t=>Boolean(t));else{const t=s(i);t&&(a=[t])}return{id:e.id,questionNumber:e.question_number,questionText:n.question||"",options:r,correctOptionId:a[0],correctOptionIds:a,imageUrl:n.imageUrl,audioUrl:n.audioUrl,optionType:o,multipleAnswers:Boolean(n.multipleAnswers||Array.isArray(i)),explanation:e.explanation}}),u=a.some(t=>!!t.audioUrl?.trim())||!!s?.audioUrl?.trim();return{questions:a,example:s,imageUrl:n?.imageUrl,groupImageUrl:o?.mainImageUrl||o?.imageUrl,groupTitle:o?.title,groupContent:o?.content,articles:o?.articles,audioUrl:u?void 0:n?.audioUrl,instruction:n?.instruction||"CHOOSE THE CORRECT ANSWER"}}export function transformChooseTheCorrectAnswerGroup(e){const n=e[0],o=n?.content,r=Array.isArray(o?.items)?o.items:[],i=Array.isArray(n?.correct_answer?.answer)?n.correct_answer.answer:[],s=r.find(t=>t.isExample),a=r.filter(t=>!t.isExample),u=(e,n)=>(e||[]).map((e,o)=>{const r="object"==typeof e&&null!==e;return{id:r&&e.id?String(e.id):`${n}-opt-${o+1}`,label:t[o]||String(o+1),text:String(r?e.text??"":e),...r&&e.imageUrl?{imageUrl:e.imageUrl}:{}}});let c;if(s){const t=r.indexOf(s),e=u(s.content?.options,`${n.id}-ex`),o=s.correctAnswer?.answer||i[t]||e[0]?.id||"";c={questionNumber:s.questionNumber||t+1,questionText:s.content?.question||"",options:e,correctOptionId:o,optionType:s.content?.optionType||"text"}}return{questions:a.map(t=>{const e=r.indexOf(t),o=u(t.content?.options,`${n.id}-item-${e}`),s=t.correctAnswer?.answer||i[e]||"";return{id:`${n.id}-item-${e}`,questionNumber:t.questionNumber||e+1,questionText:t.content?.question||"",options:o,correctOptionId:s,correctOptionIds:s?[s]:[],optionType:t.content?.optionType||"text"}}),example:c,instruction:o?.meta?.instruction||"Choose the correct answer."}}export function transformChooseCorrectAdjective(e){return{questions:e.map(e=>{const n=e.content,o=n.sentence||"",r=o.match(/^([\s\S]*?)\{0\}([\s\S]*)$/),i=r?r[1]:o,s=r?r[2]:"";return{id:e.id,questionNumber:e.question_number,sentenceBefore:i,sentenceAfter:s,options:(n.options||[]).map((n,o)=>({id:`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:n}))}}),instruction:"CHOOSE THE CORRECT ADJECTIVE"}}export function transformWriteShortLetter(t){const e=t.content;if(e.instructions?.mainInstruction||e.informations?.length)return{prompt:e.instructions?.mainInstruction||"",requirements:e.informations,minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages};return{prompt:e.contexts?.filter(t=>"text"===t.type).map(t=>t.text).join("\n")||"",minWords:e.minWords,maxWords:e.maxWords,guideImages:e.guideImages}}export function transformColorObjects(t){const e=t[0],n=e?.content,o=n?.colorNodes?.map(t=>({id:t.id,color:t.color,label:t.label}))||n?.hintItems||[],r=n?.regionNodes?.map(t=>({id:t.id,x:t.x,y:t.y,width:t.width,height:t.height,correctHintId:t.linkedColorNodeId}))||n?.regions||[],i=n?.instructions;return{instruction:(i&&i.length>0?i.join(" "):n?.instruction)||"READ AND COLOR THE OBJECTS",instructions:i,imageUrl:n?.backgroundImageUrl||n?.imageUrl||"",audioUrl:n?.audioUrl,hintItems:o,regions:r}}export function transformPictureChoose(e){const n=e[0]?.content;return{subQuestions:e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,imageUrl:n.imageUrl||"",questionText:n.questionText,options:(n.options||[]).map((n,o)=>({id:n.id||`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE AND CHOOSE THE CORRECT ANSWER"}}export function transformPictureFillBlankChoose(e){const n=e[0]?.content;return{subQuestions:e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,imageUrl:n.imageUrl||"",question:n.question||"",options:(n.options||[]).map((n,o)=>({id:n.id||`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:n.text}))}}),instruction:n?.instruction||"LOOK AT THE PICTURE, FILL IN THE BLANK AND CHOOSE THE ANSWER"}}export function transformReadingPassage(e){if(function(t){const e=t[0];if(!e)return!1;const n=e.content;return void 0!==n?.question&&!n?.questions&&void 0!==e.questionGroup?.payload?.passage}(e)){const n=e[0],o=n.questionGroup?.payload||{},r=e.map(e=>{const n=e.content;return{id:e.id,questionNumber:e.question_number,questionText:n?.question||"",options:(n?.options||[]).map((n,o)=>({id:`${e.id}-opt-${o}`,label:t[o]||String(o+1),text:"string"==typeof n?n:String(n)}))}});return{passage:o.passage||"",passageTitle:o.passageTitle,passageImageUrl:o.passageImageUrl||o.mainImageUrl,instruction:o.instructions||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}const n=e[0],o=n?.content,r=o?.questions?.map((e,o)=>({id:e.id||`${n.id}-sq-${o}`,questionNumber:o+1,questionText:e.question,options:(e.options||[]).map((o,r)=>({id:`${e.id||n.id}-opt-${r}`,label:t[r]||String(r+1),text:o}))}))||[];return{passage:o?.passage||"",passageTitle:o?.passageTitle,passageImageUrl:o?.passageImageUrl||o?.mainImageUrl,instruction:o?.instructions?.mainInstruction||"READ THE PASSAGE AND ANSWER QUESTIONS",questions:r}}export function transformLabelPicture(t){const e=t[0],n=e?.content;return{imageUrl:n?.imageUrl||"",wordBank:n?.wordBank||[],labels:n?.labels?.map(t=>({id:t.id,number:t.number,isPreFilled:t.isPreFilled||!1,correctAnswer:t.correctAnswer}))||[],instruction:n?.instruction||"LABEL THE PICTURE"}}function e(t){return t&&"string"==typeof t.word&&!t.subQuestions}export function transformFillWordHint(t){const n=t[0],o=n?.content;if(t.length>1&&t.every(t=>e(t.content))){const e=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:t.map(t=>{const e=t.content,n=e.word.replace(/\{\d+\}/,"_");return{id:t.id,questionNumber:t.question_number,imageUrl:e.imageUrl||"",word:n}}),hintLetters:e,instruction:o?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}if(e(o)){const t=o,e=n.questionGroup?.payload?.hintLetters||[];return{subQuestions:function(t){const e=[],n=t.split(",").map(t=>t.trim());for(const t of n){let n;const o=/\{(\d+)\}/g;for(;null!==(n=o.exec(t));){const o=parseInt(n[1],10),r=t.replace(n[0],"_");e.push({index:o,displayWord:r})}}return e.sort((t,e)=>t.index-e.index),e}(t.word).map(e=>({id:`${n.id}-blank-${e.index}`,questionNumber:n.question_number,imageUrl:t.imageUrl||"",word:e.displayWord,blankIndex:e.index})),hintLetters:e,instruction:t.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}const r=o;return{subQuestions:r?.subQuestions?.map((t,e)=>({id:t.id,questionNumber:n.question_number+e,imageUrl:t.imageUrl||"",word:t.word||""}))||[],hintLetters:r?.hintLetters||n.questionGroup?.payload?.hintLetters||[],instruction:r?.instruction||"LOOK AT THE PICTURE AND FILL IN THE MISSING LETTER"}}export function transformGridFill(t){const e=t[0],n=e?.content;return{grid:n?.grid||[],rows:n?.rows||0,columns:n?.columns||0,instruction:n?.instruction||"FILL IN THE MISSING WORDS",disabledCells:n?.disabledCells||[]}}export function transformAnswerTheQuestion(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:(e.question||"").replace(/\{\d+\}/g,"______"),imageUrl:e.imageUrl,prefixText:e.prefixText,suffixText:e.suffixText,suggestedAnswers:e.suggestedAnswers,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0}}),instruction:"ANSWER THE QUESTION",imageUrl:n?.mainImageUrl||n?.imageUrl||o?.imageUrl,title:o?.title,groupContent:n?.groupContent||o?.groupContent}}export function transformTrueFalse(t){const e=t[0]?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=n&&"boolean"==typeof t.correct_answer?.answer?t.correct_answer.answer:void 0;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleCorrectAnswer:o}}),instruction:"READ AND CHOOSE TRUE OR FALSE",imageUrl:e?.mainImageUrl||e?.imageUrl,groupContent:e?.content||e?.groupContent}}export function transformWordOrdering(t){return{questions:t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1,o=Array.isArray(t.correct_answer?.answer)?t.correct_answer.answer:Array.isArray(e.answer)?e.answer:void 0;return{id:t.id,questionNumber:t.question_number,words:e.words||[],imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?o:void 0}}),instruction:"ARRANGE THE LETTERS TO MAKE A WORD"}}export function transformWordFillParagraph(t){const e=t[0],n=e?.questionGroup?.payload,o=e?.content,r=o?.title||n?.title||t.find(t=>t.content?.title)?.content?.title,i=o?.wordBank||[],s=i.map(t=>"string"==typeof t?{word:t}:t),a=o?.viewMode,u=void 0!==o?.wordBank?.[0]?.options;let c;c="EMAIL"===a?"EMAIL":a||!o?.emailFrom&&!o?.emailTo?"DEFAULT"===a?"DEFAULT":"WITH_OPTIONS"===a||u?"WITH_OPTIONS":a||0!==i.length?"WITH_WORD_BANK":"DEFAULT":"EMAIL";const l=o?.emailFrom||o?.metadata?.emailFrom,m=o?.emailTo||o?.metadata?.emailTo;return{questionId:e?.id||"",paragraph:o?.paragraph||"",title:r,imageUrl:o?.imageUrl,wordBank:s,viewMode:c,instruction:"READ AND FILL IN THE BLANKS",exampleAnswer:o?.exampleAnswer,emailFrom:l,emailTo:m}}export function transformMatchByWritingAnswer(t){const e=t[0]?.questionGroup?.payload,n=t.some(t=>!!t.content?.askerName),o=t.map(t=>{const e=t.content,n=t.is_example||e.isExample||!1;return{id:t.id,questionNumber:t.question_number,question:e.question||"",imageUrl:e.imageUrl,isExample:n,exampleAnswer:n?t.correct_answer?.answer:void 0,askerName:e.askerName,answererName:e.answererName}}),r=e?.options?.map(t=>({answer:t.answer,imageUrl:t.imageUrl||"",content:t.content||""}))||[],i=n?t[0]?.content:void 0;return{questions:o,options:r,instruction:"LOOK AND WRITE THE ANSWER",viewMode:n?"CONVERSATION":"DEFAULT",groupImageUrl:e?.groupImageUrl||"",askerName:i?.askerName,answererName:i?.answererName}}export function transformWriteSentences(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload;return{questions:t.map(t=>({id:t.id,questionNumber:t.question_number})),instruction:n?.instruction||"WRITE SENTENCES ABOUT THE PICTURE",imageUrl:o?.mainImageUrl||o?.imageUrl||n?.imageUrl,title:n?.title,groupContent:o?.groupContent||n?.groupContent}}export function transformWordFillStructuredForm(t){const e=t[0],n=e?.questionGroup?.payload;return{questions:t.map(t=>{const e=t.content,n=t.correct_answer||{};let o=e?.content||"";const r=e?.blocks;return!o&&r?.length&&(o=r.map(t=>(t.heading?`<h3>${t.heading}</h3>`:"")+(t.content||"")).join("")),{id:t.id,questionNumber:t.question_number,title:e?.title||"",imageUrl:e?.imageUrl,content:o,answers:n?.answers||{},caseSensitive:n?.caseSensitive??e?.caseSensitive??!1}}),instruction:n?.instructions||"COMPLETE THE FORM BELOW",groupTitle:n?.title,groupContent:n?.content,groupImageUrl:n?.imageUrl,audioUrl:e?.audio_url||n?.audioUrl}}export function transformListenChooseObjects(t){const e=t[0],n=e?.content,o=e?.questionGroup?.payload||{};return{audioUrl:n?.audioUrl||"",backgroundImageUrl:o.backgroundImageUrl||"",objectNodes:o.objectNodes||[],correctObjectId:e?.correctAnswer?.objectId||e?.correct_answer?.objectId||"",isBackup:n?.isBackup||!1,instruction:"LISTEN AND CHOOSE THE CORRECT OBJECT"}}export function transformListenSpeakAnswer(t){return{questions:t.map(t=>{const e=t.content,n=t.questionGroup?.payload||{};return{id:t.id,questionNumber:t.question_number,audioUrl:e?.audioUrl||"",arrowNode:e?.arrowNode,backgroundImageUrl:n.backgroundImageUrl||n.imageUrl||"",isBackup:e?.isBackup||!1}}),instruction:"LISTEN AND SPEAK YOUR ANSWER"}}
|