Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,22 @@ def test_text_input_derivation():
assert answers == [{"answer": "42", "correct": True, "order": 0}]


@pytest.mark.parametrize(
"value,expected",
[
("+5", "5"),
("1E3", "1e3"),
(" +5 ", "5"),
("+0", "0"),
],
)
def test_text_input_normalises_xsd_double_answers(value, expected):
result = derive_perseus_item(_Item(_text_item("single", [value])))
assert json.loads(result.answers) == [
{"answer": expected, "correct": True, "order": 0}
]


def test_text_input_multiple_correct_values():
item = _Item(_text_item("multiple", ["1", "2"]))
result = derive_perseus_item(item)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2996,3 +2996,20 @@ def test_native_qti_perseus_derivation_resizes_sized_images(self):
),
[(100, 75), (200, 150)],
)

def test_native_qti_perseus_derivation_signed_numeric_answer(self):
raw_data = _text_item("single", ["+5"])
item = self._create_native_qti_item(raw_data)

self._create_perseus_zip(self._exercise_data([item]))

exercise_file = self.exercise_node.files.get(preset_id=format_presets.EXERCISE)
with storage.open(exercise_file.file_on_disk.name, "rb") as f:
zip_file = zipfile.ZipFile(BytesIO(f.read()))
qti_id = parse_qti_xml(raw_data.encode("utf-8")).getroot().get("identifier")
item_json = json.loads(zip_file.read(f"{qti_id}.json").decode("utf-8"))

answers = item_json["question"]["widgets"]["numeric-input 1"]["options"][
"answers"
]
self.assertEqual([answer["value"] for answer in answers], [5])
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from contentcuration.utils.assessment.qti.constants import BaseType
from contentcuration.utils.assessment.qti.html_to_markdown import html_to_markdown
from contentcuration.utils.assessment.qti.validation import parse_qti_xml
from contentcuration.utils.parser import extract_value

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -194,10 +195,17 @@ def _derive_choice(interaction, item_body, declaration):
return item_type, question, answers


def _perseus_number(value):
"""A leading "+" and capital "E" are valid xsd:double but not for
``extract_value``."""
normalised = value.strip().removeprefix("+").lower()
return normalised if extract_value(normalised) is not None else value


def _derive_text(interaction, item_body, declaration):
question = html_to_markdown([item_body])
answers = [
{"answer": value, "correct": True, "order": order}
{"answer": _perseus_number(value), "correct": True, "order": order}
for order, value in enumerate(_accepted_values(declaration))
]
return exercises.INPUT_QUESTION, question, answers
Expand Down
Loading