from typing import Optional
import numpy as np # Import numpy for rounding
import typer
from rich import print
from ..config.data import (
CONVERSION_DATA,
HELP_INSTRUCTION,
UNIT_CONVERSION_INSTRUCTIONS,
UNITS,
)
from ..config.enums import Answer
from ..utils.common import convert_units, is_valid_numeric_string
[docs]
def check_unit_existence(
dictionary: dict[str, list[str]], unit_to_check: str
) -> Optional[str]:
"""
Check if a unit exists in a dictionary.
Args:
dictionary (dict): The dictionary to check.
unit_to_check (str): The unit to check.
Returns:
str: The category of the unit (e.g., 'temperature' or 'volume').
None: If the unit does not exist.
"""
for key, units in dictionary.items():
if unit_to_check in units:
return key
return None
[docs]
def grade_response(
input_value: str, from_unit: str, to_unit: str, student_response: str
) -> Answer:
"""
Grade a student's response to a conversion question.
The student's response is correct if it matches the correct answer after both values are rounded to the tenths place. The rounding strategy follows round half to even (Banker's rounding).
For example round(4.65, 1) == 4.6 and round(4.75, 1) == 4.8.
Args:
input_value (str): The input value provided in the question.
from_unit (str): The unit mentioned in the question.
to_unit (str): The target unit mentioned in the question.
student_response (str): The student's response.
Returns:
Answer: The result of the grading.
Possible values are: Answer.CORRECT, Answer.INCORRECT, Answer.INVALID
"""
# unit name validation
category: Optional[str] = validate_input(from_unit, to_unit, input_value)
if category is None: # invalid input
return Answer.INVALID
if not is_valid_numeric_string(student_response):
typer.echo(f"\n{student_response} is not a valid numeric string.")
return Answer.INCORRECT
if from_unit == to_unit:
correct_answer: float = np.round(float(input_value), 1)
student_response: float = np.round(float(student_response), 1)
if correct_answer == student_response:
return Answer.CORRECT
else:
typer.echo(
f"\n{student_response} is not the correct answer. The correct answer is {correct_answer}."
)
return Answer.INCORRECT
student_response: float = np.round(float(student_response), 1)
input_numeric_value: float = float(input_value)
convert_value: Optional(float) = convert_units(
input_numeric_value, from_unit, to_unit, category, CONVERSION_DATA
)
if convert_value is None:
return Answer.INVALID
elif convert_value == student_response:
return Answer.CORRECT
else:
typer.echo(
f"\n{student_response} is not the correct answer. The correct answer is {convert_value}."
)
return Answer.INCORRECT