{ "cells": [ { "cell_type": "markdown", "id": "26392d3a", "metadata": {}, "source": [ "# 🏆Selbsttest: Wissen und Praxis\n", "\n", "````{admonition} Hinweis\n", ":class: hinweis\n", "Diese Übungsaufgaben dienen Ihrer Selbsteinschätzung und helfen Ihnen, das im Kapitel Gelernte zu reflektieren.\n", "\n", "Sie können die Fragen in beliebiger Reihenfolge beantworten und auch mehrfach versuchen. \n", "\n", "**So funktioniert es:**\n", "- Wählen Sie bei jeder Frage die Antwort(en), die Sie für richtig halten\n", "- Lesen Sie das Feedback zu den einzelnen Antwortoptionen sorgfältig durch\n", "- Die Erklärungen helfen Ihnen, Ihr Verständnis zu vertiefen – auch bei korrekten Antworten \n", "\n", "Es erfolgt keine Bewertung oder Speicherung Ihrer Ergebnisse. Nutzen Sie dieses Assessment, um Wissenslücken zu identifizieren und gegebenenfalls die entsprechenden Abschnitte des Kapitels noch einmal zu bearbeiten.\n", "\n", "**Geschätzte Zeit**: 45min\n", "\n", "Viel Erfolg!\n", "````\n", "\n", "## Frage 1" ] }, { "cell_type": "code", "execution_count": 1, "id": "efdfd926", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsHOjTTvkNwcCe=[{\"question\": \"Welche der folgenden Aussagen beschreibt korrekt, was NLP im Kontext der Textanalyse leistet?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"NLP dient ausschlie\\u00dflich der automatischen \\u00dcbersetzung zwischen Sprachen\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Obwohl maschinelle \\u00dcbersetzung ein Anwendungsgebiet von NLP ist, umfasst NLP viel mehr, insbesondere die Anreicherung von Texten mit linguistischen Informationen f\\u00fcr verschiedene Analysezwecke. NLP beinhaltet Methoden wie Tokenisierung, Lemmatisierung und viele weitere Techniken zur Textverarbeitung.\"}, {\"answer\": \"NLP erm\\u00f6glicht die Anreicherung von Texten mit linguistischen Informationen, die f\\u00fcr Computer sonst nicht erkennbar w\\u00e4ren\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! NLP (Natural Language Processing) erm\\u00f6glicht es, Texte mit linguistischen Informationen anzureichern und damit f\\u00fcr Computer \\\"verst\\u00e4ndlich\\\" zu machen. Computer sehen Text zun\\u00e4chst nur als Zeichenkette, w\\u00e4hrend NLP-Methoden semantische Strukturen hinzuf\\u00fcgen und Analysen auf Wortebene erm\\u00f6glichen.\"}, {\"answer\": \"NLP ist ein Verfahren zur manuellen Annotation von Texten durch Sprachwissenschaftler:innen\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. NLP bezieht sich auf automatisierte Verfahren zur Textverarbeitung durch Computer, nicht auf manuelle Annotation. W\\u00e4hrend manuelle Annotation durchaus f\\u00fcr Training und Evaluation von NLP-Systemen wichtig sein kann, ist NLP selbst ein computergest\\u00fctzter Prozess.\"}, {\"answer\": \"NLP kann nur auf modernen Texten angewendet werden, nicht auf historischen Dokumenten\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. NLP kann grunds\\u00e4tzlich auf Texte jeder Epoche angewendet werden, auch wenn historische Texte aufgrund von Sprachver\\u00e4nderungen, anderen Schriften oder OCR-Qualit\\u00e4t besondere Herausforderungen darstellen k\\u00f6nnen. Gerade in den Digital Humanities wird NLP h\\u00e4ufig f\\u00fcr historische Textanalyse eingesetzt.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
  1. Copy the text in this cell below \"Answer String\"
  2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
  3. Select the whole \"Replace Me\" text
  4. Paste in your answer string and press shift-Enter.
  5. Save the notebook using the save icon or File->Save Notebook menu item



  6. Answer String:
    ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
    \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"HOjTTvkNwcCe\")) {\n", " show_questions(questionsHOjTTvkNwcCe, HOjTTvkNwcCe); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"HOjTTvkNwcCe\");\n", " // console.log(document.getElementById(\"HOjTTvkNwcCe\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "\"\"\"\n", "Lernziel: Sie können die Grundkonzepte des Natural Language Processing erklären und die Funktionen von Tokenisierung und Lemmatisierung für die Textanalyse beschreiben.\n", "Bloom-Stufe: Verstehen\n", "Format: Multiple Choice\n", "\"\"\"\n", "\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_1 = [{\n", " \"question\": \"\"\"Welche der folgenden Aussagen beschreibt korrekt, was NLP im Kontext der Textanalyse leistet?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"NLP dient ausschließlich der automatischen Übersetzung zwischen Sprachen\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Obwohl maschinelle Übersetzung ein Anwendungsgebiet von NLP ist, umfasst NLP viel mehr, insbesondere die Anreicherung von Texten mit linguistischen Informationen für verschiedene Analysezwecke. NLP beinhaltet Methoden wie Tokenisierung, Lemmatisierung und viele weitere Techniken zur Textverarbeitung.\"\"\"\n", " },\n", " {\n", " \"answer\": \"NLP ermöglicht die Anreicherung von Texten mit linguistischen Informationen, die für Computer sonst nicht erkennbar wären\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! NLP (Natural Language Processing) ermöglicht es, Texte mit linguistischen Informationen anzureichern und damit für Computer \"verständlich\" zu machen. Computer sehen Text zunächst nur als Zeichenkette, während NLP-Methoden semantische Strukturen hinzufügen und Analysen auf Wortebene ermöglichen.\"\"\"\n", " },\n", " {\n", " \"answer\": \"NLP ist ein Verfahren zur manuellen Annotation von Texten durch Sprachwissenschaftler:innen\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. NLP bezieht sich auf automatisierte Verfahren zur Textverarbeitung durch Computer, nicht auf manuelle Annotation. Während manuelle Annotation durchaus für Training und Evaluation von NLP-Systemen wichtig sein kann, ist NLP selbst ein computergestützter Prozess.\"\"\"\n", " },\n", " {\n", " \"answer\": \"NLP kann nur auf modernen Texten angewendet werden, nicht auf historischen Dokumenten\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. NLP kann grundsätzlich auf Texte jeder Epoche angewendet werden, auch wenn historische Texte aufgrund von Sprachveränderungen, anderen Schriften oder OCR-Qualität besondere Herausforderungen darstellen können. Gerade in den Digital Humanities wird NLP häufig für historische Textanalyse eingesetzt.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_1, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "96cf7bbe", "metadata": {}, "source": [ "## Frage 2" ] }, { "cell_type": "code", "execution_count": 2, "id": "e653799a", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
    " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsNgeBbHfrIGJg=[{\"question\": \"Welche Funktion erf\\u00fcllt die Tokenisierung im NLP-Prozess?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"Sie \\u00fcbersetzt den Text in eine andere Sprache\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Die \\u00dcbersetzung ist eine komplexe NLP-Aufgabe, die weit \\u00fcber die Tokenisierung hinausgeht. Tokenisierung ist ein grundlegender Vorverarbeitungsschritt, der Texte in kleinere Einheiten zerlegt, aber keine \\u00dcbersetzung vornimmt.\"}, {\"answer\": \"Sie identifiziert die Stimmung (positiv/negativ) eines Textes\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage beschreibt nicht die Tokenisierung, sondern die Sentimentanalyse, die eine fortgeschrittene NLP-Aufgabe ist. Tokenisierung ist ein Vorverarbeitungsschritt, der f\\u00fcr die Sentimentanalyse notwendig sein kann, aber selbst keine emotionale Bewertung vornimmt.\"}, {\"answer\": \"Sie zerlegt einen Text in einzelne, sinnvolle Einheiten wie W\\u00f6rter und Satzzeichen\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Die Tokenisierung ist der Prozess der Zerlegung eines Textes in einzelne, bedeutungstragende Einheiten (Token). Diese k\\u00f6nnen W\\u00f6rter, Zahlen oder Satzzeichen sein. Sie ist der erste grundlegende Schritt in der NLP-Pipeline, auf dem weitere Verarbeitungsschritte aufbauen.\"}, {\"answer\": \"Sie wandelt alle W\\u00f6rter in ihre Grundform um\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage beschreibt nicht die Tokenisierung, sondern die Lemmatisierung. Die Tokenisierung zerlegt Text in einzelne Einheiten, w\\u00e4hrend die Lemmatisierung in einem sp\\u00e4teren Schritt diese Einheiten auf ihre Grundform zur\\u00fcckf\\u00fchrt.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
    1. Copy the text in this cell below \"Answer String\"
    2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
    3. Select the whole \"Replace Me\" text
    4. Paste in your answer string and press shift-Enter.
    5. Save the notebook using the save icon or File->Save Notebook menu item



    6. Answer String:
      ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
      \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"NgeBbHfrIGJg\")) {\n", " show_questions(questionsNgeBbHfrIGJg, NgeBbHfrIGJg); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"NgeBbHfrIGJg\");\n", " // console.log(document.getElementById(\"NgeBbHfrIGJg\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_2 = [{\n", " \"question\": \"\"\"Welche Funktion erfüllt die Tokenisierung im NLP-Prozess?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Sie übersetzt den Text in eine andere Sprache\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Die Übersetzung ist eine komplexe NLP-Aufgabe, die weit über die Tokenisierung hinausgeht. Tokenisierung ist ein grundlegender Vorverarbeitungsschritt, der Texte in kleinere Einheiten zerlegt, aber keine Übersetzung vornimmt.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Sie identifiziert die Stimmung (positiv/negativ) eines Textes\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage beschreibt nicht die Tokenisierung, sondern die Sentimentanalyse, die eine fortgeschrittene NLP-Aufgabe ist. Tokenisierung ist ein Vorverarbeitungsschritt, der für die Sentimentanalyse notwendig sein kann, aber selbst keine emotionale Bewertung vornimmt.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Sie zerlegt einen Text in einzelne, sinnvolle Einheiten wie Wörter und Satzzeichen\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Die Tokenisierung ist der Prozess der Zerlegung eines Textes in einzelne, bedeutungstragende Einheiten (Token). Diese können Wörter, Zahlen oder Satzzeichen sein. Sie ist der erste grundlegende Schritt in der NLP-Pipeline, auf dem weitere Verarbeitungsschritte aufbauen.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Sie wandelt alle Wörter in ihre Grundform um\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage beschreibt nicht die Tokenisierung, sondern die Lemmatisierung. Die Tokenisierung zerlegt Text in einzelne Einheiten, während die Lemmatisierung in einem späteren Schritt diese Einheiten auf ihre Grundform zurückführt.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_2, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "45ce509a", "metadata": {}, "source": [ "## Frage 3" ] }, { "cell_type": "code", "execution_count": 3, "id": "6af8bb2e", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
      " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsCHEluxvmwnSX=[{\"question\": \"Was ist das Hauptziel der Lemmatisierung in der NLP-Pipeline?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"Die Bestimmung der grammatikalischen Funktion eines Wortes im Satz\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage beschreibt nicht die Lemmatisierung, sondern das Part-of-Speech Tagging (POS-Tagging). Die Lemmatisierung befasst sich mit der Reduktion von Wortformen auf ihre Grundform, nicht mit der grammatikalischen Funktionsanalyse.\"}, {\"answer\": \"Die Zur\\u00fcckf\\u00fchrung verschiedener Wortformen auf ihre gemeinsame Grundform\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Die Lemmatisierung f\\u00fchrt verschiedene Formen eines Wortes auf ihre gemeinsame Grundform (Lemma) zur\\u00fcck. Beispielsweise werden \\\"gehe\\\", \\\"gehst\\\", \\\"geht\\\", \\\"ging\\\" auf \\\"gehen\\\" zur\\u00fcckgef\\u00fchrt. Dies vereinfacht die Textanalyse, da verschiedene Formen desselben Wortes als eine Einheit betrachtet werden k\\u00f6nnen.\"}, {\"answer\": \"Die Erkennung von Eigennamen und geographischen Bezeichnungen\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage beschreibt nicht die Lemmatisierung, sondern die Named Entity Recognition (NER). Die Lemmatisierung hat nicht das Ziel, bestimmte semantische Kategorien von W\\u00f6rtern zu identifizieren, sondern Wortformen zu vereinheitlichen.\"}, {\"answer\": \"Die Zerlegung von Komposita in ihre Bestandteile\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage beschreibt nicht die prim\\u00e4re Funktion der Lemmatisierung. Die Zerlegung von Komposita (zusammengesetzten W\\u00f6rtern) ist eine separate NLP-Aufgabe, die als Compound Splitting bezeichnet wird. Die Lemmatisierung befasst sich mit der Reduktion von flektierten Formen auf ihre Grundform.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
      1. Copy the text in this cell below \"Answer String\"
      2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
      3. Select the whole \"Replace Me\" text
      4. Paste in your answer string and press shift-Enter.
      5. Save the notebook using the save icon or File->Save Notebook menu item



      6. Answer String:
        ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
        \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"CHEluxvmwnSX\")) {\n", " show_questions(questionsCHEluxvmwnSX, CHEluxvmwnSX); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"CHEluxvmwnSX\");\n", " // console.log(document.getElementById(\"CHEluxvmwnSX\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_3 = [{\n", " \"question\": \"\"\"Was ist das Hauptziel der Lemmatisierung in der NLP-Pipeline?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Die Bestimmung der grammatikalischen Funktion eines Wortes im Satz\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage beschreibt nicht die Lemmatisierung, sondern das Part-of-Speech Tagging (POS-Tagging). Die Lemmatisierung befasst sich mit der Reduktion von Wortformen auf ihre Grundform, nicht mit der grammatikalischen Funktionsanalyse.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Die Zurückführung verschiedener Wortformen auf ihre gemeinsame Grundform\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Die Lemmatisierung führt verschiedene Formen eines Wortes auf ihre gemeinsame Grundform (Lemma) zurück. Beispielsweise werden \"gehe\", \"gehst\", \"geht\", \"ging\" auf \"gehen\" zurückgeführt. Dies vereinfacht die Textanalyse, da verschiedene Formen desselben Wortes als eine Einheit betrachtet werden können.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Die Erkennung von Eigennamen und geographischen Bezeichnungen\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage beschreibt nicht die Lemmatisierung, sondern die Named Entity Recognition (NER). Die Lemmatisierung hat nicht das Ziel, bestimmte semantische Kategorien von Wörtern zu identifizieren, sondern Wortformen zu vereinheitlichen.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Die Zerlegung von Komposita in ihre Bestandteile\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage beschreibt nicht die primäre Funktion der Lemmatisierung. Die Zerlegung von Komposita (zusammengesetzten Wörtern) ist eine separate NLP-Aufgabe, die als Compound Splitting bezeichnet wird. Die Lemmatisierung befasst sich mit der Reduktion von flektierten Formen auf ihre Grundform.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_3, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "d6111613", "metadata": {}, "source": [ "## Frage 4" ] }, { "cell_type": "code", "execution_count": 4, "id": "3a8f571c", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
        " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsPfPskZFGLntN=[{\"question\": \"Warum ist die Kombination von Tokenisierung und Lemmatisierung f\\u00fcr die quantitative Textanalyse besonders wertvoll?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"Sie erm\\u00f6glicht die automatische \\u00dcbersetzung des Textes\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Obwohl Tokenisierung und Lemmatisierung grundlegende Schritte in der \\u00dcbersetzungspipeline sein k\\u00f6nnen, reichen sie allein nicht aus, um eine automatische \\u00dcbersetzung zu erm\\u00f6glichen. Daf\\u00fcr sind komplexere Modelle notwendig.\"}, {\"answer\": \"Sie verbessert die Lesbarkeit des Textes f\\u00fcr Menschen\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Tokenisierung und Lemmatisierung sind in erster Linie f\\u00fcr die maschinelle Verarbeitung gedacht, nicht f\\u00fcr die menschliche Lesbarkeit. Im Gegenteil, ein lemmatisierter Text kann f\\u00fcr Menschen sogar schwerer zu lesen sein, da er nicht mehr den gewohnten grammatikalischen Formen entspricht.\"}, {\"answer\": \"Sie erm\\u00f6glicht pr\\u00e4zisere H\\u00e4ufigkeitsanalysen durch Normalisierung verschiedener Wortformen\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Die Kombination von Tokenisierung und Lemmatisierung ist f\\u00fcr quantitative Textanalysen besonders wertvoll, weil sie die Varianz der Wortformen reduziert. Dadurch k\\u00f6nnen H\\u00e4ufigkeitsanalysen pr\\u00e4ziser durchgef\\u00fchrt werden, da verschiedene Formen desselben Wortes nicht mehr als verschiedene W\\u00f6rter gez\\u00e4hlt werden.\"}, {\"answer\": \"Sie korrigiert Rechtschreibfehler im Originaltext\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Weder Tokenisierung noch Lemmatisierung sind prim\\u00e4r darauf ausgerichtet, Rechtschreibfehler zu korrigieren. Rechtschreibkorrektur ist eine separate NLP-Aufgabe, die vor der Tokenisierung und Lemmatisierung durchgef\\u00fchrt werden sollte.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
        1. Copy the text in this cell below \"Answer String\"
        2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
        3. Select the whole \"Replace Me\" text
        4. Paste in your answer string and press shift-Enter.
        5. Save the notebook using the save icon or File->Save Notebook menu item



        6. Answer String:
          ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
          \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"PfPskZFGLntN\")) {\n", " show_questions(questionsPfPskZFGLntN, PfPskZFGLntN); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"PfPskZFGLntN\");\n", " // console.log(document.getElementById(\"PfPskZFGLntN\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_4 = [{\n", " \"question\": \"\"\"Warum ist die Kombination von Tokenisierung und Lemmatisierung für die quantitative Textanalyse besonders wertvoll?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Sie ermöglicht die automatische Übersetzung des Textes\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Obwohl Tokenisierung und Lemmatisierung grundlegende Schritte in der Übersetzungspipeline sein können, reichen sie allein nicht aus, um eine automatische Übersetzung zu ermöglichen. Dafür sind komplexere Modelle notwendig.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Sie verbessert die Lesbarkeit des Textes für Menschen\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Tokenisierung und Lemmatisierung sind in erster Linie für die maschinelle Verarbeitung gedacht, nicht für die menschliche Lesbarkeit. Im Gegenteil, ein lemmatisierter Text kann für Menschen sogar schwerer zu lesen sein, da er nicht mehr den gewohnten grammatikalischen Formen entspricht.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Sie ermöglicht präzisere Häufigkeitsanalysen durch Normalisierung verschiedener Wortformen\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Die Kombination von Tokenisierung und Lemmatisierung ist für quantitative Textanalysen besonders wertvoll, weil sie die Varianz der Wortformen reduziert. Dadurch können Häufigkeitsanalysen präziser durchgeführt werden, da verschiedene Formen desselben Wortes nicht mehr als verschiedene Wörter gezählt werden.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Sie korrigiert Rechtschreibfehler im Originaltext\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Weder Tokenisierung noch Lemmatisierung sind primär darauf ausgerichtet, Rechtschreibfehler zu korrigieren. Rechtschreibkorrektur ist eine separate NLP-Aufgabe, die vor der Tokenisierung und Lemmatisierung durchgeführt werden sollte.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_4, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "fa2d9592", "metadata": {}, "source": [ "## Frage 5" ] }, { "cell_type": "code", "execution_count": 5, "id": "97b6eee8", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
          " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionseeyCIyhxfOpS=[{\"question\": \"Welcher Unterschied besteht zwischen dem urspr\\u00fcnglichen Text und dem mit NLP-Methoden verarbeiteten Text?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"Der verarbeitete Text enth\\u00e4lt keine Satzzeichen mehr\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage ist nicht allgemein zutreffend. Ob Satzzeichen im verarbeiteten Text erhalten bleiben, h\\u00e4ngt von den spezifischen NLP-Methoden und deren Konfiguration ab. In vielen NLP-Pipelines werden Satzzeichen als eigene Token behandelt und bleiben somit erhalten.\"}, {\"answer\": \"Der verarbeitete Text ist in eine andere Sprache \\u00fcbersetzt\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. NLP-Methoden umfassen viele verschiedene Verarbeitungsschritte, von denen \\u00dcbersetzung nur einer ist. Die meisten grundlegenden NLP-Verarbeitungsschritte wie Tokenisierung und Lemmatisierung ver\\u00e4ndern die Sprache des Textes nicht.\"}, {\"answer\": \"Der verarbeitete Text ist mit zus\\u00e4tzlichen linguistischen Informationen angereichert\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Der wesentliche Unterschied besteht darin, dass der mit NLP-Methoden verarbeitete Text mit zus\\u00e4tzlichen linguistischen Informationen angereichert ist. Dies k\\u00f6nnen Informationen \\u00fcber Wortarten, Grundformen, syntaktische Beziehungen oder semantische Bedeutungen sein. Der Computer kann dadurch auf verschiedenen linguistischen Ebenen mit dem Text arbeiten.\"}, {\"answer\": \"Der verarbeitete Text ist k\\u00fcrzer als der Originaltext\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage ist nicht allgemein zutreffend. Die L\\u00e4nge des verarbeiteten Textes h\\u00e4ngt von den angewendeten NLP-Methoden ab. Bei manchen Methoden (wie z.B. Zusammenfassung) kann der Text k\\u00fcrzer werden, bei anderen (wie z.B. Annotation) kann er durch zus\\u00e4tzliche Informationen sogar l\\u00e4nger werden.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
          1. Copy the text in this cell below \"Answer String\"
          2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
          3. Select the whole \"Replace Me\" text
          4. Paste in your answer string and press shift-Enter.
          5. Save the notebook using the save icon or File->Save Notebook menu item



          6. Answer String:
            ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
            \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"eeyCIyhxfOpS\")) {\n", " show_questions(questionseeyCIyhxfOpS, eeyCIyhxfOpS); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"eeyCIyhxfOpS\");\n", " // console.log(document.getElementById(\"eeyCIyhxfOpS\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_5 = [{\n", " \"question\": \"\"\"Welcher Unterschied besteht zwischen dem ursprünglichen Text und dem mit NLP-Methoden verarbeiteten Text?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Der verarbeitete Text enthält keine Satzzeichen mehr\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage ist nicht allgemein zutreffend. Ob Satzzeichen im verarbeiteten Text erhalten bleiben, hängt von den spezifischen NLP-Methoden und deren Konfiguration ab. In vielen NLP-Pipelines werden Satzzeichen als eigene Token behandelt und bleiben somit erhalten.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Der verarbeitete Text ist in eine andere Sprache übersetzt\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. NLP-Methoden umfassen viele verschiedene Verarbeitungsschritte, von denen Übersetzung nur einer ist. Die meisten grundlegenden NLP-Verarbeitungsschritte wie Tokenisierung und Lemmatisierung verändern die Sprache des Textes nicht.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Der verarbeitete Text ist mit zusätzlichen linguistischen Informationen angereichert\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Der wesentliche Unterschied besteht darin, dass der mit NLP-Methoden verarbeitete Text mit zusätzlichen linguistischen Informationen angereichert ist. Dies können Informationen über Wortarten, Grundformen, syntaktische Beziehungen oder semantische Bedeutungen sein. Der Computer kann dadurch auf verschiedenen linguistischen Ebenen mit dem Text arbeiten.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Der verarbeitete Text ist kürzer als der Originaltext\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage ist nicht allgemein zutreffend. Die Länge des verarbeiteten Textes hängt von den angewendeten NLP-Methoden ab. Bei manchen Methoden (wie z.B. Zusammenfassung) kann der Text kürzer werden, bei anderen (wie z.B. Annotation) kann er durch zusätzliche Informationen sogar länger werden.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_5, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "27b812d1", "metadata": {}, "source": [ "## Frage 6\n", "Analysieren Sie den folgenden Satz mit NLP-Methoden und beschreiben Sie die Ergebnisse:\n", "\n", "Originaltext: \"Die Forschenden untersuchten verschiedene Zeitungsartikel zur Spanischen Grippe.\"\n", "\n", "1.\tFühren Sie eine Tokenisierung durch.\n", "2.\tBestimmen Sie die Lemmata der einzelnen Token.\n", "3.\tReflektieren Sie, wie diese Verarbeitung eine quantitative Analyse unterstützen würde." ] }, { "cell_type": "code", "execution_count": 6, "id": "8c86d747", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "
            \n", " \n", " \n", "
            \n", " " ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import sys\n", "sys.path.append(\"../quadriga_config\") # Adjust path as needed\n", "from assessment import create_answer_box\n", "\n", "create_answer_box('process-1')" ] }, { "cell_type": "markdown", "id": "ac72b295", "metadata": {}, "source": [ "````{admonition} Lösung\n", ":class: solution, dropdown\n", "\n", "**Beispiellösung zur Selbstbewertung:**\n", "1.\tTokenisierung: [\"Die\", \"Forschenden\", \"untersuchten\", \"verschiedene\", \"Zeitungsartikel\", \"zur\", \"Spanischen\", \"Grippe\", \".\"]\n", "2.\tLemmatisierung: [\"der\", \"Forschende\", \"untersuchen\", \"verschieden\", \"Zeitungsartikel\", \"zu\", \"spanisch\", \"Grippe\", \".\"]\n", "\n", "**Reflexion:**\n", "- Die Tokenisierung ermöglicht die Analyse auf Wortebene und bereitet den Text für weitere Verarbeitung vor\n", "- Die Lemmatisierung würde alle Formen von \"untersuchen\" zusammenfassen, was bei einer Frequenzanalyse hilfreich ist\n", "- Durch die Lemmatisierung werden verschiedene Flexionsformen (wie \"Spanischen\" zu \"spanisch\") vereinheitlicht ('die' wird standardmäßig zu 'der' lemmatisiert).\n", "- Bei einer größeren Textsammlung würden verschiedene grammatikalische Formen desselben Wortes nicht als unterschiedliche Begriffe gezählt\n", "- Diese Normalisierung verbessert die Qualität von Häufigkeitsanalysen, Keyword-Extraktion und thematischen Analysen\n", "- Die Informationen über die ursprüngliche Form bleiben erhalten und können für detailliertere linguistische Analysen genutzt werden\n", "\n", "**Bewertungskriterien für die Selbsteinschätzung:**\n", "- Korrekte Tokenisierung mit Berücksichtigung von Satzzeichen als eigene Token\n", "- Korrekte Bestimmung der Grundformen bei der Lemmatisierung\n", "- Verständnis des Nutzens für quantitative Textanalyse, insbesondere für Häufigkeitsanalysen\n", "- Reflexion über die Vor- und Nachteile der Methoden für die spezifische Forschungsfrage\n", "\n", "````\n", "\n", "\n", "\n", "## Frage 7\n", "(Wählen Sie alle zutreffenden Antworten aus)" ] }, { "cell_type": "code", "execution_count": 7, "id": "a4fb949f", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
            " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsmSgREVYEctZc=[{\"question\": \"Welche Schritte geh\\u00f6ren zur automatischen Annotation eines Textes mit spaCy?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"Einlesen des Textes\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Der erste Schritt im Notebook ist das Einlesen des Textes mit text_path.read_text(), nachdem der Pfad zur Datei definiert wurde (text_path = Path(\\\"../data/txt/SNP2719372X-19181015-0-0-0-0.txt\\\")).\"}, {\"answer\": \"Laden des sprachspezifischen Modells\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Im Notebook wird das deutsche Sprachmodell mit nlp = spacy.load('de_core_news_sm') geladen, welches f\\u00fcr die Verarbeitung deutscher Texte optimiert ist.\"}, {\"answer\": \"Auswahl der relevanten Analysekomponenten\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Im Notebook werden nicht ben\\u00f6tigte Komponenten deaktiviert: disable_components = ['ner', 'morphologizer', 'attribute_ruler', 'sentencizer'], um die Verarbeitungsgeschwindigkeit zu erh\\u00f6hen. Dieser Schritt kann bei geringer Textmenge \\u00fcbersprungen werden.\"}, {\"answer\": \"Manuelle Korrektur der Tokenisierungsfehler\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Die Annotation mit spaCy erfolgt vollautomatisch. Im Notebook gibt es keinen Schritt zur manuellen Korrektur von Tokenisierungsfehlern.\"}, {\"answer\": \"Speichern der Ergebnisse in einem strukturierten Format\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Im letzten Schritt werden die Ergebnisse als CSV-Datei gespeichert: text_annotated_df.to_csv(output_path, index=False). Das Notebook erw\\u00e4hnt, dass CSV das Standardformat ist, um tabellarische Daten im Klartext zu speichern.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
            1. Copy the text in this cell below \"Answer String\"
            2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
            3. Select the whole \"Replace Me\" text
            4. Paste in your answer string and press shift-Enter.
            5. Save the notebook using the save icon or File->Save Notebook menu item



            6. Answer String:
              ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
              \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"mSgREVYEctZc\")) {\n", " show_questions(questionsmSgREVYEctZc, mSgREVYEctZc); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"mSgREVYEctZc\");\n", " // console.log(document.getElementById(\"mSgREVYEctZc\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "\"\"\"\n", "Lernziel: Sie können die notwendigen Schritte zur automatischen Annotation eines Texts aufzählen und Vorteile der Tokenisierung gegenüber einfacheren Methoden der Worttrennung nennen.\n", "Bloom-Stufe: Verstehen\n", "Format: Multiple Choice\n", "\"\"\"\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_1 = [{\n", " \"question\": \"\"\"Welche Schritte gehören zur automatischen Annotation eines Textes mit spaCy?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Einlesen des Textes\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Der erste Schritt im Notebook ist das Einlesen des Textes mit text_path.read_text(), nachdem der Pfad zur Datei definiert wurde (text_path = Path(\"../data/txt/SNP2719372X-19181015-0-0-0-0.txt\")).\"\"\"\n", " },\n", " {\n", " \"answer\": \"Laden des sprachspezifischen Modells\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Im Notebook wird das deutsche Sprachmodell mit nlp = spacy.load('de_core_news_sm') geladen, welches für die Verarbeitung deutscher Texte optimiert ist.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Auswahl der relevanten Analysekomponenten\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Im Notebook werden nicht benötigte Komponenten deaktiviert: disable_components = ['ner', 'morphologizer', 'attribute_ruler', 'sentencizer'], um die Verarbeitungsgeschwindigkeit zu erhöhen. Dieser Schritt kann bei geringer Textmenge übersprungen werden.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Manuelle Korrektur der Tokenisierungsfehler\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Die Annotation mit spaCy erfolgt vollautomatisch. Im Notebook gibt es keinen Schritt zur manuellen Korrektur von Tokenisierungsfehlern.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Speichern der Ergebnisse in einem strukturierten Format\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Im letzten Schritt werden die Ergebnisse als CSV-Datei gespeichert: text_annotated_df.to_csv(output_path, index=False). Das Notebook erwähnt, dass CSV das Standardformat ist, um tabellarische Daten im Klartext zu speichern.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_1, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "a86c0ea6", "metadata": {}, "source": [ "## Frage 8\n", "(Wählen Sie alle zutreffenden Antworten aus)" ] }, { "cell_type": "code", "execution_count": 8, "id": "49c7ca5c", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
              " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsCvXVZzMbXnIS=[{\"question\": \"Welche Vorteile bietet die Tokenisierung mit spaCy gegen\\u00fcber einer einfachen Worttrennung mittels split()?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"Satzzeichen werden als eigene Token erkannt\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Das Notebook zeigt im Beispiel words[100:120], dass bei der einfachen Teilung mit split() Satzzeichen an W\\u00f6rtern h\\u00e4ngen bleiben (z.B. \\\"Entfernung,\\\", \\\"anzugreisen.\\\"), w\\u00e4hrend spaCy sie als separate Token erkennt.\"}, {\"answer\": \"Die Gesamtanzahl der Token ist akkurater\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Im Notebook wird explizit darauf hingewiesen: \\\"Wie zu sehen ist, hat diese Art der 'falschen' Tokenisierung den Nachteil, dass Satzzeichen nicht von W\\u00f6rtern abgetrennt werden. Die Wortanzahl ist dementsprechend auch nicht akkurat.\\\" Der Vergleich zeigt 11.612 W\\u00f6rter mit split() gegen\\u00fcber 15.062 Token mit spaCy.\"}, {\"answer\": \"Die Tokenisierung mit spaCy ist immer schneller\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterst\\u00fctzt. Im Gegenteil, das Notebook zeigt, dass die spaCy-Annotation 1,47 Sekunden dauert, und f\\u00fcr gr\\u00f6\\u00dfere Textmengen werden sogar Optimierungen vorgeschlagen, indem nicht ben\\u00f6tigte Komponenten deaktiviert werden.\"}, {\"answer\": \"Sie erm\\u00f6glicht die Lemmatisierung der Tokens\", \"correct\": false, \"feedback\": \"x Nicht korrekt: Auch wenn im Notebook die Tokenisierung und die Lemmatisierung im selben Schritt erfolgen, ist die Lemmatisierung kein Teil der Tokenisierung, sondern erfolgt aufbauend auf dieser.\"}, {\"answer\": \"Sie korrigiert automatisch OCR-Fehler im Text\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterst\\u00fctzt. spaCy f\\u00fchrt keine automatische Korrektur von OCR-Fehlern durch. Die Qualit\\u00e4t der Annotation h\\u00e4ngt von der Qualit\\u00e4t des Eingabetextes ab.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
              1. Copy the text in this cell below \"Answer String\"
              2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
              3. Select the whole \"Replace Me\" text
              4. Paste in your answer string and press shift-Enter.
              5. Save the notebook using the save icon or File->Save Notebook menu item



              6. Answer String:
                ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
                \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"CvXVZzMbXnIS\")) {\n", " show_questions(questionsCvXVZzMbXnIS, CvXVZzMbXnIS); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"CvXVZzMbXnIS\");\n", " // console.log(document.getElementById(\"CvXVZzMbXnIS\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_2 = [{\n", " \"question\": \"\"\"Welche Vorteile bietet die Tokenisierung mit spaCy gegenüber einer einfachen Worttrennung mittels split()?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Satzzeichen werden als eigene Token erkannt\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Das Notebook zeigt im Beispiel words[100:120], dass bei der einfachen Teilung mit split() Satzzeichen an Wörtern hängen bleiben (z.B. \"Entfernung,\", \"anzugreisen.\"), während spaCy sie als separate Token erkennt.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Die Gesamtanzahl der Token ist akkurater\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Im Notebook wird explizit darauf hingewiesen: \"Wie zu sehen ist, hat diese Art der 'falschen' Tokenisierung den Nachteil, dass Satzzeichen nicht von Wörtern abgetrennt werden. Die Wortanzahl ist dementsprechend auch nicht akkurat.\" Der Vergleich zeigt 11.612 Wörter mit split() gegenüber 15.062 Token mit spaCy.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Die Tokenisierung mit spaCy ist immer schneller\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterstützt. Im Gegenteil, das Notebook zeigt, dass die spaCy-Annotation 1,47 Sekunden dauert, und für größere Textmengen werden sogar Optimierungen vorgeschlagen, indem nicht benötigte Komponenten deaktiviert werden.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Sie ermöglicht die Lemmatisierung der Tokens\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"x Nicht korrekt: Auch wenn im Notebook die Tokenisierung und die Lemmatisierung im selben Schritt erfolgen, ist die Lemmatisierung kein Teil der Tokenisierung, sondern erfolgt aufbauend auf dieser.\"\"\" \n", " },\n", " {\n", " \"answer\": \"Sie korrigiert automatisch OCR-Fehler im Text\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterstützt. spaCy führt keine automatische Korrektur von OCR-Fehlern durch. Die Qualität der Annotation hängt von der Qualität des Eingabetextes ab.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_2, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "9102fd6a", "metadata": {}, "source": [ "## Frage 9" ] }, { "cell_type": "code", "execution_count": 9, "id": "946ec387", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
                " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsgSqInALjOmuz=[{\"question\": \"Warum werden im Beispiel bestimmte Analysekomponenten von spaCy deaktiviert?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"Um die Genauigkeit der Tokenisierung zu erh\\u00f6hen\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterst\\u00fctzt. Das Deaktivieren von Komponenten dient nicht der Verbesserung der Genauigkeit.\"}, {\"answer\": \"Um die Verarbeitungsgeschwindigkeit zu erh\\u00f6hen\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Im Notebook steht explizit: \\\"Es werden einige Analysekomponent wie z. B. das Aufteilen des Texts in S\\u00e4tze (sentencizer) oder die Named Entity Recognition (ner) ausgeschlossen, da diese f\\u00fcr die Tokenisierung und die Lemmatisierung nicht ben\\u00f6tigt werden. Der Auschluss der Komponentnen erh\\u00f6ht die Annotationsgeschwindikgeit.\\\" \"}, {\"answer\": \"Um mehr Speicherplatz f\\u00fcr die Ergebnisse zu haben\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterst\\u00fctzt. Der Speicherplatz f\\u00fcr die Ergebnisse wird nicht als Grund f\\u00fcr die Deaktivierung von Komponenten genannt.\"}, {\"answer\": \"Um Kompatibilit\\u00e4tsprobleme mit dem CSV-Format zu vermeiden\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterst\\u00fctzt. Es gibt keinen Hinweis darauf, dass die Deaktivierung von Komponenten mit dem CSV-Format zusammenh\\u00e4ngt.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
                1. Copy the text in this cell below \"Answer String\"
                2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
                3. Select the whole \"Replace Me\" text
                4. Paste in your answer string and press shift-Enter.
                5. Save the notebook using the save icon or File->Save Notebook menu item



                6. Answer String:
                  ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
                  \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"gSqInALjOmuz\")) {\n", " show_questions(questionsgSqInALjOmuz, gSqInALjOmuz); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"gSqInALjOmuz\");\n", " // console.log(document.getElementById(\"gSqInALjOmuz\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_3 = [{\n", " \"question\": \"\"\"Warum werden im Beispiel bestimmte Analysekomponenten von spaCy deaktiviert?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Um die Genauigkeit der Tokenisierung zu erhöhen\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterstützt. Das Deaktivieren von Komponenten dient nicht der Verbesserung der Genauigkeit.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Um die Verarbeitungsgeschwindigkeit zu erhöhen\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Im Notebook steht explizit: \"Es werden einige Analysekomponent wie z. B. das Aufteilen des Texts in Sätze (sentencizer) oder die Named Entity Recognition (ner) ausgeschlossen, da diese für die Tokenisierung und die Lemmatisierung nicht benötigt werden. Der Auschluss der Komponentnen erhöht die Annotationsgeschwindikgeit.\" \"\"\"\n", " },\n", " {\n", " \"answer\": \"Um mehr Speicherplatz für die Ergebnisse zu haben\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterstützt. Der Speicherplatz für die Ergebnisse wird nicht als Grund für die Deaktivierung von Komponenten genannt.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Um Kompatibilitätsprobleme mit dem CSV-Format zu vermeiden\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage wird nicht durch das Notebook unterstützt. Es gibt keinen Hinweis darauf, dass die Deaktivierung von Komponenten mit dem CSV-Format zusammenhängt.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_3, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "b84f9c39", "metadata": {}, "source": [ "## Frage 10" ] }, { "cell_type": "code", "execution_count": 10, "id": "ca86062d", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
                  " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsPvcaXcIVfaaX=[{\"question\": \"Welches Dateiformat wird im Beispiel f\\u00fcr die Speicherung der annotierten Texte verwendet und warum?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"TXT, weil es am wenigsten Speicherplatz ben\\u00f6tigt\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Laut Notebook werden die annotierten Texte nicht als TXT-Dateien gespeichert.\"}, {\"answer\": \"CSV, weil es gut f\\u00fcr die Speicherung tabellarischer Daten geeignet ist\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Im Notebook steht explizit: \\\"CSV (comma-separated value) ist das Standardformat um tabellarische Daten im Klartext zu speichern.\\\" Au\\u00dferdem wird erw\\u00e4hnt: \\\"Das Tabellenformat wurde gew\\u00e4hlt, da sich darin gut relationale Daten speichern lassen.\\\" \"}, {\"answer\": \"JSON, weil es die hierarchische Struktur der Annotation am besten abbildet\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage ist nicht korrekt, da die Annotationen nicht hierarchisch strukturiert sind. Im Notebook wird JSON nicht als Speicherformat erw\\u00e4hnt, ist aber auch ein m\\u00f6gliches Format, um annotierte Daten zu speichern. \"}, {\"answer\": \"XML, weil es von den meisten Textanalysewerkzeugen unterst\\u00fctzt wird\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. XML ist in den Digital Humanities zwar ein Standardformat, um Annotationen zu speichern, allerdings sind nicht die meisten Analysewerkzeuge auf das Format ausgelegt. XML eignet sich f\\u00fcr die Speicherung von komplexeren Annotationen oder Textauszeichnungen besser.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
                  1. Copy the text in this cell below \"Answer String\"
                  2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
                  3. Select the whole \"Replace Me\" text
                  4. Paste in your answer string and press shift-Enter.
                  5. Save the notebook using the save icon or File->Save Notebook menu item



                  6. Answer String:
                    ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
                    \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"PvcaXcIVfaaX\")) {\n", " show_questions(questionsPvcaXcIVfaaX, PvcaXcIVfaaX); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"PvcaXcIVfaaX\");\n", " // console.log(document.getElementById(\"PvcaXcIVfaaX\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_4 = [{\n", " \"question\": \"\"\"Welches Dateiformat wird im Beispiel für die Speicherung der annotierten Texte verwendet und warum?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"TXT, weil es am wenigsten Speicherplatz benötigt\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Laut Notebook werden die annotierten Texte nicht als TXT-Dateien gespeichert.\"\"\"\n", " },\n", " {\n", " \"answer\": \"CSV, weil es gut für die Speicherung tabellarischer Daten geeignet ist\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Im Notebook steht explizit: \"CSV (comma-separated value) ist das Standardformat um tabellarische Daten im Klartext zu speichern.\" Außerdem wird erwähnt: \"Das Tabellenformat wurde gewählt, da sich darin gut relationale Daten speichern lassen.\" \"\"\"\n", " },\n", " {\n", " \"answer\": \"JSON, weil es die hierarchische Struktur der Annotation am besten abbildet\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage ist nicht korrekt, da die Annotationen nicht hierarchisch strukturiert sind. Im Notebook wird JSON nicht als Speicherformat erwähnt, ist aber auch ein mögliches Format, um annotierte Daten zu speichern. \"\"\"\n", " },\n", " {\n", " \"answer\": \"XML, weil es von den meisten Textanalysewerkzeugen unterstützt wird\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. XML ist in den Digital Humanities zwar ein Standardformat, um Annotationen zu speichern, allerdings sind nicht die meisten Analysewerkzeuge auf das Format ausgelegt. XML eignet sich für die Speicherung von komplexeren Annotationen oder Textauszeichnungen besser.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_4, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "12072343", "metadata": {}, "source": [ "## Frage 11" ] }, { "cell_type": "code", "execution_count": 11, "id": "1695828b", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
                    " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsRrrCVMCwFAdf=[{\"question\": \"Was zeigt der Vergleich der Textl\\u00e4nge vor und nach der Tokenisierung mit spaCy im Beispiel?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"Der tokenisierte Text ist k\\u00fcrzer, weil Stoppw\\u00f6rter entfernt wurden\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage ist nicht korrekt, da es im Notebook keinen Hinweis darauf gibt, dass Stoppw\\u00f6rter entfernt wurden. Im Gegenteil, die Tokenzahl erh\\u00f6ht sich.\"}, {\"answer\": \"Der tokenisierte Text enth\\u00e4lt mehr Elemente, weil Satzzeichen als eigene Token erkannt werden\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Das Notebook zeigt: \\\"Durch die Tokenisierung wurden z. B. Satzzeichen von W\\u00f6rtern abgetrennt. An der Textl\\u00e4nge l\\u00e4sst sich dies schon erkennen.\\\" Die Anzahl steigt von 11.612 auf 15.062 Token.\"}, {\"answer\": \"Der tokenisierte Text ist unver\\u00e4ndert in seiner L\\u00e4nge, nur die Qualit\\u00e4t der Tokens ist verbessert\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage widerspricht dem im Notebook gezeigten Unterschied in der Tokenanzahl (11.612 vs. 15.062).\"}, {\"answer\": \"Der tokenisierte Text ist k\\u00fcrzer, weil zusammengeh\\u00f6rige Mehrwortausdr\\u00fccke als ein Token erkannt werden\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Aussage widerspricht dem im Notebook gezeigten Anstieg der Tokenanzahl.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
                    1. Copy the text in this cell below \"Answer String\"
                    2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
                    3. Select the whole \"Replace Me\" text
                    4. Paste in your answer string and press shift-Enter.
                    5. Save the notebook using the save icon or File->Save Notebook menu item



                    6. Answer String:
                      ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
                      \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"RrrCVMCwFAdf\")) {\n", " show_questions(questionsRrrCVMCwFAdf, RrrCVMCwFAdf); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"RrrCVMCwFAdf\");\n", " // console.log(document.getElementById(\"RrrCVMCwFAdf\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_5 = [{\n", " \"question\": \"\"\"Was zeigt der Vergleich der Textlänge vor und nach der Tokenisierung mit spaCy im Beispiel?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Der tokenisierte Text ist kürzer, weil Stoppwörter entfernt wurden\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage ist nicht korrekt, da es im Notebook keinen Hinweis darauf gibt, dass Stoppwörter entfernt wurden. Im Gegenteil, die Tokenzahl erhöht sich.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Der tokenisierte Text enthält mehr Elemente, weil Satzzeichen als eigene Token erkannt werden\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Das Notebook zeigt: \"Durch die Tokenisierung wurden z. B. Satzzeichen von Wörtern abgetrennt. An der Textlänge lässt sich dies schon erkennen.\" Die Anzahl steigt von 11.612 auf 15.062 Token.\"\"\"\n", " },\n", " {\n", " \"answer\": \"Der tokenisierte Text ist unverändert in seiner Länge, nur die Qualität der Tokens ist verbessert\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage widerspricht dem im Notebook gezeigten Unterschied in der Tokenanzahl (11.612 vs. 15.062).\"\"\"\n", " },\n", " {\n", " \"answer\": \"Der tokenisierte Text ist kürzer, weil zusammengehörige Mehrwortausdrücke als ein Token erkannt werden\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Aussage widerspricht dem im Notebook gezeigten Anstieg der Tokenanzahl.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_5, colors=colors.jupyterquiz)" ] }, { "cell_type": "markdown", "id": "d8e4579e", "metadata": {}, "source": [ "## Frage 12\n", "Ordnen Sie die Schritte in die richtige Reihenfolge, um einen Text mit spaCy zu annotieren:\n", "\n", "1. Speichern der Annotation als CSV-Datei\n", "2. Auswahl der Analysekomponenten\n", "3. Laden des Sprachmodells\n", "4. Einlesen des Textes\n", "5. Durchführung der Annotation mit nlp(text)" ] }, { "cell_type": "code", "execution_count": 12, "id": "f7f9d851", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
                      " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsmkkPRNBzTPle=[{\"question\": \"Welche Reihenfolge der Verarbeitungsschritte ist korrekt f\\u00fcr die Textannotation mit spaCy?\", \"type\": \"multiple_choice\", \"answers\": [{\"answer\": \"3 \\u2192 2 \\u2192 4 \\u2192 5 \\u2192 1\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Reihenfolge ist nicht korrekt. Laut Notebook wird zuerst der Text eingelesen (Schritt 1), bevor weitere Verarbeitungsschritte folgen.\"}, {\"answer\": \"3 \\u2192 4 \\u2192 2 \\u2192 5 \\u2192 1\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Diese Reihenfolge stimmt nicht mit dem Ablauf im Notebook \\u00fcberein, in dem zuerst der Text eingelesen wird.\"}, {\"answer\": \"4 \\u2192 3 \\u2192 2 \\u2192 5 \\u2192 1\", \"correct\": true, \"feedback\": \"\\u2713 Richtig! Die Reihenfolge im Notebook ist: 1. Einlesen des Texts, 2. Laden des Sprachmodells, 3. Auswahl der Analysekomponenten, 4. Durchf\\u00fchrung der Annotation, 5. Speichern der Ergebnisse.\"}, {\"answer\": \"4 \\u2192 5 \\u2192 3 \\u2192 2 \\u2192 1\", \"correct\": false, \"feedback\": \"\\u00d7 Nicht korrekt. Das Sprachmodell muss vor der Annotation geladen werden, wie im Notebook gezeigt.\"}]}];\n", " // Make a random ID\n", "function makeid(length) {\n", " var result = [];\n", " var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n", " var charactersLength = characters.length;\n", " for (var i = 0; i < length; i++) {\n", " result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n", " }\n", " return result.join('');\n", "}\n", "\n", "// Choose a random subset of an array. Can also be used to shuffle the array\n", "function getRandomSubarray(arr, size) {\n", " var shuffled = arr.slice(0), i = arr.length, temp, index;\n", " while (i--) {\n", " index = Math.floor((i + 1) * Math.random());\n", " temp = shuffled[index];\n", " shuffled[index] = shuffled[i];\n", " shuffled[i] = temp;\n", " }\n", " return shuffled.slice(0, size);\n", "}\n", "\n", "function printResponses(responsesContainer) {\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
                      1. Copy the text in this cell below \"Answer String\"
                      2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
                      3. Select the whole \"Replace Me\" text
                      4. Paste in your answer string and press shift-Enter.
                      5. Save the notebook using the save icon or File->Save Notebook menu item



                      6. Answer String:
                        ';\n", " console.log(responses);\n", " responses.forEach((response, index) => {\n", " if (response) {\n", " console.log(index + ': ' + response);\n", " stringResponses+= index + ': ' + response +\"
                        \";\n", " }\n", " });\n", " responsesContainer.innerHTML=stringResponses;\n", "}\n", "/* Callback function to determine whether a selected multiple-choice\n", " button corresponded to a correct answer and to provide feedback\n", " based on the answer */\n", "function check_mc() {\n", " var id = this.id.split('-')[0];\n", " //var response = this.id.split('-')[1];\n", " //console.log(response);\n", " //console.log(\"In check_mc(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.correct) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var label = event.srcElement;\n", " //console.log(label, label.nodeName);\n", " var depth = 0;\n", " while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n", " label = label.parentElement;\n", " console.log(depth, label);\n", " depth++;\n", " }\n", "\n", "\n", "\n", " var answers = label.parentElement.children;\n", " //console.log(answers);\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", " /* Multiple choice (1 answer). Allow for 0 correct\n", " answers as an edge case */\n", " if (fb.dataset.numcorrect <= 1) {\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " responses[qnum]= response;\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " //console.log(child);\n", " child.className = \"MCButton\";\n", " }\n", "\n", "\n", "\n", " if (label.dataset.correct == \"true\") {\n", " // console.log(\"Correct action\");\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Correct!\";\n", " }\n", " label.classList.add(\"correctButton\");\n", "\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " fb.innerHTML = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", " }\n", " //console.log(\"Error action\");\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " }\n", " else { /* Many choice (more than 1 correct answer) */\n", " var reset = false;\n", " var feedback;\n", " if (label.dataset.correct == \"true\") {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Correct!\";\n", " }\n", " if (label.dataset.answered <= 0) {\n", " if (fb.dataset.answeredcorrect < 0) {\n", " fb.dataset.answeredcorrect = 1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect++;\n", " }\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"correctButton\");\n", " label.dataset.answered = 1;\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", "\n", " }\n", " } else {\n", " if (\"feedback\" in label.dataset) {\n", " feedback = jaxify(label.dataset.feedback);\n", " } else {\n", " feedback = \"Incorrect -- try again.\";\n", " }\n", " if (fb.dataset.answeredcorrect > 0) {\n", " fb.dataset.answeredcorrect = -1;\n", " reset = true;\n", " } else {\n", " fb.dataset.answeredcorrect--;\n", " }\n", "\n", " if (reset) {\n", " for (var i = 0; i < answers.length; i++) {\n", " var child = answers[i];\n", " child.className = \"MCButton\";\n", " child.dataset.answered = 0;\n", " }\n", " }\n", " label.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " //console.log(responsesContainer);\n", " var response = label.firstChild.innerText;\n", " if (label.querySelector(\".QuizCode\")){\n", " response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n", " }\n", " console.log(response);\n", " //console.log(document.getElementById(\"quizWrap\"+id));\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " if (label.dataset.correct == \"true\") {\n", " if (typeof(responses[qnum]) == \"object\"){\n", " if (!responses[qnum].includes(response))\n", " responses[qnum].push(response);\n", " } else{\n", " responses[qnum]= [ response ];\n", " }\n", " } else {\n", " responses[qnum]= response;\n", " }\n", " console.log(responses);\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End save responses stuff\n", "\n", "\n", "\n", " var numcorrect = fb.dataset.numcorrect;\n", " var answeredcorrect = fb.dataset.answeredcorrect;\n", " if (answeredcorrect >= 0) {\n", " fb.innerHTML = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.innerHTML = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n", " }\n", "\n", "\n", " }\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", "\n", "}\n", "\n", "\n", "/* Function to produce the HTML buttons for a multiple choice/\n", " many choice question and to update the CSS tags based on\n", " the question type */\n", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n", "\n", " var shuffled;\n", " if (shuffle_answers == \"True\") {\n", " //console.log(shuffle_answers+\" read as true\");\n", " shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n", " } else {\n", " //console.log(shuffle_answers+\" read as false\");\n", " shuffled = qa.answers;\n", " }\n", "\n", "\n", " var num_correct = 0;\n", "\n", " shuffled.forEach((item, index, ans_array) => {\n", " //console.log(answer);\n", "\n", " // Make input element\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"radio\";\n", " inp.id = \"quizo\" + id + index;\n", " inp.style = \"display:none;\";\n", " aDiv.append(inp);\n", "\n", " //Make label for input element\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"MCButton\";\n", " lab.id = id + '-' + index;\n", " lab.onclick = check_mc;\n", " var aSpan = document.createElement('span');\n", " aSpan.classsName = \"\";\n", " //qDiv.id=\"quizQn\"+id+index;\n", " if (\"answer\" in item) {\n", " aSpan.innerHTML = jaxify(item.answer);\n", " //aSpan.innerHTML=item.answer;\n", " }\n", " lab.append(aSpan);\n", "\n", " // Create div for code inside question\n", " var codeSpan;\n", " if (\"code\" in item) {\n", " codeSpan = document.createElement('span');\n", " codeSpan.id = \"code\" + id + index;\n", " codeSpan.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeSpan.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = item.code;\n", " lab.append(codeSpan);\n", " //console.log(codeSpan);\n", " }\n", "\n", " //lab.textContent=item.answer;\n", "\n", " // Set the data attributes for the answer\n", " lab.setAttribute('data-correct', item.correct);\n", " if (item.correct) {\n", " num_correct++;\n", " }\n", " if (\"feedback\" in item) {\n", " lab.setAttribute('data-feedback', item.feedback);\n", " }\n", " lab.setAttribute('data-answered', 0);\n", "\n", " aDiv.append(lab);\n", "\n", " });\n", "\n", " if (num_correct > 1) {\n", " outerqDiv.className = \"ManyChoiceQn\";\n", " } else {\n", " outerqDiv.className = \"MultipleChoiceQn\";\n", " }\n", "\n", " return num_correct;\n", "\n", "}\n", "function check_numeric(ths, event) {\n", "\n", " if (event.keyCode === 13) {\n", " ths.blur();\n", "\n", " var id = ths.id.split('-')[0];\n", "\n", " var submission = ths.value;\n", " if (submission.indexOf('/') != -1) {\n", " var sub_parts = submission.split('/');\n", " //console.log(sub_parts);\n", " submission = sub_parts[0] / sub_parts[1];\n", " }\n", " //console.log(\"Reader entered\", submission);\n", "\n", " if (\"precision\" in ths.dataset) {\n", " var precision = ths.dataset.precision;\n", " submission = Number(Number(submission).toPrecision(precision));\n", " }\n", "\n", "\n", " //console.log(\"In check_numeric(), id=\"+id);\n", " //console.log(event.srcElement.id) \n", " //console.log(event.srcElement.dataset.feedback)\n", "\n", " var fb = document.getElementById(\"fb\" + id);\n", " fb.style.display = \"none\";\n", " fb.innerHTML = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"Incorrect. Try again.\";\n", " var correct;\n", " var done = false;\n", " answers.every(answer => {\n", " //console.log(answer.type);\n", "\n", " correct = false;\n", " // if (answer.type==\"value\"){\n", " if ('value' in answer) {\n", " if (submission == answer.value) {\n", " if (\"feedback\" in answer) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " } else {\n", " fb.innerHTML = jaxify(\"Correct\");\n", " }\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " // } else if (answer.type==\"range\") {\n", " } else if ('range' in answer) {\n", " console.log(answer.range);\n", " console.log(submission, submission >=answer.range[0], submission < answer.range[1])\n", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.innerHTML = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " if (\"feedback\" in answer) {\n", " defaultFB = answer.feedback;\n", " } \n", " }\n", " if (done) {\n", " return false; // Break out of loop if this has been marked correct\n", " } else {\n", " return true; // Keep looking for case that includes this as a correct answer\n", " }\n", " });\n", " console.log(\"done:\", done);\n", "\n", " if ((!done) && (defaultFB != \"\")) {\n", " fb.innerHTML = jaxify(defaultFB);\n", " //console.log(\"Default feedback\", defaultFB);\n", " }\n", "\n", " fb.style.display = \"block\";\n", " if (correct) {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"correctButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"correct\");\n", " } else {\n", " ths.className = \"Input-text\";\n", " ths.classList.add(\"incorrectButton\");\n", " fb.className = \"Feedback\";\n", " fb.classList.add(\"incorrect\");\n", " }\n", "\n", " // What follows is for the saved responses stuff\n", " var outerContainer = fb.parentElement.parentElement;\n", " var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n", " if (responsesContainer) {\n", " console.log(submission);\n", " var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n", " //console.log(\"Question \" + qnum);\n", " //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n", " var responses=JSON.parse(responsesContainer.dataset.responses);\n", " console.log(responses);\n", " if (submission == ths.value){\n", " responses[qnum]= submission;\n", " } else {\n", " responses[qnum]= ths.value + \"(\" + submission +\")\";\n", " }\n", " responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n", " printResponses(responsesContainer);\n", " }\n", " // End code to preserve responses\n", "\n", " if (typeof MathJax != 'undefined') {\n", " var version = MathJax.version;\n", " console.log('MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " MathJax.typeset([fb]);\n", " }\n", " } else {\n", " console.log('MathJax not detected');\n", " }\n", " return false;\n", " }\n", "\n", "}\n", "\n", "function isValid(el, charC) {\n", " //console.log(\"Input char: \", charC);\n", " if (charC == 46) {\n", " if (el.value.indexOf('.') === -1) {\n", " return true;\n", " } else if (el.value.indexOf('/') != -1) {\n", " var parts = el.value.split('/');\n", " if (parts[1].indexOf('.') === -1) {\n", " return true;\n", " }\n", " }\n", " else {\n", " return false;\n", " }\n", " } else if (charC == 47) {\n", " if (el.value.indexOf('/') === -1) {\n", " if ((el.value != \"\") && (el.value != \".\")) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 45) {\n", " var edex = el.value.indexOf('e');\n", " if (edex == -1) {\n", " edex = el.value.indexOf('E');\n", " }\n", "\n", " if (el.value == \"\") {\n", " return true;\n", " } else if (edex == (el.value.length - 1)) { // If just after e or E\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else if (charC == 101) { // \"e\"\n", " if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n", " // Prev symbol must be digit or decimal point:\n", " if (el.value.slice(-1).search(/\\d/) >= 0) {\n", " return true;\n", " } else if (el.value.slice(-1).search(/\\./) >= 0) {\n", " return true;\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " return false;\n", " }\n", " } else {\n", " if (charC > 31 && (charC < 48 || charC > 57))\n", " return false;\n", " }\n", " return true;\n", "}\n", "\n", "function numeric_keypress(evnt) {\n", " var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n", "\n", " if (charC == 13) {\n", " check_numeric(this, evnt);\n", " } else {\n", " return isValid(this, charC);\n", " }\n", "}\n", "\n", "\n", "\n", "\n", "\n", "function make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n", "\n", "\n", "\n", " //console.log(answer);\n", "\n", "\n", " outerqDiv.className = \"NumericQn\";\n", " aDiv.style.display = 'block';\n", "\n", " var lab = document.createElement(\"label\");\n", " lab.className = \"InpLabel\";\n", " lab.innerHTML = \"Type numeric answer here:\";\n", " aDiv.append(lab);\n", "\n", " var inp = document.createElement(\"input\");\n", " inp.type = \"text\";\n", " //inp.id=\"input-\"+id;\n", " inp.id = id + \"-0\";\n", " inp.className = \"Input-text\";\n", " inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n", " if (\"precision\" in qa) {\n", " inp.setAttribute('data-precision', qa.precision);\n", " }\n", " aDiv.append(inp);\n", " //console.log(inp);\n", "\n", " //inp.addEventListener(\"keypress\", check_numeric);\n", " //inp.addEventListener(\"keypress\", numeric_keypress);\n", " /*\n", " inp.addEventListener(\"keypress\", function(event) {\n", " return numeric_keypress(this, event);\n", " }\n", " );\n", " */\n", " //inp.onkeypress=\"return numeric_keypress(this, event)\";\n", " inp.onkeypress = numeric_keypress;\n", " inp.onpaste = event => false;\n", "\n", " inp.addEventListener(\"focus\", function (event) {\n", " this.value = \"\";\n", " return false;\n", " }\n", " );\n", "\n", "\n", "}\n", "function jaxify(string) {\n", " var mystring = string;\n", "\n", " var count = 0;\n", " var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", "\n", " var count2 = 0;\n", " var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", "\n", " //console.log(loc);\n", "\n", " while ((loc >= 0) || (loc2 >= 0)) {\n", "\n", " /* Have to replace all the double $$ first with current implementation */\n", " if (loc2 >= 0) {\n", " if (count2 % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n", " }\n", " count2++;\n", " } else {\n", " if (count % 2 == 0) {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n", " } else {\n", " mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n", " }\n", " count++;\n", " }\n", " loc = mystring.search(/([^\\\\]|^)(\\$)/);\n", " loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n", " //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n", " }\n", "\n", " // repace markdown style links with actual links\n", " mystring = mystring.replace(/<(.*?)>/, '$1');\n", " mystring = mystring.replace(/\\[(.*?)\\]\\((.*?)\\)/, '$1');\n", "\n", " //console.log(mystring);\n", " return mystring;\n", "}\n", "\n", "\n", "function show_questions(json, mydiv) {\n", " console.log('show_questions');\n", " //var mydiv=document.getElementById(myid);\n", " var shuffle_questions = mydiv.dataset.shufflequestions;\n", " var num_questions = mydiv.dataset.numquestions;\n", " var shuffle_answers = mydiv.dataset.shuffleanswers;\n", " var max_width = mydiv.dataset.maxwidth;\n", "\n", " if (num_questions > json.length) {\n", " num_questions = json.length;\n", " }\n", "\n", " var questions;\n", " if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n", " //console.log(num_questions+\",\"+json.length);\n", " questions = getRandomSubarray(json, num_questions);\n", " } else {\n", " questions = json;\n", " }\n", "\n", " //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n", "\n", " // Iterate over questions\n", " questions.forEach((qa, index, array) => {\n", " //console.log(qa.question); \n", "\n", " var id = makeid(8);\n", " //console.log(id);\n", "\n", "\n", " // Create Div to contain question and answers\n", " var iDiv = document.createElement('div');\n", " //iDiv.id = 'quizWrap' + id + index;\n", " iDiv.id = 'quizWrap' + id;\n", " iDiv.className = 'Quiz';\n", " iDiv.setAttribute('data-qnum', index);\n", " iDiv.style.maxWidth =max_width+\"px\";\n", " mydiv.appendChild(iDiv);\n", " // iDiv.innerHTML=qa.question;\n", " \n", " var outerqDiv = document.createElement('div');\n", " outerqDiv.id = \"OuterquizQn\" + id + index;\n", " // Create div to contain question part\n", " var qDiv = document.createElement('div');\n", " qDiv.id = \"quizQn\" + id + index;\n", " \n", " if (qa.question) {\n", " iDiv.append(outerqDiv);\n", "\n", " //qDiv.textContent=qa.question;\n", " qDiv.innerHTML = jaxify(qa.question);\n", " outerqDiv.append(qDiv);\n", " }\n", "\n", " // Create div for code inside question\n", " var codeDiv;\n", " if (\"code\" in qa) {\n", " codeDiv = document.createElement('div');\n", " codeDiv.id = \"code\" + id + index;\n", " codeDiv.className = \"QuizCode\";\n", " var codePre = document.createElement('pre');\n", " codeDiv.append(codePre);\n", " var codeCode = document.createElement('code');\n", " codePre.append(codeCode);\n", " codeCode.innerHTML = qa.code;\n", " outerqDiv.append(codeDiv);\n", " //console.log(codeDiv);\n", " }\n", "\n", "\n", " // Create div to contain answer part\n", " var aDiv = document.createElement('div');\n", " aDiv.id = \"quizAns\" + id + index;\n", " aDiv.className = 'Answer';\n", " iDiv.append(aDiv);\n", "\n", " //console.log(qa.type);\n", "\n", " var num_correct;\n", " if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n", " num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n", " if (\"answer_cols\" in qa) {\n", " //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n", " aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n", " }\n", " } else if (qa.type == \"numeric\") {\n", " //console.log(\"numeric\");\n", " make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n", " }\n", "\n", "\n", " //Make div for feedback\n", " var fb = document.createElement(\"div\");\n", " fb.id = \"fb\" + id;\n", " //fb.style=\"font-size: 20px;text-align:center;\";\n", " fb.className = \"Feedback\";\n", " fb.setAttribute(\"data-answeredcorrect\", 0);\n", " fb.setAttribute(\"data-numcorrect\", num_correct);\n", " iDiv.append(fb);\n", "\n", "\n", " });\n", " var preserveResponses = mydiv.dataset.preserveresponses;\n", " console.log(preserveResponses);\n", " console.log(preserveResponses == \"true\");\n", " if (preserveResponses == \"true\") {\n", " console.log(preserveResponses);\n", " // Create Div to contain record of answers\n", " var iDiv = document.createElement('div');\n", " iDiv.id = 'responses' + mydiv.id;\n", " iDiv.className = 'JCResponses';\n", " // Create a place to store responses as an empty array\n", " iDiv.setAttribute('data-responses', '[]');\n", "\n", " // Dummy Text\n", " iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n", " //iDiv.className = 'Quiz';\n", " mydiv.appendChild(iDiv);\n", " }\n", "//console.log(\"At end of show_questions\");\n", " if (typeof MathJax != 'undefined') {\n", " console.log(\"MathJax version\", MathJax.version);\n", " var version = MathJax.version;\n", " setTimeout(function(){\n", " var version = MathJax.version;\n", " console.log('After sleep, MathJax version', version);\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " }\n", " }, 500);\n", "if (typeof version == 'undefined') {\n", " } else\n", " {\n", " if (version[0] == \"2\") {\n", " MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n", " } else if (version[0] == \"3\") {\n", " if (MathJax.hasOwnProperty('typeset') ) {\n", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log('WARNING: Trying to force load MathJax 3');\n", " window.MathJax = {\n", " tex: {\n", " inlineMath: [['$', '$'], ['\\\\(', '\\\\)']]\n", " },\n", " svg: {\n", " fontCache: 'global'\n", " }\n", " };\n", "\n", " (function () {\n", " var script = document.createElement('script');\n", " script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';\n", " script.async = true;\n", " document.head.appendChild(script);\n", " })();\n", " }\n", " } else {\n", " console.log(\"MathJax not found\");\n", " }\n", " }\n", " }\n", "\n", " // stop event propagation for the .Link class\n", " var links = document.getElementsByClassName('Link')\n", " for (var i = 0; i < links.length; i++) {\n", " links[i].addEventListener('click', function(e){\n", " e.stopPropagation();\n", " });\n", " }\n", "\n", " return false;\n", "}\n", "/* This is to handle asynchrony issues in loading Jupyter notebooks\n", " where the quiz has been previously run. The Javascript was generally\n", " being run before the div was added to the DOM. I tried to do this\n", " more elegantly using Mutation Observer, but I didn't get it to work.\n", "\n", " Someone more knowledgeable could make this better ;-) */\n", "\n", " function try_show() {\n", " if(document.getElementById(\"mkkPRNBzTPle\")) {\n", " show_questions(questionsmkkPRNBzTPle, mkkPRNBzTPle); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"mkkPRNBzTPle\");\n", " // console.log(document.getElementById(\"mkkPRNBzTPle\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "from quadriga_config import colors\n", "\n", "multiple_choice_6 = [{\n", " \"question\": \"\"\"Welche Reihenfolge der Verarbeitungsschritte ist korrekt für die Textannotation mit spaCy?\"\"\",\n", " \"type\": \"multiple_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"3 → 2 → 4 → 5 → 1\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Reihenfolge ist nicht korrekt. Laut Notebook wird zuerst der Text eingelesen (Schritt 1), bevor weitere Verarbeitungsschritte folgen.\"\"\"\n", " },\n", " {\n", " \"answer\": \"3 → 4 → 2 → 5 → 1\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Diese Reihenfolge stimmt nicht mit dem Ablauf im Notebook überein, in dem zuerst der Text eingelesen wird.\"\"\"\n", " },\n", " {\n", " \"answer\": \"4 → 3 → 2 → 5 → 1\",\n", " \"correct\": True,\n", " \"feedback\": \"\"\"✓ Richtig! Die Reihenfolge im Notebook ist: 1. Einlesen des Texts, 2. Laden des Sprachmodells, 3. Auswahl der Analysekomponenten, 4. Durchführung der Annotation, 5. Speichern der Ergebnisse.\"\"\"\n", " },\n", " {\n", " \"answer\": \"4 → 5 → 3 → 2 → 1\",\n", " \"correct\": False,\n", " \"feedback\": \"\"\"× Nicht korrekt. Das Sprachmodell muss vor der Annotation geladen werden, wie im Notebook gezeigt.\"\"\"\n", " }\n", " ]\n", "}]\n", "\n", "display_quiz(multiple_choice_6, colors=colors.jupyterquiz)" ] } ], "metadata": { "jupytext": { "formats": "md:myst", "text_representation": { "extension": ".md", "format_name": "myst" } }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.11" }, "source_map": [ 11, 35, 78, 82, 118, 122, 158, 162, 198, 202, 238, 250, 257, 287, 334, 339, 380, 384, 420, 424, 460, 464, 500, 511 ] }, "nbformat": 4, "nbformat_minor": 5 }