mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 05:58:34 +01:00
MDL-68597 qtype_essay: show the word count on the review screen
This commit is contained in:
parent
6fc462ad4d
commit
c4e2b67c22
@ -69,3 +69,6 @@ $string['responseisrequired'] = 'Require the student to enter text';
|
||||
$string['responsetemplate'] = 'Response template';
|
||||
$string['responsetemplateheader'] = 'Response Template';
|
||||
$string['responsetemplate_help'] = 'Any text entered here will be displayed in the response input box when a new attempt at the question starts.';
|
||||
$string['wordcount'] = 'Word count: {$a}';
|
||||
$string['wordcounttoofew'] = 'Word count: {$a->count}, less than the required {$a->limit} words.';
|
||||
$string['wordcounttoomuch'] = 'Word count: {$a->count}, more than the limit of {$a->limit} words.';
|
||||
|
@ -252,19 +252,52 @@ class qtype_essay_question extends question_with_responses {
|
||||
if (!$this->responserequired) {
|
||||
return null;
|
||||
}
|
||||
if ((isset($this->minwordlimit) && $this->minwordlimit > 0) ||
|
||||
(isset($this->maxwordlimit) && $this->maxwordlimit > 0)) {
|
||||
// Count the number of words in the response string.
|
||||
$responsewords = count_words($responsestring);
|
||||
if (isset($this->minwordlimit) && $this->minwordlimit > $responsewords) {
|
||||
return get_string('minwordlimitboundary', 'qtype_essay',
|
||||
['limit' => $this->minwordlimit, 'count' => $responsewords]);
|
||||
}
|
||||
if (isset($this->maxwordlimit) && $this->maxwordlimit < $responsewords) {
|
||||
return get_string('maxwordlimitboundary', 'qtype_essay',
|
||||
['limit' => $this->maxwordlimit, 'count' => $responsewords]);
|
||||
}
|
||||
if (!$this->minwordlimit && !$this->maxwordlimit) {
|
||||
// This question does not care about the word count.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Count the number of words in the response string.
|
||||
$count = count_words($responsestring);
|
||||
if ($this->maxwordlimit && $count > $this->maxwordlimit) {
|
||||
return get_string('maxwordlimitboundary', 'qtype_essay',
|
||||
['limit' => $this->maxwordlimit, 'count' => $count]);
|
||||
} else if ($count < $this->minwordlimit) {
|
||||
return get_string('minwordlimitboundary', 'qtype_essay',
|
||||
['limit' => $this->minwordlimit, 'count' => $count]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this question uses word counts, then return a display of the current
|
||||
* count, and whether it is within limit, for when the question is being reviewed.
|
||||
*
|
||||
* @param array $response responses, as returned by
|
||||
* {@see question_attempt_step::get_qt_data()}.
|
||||
* @return string If relevant to this question, a display of the word count.
|
||||
*/
|
||||
public function get_word_count_message_for_review(array $response): string {
|
||||
if (!$this->minwordlimit && !$this->maxwordlimit) {
|
||||
// This question does not care about the word count.
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!array_key_exists('answer', $response) || ($response['answer'] === '')) {
|
||||
// No response.
|
||||
return '';
|
||||
}
|
||||
|
||||
$count = count_words($response['answer']);
|
||||
if ($this->maxwordlimit && $count > $this->maxwordlimit) {
|
||||
return get_string('wordcounttoomuch', 'qtype_essay',
|
||||
['limit' => $this->maxwordlimit, 'count' => $count]);
|
||||
} else if ($count < $this->minwordlimit) {
|
||||
return get_string('wordcounttoofew', 'qtype_essay',
|
||||
['limit' => $this->minwordlimit, 'count' => $count]);
|
||||
} else {
|
||||
return get_string('wordcount', 'qtype_essay', $count);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,8 @@ class qtype_essay_renderer extends qtype_renderer {
|
||||
} else {
|
||||
$answer = $responseoutput->response_area_read_only('answer', $qa,
|
||||
$step, $question->responsefieldlines, $options->context);
|
||||
$answer .= html_writer::nonempty_tag('p', $question->get_word_count_message_for_review($step->get_qt_data()));
|
||||
|
||||
}
|
||||
|
||||
$files = '';
|
||||
|
@ -186,8 +186,8 @@ class qtype_essay_question_test extends advanced_testcase {
|
||||
$this->assertTrue($essay->is_complete_response($response));
|
||||
|
||||
// Unset the minwordlimit/maxwordlimit variables to avoid the extra check in is_complete_response() for further tests.
|
||||
unset($essay->minwordlimit);
|
||||
unset($essay->maxwordlimit);
|
||||
$essay->minwordlimit = null;
|
||||
$essay->maxwordlimit = null;
|
||||
|
||||
// Test the case where two files are required.
|
||||
$essay->attachmentsrequired = 2;
|
||||
@ -284,8 +284,10 @@ class qtype_essay_question_test extends advanced_testcase {
|
||||
/**
|
||||
* Test get_validation_error when users submit their input text.
|
||||
*
|
||||
* (The tests are done with a fixed 14-word response.)
|
||||
*
|
||||
* @dataProvider get_min_max_wordlimit_test_cases()
|
||||
* @param int $responserequired whether reponse required (yes = 1, no = 0)
|
||||
* @param int $responserequired whether response required (yes = 1, no = 0)
|
||||
* @param int $minwordlimit minimum word limit
|
||||
* @param int $maxwordlimit maximum word limit
|
||||
* @param string $expected error message | null
|
||||
@ -303,8 +305,10 @@ class qtype_essay_question_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Data provider for get_validation_error test.
|
||||
*
|
||||
* @return array the test cases.
|
||||
*/
|
||||
public function get_min_max_wordlimit_test_cases() {
|
||||
public function get_min_max_wordlimit_test_cases(): array {
|
||||
return [
|
||||
'text input required, min/max word limit not set' => [1, 0, 0, ''],
|
||||
'text input required, min/max word limit valid (within the boundaries)' => [1, 10, 25, ''],
|
||||
@ -315,4 +319,49 @@ class qtype_essay_question_test extends advanced_testcase {
|
||||
'text input not required, min/max word limit not set' => [0, 5, 12, ''],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_word_count_message_for_review when users submit their input text.
|
||||
*
|
||||
* (The tests are done with a fixed 14-word response.)
|
||||
*
|
||||
* @dataProvider get_word_count_message_for_review_test_cases()
|
||||
* @param int|null $minwordlimit minimum word limit
|
||||
* @param int|null $maxwordlimit maximum word limit
|
||||
* @param string $expected error message | null
|
||||
*/
|
||||
public function test_get_word_count_message_for_review(?int $minwordlimit, ?int $maxwordlimit, string $expected): void {
|
||||
$question = test_question_maker::make_an_essay_question();
|
||||
$question->minwordlimit = $minwordlimit;
|
||||
$question->maxwordlimit = $maxwordlimit;
|
||||
|
||||
$response = ['answer' => 'One two three four five six seven eight nine ten eleven twelve thirteen fourteen.'];
|
||||
$this->assertEquals($expected, $question->get_word_count_message_for_review($response));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_get_word_count_message_for_review.
|
||||
*
|
||||
* @return array the test cases.
|
||||
*/
|
||||
public function get_word_count_message_for_review_test_cases() {
|
||||
return [
|
||||
'No limit' =>
|
||||
[null, null, ''],
|
||||
'min and max, answer within range' =>
|
||||
[10, 25, get_string('wordcount', 'qtype_essay', 14)],
|
||||
'min and max, answer too short' =>
|
||||
[15, 25, get_string('wordcounttoofew', 'qtype_essay', ['count' => 14, 'limit' => 15])],
|
||||
'min and max, answer too long' =>
|
||||
[5, 12, get_string('wordcounttoomuch', 'qtype_essay', ['count' => 14, 'limit' => 12])],
|
||||
'min only, answer within range' =>
|
||||
[14, null, get_string('wordcount', 'qtype_essay', 14)],
|
||||
'min only, answer too short' =>
|
||||
[15, null, get_string('wordcounttoofew', 'qtype_essay', ['count' => 14, 'limit' => 15])],
|
||||
'max only, answer within range' =>
|
||||
[null, 14, get_string('wordcount', 'qtype_essay', 14)],
|
||||
'max only, answer too short' =>
|
||||
[null, 13, get_string('wordcounttoomuch', 'qtype_essay', ['count' => 14, 'limit' => 13])],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -715,5 +715,17 @@ class qtype_essay_walkthrough_testcase extends qbehaviour_walkthrough_test_base
|
||||
'attempting to submit 8 words. Please shorten your response and try again.',
|
||||
$this->currentoutput);
|
||||
|
||||
// Now submit all and finish.
|
||||
$this->finish();
|
||||
|
||||
// Verify.
|
||||
$this->check_current_state(question_state::$needsgrading);
|
||||
$this->check_current_mark(null);
|
||||
$this->render();
|
||||
$this->check_current_output(
|
||||
$this->get_contains_question_text_expectation($q),
|
||||
$this->get_contains_general_feedback_expectation($q));
|
||||
$this->assertStringContainsString('Word count: 8, more than the limit of 7 words.',
|
||||
$this->currentoutput);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user