starting quiz tests

This commit is contained in:
2024-08-21 15:43:16 -06:00
parent 7bb15126b6
commit 15c4a2241f
9 changed files with 514 additions and 10 deletions

View File

@@ -0,0 +1,154 @@
import { LocalQuiz } from "../localQuiz";
import { quizQuestionMarkdownUtils } from "./quizQuestionMarkdownUtils";
const extractLabelValue = (input: string, label: string): string => {
const pattern = new RegExp(`${label}: (.*?)\n`);
const match = pattern.exec(input);
return match ? match[1].trim() : "";
};
const extractDescription = (input: string): string => {
const pattern = new RegExp("Description: (.*?)$", "s");
const match = pattern.exec(input);
return match ? match[1].trim() : "";
};
const parseBooleanOrThrow = (value: string, label: string): boolean => {
if (value.toLowerCase() === "true") return true;
if (value.toLowerCase() === "false") return false;
throw new Error(`Error with ${label}: ${value}`);
};
const parseBooleanOrDefault = (
value: string,
label: string,
defaultValue: boolean
): boolean => {
if (value.toLowerCase() === "true") return true;
if (value.toLowerCase() === "false") return false;
return defaultValue;
};
const parseNumberOrThrow = (value: string, label: string): number => {
const parsed = parseInt(value, 10);
if (isNaN(parsed)) {
throw new Error(`Error with ${label}: ${value}`);
}
return parsed;
};
const parseDateOrThrow = (value: string, label: string): string => {
const date = new Date(value);
if (isNaN(date.getTime())) {
throw new Error(`Error with ${label}: ${value}`);
}
return date.toISOString();
};
const parseDateOrNull = (value: string): string | undefined => {
const date = new Date(value);
return isNaN(date.getTime()) ? undefined : date.toISOString();
};
const getQuizWithOnlySettings = (settings: string): LocalQuiz => {
const name = extractLabelValue(settings, "Name");
const rawShuffleAnswers = extractLabelValue(settings, "ShuffleAnswers");
const shuffleAnswers = parseBooleanOrThrow(
rawShuffleAnswers,
"ShuffleAnswers"
);
const password = extractLabelValue(settings, "Password") || undefined;
const rawShowCorrectAnswers = extractLabelValue(
settings,
"ShowCorrectAnswers"
);
const showCorrectAnswers = parseBooleanOrDefault(
rawShowCorrectAnswers,
"ShowCorrectAnswers",
true
);
const rawOneQuestionAtATime = extractLabelValue(
settings,
"OneQuestionAtATime"
);
const oneQuestionAtATime = parseBooleanOrThrow(
rawOneQuestionAtATime,
"OneQuestionAtATime"
);
const rawAllowedAttempts = extractLabelValue(settings, "AllowedAttempts");
const allowedAttempts = parseNumberOrThrow(
rawAllowedAttempts,
"AllowedAttempts"
);
const rawDueAt = extractLabelValue(settings, "DueAt");
const dueAt = parseDateOrThrow(rawDueAt, "DueAt");
const rawLockAt = extractLabelValue(settings, "LockAt");
const lockAt = parseDateOrNull(rawLockAt);
const description = extractDescription(settings);
const localAssignmentGroupName = extractLabelValue(
settings,
"AssignmentGroup"
);
const quiz: LocalQuiz = {
name,
description,
password,
lockAt,
dueAt,
shuffleAnswers,
showCorrectAnswers,
oneQuestionAtATime,
localAssignmentGroupName,
allowedAttempts,
questions: [],
};
return quiz;
};
export const quizMarkdownUtils = {
toMarkdown(quiz: LocalQuiz): string {
const questionMarkdownArray = quiz.questions.map((q) =>
quizQuestionMarkdownUtils.toMarkdown(q)
);
const questionDelimiter = "\n\n---\n\n";
const questionMarkdown = questionMarkdownArray.join(questionDelimiter);
return `Name: ${quiz.name}
LockAt: ${quiz.lockAt ?? ""}
DueAt: ${quiz.dueAt}
Password: ${quiz.password ?? ""}
ShuffleAnswers: ${quiz.shuffleAnswers.toString().toLowerCase()}
ShowCorrectAnswers: ${quiz.showCorrectAnswers.toString().toLowerCase()}
OneQuestionAtATime: ${quiz.oneQuestionAtATime.toString().toLowerCase()}
AssignmentGroup: ${quiz.localAssignmentGroupName}
AllowedAttempts: ${quiz.allowedAttempts}
Description: ${quiz.description}
---
${questionMarkdown}`;
},
parseMarkdown(input: string): LocalQuiz {
const splitInput = input.split("---\n");
const settings = splitInput[0];
const quizWithoutQuestions = getQuizWithOnlySettings(settings);
const rawQuestions = splitInput.slice(1);
const questions = rawQuestions
.filter((str) => str.trim().length > 0)
.map((q, i) => quizQuestionMarkdownUtils.parseMarkdown(q, i));
return {
...quizWithoutQuestions,
questions,
};
},
};