91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
import type Config from '../../types/config';
|
|
import type GPTAnswer from '../../types/gpt-answer';
|
|
import Logs from 'background/utils/logs';
|
|
import normalizeText from 'background/utils/normalize-text';
|
|
import { pickBestReponse } from 'background/utils/pick-best-response';
|
|
import { MoodleQuestionType, MultipleChoiceResponse } from '../../types/question-types';
|
|
|
|
/**
|
|
* Handle input checkbox elements
|
|
* @param config
|
|
* @param inputList
|
|
* @param gptAnswer
|
|
*/
|
|
function handleCheckbox(
|
|
config: Config,
|
|
inputList: NodeListOf<HTMLElement>,
|
|
gptAnswer: GPTAnswer
|
|
): boolean {
|
|
const firstInput = inputList?.[0] as HTMLInputElement;
|
|
|
|
// Handle the case the input is not a checkbox
|
|
if (!firstInput || firstInput.type !== 'checkbox') {
|
|
return false;
|
|
}
|
|
|
|
const correctElements: Set<HTMLInputElement> = new Set();
|
|
|
|
// New structured mode
|
|
if (
|
|
gptAnswer.response &&
|
|
gptAnswer.response.question_type === MoodleQuestionType.MULTIPLE_CHOICE
|
|
) {
|
|
const response = gptAnswer.response as MultipleChoiceResponse;
|
|
const correctIndexes = new Set(response.correct_answer.indexes);
|
|
|
|
Array.from(inputList).forEach((inp, index) => {
|
|
const element = inp as HTMLInputElement;
|
|
if (correctIndexes.has(index)) {
|
|
correctElements.add(element);
|
|
}
|
|
});
|
|
|
|
if (config.logs) {
|
|
console.log('Using strict mode multiple choice selection:', response.correct_answer.indexes);
|
|
}
|
|
}
|
|
// Fallback to fuzzy text matching if structural failed
|
|
else {
|
|
const corrects = gptAnswer.rawResponse.split('\n');
|
|
|
|
const possibleAnswers = Array.from(inputList)
|
|
.map(inp => ({
|
|
element: inp as HTMLInputElement,
|
|
value: normalizeText(inp?.parentElement?.textContent ?? '')
|
|
}))
|
|
.filter(obj => obj.value !== '');
|
|
|
|
for (const correct of corrects) {
|
|
const bestAnswer = pickBestReponse(correct, possibleAnswers);
|
|
|
|
if (config.logs && bestAnswer.value) {
|
|
Logs.bestAnswer(bestAnswer.value, bestAnswer.similarity);
|
|
}
|
|
|
|
correctElements.add(bestAnswer.element as HTMLInputElement);
|
|
}
|
|
}
|
|
|
|
// Check if it should be checked or not
|
|
for (const inp of Array.from(inputList)) {
|
|
const element = inp as HTMLInputElement;
|
|
const needAction =
|
|
(element.checked && !correctElements.has(element)) ||
|
|
(!element.checked && correctElements.has(element));
|
|
|
|
const action = () => needAction && element.click();
|
|
|
|
if (config.mouseover) {
|
|
element.addEventListener('mouseover', action, {
|
|
once: true
|
|
});
|
|
} else {
|
|
action();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
export default handleCheckbox;
|