Skip to content

Commit

Permalink
docs: add a multichoice example package
Browse files Browse the repository at this point in the history
  • Loading branch information
MHajoha committed Dec 19, 2024
1 parent 61d0b32 commit 667b558
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 0 deletions.
2 changes: 2 additions & 0 deletions examples/multichoice/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__
/dist
8 changes: 8 additions & 0 deletions examples/multichoice/python/local/multichoice/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This file is part of the QuestionPy SDK. (https://questionpy.org)
# The QuestionPy SDK is free software released under terms of the MIT license. See LICENSE.md.
# (c) Technische Universität Berlin, innoCampus <[email protected]>
from questionpy import make_question_type_init

from .question_type import MultichoiceQuestion

init = make_question_type_init(MultichoiceQuestion)
18 changes: 18 additions & 0 deletions examples/multichoice/python/local/multichoice/form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from questionpy.form import FormModel, OptionEnum, checkbox, generated_id, option, repeat, select, text_input


class ChoiceMode(OptionEnum):
SELECT = option("<select> element")
RADIO = option('<input type="radio"> element')


class Choice(FormModel):
id: str = generated_id()
text: str = text_input("Text", required=True)
correct: bool = checkbox("Korrekt")


class MultichoiceFormModel(FormModel):
description: str = text_input("Beschreibung", required=True)
mode: ChoiceMode = select("Auswahlelement", ChoiceMode, required=True)
choices: list[Choice] = repeat(Choice, initial=3, minimum=2)
35 changes: 35 additions & 0 deletions examples/multichoice/python/local/multichoice/question_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from typing import Any

from questionpy import Attempt, Question, ResponseNotScorableError

from .form import ChoiceMode, MultichoiceFormModel


class MultichoiceAttempt(Attempt):
def _compute_score(self) -> float:
if not self.response or "choice" not in self.response:
msg = "'choice' is missing"
raise ResponseNotScorableError(msg)

chosen_id = self.response["choice"]
correct_choice_ids = [choice.id for choice in self.question.options.choices if choice.correct]

if chosen_id in correct_choice_ids:
return 1

return 0

def __init__(self, *args: Any):
super().__init__(*args)

self.placeholders["description"] = self.question.options.description

@property
def formulation(self) -> str:
return self.jinja2.get_template("local.multichoice/formulation.xhtml.j2").render(ChoiceMode=ChoiceMode)


class MultichoiceQuestion(Question):
attempt_class = MultichoiceAttempt

options: MultichoiceFormModel
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div xmlns="http://www.w3.org/1999/xhtml"
xmlns:qpy="http://questionpy.org/ns/question">
<p><?p description?></p>
<p>
{% if question.options.mode == ChoiceMode.SELECT %}
<label>
Auswahl:

<select name="choice" qpy:shuffle-contents="">
{% for choice in question.options.choices %}
<option value="{{ choice.id }}">{{ choice.text }}</option>
{% endfor %}
</select>
</label>
{% else %}
<fieldset style="display: flex; flex-direction: column" qpy:shuffle-contents="">
{% for choice in question.options.choices %}
<label><input type="radio" name="choice" value="{{ choice.id }}"/> {{ choice.text }}</label>
{% endfor %}
</fieldset>
{% endif %}
</p>
</div>
9 changes: 9 additions & 0 deletions examples/multichoice/qpy_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
short_name: multichoice
namespace: local
version: 0.1.0
api_version: "0.1"
author: Jane Doe <[email protected]>
name:
de: Multiple-Choice
en: Multiple-Choice
languages: [de, en]

0 comments on commit 667b558

Please sign in to comment.