Add quizzes
authorLanius Trolling <lanius@laniustrolling.dev>
Tue, 15 Aug 2023 15:42:09 +0000 (11:42 -0400)
committerLanius Trolling <lanius@laniustrolling.dev>
Tue, 15 Aug 2023 15:42:09 +0000 (11:42 -0400)
src/main/kotlin/info/mechyrdia/Configuration.kt
src/main/kotlin/info/mechyrdia/lore/parser_tags.kt
src/main/resources/static/init.js

index adbffa5d6baae5566c2a4f18b9cbe1e8f727b167..06572934b3b5d17e8bbe322a85c278edaf4076a8 100644 (file)
@@ -16,6 +16,7 @@ data class Configuration(
        val assetDir: String = "../assets",
        val templateDir: String = "../tpl",
        val jsonDocDir: String = "../data",
+       val quizDir: String = "../quizzes",
        val scriptDir: String = "../funcs",
        
        val dbName: String = "nslore",
index 87039f1898656e0f1154331f374331d212dba0b8..5765f7f1d1a9395a69eabf3a42521424db602da6 100644 (file)
@@ -1,6 +1,8 @@
 package info.mechyrdia.lore
 
 import info.mechyrdia.Configuration
+import info.mechyrdia.JsonStorageCodec
+import kotlinx.serialization.builtins.serializer
 import kotlinx.serialization.json.JsonPrimitive
 import java.io.File
 
@@ -177,6 +179,14 @@ enum class TextParserFormattingTag(val type: TextParserTagType<Unit>) {
                        "<canvas data-model=\"$modelUrl\"$sizeAttrs></canvas>"
                }
        ),
+       QUIZ(
+               TextParserTagType.Indirect { _, content, _ ->
+                       val quizText = File(Configuration.CurrentConfiguration.quizDir, "$content.json").readText()
+                       val quizJson = JsonStorageCodec.encodeToString(String.serializer(), quizText)
+                       
+                       "<script>window.renderQuiz(JSON.parse($quizJson));</script>"
+               }
+       ),
        
        // Lists
        UL(
index a854c9fe56239c4dce26e9f3ea57e6542847b800..5b733e6b0895f338e2a4abdd58be1f76e19cd274 100644 (file)
                }
        });
 
