icoa-cli 2.19.21 → 2.19.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/lang.js +45 -15
- package/dist/lib/demo-exam.js +21 -11
- package/dist/types/index.d.ts +2 -0
- package/package.json +1 -1
package/dist/commands/lang.js
CHANGED
|
@@ -51,25 +51,55 @@ export function registerLangCommand(program) {
|
|
|
51
51
|
}
|
|
52
52
|
saveConfig({ language: code });
|
|
53
53
|
printSuccess(`Language set to: ${LANG_NAMES[code] || code}`);
|
|
54
|
-
// If demo
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
54
|
+
// If demo in progress, re-translate each drawn question in place using
|
|
55
|
+
// sourceNumber + sourceOrder so the user's answers and option positions are
|
|
56
|
+
// preserved. If an older state lacks these fields (pre-v2.19.22), fall back
|
|
57
|
+
// to restart-with-fresh-pick so nothing crashes.
|
|
58
58
|
const state = getExamState();
|
|
59
59
|
if (state && state.session.examId === 'demo-free') {
|
|
60
60
|
try {
|
|
61
|
-
const { pickDemoQuestions, getLocalizedDemoSession, DEMO_PICK_SIZE } = await import('../lib/demo-exam.js');
|
|
62
|
-
const freshQuestions = pickDemoQuestions(DEMO_PICK_SIZE);
|
|
63
|
-
state.questions = freshQuestions;
|
|
64
|
-
state.answers = {};
|
|
65
|
-
state.session.examName = getLocalizedDemoSession().examName;
|
|
66
|
-
state.session.startedAt = new Date().toISOString();
|
|
67
|
-
state._lastQ = 1;
|
|
61
|
+
const { pickDemoQuestions, getLocalizedDemoSession, getLocalizedDemoQuestions, getLocalizedExplanations, DEMO_PICK_SIZE, } = await import('../lib/demo-exam.js');
|
|
68
62
|
const { saveExamState } = await import('../lib/exam-state.js');
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
const canRetranslate = state.questions.every((q) => q.sourceNumber != null && Array.isArray(q.sourceOrder) && q.sourceOrder.length === 4);
|
|
64
|
+
if (canRetranslate) {
|
|
65
|
+
const pool = getLocalizedDemoQuestions();
|
|
66
|
+
const explanations = getLocalizedExplanations();
|
|
67
|
+
state.questions = state.questions.map((q) => {
|
|
68
|
+
const src = pool.find((p) => p.number === q.sourceNumber);
|
|
69
|
+
if (!src || !q.sourceOrder)
|
|
70
|
+
return q;
|
|
71
|
+
return {
|
|
72
|
+
...q,
|
|
73
|
+
text: src.text,
|
|
74
|
+
category: src.category,
|
|
75
|
+
options: {
|
|
76
|
+
A: src.options[q.sourceOrder[0]],
|
|
77
|
+
B: src.options[q.sourceOrder[1]],
|
|
78
|
+
C: src.options[q.sourceOrder[2]],
|
|
79
|
+
D: src.options[q.sourceOrder[3]],
|
|
80
|
+
},
|
|
81
|
+
explanation: explanations[q.sourceNumber],
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
state.session.examName = getLocalizedDemoSession().examName;
|
|
85
|
+
saveExamState(state);
|
|
86
|
+
const currentQ = state._lastQ || 1;
|
|
87
|
+
console.log();
|
|
88
|
+
console.log(chalk.green(` Demo continues in ${LANG_NAMES[code] || code}. Your progress is kept.`));
|
|
89
|
+
console.log(chalk.white(` Resume: exam q ${currentQ}`));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Legacy state from before v2.19.22 — safely reset
|
|
93
|
+
state.questions = pickDemoQuestions(DEMO_PICK_SIZE);
|
|
94
|
+
state.answers = {};
|
|
95
|
+
state.session.examName = getLocalizedDemoSession().examName;
|
|
96
|
+
state.session.startedAt = new Date().toISOString();
|
|
97
|
+
state._lastQ = 1;
|
|
98
|
+
saveExamState(state);
|
|
99
|
+
console.log();
|
|
100
|
+
console.log(chalk.green(` Demo restarted in ${LANG_NAMES[code] || code}.`));
|
|
101
|
+
console.log(chalk.white(' Type: exam q 1'));
|
|
102
|
+
}
|
|
73
103
|
}
|
|
74
104
|
catch {
|
|
75
105
|
console.log(chalk.gray(' Language changed. Type: demo'));
|
package/dist/lib/demo-exam.js
CHANGED
|
@@ -127,16 +127,24 @@ function shuffle(arr) {
|
|
|
127
127
|
}
|
|
128
128
|
return out;
|
|
129
129
|
}
|
|
130
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* Shuffle the four options within a single question; recompute the answer letter
|
|
132
|
+
* and record `sourceOrder` so the shuffle can be replayed against a different
|
|
133
|
+
* translation of the same question (used by lang-switch to keep answers).
|
|
134
|
+
*/
|
|
131
135
|
function shuffleQuestionOptions(q) {
|
|
132
136
|
if (!q.answer)
|
|
133
137
|
return q;
|
|
134
|
-
const correctText = q.options[q.answer];
|
|
135
138
|
const keys = ['A', 'B', 'C', 'D'];
|
|
136
|
-
const
|
|
137
|
-
const newOptions = {
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
const sourceOrder = shuffle(keys);
|
|
140
|
+
const newOptions = {
|
|
141
|
+
A: q.options[sourceOrder[0]],
|
|
142
|
+
B: q.options[sourceOrder[1]],
|
|
143
|
+
C: q.options[sourceOrder[2]],
|
|
144
|
+
D: q.options[sourceOrder[3]],
|
|
145
|
+
};
|
|
146
|
+
const newAnswer = keys[sourceOrder.indexOf(q.answer)];
|
|
147
|
+
return { ...q, options: newOptions, answer: newAnswer, sourceOrder };
|
|
140
148
|
}
|
|
141
149
|
/**
|
|
142
150
|
* Pick `n` random questions from the pool, shuffle each question's options,
|
|
@@ -152,12 +160,14 @@ export function pickDemoQuestions(n = DEMO_PICK_SIZE) {
|
|
|
152
160
|
answer: DEMO_ANSWERS[q.number],
|
|
153
161
|
explanation: explanations[q.number],
|
|
154
162
|
}));
|
|
155
|
-
// Shuffle pool, pick n, shuffle each question's options, renumber 1..n
|
|
163
|
+
// Shuffle pool, pick n, shuffle each question's options, renumber 1..n.
|
|
164
|
+
// Keep the original pool number as `sourceNumber` so lang-switch can re-translate
|
|
165
|
+
// this exact question without losing the user's answer.
|
|
156
166
|
const picked = shuffle(enriched).slice(0, n);
|
|
157
|
-
return picked.map((q, i) =>
|
|
158
|
-
|
|
159
|
-
number: i + 1
|
|
160
|
-
})
|
|
167
|
+
return picked.map((q, i) => {
|
|
168
|
+
const shuffled = shuffleQuestionOptions(q);
|
|
169
|
+
return { ...shuffled, sourceNumber: q.number, number: i + 1 };
|
|
170
|
+
});
|
|
161
171
|
}
|
|
162
172
|
/**
|
|
163
173
|
* Get localized explanations for demo questions.
|
package/dist/types/index.d.ts
CHANGED