MDL-40992 question engine: new ways modify question usages

* A method to change the max mark for one question_attempt in the usage

* A method to replace one question in a usage with another, moving the
old question_attempt to the end.

* Methods to set and get metadata (string name value pairs) for each
question_attempt in the usage. This gets stored in the first step in a
way that should not interfere with anything else.
This commit is contained in:
Tim Hunt
2015-03-26 17:46:48 +00:00
parent 47be39ef41
commit f6579bea94
8 changed files with 610 additions and 87 deletions
+96 -28
View File
@@ -172,6 +172,42 @@ class question_usage_by_activity {
return $qa->get_slot();
}
/**
* Add another question to this usage, in the place of an existing slot.
* The question_attempt that was in that slot is moved to the end at a new
* slot number, which is returned.
*
* The added question is not started until you call {@link start_question()}
* on it.
*
* @param int $slot the slot-number of the question to replace.
* @param question_definition $question the question to add.
* @param number $maxmark the maximum this question will be marked out of in
* this attempt (optional). If not given, the max mark from the $qa we
* are replacing is used.
* @return int the new slot number of the question that was displaced.
*/
public function add_question_in_place_of_other($slot, question_definition $question, $maxmark = null) {
$newslot = $this->next_slot_number();
$oldqa = $this->get_question_attempt($slot);
$oldqa->set_slot($newslot);
$this->questionattempts[$newslot] = $oldqa;
if ($maxmark === null) {
$maxmark = $oldqa->get_max_mark();
}
$qa = new question_attempt($question, $this->get_id(), $this->observer, $maxmark);
$qa->set_slot($slot);
$this->questionattempts[$slot] = $qa;
$this->observer->notify_attempt_moved($oldqa, $slot);
$this->observer->notify_attempt_added($qa);
return $newslot;
}
/**
* The slot number that will be allotted to the next question added.
*/
@@ -377,6 +413,27 @@ class question_usage_by_activity {
return $this->get_question_attempt($slot)->get_right_answer_summary();
}
/**
* Return one of the bits of metadata for a particular question attempt in
* this usage.
* @param int $slot the slot number of the question of inereest.
* @param string $name the name of the metadata variable to return.
* @return string the value of that metadata variable.
*/
public function get_question_attempt_metadata($slot, $name) {
return $this->get_question_attempt($slot)->get_metadata($name);
}
/**
* Set some metadata for a particular question attempt in this usage.
* @param int $slot the slot number of the question of inerest.
* @param string $name the name of the metadata variable to return.
* @param string $value the value to set that metadata variable to.
*/
public function set_question_attempt_metadata($slot, $name, $value) {
$this->get_question_attempt($slot)->set_metadata($name, $value);
}
/**
* Get the {@link core_question_renderer}, in collaboration with appropriate
* {@link qbehaviour_renderer} and {@link qtype_renderer} subclasses, to generate the
@@ -822,22 +879,6 @@ class question_usage_by_activity {
$this->observer->notify_attempt_modified($newqa);
}
/**
* Replace a question in this usage.
* @param int $slot the number used to identify this question within this usage.*
*/
public function replace_question($slot) {
global $OUTPUT;
$oldqa = $this->get_question_attempt($slot);
$newqa = new question_attempt($oldqa->get_question(), $oldqa->get_usage_id(), $this->observer);
$newqa->set_database_id($oldqa->get_database_id());
$newqa->set_slot($oldqa->get_slot());
$this->questionattempts[$slot] = $newqa;
$this->observer->notify_attempt_deleted($oldqa);
$this->observer->notify_attempt_added($newqa);
$this->start_question($slot);
}
/**
* Regrade all the questions in this usage (without changing their max mark).
* @param bool $finished whether each question should be forced to be finished
@@ -849,6 +890,15 @@ class question_usage_by_activity {
}
}
/**
* Change the max mark for this question_attempt.
* @param int $slot the slot number of the question of inerest.
* @param float $maxmark the new max mark.
*/
public function set_max_mark($slot, $maxmark) {
$this->get_question_attempt($slot)->set_max_mark($maxmark);
}
/**
* Create a question_usage_by_activity from records loaded from the database.
*
@@ -983,12 +1033,6 @@ interface question_usage_observer {
/** Called when a field of the question_usage_by_activity is changed. */
public function notify_modified();
/**
* Called when the fields of a question attempt in this usage are modified.
* @param question_attempt $qa the newly added question attempt.
*/
public function notify_attempt_modified(question_attempt $qa);
/**
* Called when a new question attempt is added to this usage.
* @param question_attempt $qa the newly added question attempt.
@@ -996,10 +1040,17 @@ interface question_usage_observer {
public function notify_attempt_added(question_attempt $qa);
/**
* Called when the fields of a question attempt in this usage are deleted.
* @param question_attempt $qa
* Called when the fields of a question attempt in this usage are modified.
* @param question_attempt $qa the newly added question attempt.
*/
public function notify_attempt_deleted(question_attempt $qa);
public function notify_attempt_modified(question_attempt $qa);
/**
* Called when a question_attempt has been moved to a new slot.
* @param question_attempt $qa The question attempt that was moved.
* @param int $oldslot The previous slot number of that attempt.
*/
public function notify_attempt_moved(question_attempt $qa, $oldslot);
/**
* Called when a new step is added to a question attempt in this usage.
@@ -1024,6 +1075,19 @@ interface question_usage_observer {
*/
public function notify_step_deleted(question_attempt_step $step, question_attempt $qa);
/**
* Called when a new metadata variable is set on a question attempt in this usage.
* @param question_attempt $qa the question attempt the metadata is being added to.
* @param int $name the name of the metadata variable added.
*/
public function notify_metadata_added(question_attempt $qa, $name);
/**
* Called when a metadata variable on a question attempt in this usage is updated.
* @param question_attempt $qa the question attempt where the metadata is being modified.
* @param int $name the name of the metadata variable modified.
*/
public function notify_metadata_modified(question_attempt $qa, $name);
}
@@ -1037,11 +1101,11 @@ interface question_usage_observer {
class question_usage_null_observer implements question_usage_observer {
public function notify_modified() {
}
public function notify_attempt_added(question_attempt $qa) {
}
public function notify_attempt_modified(question_attempt $qa) {
}
public function notify_attempt_deleted(question_attempt $qa) {
}
public function notify_attempt_added(question_attempt $qa) {
public function notify_attempt_moved(question_attempt $qa, $oldslot) {
}
public function notify_step_added(question_attempt_step $step, question_attempt $qa, $seq) {
}
@@ -1049,4 +1113,8 @@ class question_usage_null_observer implements question_usage_observer {
}
public function notify_step_deleted(question_attempt_step $step, question_attempt $qa) {
}
public function notify_metadata_added(question_attempt $qa, $name) {
}
public function notify_metadata_modified(question_attempt $qa, $name) {
}
}