mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-26 07:38:33 -06:00
162 lines
4.7 KiB
TypeScript
162 lines
4.7 KiB
TypeScript
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}`);
|
|
}
|
|
const day = String(date.getDate()).padStart(2, "0");
|
|
const month = String(date.getMonth() + 1).padStart(2, "0"); // Months are zero-based
|
|
const year = date.getFullYear();
|
|
const hours = String(date.getHours()).padStart(2, "0");
|
|
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
|
|
return `${day}/${month}/${year} ${hours}:${minutes}:${seconds}`;
|
|
};
|
|
|
|
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,
|
|
};
|
|
},
|
|
};
|