Skip to content

Commit

Permalink
Tidy up questiontype.php and question.php #834537
Browse files Browse the repository at this point in the history
  • Loading branch information
mkassaei committed Nov 12, 2024
1 parent 82310b6 commit 59fc87a
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 74 deletions.
117 changes: 72 additions & 45 deletions question.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class qtype_drawlines_question extends question_graded_automatically {
public function get_expected_data() {
$expecteddata = [];
foreach ($this->lines as $line) {
$expecteddata[$this->choice($line->number - 1)] = PARAM_RAW;
$expecteddata[$this->field($line->number - 1)] = PARAM_RAW;
}
return $expecteddata;
}
Expand All @@ -75,8 +75,8 @@ public function is_complete_response(array $response): bool {
return false;
}
foreach ($this->lines as $key => $line) {
if (isset($response[$this->choice($key)]) &&
!line::are_response_coordinates_valid($response[$this->choice($key)], $line->type)) {
if (isset($response[$this->field($key)]) &&
!line::are_response_coordinates_valid($response[$this->field($key)], $line->type)) {
return false;
}
}
Expand All @@ -87,7 +87,7 @@ public function is_complete_response(array $response): bool {
public function get_correct_response() {
$response = [];
foreach ($this->lines as $key => $line) {
$response[$this->choice($key)] = line::get_coordinates($line->zonestart) . ' '
$response[$this->field($key)] = line::get_coordinates($line->zonestart) . ' '
. line::get_coordinates($line->zoneend);
}
return $response;
Expand All @@ -98,14 +98,14 @@ public function summarise_response(array $response): ?string {
$responsewords = [];
$answers = [];
foreach ($this->lines as $key => $line) {
if (array_key_exists($this->choice($key), $response) && $response[$this->choice($key)] != '') {
$coordinates = explode(' ', $response[$this->choice($key)]);
if (array_key_exists($this->field($key), $response) && $response[$this->field($key)] != '') {
$coordinates = explode(' ', $response[$this->field($key)]);
if ($line->type == 'lineinfinite' && count($coordinates) == 4) {
$coordinates = explode(' ', $response[$this->choice($key)]);
$coordinates = explode(' ', $response[$this->field($key)]);
$answers[] = 'Line ' . $line->number . ': ' . $coordinates[1] . ' ' . $coordinates[2];
continue;
}
$answers[] = 'Line ' . $line->number . ': ' . $response[$this->choice($key)];
$answers[] = 'Line ' . $line->number . ': ' . $response[$this->field($key)];
}
}
if (count($answers) > 0) {
Expand All @@ -117,7 +117,7 @@ public function summarise_response(array $response): ?string {
#[\Override]
public function is_gradable_response(array $response) {
foreach ($this->lines as $key => $line) {
if (array_key_exists($this->choice($key), $response)) {
if (array_key_exists($this->field($key), $response)) {
return true;
}
}
Expand All @@ -127,40 +127,28 @@ public function is_gradable_response(array $response) {
#[\Override]
public function is_same_response(array $prevresponse, array $newresponse) {
foreach ($this->lines as $key => $line) {
$fieldname = $this->choice($key);
$fieldname = $this->field($key);
if (!question_utils::arrays_same_at_key_missing_is_blank($prevresponse, $newresponse, $fieldname)) {
return false;
}
}
return true;
}

#[\Override]
public function grade_response(array $response): array {
// Retrieve the number of right responses and the total number of responses.
if ($this->grademethod == 'partial') {
[$numright, $total] = $this->get_num_parts_right_grade_partialt($response);
} else {
[$numright, $total] = $this->get_num_parts_right_grade_allornone($response);
}
$fraction = $numright / $total;
return [$fraction, question_state::graded_state_for_fraction($fraction)];
}

/**
* Get the number of correct choices selected in the response, for 'Give partial credit' grade method.
*
* @param array $response The response list.
* @return array The array of number of correct lines (start, end or both points of lines).
*/
public function get_num_parts_right_grade_partialt(array $response): array {
public function get_num_parts_right_grade_partial(array $response): array {
if (!$response) {
return [0, 0];
}
$numpartright = 0;
foreach ($this->lines as $key => $line) {
if (array_key_exists($this->choice($key), $response) && $response[$this->choice($key)] !== '') {
$coords = explode(' ', $response[$this->choice($key)]);
if (array_key_exists($this->field($key), $response) && $response[$this->field($key)] !== '') {
$coords = explode(' ', $response[$this->field($key)]);
if ($line->type == 'lineinfinite') {
if (count($coords) == 2) {
// Response with 2 coordinates (x1,y1 x2,y2).
Expand All @@ -185,12 +173,15 @@ public function get_num_parts_right_grade_partialt(array $response): array {
}
}
} else {
$numpartrightstart = 0;
$numpartrightend = 0;
if (line::is_dragitem_in_the_right_place($coords[0], $line->zonestart)) {
$numpartright++;
$numpartrightstart++;
}
if (line::is_dragitem_in_the_right_place($coords[1], $line->zoneend)) {
$numpartright++;
$numpartrightend++;
}
$numpartright += $numpartrightstart + $numpartrightend;
}
}
}
Expand All @@ -210,25 +201,25 @@ public function get_num_parts_right_grade_allornone(array $response): array {
}
$numright = 0;
foreach ($this->lines as $key => $line) {
if (array_key_exists($this->choice($key), $response) && $response[$this->choice($key)] !== '') {
$coords = explode(' ', $response[$this->choice($key)]);
if (array_key_exists($this->field($key), $response) && $response[$this->field($key)] !== '') {
$coords = explode(' ', $response[$this->field($key)]);
if ($line->type == 'lineinfinite') {
if (count($coords) == 2) {
// Response with 2 coordinates (x1,y1 x2,y2 x3,y3 x4,y4).
$isstartrightplace = line::is_item_positioned_correctly_on_axis(
$coords[0], $line->zonestart, $line->zoneend, 'start'
$coords[0], $line->zonestart, $line->zoneend, 'start'
);
$isendrightplace = line::is_item_positioned_correctly_on_axis(
$coords[1], $line->zonestart, $line->zoneend, 'end'
$coords[1], $line->zonestart, $line->zoneend, 'end'
);
} else {
// Response has 4 coordinates(x1,y1 x2,y2 x3,y3 x4,y4).
// Here we need to consider x2,y2 x3,y3 for calculation.
$isstartrightplace = line::is_item_positioned_correctly_on_axis(
$coords[1], $line->zonestart, $line->zoneend, 'start'
$coords[1], $line->zonestart, $line->zoneend, 'start'
);
$isendrightplace = line::is_item_positioned_correctly_on_axis(
$coords[2], $line->zonestart, $line->zoneend, 'end'
$coords[2], $line->zonestart, $line->zoneend, 'end'
);
}
if ($isstartrightplace && $isendrightplace) {
Expand All @@ -242,7 +233,7 @@ public function get_num_parts_right_grade_allornone(array $response): array {
}
}
}
$total = count($this->lines);
$total = count($this->lines);
return [$numright, $total];
}

Expand Down Expand Up @@ -274,15 +265,15 @@ public function get_validation_error(array $response): string {
public function classify_response(array $response) {
$classifiedresponse = [];
foreach ($this->lines as $key => $line) {
if (array_key_exists($this->choice($key), $response) && $response[$this->choice($key)] !== '') {
if (array_key_exists($this->field($key), $response) && $response[$this->field($key)] !== '') {
if ($this->grademethod == 'partial') {
$fraction = 0.5;
} else {
$fraction = 1;
}
$classifiedresponse[$key] = new question_classified_response(
$line->number,
'Line ' . $line->number . ': ' . $response[$this->choice($key)],
'Line ' . $line->number . ': ' . $response[$this->field($key)],
$fraction);
} else {
$classifiedresponse[$key] = question_classified_response::no_response();
Expand All @@ -291,6 +282,30 @@ public function classify_response(array $response) {
return $classifiedresponse;
}

#[\Override]
public function grade_response(array $response): array {
// Retrieve the number of right responses and the total number of responses.
[$numright, $numtotal] = $this->retrieve_numright_numtotal($response);
$fraction = $numright / $numtotal;
return [$fraction, question_state::graded_state_for_fraction($fraction)];
}

/**
* Return number of correct responses and the total numbe of answers.
*
* @param array $response The respnse array
* @return array|int[] The array containing number of correct responses and the total.
*/
public function retrieve_numright_numtotal(array $response): array {
// Retrieve the number of right responses and the total number of responses.
if ($this->grademethod == 'partial') {
[$numright, $numtotal] = $this->get_num_parts_right_grade_partial($response);
} else {
[$numright, $numtotal] = $this->get_num_parts_right_grade_allornone($response);
}
return [$numright, $numtotal];
}

/**
* Work out a final grade for this attempt, taking into account
* all the tries the student made and return the grade value.
Expand All @@ -304,24 +319,36 @@ public function classify_response(array $response) {
* @return float the fraction that should be awarded for this
* sequence of response.
*/
public function compute_final_grade(array $responses, int $totaltries): float {
// TODO: To incorporate the question penalty for interactive with multiple tries behaviour.

public function compute_final_grade(array $responses, int $totaltries): int|float {
$grade = 0;
foreach ($responses as $response) {
if ($totaltries === 1) {
foreach ($responses as $key => $response) {
[$fraction, $state] = $this->grade_response($response);
$grade += $fraction;
}
return $grade;
}
$reversedresponses = array_reverse($responses, true);
for ($tr = $totaltries; $tr >= 1; $tr--) {
$response = $reversedresponses[$tr];
[$fraction, $state] = $this->grade_response($response);
$grade += $fraction;

// Apply penalties.
[$numright, $numtotal] = $this->retrieve_numright_numtotal($response);
$penalty = ($numtotal - $numright) * ($this->penalty/$numtotal);
$grade += $fraction - $penalty;
}
return $grade;
$finalgrade = $grade / $totaltries;
return $finalgrade;
}

/**
* Get a choice identifier
* Get a choice index identifier
*
* @param int $choice stem number
* @param int $choice
* @return string the question-type variable name.
*/
public function choice($choice) {
public function field($choice): string {
return 'c' . $choice;
}
}
6 changes: 0 additions & 6 deletions questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,6 @@ public function save_hints($fromform, $withparts = false) {
}
}

#[\Override]
protected function make_question_instance($questiondata) {
question_bank::load_question_definition_classes($this->name());
return new qtype_drawlines_question;
}

#[\Override]
protected function initialise_question_instance(question_definition $question, $questiondata): void {
parent::initialise_question_instance($question, $questiondata);
Expand Down
2 changes: 1 addition & 1 deletion renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $valu
* @return mixed
*/
protected function hidden_field_choice(question_attempt $qa, $choicenumber, $value = null, $class = null) {
$varname = 'c'. $choicenumber;
$varname = $qa->get_question()->field($choicenumber);
$classes = ['choices', 'choice'. $choicenumber];
[, $html] = $this->hidden_field_for_qt_var($qa, $varname, $value, $classes);
return $html;
Expand Down
4 changes: 2 additions & 2 deletions tests/behat/preview.feature
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ Feature: Preview a DrawLines question

@javascript
Scenario: Preview a question using the keyboard
When I am on the "Drawlines to preview" "core_question > preview" page logged in as teacher
Given I am on the "Drawlines to preview" "core_question > preview" page logged in as teacher
And I type "up" "360" times on line "1" "line" in the drawlines question
And I type "left" "40" times on line "1" "line" in the drawlines question
And I type "down" "190" times on line "1" "endcircle" in the drawlines question
And I type "left" "200" times on line "1" "endcircle" in the drawlines question
And I press "Submit and finish"
When I press "Submit and finish"
Then the state of "Draw 2 lines on the map" question is shown as "Partially correct"
And I should see "Mark 0.50 out of 1.00"
Loading

0 comments on commit 59fc87a

Please sign in to comment.