{ "cells": [ { "cell_type": "markdown", "id": "98df2f68-985d-40ee-9461-320ad369ec32", "metadata": {}, "source": [ "# Software Development Best Practice Quiz\n", "The following questions are aimed at testing your understanding of the content that is covered within this course. There is no defined threshold where we believe you should attend the course if you score below. Rather it is aimed to make you engage with the content and reflect for yourself if you feel you would benefit from attending the course. Of note, is that the quiz is intended for you to use google throuhgout and engage with documentation. Even if you get all of the questions right, you are ofcourse more than welcome to still attend the course and use it as a refresher!" ] }, { "cell_type": "code", "execution_count": 1, "id": "0ea5cc26-ea70-4085-b9ed-94b948d9c81b", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "var questionsszttPyKCFZzH=[\n", " {\n", " \"question\": \"What is the primary purpose of the Requirements Gathering phase in the Software Development Life Cycle (SDLC)?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"To design the software components and their interactions\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To test the software for bugs and issues\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To deploy the software to end-users\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To identify and document the exact requirements of the software\",\n", " \"correct\": true,\n", " \"feedback\": \"correct.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"Which statement best describes the Agile methodology?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Agile follows a strict sequential process without deviation\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Agile prioritizes comprehensive documentation over working software.\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Agile emphasizes individuals and interactions over processes and tools.\",\n", " \"correct\": true,\n", " \"feedback\": \"correct.\"\n", " },\n", " {\n", " \"answer\": \"Agile development is a rigid and inflexible methodology.\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"Which Agile tool or technique can be adapted for use by solo workers to maintain focus and assess daily progress?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Sprint planning meetings\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Show and tell\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Daily standup\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"Retrospective Meetings\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What is the purpose of the Data Management Plan (DMP)?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"To document the financial details of a research project\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To outline how data will be acquired, managed, preserved, and shared\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"To provide a biography of th eresearch team members\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To list the publication dates for research findings\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"Which principle is NOT pir of the FAIR guiding principles?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Findability\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Accessibility\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Interoperability\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Confidentiality\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What is a recommended practice for backing up research data?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Store all copies in the same location for convenience\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Use the 3-2-1 principles: 3 copies on 2 different mediums with 1 offsite\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"Backup data only at the end of the project\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Use only online cloud service for all backups\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What is the primary purpose of decomposing a large problem into smaller tasks in software development?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"To increase the complexiy of the problem\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To make each component depend heavily on others\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To makethe problem more manageable and reduce complexity\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"To require mor time in planning and execution\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What is the primary purpose of using a virtual environment in Python development?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"To increase the speed of Python applications\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To ensure that Python scripts are compatible with all operating systems\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To isolate and manage project-specific dependencies\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"To automatically update Python to the latest version\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What is the primary purpose of ensuring code is well structured?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"To increase the complexity of the code\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To make the code execute faster\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To improve clarity and reduce dependencies among components\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"To make the code longer and more detailed\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"Which type of documentation provides high level views of the software design and architecture?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"User Guides\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Tutorials\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Conceptual Documentation\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"Reference Documentation\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What is a key benefit of using consistent naming conventions in code?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"They allow for more variables and functions in the code\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"They make the code run more efficiently\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"They increase the need for detailed comments\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"They reduce the cognitive load on the reader, making the code easier to understand\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What is the primary benefit of unit testing individual components of software?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"It ensures that all software components can interface with external systems\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"It verifies that each component works as intended in isolation\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"It tests the software response time and performance under stress\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"It allows developers to change the user interface without additional coding\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"Which type of testing is particularly important when code is developed collaboratively?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"User acceptance testing\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Stress testing\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Integration testing\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"Performance testing\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What is the primary benefit of using agile principles in a long term, highly collaborative research project?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"To limit communication between organisations\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To ensure that the project follows a strict, unchanging plan\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"To maintain flexibility and efficiently respond to changes\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"To reduce the overall cost of the project\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"Which of the following is NOT a benefit of investing in reproducibility?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Enhanced credibility of research through verification of results\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Increased rate of research progression\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Reducded need for peer review\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Immediate financial return on research investments\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " }\n", " ]\n", " },\n", " {\n", " \"question\": \"What tools and practices are suggested to enhance the reproducibility of research?\",\n", " \"type\": \"many_choice\",\n", " \"answers\": [\n", " {\n", " \"answer\": \"Keeping all data and methods confidential\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Using open source software and version control systems\",\n", " \"correct\": true,\n", " \"feedback\": \"Correct.\"\n", " },\n", " {\n", " \"answer\": \"Avoiding peer reviews to speed up publication\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " },\n", " {\n", " \"answer\": \"Only sharing results without underlying data and methods\",\n", " \"correct\": false,\n", " \"feedback\": \"Incorrect.\"\n", " }\n", " ]\n", " }\n", "];\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", "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", "\n", " //console.log(answers);\n", "\n", "\n", " // Split behavior based on multiple choice vs many choice:\n", " var fb = document.getElementById(\"fb\" + id);\n", "\n", "\n", "\n", "\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.textContent = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.textContent = \"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.textContent = jaxify(label.dataset.feedback);\n", " } else {\n", " fb.textContent = \"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 {\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.textContent = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n", " } else {\n", " fb.textContent = 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", "function make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\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", "\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", " // console.log(\"1:\", submission)\n", " submission = Math.round((1 * submission + Number.EPSILON) * 10 ** precision) / 10 ** precision;\n", " // console.log(\"Rounded to \", submission, \" precision=\", 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.textContent = \"Incorrect -- try again.\";\n", "\n", " var answers = JSON.parse(ths.dataset.answers);\n", " //console.log(answers);\n", "\n", " var defaultFB = \"\";\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.textContent = jaxify(answer.feedback);\n", " } else {\n", " fb.textContent = 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", " if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n", " fb.textContent = jaxify(answer.feedback);\n", " correct = answer.correct;\n", " //console.log(answer.correct);\n", " done = true;\n", " }\n", " } else if (answer.type == \"default\") {\n", " defaultFB = answer.feedback;\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", "\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.textContent = \"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", " //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", " MathJax.typeset([mydiv]);\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", " MathJax.typeset([mydiv]);\n", " } else {\n", " console.log(\"MathJax not found\");\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(\"szttPyKCFZzH\")) {\n", " show_questions(questionsszttPyKCFZzH, szttPyKCFZzH); \n", " } else {\n", " setTimeout(try_show, 200);\n", " }\n", " };\n", " \n", " {\n", " // console.log(element);\n", "\n", " //console.log(\"szttPyKCFZzH\");\n", " // console.log(document.getElementById(\"szttPyKCFZzH\"));\n", "\n", " try_show();\n", " }\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyterquiz import display_quiz\n", "display_quiz(\"quizes/software_development_best_practice.json\")" ] }, { "cell_type": "code", "execution_count": null, "id": "8438b313-a54e-4b2b-b92a-487718e1a479", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.12.2" } }, "nbformat": 4, "nbformat_minor": 5 }