Files
MoodleGPT/src/background/core/questions/checkbox.ts
T

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;