Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shuffleanswers aus Quiz-Einstellungen berücksichtigen #103

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
# Since package.json only contains dev dependencies, comitting the lockfile makes little sence.
/package-lock.json
/node_modules

.idea
6 changes: 6 additions & 0 deletions classes/question_service.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public function get_question(int $questionid): object {

$result->qpy_package_hash = $package->hash;
$result->qpy_state = $record->state;
$result->shuffleanswers = $record->shuffleanswers;
}

return $result;
Expand Down Expand Up @@ -124,6 +125,10 @@ public function upsert_question(object $question): void {
$update["pkgversionid"] = $pkgversionid;
}

if ($question->shuffleanswers !== $existingrecord->shuffleanswers) {
$update["shuffleanswers"] = $question->shuffleanswers;
}

if (count($update) > 1) {
$DB->update_record(self::QUESTION_TABLE, (object)$update);
}
Expand All @@ -134,6 +139,7 @@ public function upsert_question(object $question): void {
"feedback" => "",
"pkgversionid" => $pkgversionid,
"state" => $response->state,
"shuffleanswers" => $question->shuffleanswers,
]);
}
}
Expand Down
9 changes: 7 additions & 2 deletions classes/question_ui_renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class question_ui_renderer {
/** @var question_metadata|null $metadata */
private ?question_metadata $metadata = null;

/** @var boolean Whether the questions answers should be shuffled. */
public bool $shuffleanswers;

/**
* Parses the given XML and initializes a new {@see question_ui_renderer} instance.
*
Expand Down Expand Up @@ -282,14 +285,16 @@ private function shuffle_contents(\DOMXPath $xpath): void {
$childelements[] = $child;
}
}
shuffle($childelements);
if ($this->shuffleanswers) {
shuffle($childelements);
}

// Iterate over children, replacing elements with random ones while copying everything else.
$i = 1;
while ($element->hasChildNodes()) {
$child = $element->firstChild;
if ($child instanceof DOMElement) {
$child = array_pop($childelements);
$child = array_shift($childelements);
$newelement->appendChild($child);
$this->replace_shuffled_indices($xpath, $child, $i++);
} else {
Expand Down
1 change: 1 addition & 0 deletions db/install.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<FIELD NAME="feedback" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Feedback shown for any response."/>
<FIELD NAME="pkgversionid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="state" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="shuffleanswers" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Whether the content of a qpy:shuffle-contents can be randomly shuffled."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
Expand Down
4 changes: 4 additions & 0 deletions edit_questionpy_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ protected function definition_inner($mform): void {
$mform->addElement('hidden', 'qpy_package_hash', '');
$mform->setType('qpy_package_hash', PARAM_RAW);

// Whether the content of a qpy:shuffle-contents can be randomly shuffled.
$mform->addElement('hidden', 'shuffleanswers', get_config('qtype_questionpy', 'shuffleanswers'));
$mform->setType('shuffleanswers', PARAM_BOOL);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bitte keine neuen Einstellungen einführen. Ob so eine Einstellung für das jeweilige Paket sinnvoll ist, müssen die Pakete selber wissen und in ihren Options definieren.

// While not a button, we need a way of telling moodle not to save the submitted data to the question when the
// package has simply been changed. The hidden element is enabled from JS when a package is selected or changed.
$mform->registerNoSubmitButton('qpy_package_changed');
Expand Down
5 changes: 5 additions & 0 deletions lang/en/qtype_questionpy.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
$string['server_password_description'] = 'The Password to access the Application Server';
$string['server_timeout'] = 'Server timeout time';
$string['server_timeout_description'] = 'Server timeout time in seconds';
$string['heading_packages'] = 'Packages';
$string['max_package_size_kb'] = 'Maximum file size of a QuestionPy package';
$string['max_package_size_kb_description'] = 'Maximum file size in kB';
$string['packages_subheading'] = 'Packages';
Expand All @@ -52,6 +53,10 @@
$string['server_info_requests_in_process'] = 'Requests in process';
$string['server_info_requests_in_queue'] = 'Requests in queue';

// Question settings.
$string['shuffleanswers'] = 'Shuffle the contents?';
$string['shuffleanswers_desc'] = 'Whether the content of a qpy:shuffle-contents should be randomly shuffled for each attempt by default.';

// Package upload.
$string['formerror_noqpy_package'] = 'Selected file must be of type .qpy';

Expand Down
5 changes: 5 additions & 0 deletions question.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class qtype_questionpy_question extends question_graded_automatically_with_count
private string $packagehash;
/** @var string */
private string $questionstate;
/** @var boolean Whether the questions answers should be shuffled. */
public bool $shuffleanswers;

// Properties which do change between attempts (i.e. are modified by start_attempt and apply_attempt_state).
/** @var string */
Expand Down Expand Up @@ -92,6 +94,7 @@ public function start_attempt(question_attempt_step $step, $variant): void {
$this->scoringstate = null;

$this->ui = new question_ui_renderer($attempt->ui->content, $attempt->ui->placeholders);
$this->ui->shuffleanswers = $this->shuffleanswers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bitte im Konstruktor übergeben.

}

/**
Expand Down Expand Up @@ -123,6 +126,7 @@ public function apply_attempt_state(question_attempt_step $step) {
$attempt = $this->api->view_attempt($this->packagehash, $this->questionstate, $this->attemptstate,
$this->scoringstate);
$this->ui = new question_ui_renderer($attempt->ui->content, $attempt->ui->placeholders);
$this->ui->shuffleanswers = $this->shuffleanswers;
}

/**
Expand Down Expand Up @@ -223,6 +227,7 @@ public function grade_response(array $response): array {
$response
);
$this->ui = new question_ui_renderer($attemptscored->ui->content, $attemptscored->ui->placeholders);
$this->ui->shuffleanswers = $this->shuffleanswers;
// TODO: Persist scoring state. We need to set a qtvar, but we don't have access to the pending step here.
$this->scoringstate = $attemptscored->scoringstate;
switch ($attemptscored->scoringcode) {
Expand Down
10 changes: 10 additions & 0 deletions questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,14 @@ public function get_question_options($question): bool {
protected function make_question_instance($questiondata) {
return new qtype_questionpy_question($questiondata->qpy_package_hash, $questiondata->qpy_state);
}

/**
* Initialise the question_definition fields.
* @param question_definition $question the question_definition we are creating.
* @param object $questiondata the question data loaded from the database.
*/
protected function initialise_question_instance(question_definition $question, $questiondata) {
parent::initialise_question_instance($question, $questiondata);
$question->shuffleanswers = $questiondata->shuffleanswers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greifst du hier auf das richtige Attribut zu? Moodle schreibt ja in $questiondata->options->shuffleanswers.

}
}
11 changes: 11 additions & 0 deletions renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,19 @@ public function head_code(question_attempt $qa) {
* @throws coding_exception
*/
public function formulation_and_controls(question_attempt $qa, question_display_options $options): string {
global $DB;
$question = $qa->get_question();
assert($question instanceof qtype_questionpy_question);

// Check if we are in a quiz context.
if ($this->page->context->contextlevel == CONTEXT_MODULE && $this->page->cm->modname == 'quiz') {
$quiz = $DB->get_record('quiz', ['id' => $this->page->cm->instance]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Die Information steckt doch bereits in $question->shuffleanswers!?

Copy link
Contributor Author

@alexanderschmitz alexanderschmitz Mar 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wird das $question->shuffleanswers denn automatisch überschrieben, wenn man in den Quiz Settings > Question Behaviour > Shuffle within questions ändert?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wenn ich mir https://github.com/moodle/moodle/blob/main/question/engine/bank.php#L278 ansehe, dann scheint das ja gemacht zu werden. Da der Wert aber nur im Falle von "kein shuffle" gesetzt/überschrieben wird, müsstest du vermutlich vorher mittels isset prüfen, ob das Attribut überhaupt existiert.

if ($quiz) {
// Access the shuffleanswers property of the quiz.
$question->ui->shuffleanswers = $quiz->shuffleanswers;
}
}

return $question->ui->render_formulation($qa, $options);
}

Expand Down
8 changes: 7 additions & 1 deletion settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
// Package settings.
$settings->add(new admin_setting_heading(
'qtype_questionpy/heading_packages',
'Packages',
new lang_string('heading_packages', 'qtype_questionpy'),
null
));

Expand All @@ -71,6 +71,12 @@
5
));

// Question settings.
$settings->add(new admin_setting_configcheckbox('qtype_questionpy/shuffleanswers',
new lang_string('shuffleanswers', 'qtype_questionpy'),
new lang_string('shuffleanswers_desc', 'qtype_questionpy'), '1'));

// Server Status/Info.
$settings->add(new admin_setting_heading(
'qtype_questionpy/server_info',
new lang_string('server_info_heading', 'qtype_questionpy'),
Expand Down
Loading