+       window.renderQuiz = function (quiz) {
+               const quizFunctions = {};
+               const quizRoot = document.createElement("table");
+               const questionAnswers = [];
+
+               quizFunctions.clearRoot = function () {
+                       while (quizRoot.hasChildNodes()) {
+                               quizRoot.firstChild.remove();
+                       }
+               };
+
+               quizFunctions.renderIntro = function () {
+                       quizFunctions.clearRoot();
+
+                       const firstRow = document.createElement("tr");
+                       const firstCell = document.createElement("td");
+                       firstCell.style.textAlign = "center";
+                       firstCell.style.fontSize = "1.5em";
+                       firstCell.style.fontWeight = "bold";
+                       firstCell.append(quiz.title.toString());
+                       firstRow.appendChild(firstCell);
+                       quizRoot.appendChild(firstRow);
+
+                       const secondRow = document.createElement("tr");
+                       const secondCell = document.createElement("td");
+                       secondCell.style.textAlign = "center";
+                       secondCell.appendChild(document.createElement("img")).src = quiz.image;
+                       for (const paragraph of quiz.intro.toString().split('\n')) {
+                               secondCell.appendChild(document.createElement("p")).append(paragraph);
+                       }
+                       secondRow.appendChild(secondCell);
+                       quizRoot.appendChild(secondRow);
+
+                       const thirdRow = document.createElement("tr");
+                       const thirdCell = document.createElement("td");
+                       thirdCell.style.textAlign = "center";
+                       const beginLink = thirdCell.appendChild(document.createElement("a"));
+                       beginLink.href = "#";
+                       beginLink.append("Begin Quiz");
+                       beginLink.onclick = e => {
+                               e.preventDefault();
+                               quizFunctions.renderQuestion(0);
+                       };
+                       thirdRow.appendChild(thirdCell);
+                       quizRoot.appendChild(thirdRow);
+               };
+
+               quizFunctions.renderOutro = function (outcome) {
+                       quizFunctions.clearRoot();
+
+                       const firstRow = document.createElement("tr");
+                       const firstCell = document.createElement("td");
+                       firstCell.style.textAlign = "center";
+                       firstCell.style.fontSize = "1.5em";
+                       firstCell.style.fontWeight = "bold";
+                       firstCell.append(outcome.name.toString());
+                       firstRow.appendChild(firstCell);
+                       quizRoot.appendChild(firstRow);
+
+                       const secondRow = document.createElement("tr");
+                       const secondCell = document.createElement("td");
+                       secondCell.style.textAlign = "center";
+                       secondCell.appendChild(document.createElement("img")).src = outcome.img;
+                       for (const paragraph of outcome.desc.toString().split('\n')) {
+                               secondCell.appendChild(document.createElement("p")).append(paragraph);
+                       }
+                       secondRow.appendChild(secondCell);
+                       quizRoot.appendChild(secondRow);
+
+                       const thirdRow = document.createElement("tr");
+                       const thirdCell = document.createElement("td");
+                       thirdCell.style.textAlign = "center";
+                       const moreInfoLink = thirdCell.appendChild(document.createElement("a"));
+                       moreInfoLink.href = outcome.url;
+                       moreInfoLink.append("More Information");
+                       thirdRow.appendChild(thirdCell);
+                       quizRoot.appendChild(thirdRow);
+               };
+
+               quizFunctions.calculateResults = function () {
+                       const total = {};
+                       for (const result of questionAnswers) {
+                               for (const resKey of Object.keys(result)) {
+                                       if (total[resKey] == null) {
+                                               total[resKey] = 0;
+                                       }
+                                       total[resKey] += result[resKey];
+                               }
+                       }
+
+                       let maxKey;
+                       let maxValue = null;
+                       for (const key of Object.keys(total)) {
+                               const result = total[key];
+                               if (maxValue == null || result > maxValue) {
+                                       maxKey = key;
+                                       maxValue = result;
+                               }
+                       }
+
+                       return quiz.outcomes[maxKey];
+               };
+
+               quizFunctions.renderQuestion = function (index) {
+                       quizFunctions.clearRoot();
+
+                       const question = quiz.questions[index];
+
+                       const firstRow = document.createElement("tr");
+                       const firstCell = document.createElement("td");
+                       firstCell.style.textAlign = "center";
+                       firstCell.style.fontSize = "1.5em";
+                       firstCell.style.fontWeight = "bold";
+                       firstCell.append(question.asks.toString());
+                       firstRow.appendChild(firstCell);
+                       quizRoot.appendChild(firstRow);
+
+                       for (const answer of question.answers) {
+                               const secondRow = document.createElement("tr");
+                               const secondCell = document.createElement("td");
+                               secondCell.style.textAlign = "center";
+                               const answerLink = secondCell.appendChild(document.createElement("a"));
+                               answerLink.href = "#";
+                               answerLink.append(answer.answer.toString());
+                               answerLink.onclick = e => {
+                                       e.preventDefault();
+                                       questionAnswers[index] = answer.result;
+                                       if (index === quiz.questions.length - 1) {
+                                               quizFunctions.renderOutro(quizFunctions.calculateResults());
+                                       } else {
+                                               quizFunctions.renderQuestion(index + 1);
+                                       }
+                               };
+                               secondRow.appendChild(secondCell);
+                               quizRoot.appendChild(secondRow);
+                       }
+
+                       const thirdRow = document.createElement("tr");
+                       const thirdCell = document.createElement("td");
+                       thirdCell.style.textAlign = "center";
+                       const prevLink = thirdCell.appendChild(document.createElement("a"));
+                       prevLink.href = "#";
+                       prevLink.append("Previous Question");
+                       prevLink.onclick = e => {
+                               e.preventDefault();
+                               if (index === 0) {
+                                       quizFunctions.renderIntro();
+                               } else {
+                                       quizFunctions.renderQuestion(index - 1);
+                               }
+                       };
+                       thirdRow.appendChild(thirdCell);
+                       quizRoot.appendChild(thirdRow);
+               };
+
+               document.currentScript.after(quizRoot);
+
+               quizFunctions.renderIntro();
+       };
+
        window.addEventListener("load", function () {
                // Comment previews
                async function commentPreview(input, output) {