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
2 changes: 2 additions & 0 deletions app/docs/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This function is used to compare two number arrays/vectors/matrices, provided absolute and/or relative tolerance parameters `rtol` and `atol`. This is carried out using the [numpy.allclose](https://numpy.org/doc/stable/reference/generated/numpy.allclose.html) function.

If the answer is not an array of numbers an exception is raised. If the response is not an array of numbers, a feedback message that informs the user that only numbers are accepte will be generated.

### Optional parameters

There is one optional parameter: `feedback_for_incorrect_response`.
Expand Down
44 changes: 28 additions & 16 deletions app/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,41 @@ def evaluation_function(response, answer, params) -> dict:
to output the grading response.
"""

answer_ok = process_element(answer)
if not answer_ok:
try:
process_element(answer)
except ValueError:
raise Exception("Answer has at least one field that is not a number.")
except Exception:
raise Exception("Answer has empty fields.")
response_ok = process_element(response)
if not response_ok:
return {"is_correct": False}

feedback = ""
try:
process_element(response)
except ValueError:
feedback = "Only numbers are permitted."
except Exception:
feedback = "Response has at least one empty field."

if len(feedback) > 0:
return {
"is_correct": False,
"feedback": "Response has empty fields."
"feedback": feedback,
}

try:
res = np.array(response, dtype=np.float32)
except Exception as e:
ans = np.array(answer, dtype=np.float32)
except ValueError as e:
raise EvaluationException(
f"Failed to parse user response",
f"Failed to parse correct answer",
detail=repr(e)
)

try:
ans = np.array(answer, dtype=np.float32)
except Exception as e:
res = np.array(response, dtype=np.float32)
except ValueError as e:
raise EvaluationException(
f"Failed to parse correct answer",
f"Failed to parse response",
detail=repr(e)
)

Expand All @@ -65,14 +77,14 @@ def evaluation_function(response, answer, params) -> dict:

def process_element(element):
is_ok = True
if isinstance(element,list):
if isinstance(element, list):
for e in element:
is_ok = process_element(e)
process_element(e)
else:
if isinstance(element,str):
if isinstance(element, str):
element = element.strip()
if len(element) == 0 or "element" == "undefined":
is_ok = False
raise Exception("Contains an empty element")
else:
element = float(element)
return is_ok
return
22 changes: 21 additions & 1 deletion app/evaluation_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_2D_empty_string_in_response(self):
response = evaluation_function(response, answer, {})

self.assertEqual(response["is_correct"], False)
self.assertEqual(response["feedback"], "Response has empty fields.")
self.assertEqual(response["feedback"], "Response has at least one empty field.")

def test_no_tolerance_correct(self):
response = [1, 2]
Expand Down Expand Up @@ -132,6 +132,26 @@ def test_2D_incorrect_with_custom_feedback(self):
#
# self.assertEqual(response.get("is_correct"), True)

def test_answer_not_array_of_numbers(self):
response = [[1, 1], [1, 1]]
answer = [[1, 1], [1, "a"]]

self.assertRaises(
Exception,
evaluation_function,
response,
answer,
{},
)

def test_response_not_array_of_numbers(self):
response = [[1, 1], [1, "a"]]
answer = [[1, 1], [1, 0]]

response = evaluation_function(response, answer, {})

self.assertEqual(response.get("is_correct"), False)
self.assertEqual(response["feedback"], "Only numbers are permitted.")

if __name__ == "__main__":
unittest.main()