Enhance clipboard mode to format answers based on question type

This commit is contained in:
2026-05-05 19:12:54 +02:00
parent e7f00359a1
commit d36949b42f
4 changed files with 122 additions and 4 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+120 -1
View File
@@ -1,6 +1,7 @@
import type Config from '../../types/config'; import type Config from '../../types/config';
import type GPTAnswer from '../../types/gpt-answer'; import type GPTAnswer from '../../types/gpt-answer';
import titleIndications from 'background/utils/title-indications'; import titleIndications from 'background/utils/title-indications';
import { MoodleQuestionType } from '../../types/question-types';
/** /**
* Copy the response in the clipboard if we can automaticaly fill the question * Copy the response in the clipboard if we can automaticaly fill the question
@@ -9,7 +10,125 @@ import titleIndications from 'background/utils/title-indications';
*/ */
function handleClipboard(config: Config, gptAnswer: GPTAnswer) { function handleClipboard(config: Config, gptAnswer: GPTAnswer) {
if (config.title) titleIndications('Copied to clipboard'); if (config.title) titleIndications('Copied to clipboard');
const textToCopy = gptAnswer.rawResponse || JSON.stringify(gptAnswer.response) || '';
let textToCopy = '';
if (gptAnswer.response && gptAnswer.questionQuery) {
const q = gptAnswer.questionQuery;
const r = gptAnswer.response;
if (q.question_type === r.question_type) {
switch (r.question_type) {
case MoodleQuestionType.SINGLE_CHOICE: {
const query = q as Extract<typeof q, { question_type: MoodleQuestionType.SINGLE_CHOICE }>;
const resp = r as Extract<typeof r, { question_type: MoodleQuestionType.SINGLE_CHOICE }>;
const opt = query.answer_options.find(o => o.index === resp.correct_answer.index);
textToCopy = opt ? opt.text : '';
break;
}
case MoodleQuestionType.MULTIPLE_CHOICE: {
const query = q as Extract<
typeof q,
{ question_type: MoodleQuestionType.MULTIPLE_CHOICE }
>;
const resp = r as Extract<
typeof r,
{ question_type: MoodleQuestionType.MULTIPLE_CHOICE }
>;
const texts = resp.correct_answer.indexes
.map(idx => {
const opt = query.answer_options.find(o => o.index === idx);
return opt ? opt.text : '';
})
.filter(Boolean);
textToCopy = texts.join('\n');
break;
}
case MoodleQuestionType.TRUE_FALSE: {
const resp = r as Extract<typeof r, { question_type: MoodleQuestionType.TRUE_FALSE }>;
textToCopy = resp.correct_answer ? 'True' : 'False';
break;
}
case MoodleQuestionType.SHORT_TEXT:
case MoodleQuestionType.ESSAY: {
const resp = r as Extract<
typeof r,
{ question_type: MoodleQuestionType.SHORT_TEXT | MoodleQuestionType.ESSAY }
>;
textToCopy = resp.correct_answer;
break;
}
case MoodleQuestionType.NUMERICAL: {
const resp = r as Extract<typeof r, { question_type: MoodleQuestionType.NUMERICAL }>;
textToCopy = resp.correct_answer.toString();
break;
}
case MoodleQuestionType.MATCH: {
const query = q as Extract<typeof q, { question_type: MoodleQuestionType.MATCH }>;
const resp = r as Extract<typeof r, { question_type: MoodleQuestionType.MATCH }>;
const matches = resp.correct_answers.map(ans => {
const sub = query.sub_questions.find(s => s.index === ans.sub_question_index);
const opt = query.options.find(o => o.index === ans.option_index);
return `${sub?.text || `Sub ${ans.sub_question_index}`} -> ${opt?.text || `Option ${ans.option_index}`}`;
});
textToCopy = matches.join('\n');
break;
}
case MoodleQuestionType.SELECT_MISSING_WORD: {
const query = q as Extract<
typeof q,
{ question_type: MoodleQuestionType.SELECT_MISSING_WORD }
>;
const resp = r as Extract<
typeof r,
{ question_type: MoodleQuestionType.SELECT_MISSING_WORD }
>;
const answers = resp.correct_answers.map(ans => {
const dd = query.drop_downs.find(d => d.index === ans.drop_down_index);
const opt = dd?.options.find(o => o.index === ans.option_index);
return `Blank ${ans.drop_down_index}: ${opt?.text || `Option ${ans.option_index}`}`;
});
textToCopy = answers.join('\n');
break;
}
case MoodleQuestionType.DRAG_DROP_TEXT: {
const query = q as Extract<
typeof q,
{ question_type: MoodleQuestionType.DRAG_DROP_TEXT }
>;
const resp = r as Extract<typeof r, { question_type: MoodleQuestionType.DRAG_DROP_TEXT }>;
const answers = resp.correct_answers.map(ans => {
const drag = query.draggables.find(d => d.index === ans.draggable_index);
return `Blank ${ans.blank_index}: ${drag?.text || `Draggable ${ans.draggable_index}`}`;
});
textToCopy = answers.join('\n');
break;
}
case MoodleQuestionType.ORDERING: {
const query = q as Extract<typeof q, { question_type: MoodleQuestionType.ORDERING }>;
const resp = r as Extract<typeof r, { question_type: MoodleQuestionType.ORDERING }>;
const texts = resp.correct_order.indexes.map((idx, i) => {
const item = query.items.find(o => o.index === idx);
return `${i + 1}. ${item?.text || `Item ${idx}`}`;
});
textToCopy = texts.join('\n');
break;
}
}
}
}
// Fallback if empty or types didn't match / no response
if (!textToCopy) {
if (gptAnswer.response) {
textToCopy = JSON.stringify(gptAnswer.response, null, 2);
} else if (gptAnswer.rawResponse) {
textToCopy = gptAnswer.rawResponse;
} else {
textToCopy = '';
}
}
navigator.clipboard.writeText(textToCopy); navigator.clipboard.writeText(textToCopy);
} }
-1
View File
@@ -22,7 +22,6 @@ class Logs {
static response(gptAnswer: GPTAnswer) { static response(gptAnswer: GPTAnswer) {
console.log('Original:\n' + gptAnswer.response); console.log('Original:\n' + gptAnswer.response);
console.log('Normalized:\n' + gptAnswer.normalizedResponse);
} }
} }