Skip to content

Grading

Utilities for grading in PrairieLearn.

from prairielearn import ...

check_answers_names

check_answers_names(data: QuestionData, name: str) -> None

Check that answers names are distinct using property in data dict.

Updates the data dictionary with the name if it is not already present.

Raises:

Type Description
KeyError

If the name is already present in the data dictionary.

determine_score_params

determine_score_params(
    score: float,
) -> tuple[
    Literal["correct", "partial", "incorrect"], bool | float
]

Determine appropriate key and value for display on the frontend given the score for a particular question. For elements following PrairieLearn conventions, the return value can be used as a key/value pair in the dictionary passed to an element's Mustache template to display a score badge.

Returns:

Type Description
tuple[Literal['correct', 'partial', 'incorrect'], bool | float]

A tuple containing the key and value for the score badge.

Examples:

>>> determine_score_params(1)
("correct", True)
>>> determine_score_params(0)
("incorrect", True)
>>> determine_score_params(0.5)
("partial", 50)

grade_answer_parameterized

grade_answer_parameterized(
    data: QuestionData,
    name: str,
    grade_function: Callable[
        [Any], tuple[bool | float, str | None]
    ],
    weight: int = 1,
) -> None

Grade the answer for the input name using the provided grade_function.

Updates the data dictionary with the partial score and feedback for the question.

grade_function should take in a single parameter (which will be the submitted answer) and return a 2-tuple.

The first element of the 2-tuple should either be:

  • a boolean indicating whether the question should be marked correct
  • a partial score between 0 and 1, inclusive

The second element of the 2-tuple should either be:

  • a string containing feedback
  • None, if there is no feedback (usually this should only occur if the answer is correct)

Examples:

>>> def grading_function(submitted_answer):
...     if submitted_answer == "foo":
...         return True, None
...     elif submitted_answer == "bar":
...         return 0.5, "Almost there!"
...     return False, "Try again!"
>>> data = {
...     "submitted_answers": {"my_string_input": "bar"},
...     "partial_scores": {},
...     "answers_names": {},
... }
>>> grade_answer_parameterized(data, "my_string_input", grading_function, weight=2)
>>> data["partial_scores"]
{"my_string_input": {"score": 0.5, "weight": 2, "feedback": "Almost there!"}}

is_correct_ndarray2d_dd

is_correct_ndarray2d_dd(
    a_sub: NDArray[Any],
    a_tru: NDArray[Any],
    digits: int = 2,
) -> bool

Check if a submitted 2D numpy array is correct within a certain number of decimal digits after the decimal place.

Returns:

Type Description
bool

True if they are equal, False otherwise.

is_correct_ndarray2d_ra

is_correct_ndarray2d_ra(
    a_sub: NDArray[Any],
    a_tru: NDArray[Any],
    rtol: float = 1e-05,
    atol: float = 1e-08,
) -> bool

Check if a submitted 2D numpy array is correct within a relative and absolute tolerance.

Returns:

Type Description
bool

True if they are equal, False otherwise.

is_correct_ndarray2d_sf

is_correct_ndarray2d_sf(
    a_sub: NDArray[Any],
    a_tru: NDArray[Any],
    digits: int = 2,
) -> bool

Check if a submitted 2D numpy array is correct within a certain number of significant figures.

Returns:

Type Description
bool

True if they are equal, False otherwise.

is_correct_scalar_dd

is_correct_scalar_dd(
    a_sub: ArrayLike, a_tru: ArrayLike, digits: int = 2
) -> bool

Compare a_sub and a_tru using digits many digits after the decimal place.

Returns:

Type Description
bool

True if they are equal, False otherwise.

is_correct_scalar_ra

is_correct_scalar_ra(
    a_sub: ArrayLike,
    a_tru: ArrayLike,
    rtol: float = 1e-05,
    atol: float = 1e-08,
) -> bool

Compare a_sub and a_tru using relative tolerance rtol and absolute tolerance atol.

Returns:

Type Description
bool

True if they are equal, False otherwise.

is_correct_scalar_sf

is_correct_scalar_sf(
    a_sub: ArrayLike, a_tru: ArrayLike, digits: int = 2
) -> bool

Compare a_sub and a_tru using digits many significant figures.

Returns:

Type Description
bool

True if they are equal, False otherwise.