Skip to content

Commit 8a77b97

Browse files
khdebruijnKevinfloriscalkoen
authored
Kevin/numeric questions (#110)
* adjusted numeric question_type to work with significant figures * i dont understand anything anymore * finalized numeric_quesiton type * update version number * hope test does not fail anymore stylistic stuff * hook * rm output --------- Co-authored-by: Kevin <[email protected]> Co-authored-by: floriscalkoen <[email protected]>
1 parent 926cc5c commit 8a77b97

File tree

9 files changed

+59
-23
lines changed

9 files changed

+59
-23
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,6 @@ dist*
146146

147147
# don't add ruff cache
148148
*.ruff_cache*
149+
150+
# don't add questions to public github
151+
questions/*.json

notebooks/6_cross_shore_transport.ipynb

+1-1
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@
482482
{
483483
"cell_type": "code",
484484
"execution_count": null,
485-
"id": "727482ed-a483-426c-b08a-2ed418650823",
485+
"id": "843e7e78-4c57-4741-8db3-6dddc232670f",
486486
"metadata": {},
487487
"outputs": [],
488488
"source": [

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "coastal-dynamics"
3-
version = "0.0.6"
3+
version = "0.0.7"
44
description = "Jupyterbook for Delft Technical University Coastal Systems"
55
authors = ["Floris Calkoen"]
66
license = "MIT"

scripts/python/hash_questions.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
def process_questions(questions):
1313
"""Process and hash answers within the questions dictionary based on question type."""
1414
for _, q_data in questions.items():
15-
q_data["answer"] = cd.hash_answer(q_data.get("answer"), q_data.get("type"))
15+
print(1)
16+
q_data["answer"] = cd.hash_answer(
17+
q_data.get("answer"), q_data.get("type"), sig_figs=q_data.get("sig_figs")
18+
)
19+
print(2)
1620
return questions
1721

1822

src/coastal_dynamics/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
__author__ = """Floris Calkoen"""
44
__email__ = "[email protected]"
5-
__version__ = "0.0.6"
5+
__version__ = "0.0.7"
66

77
from .factory import QuestionFactory
88
from .io import read_questions, write_questions

src/coastal_dynamics/factory.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ def _create_numeric_question(self):
7373
question_text=self.question_data["question"],
7474
question_answer=self.question_data["answer"],
7575
question_feedback=self.question_data["feedback"],
76-
precision=self.question_data.get(
77-
"precision", 0
76+
sig_figs=self.question_data.get(
77+
"sig_figs", 0
7878
), # Handle precision as optional
7979
)
8080

src/coastal_dynamics/numeric.py

+34-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import Literal
22

3+
import numpy as np
34
import panel as pn
45

56
import coastal_dynamics as cd
@@ -11,24 +12,24 @@ class NumericQuestion(Question):
1112
A class to create and manage a numeric answer question widget.
1213
1314
This class creates a numeric question using Panel widgets.
14-
It supports a question text, numeric answer, and precision for the answer.
15+
It supports a question text, numeric answer, and sig_figs for the answer.
1516
1617
Attributes:
1718
correct_answer (float): The correct numeric answer.
18-
precision (int): The precision of the numeric answer.
19+
sig_figs (int): The number of significant figures of the numeric answer.
1920
answer_input (pn.widgets.FloatInput): The widget for inputting the answer.
2021
"""
2122

2223
def __init__(
2324
self,
2425
question_name: str,
2526
question_text: str,
26-
question_answer: float,
27+
question_answer: str,
2728
question_feedback: dict[Literal["correct", "incorrect"], str],
28-
precision: int | None = None,
29+
sig_figs: int | None = None,
2930
):
3031
self.correct_answer = question_answer
31-
self.precision = precision
32+
self.sig_figs = sig_figs
3233
self.answer_input: pn.widgets.FloatInput
3334

3435
super().__init__(question_name, question_text, question_feedback)
@@ -43,12 +44,26 @@ def check_answer(self, event) -> None:
4344
"""Check the submitted answer against the correct answer."""
4445
try:
4546
user_answer = float(self.answer_input.value)
46-
if self.precision:
47-
user_answer = round(user_answer, self.precision)
48-
if self.hash_answer(user_answer, "numeric") == self.correct_answer:
47+
48+
if self.sig_figs:
49+
user_answer = np.format_float_positional(
50+
user_answer,
51+
precision=self.sig_figs,
52+
unique=False,
53+
fractional=False,
54+
trim="k",
55+
)
56+
57+
hashed_user_answer = self.hash_answer(
58+
user_answer, "numeric", sig_figs=self.sig_figs
59+
)
60+
61+
if hashed_user_answer == self.correct_answer:
4962
self.feedback_widget.value = self.feedback["correct"]
63+
5064
else:
5165
self.feedback_widget.value = self.feedback["incorrect"]
66+
5267
except ValueError:
5368
self.feedback_widget.value = "Please enter a valid number."
5469

@@ -65,21 +80,28 @@ def serve(self) -> pn.Column:
6580
if __name__ == "__main__":
6681
question_data = {
6782
"question": "What is the relative importance of S2 vs M2?",
68-
"answer": 0.33,
69-
"precision": 2,
83+
"answer": 35,
84+
"sig_figs": 2,
7085
}
7186

7287
nq = NumericQuestion(
7388
question_name="Q3: Simple numeric question",
7489
question_text=question_data["question"],
7590
question_answer=cd.hash_answer(
76-
round(float(question_data["answer"]), question_data["precision"]), "numeric"
91+
np.format_float_positional(
92+
float(question_data["answer"]),
93+
precision=question_data["sig_figs"],
94+
unique=False,
95+
fractional=False,
96+
trim="k",
97+
),
98+
"numeric",
7799
),
78100
question_feedback={
79101
"correct": "Correct!...",
80102
"incorrect": "Incorrect, try again. Please consider that...",
81103
},
82-
precision=question_data["precision"],
104+
sig_figs=question_data["sig_figs"],
83105
)
84106
nq.serve().show()
85107
print("done")

src/coastal_dynamics/question.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,6 @@ def check_answer(self, event) -> None:
4646
msg = "This method should be implemented by subclasses"
4747
raise NotImplementedError(msg)
4848

49-
def hash_answer(self, answer, question_type):
49+
def hash_answer(self, answer, question_type, sig_figs=None):
5050
"""Delegate the hashing of an answer to the coastal_dynamics module."""
51-
return cd.hash_answer(answer, question_type)
51+
return cd.hash_answer(answer, question_type, sig_figs=sig_figs)

src/coastal_dynamics/utils.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import hashlib
2+
import numpy as np
23

34

4-
def hash_answer(answer, question_type, precision=None):
5+
def hash_answer(answer, question_type, sig_figs=None):
56
"""Hash a single answer or a list of answers based on the question type."""
67
if question_type == "multiple_selection":
78
# For multiple_selection, directly hash each answer in the list
@@ -13,8 +14,14 @@ def hash_answer(answer, question_type, precision=None):
1314
# For multiple_choice and numeric, directly hash the answer
1415
return hashlib.sha256(str(answer).encode()).hexdigest()
1516
elif question_type == "numeric":
16-
if precision:
17-
answer = round(float(answer), precision)
17+
if sig_figs:
18+
answer = np.format_float_positional(
19+
float(answer),
20+
precision=sig_figs,
21+
unique=False,
22+
fractional=False,
23+
trim="k",
24+
)
1825
return hashlib.sha256(str(answer).encode()).hexdigest()
1926
else:
2027
msg = f"Unsupported question type: {question_type}"

0 commit comments

Comments
 (0)