MDL-27412 qtype_calculatedmulti Fix lots of coding style issues.

This commit is contained in:
Tim Hunt
2011-05-17 16:01:16 +01:00
parent f184c65cda
commit 29b689142f
5 changed files with 287 additions and 329 deletions
@@ -24,7 +24,8 @@
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/type/calculated/backup/moodle2/backup_qtype_calculated_plugin.class.php');
require_once($CFG->dirroot .
'/question/type/calculated/backup/moodle2/backup_qtype_calculated_plugin.class.php');
/**
@@ -33,4 +34,5 @@ require_once($CFG->dirroot . '/question/type/calculated/backup/moodle2/backup_qt
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class backup_qtype_calculatedmulti_plugin extends backup_qtype_calculated_plugin {}
class backup_qtype_calculatedmulti_plugin extends backup_qtype_calculated_plugin {
}
@@ -25,7 +25,8 @@
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/type/calculated/backup/moodle2/restore_qtype_calculated_plugin.class.php');
require_once($CFG->dirroot .
'/question/type/calculated/backup/moodle2/restore_qtype_calculated_plugin.class.php');
/**
* restore plugin class that provides the necessary information
@@ -33,47 +33,50 @@ defined('MOODLE_INTERNAL') || die();
* @copyright 2007 Jamie Pratt [email protected]
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class question_edit_calculatedmulti_form extends question_edit_form {
class qtype_calculatedmulti_edit_form extends question_edit_form {
/**
* Handle to the question type for this question.
*
* @var question_calculatedmulti_qtype
*/
public $qtypeobj;
public $questiondisplay ;
public $questiondisplay;
public $initialname = '';
public $reload = false ;
function question_edit_calculatedmulti_form(&$submiturl, &$question, &$category, &$contexts, $formeditable = true) {
global $QTYPES, $SESSION, $CFG, $DB;
public $reload = false;
public function __construct($submiturl, $question, $category,
$contexts, $formeditable = true) {
global $SESSION, $CFG, $DB;
$this->question = $question;
$this->qtypeobj =& $QTYPES[$this->question->qtype];
if ( "1" == optional_param('reload','', PARAM_INT )) {
$this->reload = true ;
}else {
$this->reload = false ;
$this->qtypeobj = $QTYPES[$this->question->qtype];
if (1 == optional_param('reload', '', PARAM_INT)) {
$this->reload = true;
} else {
$this->reload = false;
}
if(!$this->reload ){ // use database data as this is first pass
if(isset($this->question->id )){
if (!$this->reload) {
// use database data as this is first pass
if (isset($this->question->id)) {
// remove prefix #{..}# if exists
$this->initialname = $question->name ;
$this->initialname = $question->name;
$regs= array();
if(preg_match('~#\{([^[:space:]]*)#~',$question->name , $regs)){
if (preg_match('~#\{([^[:space:]]*)#~', $question->name , $regs)) {
$question->name = str_replace($regs[0], '', $question->name);
};
}
}else {
}
parent::question_edit_form($submiturl, $question, $category, $contexts, $formeditable);
parent::__construct($submiturl, $question, $category, $contexts, $formeditable);
}
function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
// $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
public function get_per_answer_fields($mform, $label, $gradeoptions,
&$repeatedoptions, &$answersoption) {
$repeated = array();
$repeated[] =& $mform->createElement('header', 'answerhdr', $label);
// if ($this->editasmultichoice == 1){
$repeated[] =& $mform->createElement('text', 'answer', get_string('answer', 'question'), array('size' => 50));
$repeated[] =& $mform->createElement('select', 'fraction', get_string('grade'), $gradeoptions);
$repeated[] =& $mform->createElement('editor', 'feedback', get_string('feedback', 'question'), null, $this->editoroptions);
$repeated[] = $mform->createElement('header', 'answerhdr', $label);
$repeated[] = $mform->createElement('text', 'answer',
get_string('answer', 'question'), array('size' => 50));
$repeated[] = $mform->createElement('select', 'fraction',
get_string('grade'), $gradeoptions);
$repeated[] = $mform->createElement('editor', 'feedback',
get_string('feedback', 'question'), null, $this->editoroptions);
$repeatedoptions['answer']['type'] = PARAM_RAW;
$repeatedoptions['fraction']['default'] = 0;
$answersoption = 'answers';
@@ -81,16 +84,21 @@ class question_edit_calculatedmulti_form extends question_edit_form {
$mform->setType('answer', PARAM_NOTAGS);
$addrepeated = array();
$addrepeated[] =& $mform->createElement('hidden', 'tolerance');
$addrepeated[] =& $mform->createElement('hidden', 'tolerancetype',1);
$addrepeated[] = $mform->createElement('hidden', 'tolerance');
$addrepeated[] = $mform->createElement('hidden', 'tolerancetype', 1);
$repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
$repeatedoptions['tolerance']['default'] = 0.01;
$addrepeated[] =& $mform->createElement('select', 'correctanswerlength', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
$addrepeated[] = $mform->createElement('select', 'correctanswerlength',
get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
$repeatedoptions['correctanswerlength']['default'] = 2;
$answerlengthformats = array('1' => get_string('decimalformat', 'qtype_numerical'), '2' => get_string('significantfiguresformat', 'qtype_calculated'));
$addrepeated[] =& $mform->createElement('select', 'correctanswerformat', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
$answerlengthformats = array(
'1' => get_string('decimalformat', 'qtype_numerical'),
'2' => get_string('significantfiguresformat', 'qtype_calculated')
);
$addrepeated[] = $mform->createElement('select', 'correctanswerformat',
get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
array_splice($repeated, 3, 0, $addrepeated);
$repeated[1]->setLabel('...<strong>{={x}+..}</strong>...');
@@ -103,94 +111,101 @@ class question_edit_calculatedmulti_form extends question_edit_form {
* @param MoodleQuickForm $mform the form being built.
*/
protected function definition_inner($mform) {
global $QTYPES;
$this->qtypeobj =& $QTYPES[$this->qtype()];
// echo code left for testing period
// echo "<p>question ".optional_param('multichoice', '', PARAM_RAW)." optional<pre>";print_r($this->question);echo "</pre></p>";
$label = get_string("sharedwildcards", "qtype_calculated");
$this->qtypeobj = $QTYPES[$this->qtype()];
$label = get_string('sharedwildcards', 'qtype_calculated');
$mform->addElement('hidden', 'initialcategory', 1);
$mform->addElement('hidden', 'reload', 1);
$mform->setType('initialcategory', PARAM_INT);
// $html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
$html2 ="";
$mform->insertElementBefore($mform->createElement('static','listcategory',$label,$html2),'name');
if(isset($this->question->id )){
$mform->insertElementBefore($mform->createElement('static','initialname',get_string('questionstoredname','qtype_calculated'),$this->initialname),'name');
$html2 = '';
$mform->insertElementBefore(
$mform->createElement('static', 'listcategory', $label, $html2), 'name');
if (isset($this->question->id)) {
$mform->insertElementBefore($mform->createElement('static', 'initialname',
get_string('questionstoredname', 'qtype_calculated'),
$this->initialname), 'name');
};
$addfieldsname='updatecategory';
$addstring=get_string("updatecategory", "qtype_calculated");
$addfieldsname = 'updatecategory';
$addstring = get_string('updatecategory', 'qtype_calculated');
$mform->registerNoSubmitButton($addfieldsname);
$this->editasmultichoice = 1 ;
$this->editasmultichoice = 1;
$mform->insertElementBefore( $mform->createElement('submit', $addfieldsname, $addstring),'listcategory');
$mform->insertElementBefore(
$mform->createElement('submit', $addfieldsname, $addstring), 'listcategory');
$mform->registerNoSubmitButton('createoptionbutton');
$mform->addElement('hidden', 'multichoice',$this->editasmultichoice);
$mform->addElement('hidden', 'multichoice', $this->editasmultichoice);
$mform->setType('multichoice', PARAM_INT);
// $mform->addElement('header', 'choicehdr',get_string('multichoicecalculatedquestion', 'qtype_calculated'));
$menu = array(get_string('answersingleno', 'qtype_multichoice'), get_string('answersingleyes', 'qtype_multichoice'));
$mform->addElement('select', 'single', get_string('answerhowmany', 'qtype_multichoice'), $menu);
$menu = array(get_string('answersingleno', 'qtype_multichoice'),
get_string('answersingleyes', 'qtype_multichoice'));
$mform->addElement('select', 'single',
get_string('answerhowmany', 'qtype_multichoice'), $menu);
$mform->setDefault('single', 1);
$mform->addElement('advcheckbox', 'shuffleanswers', get_string('shuffleanswers', 'qtype_multichoice'), null, null, array(0,1));
$mform->addElement('advcheckbox', 'shuffleanswers',
get_string('shuffleanswers', 'qtype_multichoice'), null, null, array(0, 1));
$mform->addHelpButton('shuffleanswers', 'shuffleanswers', 'qtype_multichoice');
$mform->setDefault('shuffleanswers', 1);
$numberingoptions = $QTYPES['multichoice']->get_numbering_styles();
$menu = array();
foreach ($numberingoptions as $numberingoption) {
$menu[$numberingoption] = get_string('answernumbering' . $numberingoption, 'qtype_multichoice');
$menu[$numberingoption] = get_string(
'answernumbering' . $numberingoption, 'qtype_multichoice');
}
$mform->addElement('select', 'answernumbering', get_string('answernumbering', 'qtype_multichoice'), $menu);
$mform->addElement('select', 'answernumbering',
get_string('answernumbering', 'qtype_multichoice'), $menu);
$mform->setDefault('answernumbering', 'abc');
$creategrades = get_grade_options();
$this->add_per_answer_fields($mform, get_string('choiceno', 'qtype_multichoice', '{no}'),
$creategrades->gradeoptionsfull, max(5, QUESTION_NUMANS_START));
$creategrades->gradeoptionsfull, max(5, QUESTION_NUMANS_START));
$repeated = array();
// if ($this->editasmultichoice == 1){
// if ($this->editasmultichoice == 1) {
$nounits = optional_param('nounits', 1, PARAM_INT);
$mform->addElement('hidden', 'nounits', $nounits);
$mform->setType('nounits', PARAM_INT);
$mform->setConstants(array('nounits'=>$nounits));
for ($i=0; $i< $nounits; $i++) {
$mform->addElement('hidden','unit'."[$i]", optional_param('unit'."[$i]", '', PARAM_NOTAGS));
for ($i = 0; $i < $nounits; $i++) {
$mform->addElement('hidden', 'unit'."[$i]",
optional_param('unit'."[$i]", '', PARAM_NOTAGS));
$mform->setType('unit'."[$i]", PARAM_NOTAGS);
$mform->addElement('hidden', 'multiplier'."[$i]", optional_param('multiplier'."[$i]", '', PARAM_NUMBER));
$mform->addElement('hidden', 'multiplier'."[$i]",
optional_param('multiplier'."[$i]", '', PARAM_NUMBER));
$mform->setType('multiplier'."[$i]", PARAM_NUMBER);
}
$mform->setType('addunits','hidden');
$mform->addElement('header', 'overallfeedbackhdr', get_string('overallfeedback', 'qtype_multichoice'));
$mform->setType('addunits', 'hidden');
$mform->addElement('header', 'overallfeedbackhdr',
get_string('overallfeedback', 'qtype_multichoice'));
foreach (array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback') as $feedbackname) {
$mform->addElement('editor', $feedbackname, get_string($feedbackname, 'qtype_multichoice'), null, $this->editoroptions);
foreach (array('correctfeedback', 'partiallycorrectfeedback',
'incorrectfeedback') as $feedbackname) {
$mform->addElement('editor', $feedbackname,
get_string($feedbackname, 'qtype_multichoice'), null, $this->editoroptions);
$mform->setType($feedbackname, PARAM_RAW);
}
//hidden elements
$mform->addElement('hidden', 'synchronize', '');
$mform->setType('synchronize', PARAM_INT);
if (isset($this->question->options)&& isset($this->question->options->synchronize) ){
$mform->setDefault("synchronize", $this->question->options->synchronize);
if (isset($this->question->options) && isset($this->question->options->synchronize)) {
$mform->setDefault('synchronize', $this->question->options->synchronize);
} else {
$mform->setDefault("synchronize", 0 );
$mform->setDefault('synchronize', 0);
}
$mform->addElement('hidden', 'wizard', 'datasetdefinitions');
$mform->setType('wizard', PARAM_ALPHA);
}
function data_preprocessing($question) {
$default_values['multichoice']= $this->editasmultichoice ; //$this->editasmultichoice ;
if (isset($question->options)){
public function data_preprocessing($question) {
$default_values['multichoice']= $this->editasmultichoice;
if (isset($question->options)) {
$answers = $question->options->answers;
if (count($answers)) {
$key = 0;
foreach ($answers as $answer){
foreach ($answers as $answer) {
$draftid = file_get_submitted_draft_itemid('feedback['.$key.']');
$default_values['answer['.$key.']'] = $answer->answer;
$default_values['fraction['.$key.']'] = $answer->fraction;
@@ -200,15 +215,18 @@ class question_edit_calculatedmulti_form extends question_edit_form {
$default_values['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
$default_values['feedback['.$key.']'] = array();
// prepare draftarea
$default_values['feedback['.$key.']']['text'] = file_prepare_draft_area($draftid, $this->context->id, 'question', 'answerfeedback', empty($answer->id)?null:(int)$answer->id, $this->fileoptions, $answer->feedback);
$default_values['feedback['.$key.']']['text'] = file_prepare_draft_area(
$draftid, $this->context->id, 'question', 'answerfeedback',
empty($answer->id) ? null : (int) $answer->id,
$this->fileoptions, $answer->feedback);
$default_values['feedback['.$key.']']['format'] = $answer->feedbackformat;
$default_values['feedback['.$key.']']['itemid'] = $draftid;
$key++;
}
}
$default_values['synchronize'] = $question->options->synchronize ;
$default_values['synchronize'] = $question->options->synchronize;
if (isset($question->options->units)){
if (isset($question->options->units)) {
$units = array_values($question->options->units);
// make sure the default unit is at index 0
usort($units, create_function('$a, $b',
@@ -216,7 +234,7 @@ class question_edit_calculatedmulti_form extends question_edit_form {
'if (1.0 === (float)$b->multiplier) { return 1; } else { return 0; }'));
if (count($units)) {
$key = 0;
foreach ($units as $unit){
foreach ($units as $unit) {
$default_values['unit['.$key.']'] = $unit->unit;
$default_values['multiplier['.$key.']'] = $unit->multiplier;
$key++;
@@ -224,7 +242,7 @@ class question_edit_calculatedmulti_form extends question_edit_form {
}
}
}
if (isset($question->options->single)){
if (isset($question->options->single)) {
$default_values['single'] = $question->options->single;
$default_values['answernumbering'] = $question->options->answernumbering;
$default_values['shuffleanswers'] = $question->options->shuffleanswers;
@@ -233,7 +251,8 @@ class question_edit_calculatedmulti_form extends question_edit_form {
$default_values['makecopy'] = get_string('makecopynextpage', 'qtype_calculated');
// prepare draft files
foreach (array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback') as $feedbackname) {
foreach (array('correctfeedback', 'partiallycorrectfeedback',
'incorrectfeedback') as $feedbackname) {
if (!isset($question->options->$feedbackname)) {
continue;
}
@@ -258,54 +277,54 @@ class question_edit_calculatedmulti_form extends question_edit_form {
* set the wild cards category display given that on loading the category element is
* unselected when processing this function but have a valid value when processing the
* update category button. The value can be obtain by
* $qu->category =$this->_form->_elements[$this->_form->_elementIndex['category']]->_values[0];
* $qu->category = $this->_form->_elements[$this->_form->
* _elementIndex['category']]->_values[0];
* but is coded using existing functions
*/
$qu = new stdClass();
$el = new stdClass();
/* no need to call elementExists() here */
if ($this->_form->elementExists('category')){
$el=$this->_form->getElement('category');
// no need to call elementExists() here.
if ($this->_form->elementExists('category')) {
$el = $this->_form->getElement('category');
} else {
$el=$this->_form->getElement('categorymoveto');
$el = $this->_form->getElement('categorymoveto');
}
if($value =$el->getSelected()) {
$qu->category =$value[0];
}else {
$qu->category=$question->category;// on load $question->category is set by question.php
if ($value = $el->getSelected()) {
$qu->category = $value[0];
} else {
// on load $question->category is set by question.php
$qu->category = $question->category;
}
$html2 = $this->qtypeobj->print_dataset_definitions_category($qu);
$this->_form->_elements[$this->_form->_elementIndex['listcategory']]->_text = $html2 ;
$this->_form->_elements[$this->_form->_elementIndex['listcategory']]->_text = $html2;
$question = (object)((array)$question + $default_values);
return $question;
}
function qtype() {
public function qtype() {
return 'calculatedmulti';
}
function validation($data, $files) {
// echo code left for testing period
// echo "<p>question <pre>";print_r($this->question);echo "</pre></p>";
// echo "<p>data <pre>";print_r($data);echo "</pre></p>";
public function validation($data, $files) {
$errors = parent::validation($data, $files);
//verifying for errors in {=...} in question text;
$qtext = "";
$qtext = '';
$qtextremaining = $data['questiontext']['text'];
$possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']);
foreach ($possibledatasets as $name => $value) {
$qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
}
// echo "numericalquestion qtextremaining <pre>";print_r($possibledatasets);
while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
$qtextsplits = explode($regs1[0], $qtextremaining, 2);
$qtext =$qtext.$qtextsplits[0];
$qtext = $qtext.$qtextsplits[0];
$qtextremaining = $qtextsplits[1];
if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
if(!isset($errors['questiontext'])){
$errors['questiontext'] = $formulaerrors.':'.$regs1[1] ;
}else {
if (!empty($regs1[1]) && $formulaerrors =
qtype_calculated_find_formula_errors($regs1[1])) {
if (!isset($errors['questiontext'])) {
$errors['questiontext'] = $formulaerrors.':'.$regs1[1];
} else {
$errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
}
}
@@ -315,47 +334,50 @@ class question_edit_calculatedmulti_form extends question_edit_form {
$maxgrade = false;
$possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']);
$mandatorydatasets = array();
foreach ($answers as $key => $answer){
foreach ($answers as $key => $answer) {
$mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
}
if ( count($mandatorydatasets )==0){
// $errors['questiontext']=get_string('atleastonewildcard', 'qtype_datasetdependent');
foreach ($answers as $key => $answer){
$errors['answer['.$key.']'] = get_string('atleastonewildcard', 'qtype_datasetdependent');
if (count($mandatorydatasets) == 0) {
foreach ($answers as $key => $answer) {
$errors['answer['.$key.']'] =
get_string('atleastonewildcard', 'qtype_datasetdependent');
}
}
if ($data['multichoice']== 1 ){
foreach ($answers as $key => $answer){
if ($data['multichoice'] == 1) {
foreach ($answers as $key => $answer) {
$trimmedanswer = trim($answer);
if (($trimmedanswer!='')||$answercount==0){
if ($trimmedanswer != '' || $answercount == 0) {
//verifying for errors in {=...} in answer text;
$qanswer = "";
$qanswerremaining = $trimmedanswer ;
$qanswer = '';
$qanswerremaining = $trimmedanswer;
$possibledatasets = $this->qtypeobj->find_dataset_names($trimmedanswer);
foreach ($possibledatasets as $name => $value) {
$qanswerremaining = str_replace('{'.$name.'}', '1', $qanswerremaining);
}
// echo "numericalquestion qanswerremaining <pre>";print_r($possibledatasets);
while (preg_match('~\{=([^[:space:]}]*)}~', $qanswerremaining, $regs1)) {
while (preg_match('~\{=([^[:space:]}]*)}~', $qanswerremaining, $regs1)) {
$qanswersplits = explode($regs1[0], $qanswerremaining, 2);
$qanswer =$qanswer.$qanswersplits[0];
$qanswer = $qanswer . $qanswersplits[0];
$qanswerremaining = $qanswersplits[1];
if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
if(!isset($errors['answer['.$key.']'])){
$errors['answer['.$key.']'] = $formulaerrors.':'.$regs1[1] ;
}else {
if (!empty($regs1[1]) && $formulaerrors =
qtype_calculated_find_formula_errors($regs1[1])) {
if (!isset($errors['answer['.$key.']'])) {
$errors['answer['.$key.']'] = $formulaerrors.':'.$regs1[1];
} else {
$errors['answer['.$key.']'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
}
}
}
}
if ($trimmedanswer!=''){
if ('2' == $data['correctanswerformat'][$key]
&& '0' == $data['correctanswerlength'][$key]) {
$errors['correctanswerlength['.$key.']'] = get_string('zerosignificantfiguresnotallowed','qtype_calculated');
}
if (!is_numeric($data['tolerance'][$key])){
$errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
if ($trimmedanswer != '') {
if ('2' == $data['correctanswerformat'][$key] &&
'0' == $data['correctanswerlength'][$key]) {
$errors['correctanswerlength['.$key.']'] =
get_string('zerosignificantfiguresnotallowed', 'qtype_calculated');
}
if (!is_numeric($data['tolerance'][$key])) {
$errors['tolerance['.$key.']'] =
get_string('mustbenumeric', 'qtype_calculated');
}
if ($data['fraction'][$key] == 1) {
$maxgrade = true;
@@ -364,8 +386,8 @@ class question_edit_calculatedmulti_form extends question_edit_form {
$answercount++;
}
//check grades
$totalfraction = 0 ;
$maxfraction = 0 ;
$totalfraction = 0;
$maxfraction = 0;
if ($answer != '') {
if ($data['fraction'][$key] > 0) {
$totalfraction += $data['fraction'][$key];
@@ -375,29 +397,31 @@ class question_edit_calculatedmulti_form extends question_edit_form {
}
}
}
if ($answercount==0){
if ($answercount == 0) {
$errors['answer[0]'] = get_string('notenoughanswers', 'qtype_multichoice', 2);
$errors['answer[1]'] = get_string('notenoughanswers', 'qtype_multichoice', 2);
} elseif ($answercount==1){
} else if ($answercount == 1) {
$errors['answer[1]'] = get_string('notenoughanswers', 'qtype_multichoice', 2);
}
/// Perform sanity checks on fractional grades
if ($data['single']) {
if ($maxfraction > 0.999 ) {
if ($maxfraction > 0.999) {
$maxfraction = $maxfraction * 100;
$errors['fraction[0]'] = get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction);
$errors['fraction[0]'] =
get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction);
}
} else {
$totalfraction = round($totalfraction,2);
$totalfraction = round($totalfraction, 2);
if ($totalfraction != 1) {
$totalfraction = $totalfraction * 100;
$errors['fraction[0]'] = get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction);
$errors['fraction[0]'] =
get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction);
}
}
if ($answercount==0){
if ($answercount == 0) {
$errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated');
}
if ($maxgrade == false) {
+4 -2
View File
@@ -31,8 +31,10 @@ defined('MOODLE_INTERNAL') || die();
/**
* Checks file access for calculated multiple-choice questions.
*/
function qtype_calculatedmulti_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
function qtype_calculatedmulti_pluginfile($course, $cm, $context, $filearea, $args,
$forcedownload) {
global $DB, $CFG;
require_once($CFG->libdir . '/questionlib.php');
question_pluginfile($course, $context, 'qtype_calculatedmulti', $filearea, $args, $forcedownload);
question_pluginfile($course, $context, 'qtype_calculatedmulti', $filearea, $args,
$forcedownload);
}
+123 -194
View File
@@ -33,30 +33,26 @@ defined('MOODLE_INTERNAL') || die();
* @copyright 2009 Pierre Pichet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class question_calculatedmulti_qtype extends qtype_calculated {
class qtype_calculatedmulti extends qtype_calculated {
// Used by the function custom_generator_tools:
public $calcgenerateidhasbeenadded = false;
public $virtualqtype = false;
function name() {
return 'calculatedmulti';
public function requires_qtypes() {
return array('calculated', 'multichoice');
}
function requires_qtypes() {
return array('multichoice');
}
function save_question_options($question) {
global $CFG, $DB, $QTYPES ;
public function save_question_options($question) {
global $CFG, $DB;
$context = $question->context;
if (isset($question->answer) && !isset($question->answers)) {
$question->answers = $question->answer;
}
// calculated options
$update = true ;
$options = $DB->get_record("question_calculated_options", array("question" => $question->id));
$update = true;
$options = $DB->get_record('question_calculated_options',
array('question' => $question->id));
if (!$options) {
$update = false;
$options = new stdClass();
@@ -77,25 +73,30 @@ class question_calculatedmulti_qtype extends qtype_calculated {
$options->$feedbackname = trim($feedback['text']);
$files = $feedback['files'];
foreach ($files as $file) {
$this->import_file($question->context, 'qtype_calculatedmulti', $feedbackname, $question->id, $file);
$this->import_file($question->context, 'qtype_calculatedmulti',
$feedbackname, $question->id, $file);
}
} else {
$options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_calculatedmulti', $feedbackname, $question->id, $this->fileoptionsa , trim($feedback['text']));
$options->$feedbackname = file_save_draft_area_files($feedback['itemid'],
$context->id, 'qtype_calculatedmulti', $feedbackname,
$question->id, $this->fileoptionsa, trim($feedback['text']));
}
}
if ($update) {
$DB->update_record("question_calculated_options", $options);
$DB->update_record('question_calculated_options', $options);
} else {
$DB->insert_record("question_calculated_options", $options);
$DB->insert_record('question_calculated_options', $options);
}
// Get old versions of the objects
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
if (!$oldanswers = $DB->get_records('question_answers',
array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
if (!$oldoptions = $DB->get_records('question_calculated', array('question' => $question->id), 'answer ASC')) {
if (!$oldoptions = $DB->get_records('question_calculated',
array('question' => $question->id), 'answer ASC')) {
$oldoptions = array();
}
@@ -114,7 +115,7 @@ class question_calculatedmulti_qtype extends qtype_calculated {
if (is_array($dataanswer)) {
$dataanswer = $dataanswer['text'];
}
if ( trim($dataanswer) != '' ) {
if (trim($dataanswer) != '') {
$answer = new stdClass();
$answer->question = $question->id;
$answer->answer = trim($dataanswer);
@@ -125,21 +126,30 @@ class question_calculatedmulti_qtype extends qtype_calculated {
$files = $question->feedback[$key]['files'];
}
if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
if ($oldanswer = array_shift($oldanswers)) {
// Existing answer, so reuse it
$answer->id = $oldanswer->id;
$answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, $this->fileoptionsa, $answer->feedback);
$DB->update_record("question_answers", $answer);
} else { // This is a completely new answer
$answer->id = $DB->insert_record("question_answers", $answer);
$answer->feedback = file_save_draft_area_files(
$question->feedback[$key]['itemid'], $context->id, 'question',
'answerfeedback', $answer->id, $this->fileoptionsa, $answer->feedback);
$DB->update_record('question_answers', $answer);
} else {
// This is a completely new answer
$answer->id = $DB->insert_record('question_answers', $answer);
if (isset($files)) {
$feedbacktext = $answer->feedback;
foreach ($files as $file) {
$this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
$this->import_file($context, 'question', 'answerfeedback',
$answer->id, $file);
}
} else {
$feedbacktext = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, $this->fileoptionsa, $answer->feedback);
$feedbacktext = file_save_draft_area_files(
$question->feedback[$key]['itemid'], $context->id,
'question', 'answerfeedback', $answer->id,
$this->fileoptionsa, $answer->feedback);
}
$DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$answer->id));
$DB->set_field('question_answers', 'feedback', $feedbacktext,
array('id'=>$answer->id));
}
// Set up the options object
@@ -163,20 +173,19 @@ class question_calculatedmulti_qtype extends qtype_calculated {
}
// delete old answer records
if (!empty($oldanswers)) {
foreach($oldanswers as $oa) {
foreach ($oldanswers as $oa) {
$DB->delete_records('question_answers', array('id' => $oa->id));
}
}
// delete old answer records
if (!empty($oldoptions)) {
foreach($oldoptions as $oo) {
foreach ($oldoptions as $oo) {
$DB->delete_records('question_calculated', array('id' => $oo->id));
}
}
if( isset($question->import_process)&&$question->import_process){
if (isset($question->import_process) && $question->import_process) {
$this->import_datasets($question);
}
// Report any problems.
@@ -186,9 +195,9 @@ class question_calculatedmulti_qtype extends qtype_calculated {
return true;
}
function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) {
public function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) {
// Find out how many datasets are available
global $CFG, $DB, $QTYPES, $OUTPUT ;
global $CFG, $DB, $OUTPUT;
$maxnumber = (int)$DB->get_field_sql(
"SELECT MIN(a.itemcount)
FROM {question_dataset_definitions} a, {question_datasets} b
@@ -199,27 +208,29 @@ class question_calculatedmulti_qtype extends qtype_calculated {
$sql = "SELECT i.*
FROM {question_datasets} d, {question_dataset_definitions} i
WHERE d.question = ? AND d.datasetdefinition = i.id AND i.category != 0";
if (!$question->options->synchronize || !$records = $DB->get_records_sql($sql, array($question->id))) {
$synchronize_calculated = false ;
if (!$question->options->synchronize || !$records = $DB->get_records_sql($sql,
array($question->id))) {
$synchronize_calculated = false;
} else {
// i.e records is true so test coherence
$coherence = true ;
$a = new stdClass() ;
$a->qid = $question->id ;
$a->qcat = $question->category ;
foreach($records as $def ){
if ($def->category != $question->category){
$coherence = true;
$a = new stdClass();
$a->qid = $question->id;
$a->qcat = $question->category;
foreach ($records as $def) {
if ($def->category != $question->category) {
$a->name = $def->name;
$a->sharedcat = $def->category ;
$coherence = false ;
$a->sharedcat = $def->category;
$coherence = false;
break;
}
}
if(!$coherence){
echo $OUTPUT->notification(get_string('nocoherencequestionsdatyasetcategory','qtype_calculated',$a));
if (!$coherence) {
echo $OUTPUT->notification(
get_string('nocoherencequestionsdatyasetcategory', 'qtype_calculated', $a));
}
$synchronize_calculated = true ;
$synchronize_calculated = true;
}
// Choose a random dataset
@@ -227,19 +238,20 @@ class question_calculatedmulti_qtype extends qtype_calculated {
if ($maxnumber > qtype_calculated::MAX_DATASET_ITEMS) {
$maxnumber = qtype_calculated::MAX_DATASET_ITEMS;
}
if ( $synchronize_calculated === false ) {
if ($synchronize_calculated === false) {
$state->options->datasetitem = rand(1, $maxnumber);
}else{
$state->options->datasetitem = intval( $maxnumber * substr($attempt->timestart,-2) /100 ) ;
} else {
$state->options->datasetitem =
intval($maxnumber * substr($attempt->timestart, -2) /100);
if ($state->options->datasetitem < 1) {
$state->options->datasetitem =1 ;
} else if ($state->options->datasetitem > $maxnumber){
$state->options->datasetitem = $maxnumber ;
$state->options->datasetitem =1;
} else if ($state->options->datasetitem > $maxnumber) {
$state->options->datasetitem = $maxnumber;
}
};
$state->options->dataset =
$this->pick_question_dataset($question,$state->options->datasetitem);
$this->pick_question_dataset($question, $state->options->datasetitem);
// create an array of answerids ??? why so complicated ???
$answerids = array_values(array_map(create_function('$val',
'return $val->id;'), $question->options->answers));
@@ -257,9 +269,9 @@ class question_calculatedmulti_qtype extends qtype_calculated {
return true;
}
function save_session_and_responses(&$question, &$state) {
public function save_session_and_responses(&$question, &$state) {
global $DB;
$responses = 'dataset'.$state->options->datasetitem.'-' ;
$responses = 'dataset'.$state->options->datasetitem.'-';
$responses .= implode(',', $state->options->order) . ':';
$responses .= implode(',', $state->responses);
@@ -268,7 +280,7 @@ class question_calculatedmulti_qtype extends qtype_calculated {
return true;
}
function create_runtime_question($question, $form) {
public function create_runtime_question($question, $form) {
$question = parent::create_runtime_question($question, $form);
$question->options->answers = array();
foreach ($form->answers as $key => $answer) {
@@ -284,13 +296,13 @@ class question_calculatedmulti_qtype extends qtype_calculated {
return $question;
}
function convert_answers (&$question, &$state){
public function convert_answers(&$question, &$state) {
foreach ($question->options->answers as $key => $answer) {
$answer->answer = $this->substitute_variables($answer->answer, $state->options->dataset);
$answer->answer = $this->substitute_variables(
$answer->answer, $state->options->dataset);
//evaluate the equations i.e {=5+4)
$qtext = "";
$qtextremaining = $answer->answer ;
// while (preg_match('~\{(=)|%[[:digit]]\.=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
$qtext = '';
$qtextremaining = $answer->answer;
while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
$qtextsplits = explode($regs1[0], $qtextremaining, 2);
@@ -299,9 +311,9 @@ class question_calculatedmulti_qtype extends qtype_calculated {
if (empty($regs1[1])) {
$str = '';
} else {
if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
$str=$formulaerrors ;
}else {
if ($formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
$str=$formulaerrors;
} else {
eval('$str = '.$regs1[1].';');
$texteval= qtype_calculated_calculate_answer(
$str, $state->options->dataset, $answer->tolerance,
@@ -310,67 +322,56 @@ class question_calculatedmulti_qtype extends qtype_calculated {
$str = $texteval->answer;
}
}
$qtext = $qtext.$str ;
$qtext = $qtext.$str;
}
$answer->answer = $qtext.$qtextremaining ; ;
$answer->answer = $qtext.$qtextremaining;;
}
}
function get_default_numerical_unit($question, $virtualqtype){
public function get_default_numerical_unit($question, $virtualqtype) {
$unit = '';
return $unit ;
return $unit;
}
function grade_responses(&$question, &$state, $cmoptions) {
public function grade_responses(&$question, &$state, $cmoptions) {
// Forward the grading to the virtual qtype
// We modify the question to look like a multichoice question
// for grading nothing to do
/* $numericalquestion = fullclone($question);
foreach ($numericalquestion->options->answers as $key => $answer) {
$answer = $numericalquestion->options->answers[$key]->answer; // for PHP 4.x
$numericalquestion->options->answers[$key]->answer = $this->substitute_variables_and_eval($answer,
$state->options->dataset);
}*/
$virtualqtype = $this->get_virtual_qtype( $question);
return $virtualqtype->grade_responses($question, $state, $cmoptions) ;
$virtualqtype = $this->get_virtual_qtype($question);
return $virtualqtype->grade_responses($question, $state, $cmoptions);
}
// ULPGC ecastro
function get_actual_response(&$question, &$state) {
public function get_actual_response(&$question, &$state) {
// Substitute variables in questiontext before giving the data to the
// virtual type
$virtualqtype = $this->get_virtual_qtype( $question);
$unit = '' ;//$virtualqtype->get_default_numerical_unit($question);
$virtualqtype = $this->get_virtual_qtype($question);
$unit = '';
// We modify the question to look like a multichoice question
$numericalquestion = clone($question);
$this->convert_answers ($numericalquestion, $state);
$this->convert_questiontext ($numericalquestion, $state);
/* $numericalquestion->questiontext = $this->substitute_variables_and_eval(
$numericalquestion->questiontext, $state->options->dataset);*/
$responses = $virtualqtype->get_all_responses($numericalquestion, $state);
$response = reset($responses->responses);
$correct = $response->answer.' : ';
$responses = $virtualqtype->get_actual_response($numericalquestion, $state);
foreach ($responses as $key=>$response){
$responses[$key] = $correct.$response;
foreach ($responses as $key => $response) {
$responses[$key] = $correct . $response;
}
return $responses;
}
function create_virtual_qtype() {
public function create_virtual_qtype() {
global $CFG;
require_once("$CFG->dirroot/question/type/multichoice/questiontype.php");
return new question_multichoice_qtype();
}
function comment_header($question) {
//$this->get_question_options($question);
public function comment_header($question) {
$strheader = '';
$delimiter = '';
@@ -387,18 +388,13 @@ class question_calculatedmulti_qtype extends qtype_calculated {
return $strheader;
}
function comment_on_datasetitems($qtypeobj,$questionid,$questiontext, $answers,$data, $number) { //multichoice_
public function comment_on_datasetitems($qtypeobj, $questionid, $questiontext,
$answers, $data, $number) {
global $DB;
$comment = new stdClass();
$comment->stranswers = array();
$comment->outsidelimit = false ;
$comment->outsidelimit = false;
$comment->answers = array();
/// Find a default unit:
/* if (!empty($questionid) && $unit = $DB->get_record('question_numerical_units', array('question'=> $questionid, 'multiplier' => 1.0))) {
$unit = $unit->unit;
} else {
$unit = '';
}*/
$answers = fullclone($answers);
$strmin = get_string('min');
@@ -408,109 +404,45 @@ class question_calculatedmulti_qtype extends qtype_calculated {
foreach ($answers as $key => $answer) {
$answer->answer = $this->substitute_variables($answer->answer, $data);
//evaluate the equations i.e {=5+4)
$qtext = "";
$qtextremaining = $answer->answer ;
while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
$qtext = '';
$qtextremaining = $answer->answer;
while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
$qtextsplits = explode($regs1[0], $qtextremaining, 2);
$qtext =$qtext.$qtextsplits[0];
$qtextremaining = $qtextsplits[1];
if (empty($regs1[1])) {
$str = '';
} else {
if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
$str=$formulaerrors ;
}else {
if ($formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
$str=$formulaerrors;
} else {
eval('$str = '.$regs1[1].';');
}
}
$qtext = $qtext.$str ;
$qtext = $qtext.$str;
}
$answer->answer = $qtext.$qtextremaining;
$comment->stranswers[$key] = $answer->answer;
/* $formula = $this->substitute_variables($answer->answer,$data);
$formattedanswer = qtype_calculated_calculate_answer(
$answer->answer, $data, $answer->tolerance,
$answer->tolerancetype, $answer->correctanswerlength,
$answer->correctanswerformat, $unit);
if ( $formula === '*'){
$answer->min = ' ';
$formattedanswer->answer = $answer->answer ;
}else {
eval('$answer->answer = '.$formula.';') ;
$virtualqtype->get_tolerance_interval($answer);
}
if ($answer->min === '') {
// This should mean that something is wrong
$comment->stranswers[$key] = " $formattedanswer->answer".'<br/><br/>';
} else if ($formula === '*'){
$comment->stranswers[$key] = $formula.' = '.get_string('anyvalue','qtype_calculated').'<br/><br/><br/>';
}else{
$comment->stranswers[$key]= $formula.' = '.$formattedanswer->answer.'<br/>' ;
$comment->stranswers[$key] .= $strmin. $delimiter.$answer->min.'---';
$comment->stranswers[$key] .= $strmax.$delimiter.$answer->max;
$comment->stranswers[$key] .='<br/>';
$correcttrue->correct = $formattedanswer->answer ;
$correcttrue->true = $answer->answer ;
if ($formattedanswer->answer < $answer->min || $formattedanswer->answer > $answer->max){
$comment->outsidelimit = true ;
$comment->answers[$key] = $key;
$comment->stranswers[$key] .=get_string('trueansweroutsidelimits','qtype_calculated',$correcttrue);//<span class="error">ERROR True answer '..' outside limits</span>';
}else {
$comment->stranswers[$key] .=get_string('trueanswerinsidelimits','qtype_calculated',$correcttrue);//' True answer :'.$calculated->trueanswer.' inside limits';
}
$comment->stranswers[$key] .='';
}*/
}
return fullclone($comment);
}
function get_correct_responses1(&$question, &$state) {
$virtualqtype = $this->get_virtual_qtype( $question);
/* if ($question->options->multichoice != 1 ) {
if($unit = $virtualqtype->get_default_numerical_unit($question)){
$unit = $unit->unit;
} else {
$unit = '';
}
foreach ($question->options->answers as $answer) {
if (((int) $answer->fraction) === 1) {
$answernumerical = qtype_calculated_calculate_answer(
$answer->answer, $state->options->dataset, $answer->tolerance,
$answer->tolerancetype, $answer->correctanswerlength,
$answer->correctanswerformat, ''); // remove unit
$correct = array('' => $answernumerical->answer);
$correct['answer']= $correct[''];
if (isset($correct['']) && $correct[''] != '*' && $unit ) {
$correct[''] .= ' '.$unit;
$correct['unit']= $unit;
}
return $correct;
}
}
}else{**/
return $virtualqtype->get_correct_responses($question, $state) ;
// }
return null;
public function get_correct_responses1(&$question, &$state) {
$virtualqtype = $this->get_vir(al_qtype($question));
return $virtualqtype->get_correct_responses($question, $state);
}
function get_virtual_qtype() {
global $QTYPES;
// if ( isset($question->options->multichoice) && $question->options->multichoice == '1'){
$this->virtualqtype =& $QTYPES['multichoice'];
// }else {
// $this->virtualqtype =& $QTYPES['numerical'];
// }
public function get_virtual_qtype() {
$this->virtualqtype = $QTYPES['multichoice'];
return $this->virtualqtype;
}
/**
* Runs all the code required to set up and save an essay question for testing purposes.
* Alternate DB table prefix may be used to facilitate data deletion.
*/
function generate_test($name, $courseid = null) {
public function generate_test($name, $courseid = null) {
global $DB;
list($form, $question) = parent::generate_test($name, $courseid);
$form->feedback = 1;
@@ -534,15 +466,14 @@ class question_calculatedmulti_qtype extends qtype_calculated {
$new_question = $this->save_question($question, $form);
$dataset_form = new stdClass();
$dataset_form->nextpageparam["forceregeneration"]= 1;
$dataset_form->nextpageparam['forceregeneration']= 1;
$dataset_form->calcmin = array(1 => 1.0, 2 => 1.0);
$dataset_form->calcmax = array(1 => 10.0, 2 => 10.0);
$dataset_form->calclength = array(1 => 1, 2 => 1);
$dataset_form->number = array(1 => 5.4 , 2 => 4.9);
$dataset_form->itemid = array(1 => '' , 2 => '');
$dataset_form->number = array(1 => 5.4, 2 => 4.9);
$dataset_form->itemid = array(1 => '', 2 => '');
$dataset_form->calcdistribution = array(1 => 'uniform', 2 => 'uniform');
$dataset_form->definition = array(1 => "1-0-a",
2 => "1-0-b");
$dataset_form->definition = array(1 => "1-0-a", 2 => "1-0-b");
$dataset_form->nextpageparam = array('forceregeneration' => false);
$dataset_form->addbutton = 1;
$dataset_form->selectadd = 1;
@@ -554,7 +485,7 @@ class question_calculatedmulti_qtype extends qtype_calculated {
return $new_question;
}
function move_files($questionid, $oldcontextid, $newcontextid) {
public function move_files($questionid, $oldcontextid, $newcontextid) {
$fs = get_file_storage();
parent::move_files($questionid, $oldcontextid, $newcontextid);
@@ -573,12 +504,15 @@ class question_calculatedmulti_qtype extends qtype_calculated {
parent::delete_files($questionid, $contextid);
$this->delete_files_in_answers($questionid, $contextid, true);
$fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid);
$fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid);
$fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid);
$fs->delete_area_files($contextid, 'qtype_calculatedmulti',
'correctfeedback', $questionid);
$fs->delete_area_files($contextid, 'qtype_calculatedmulti',
'partiallycorrectfeedback', $questionid);
$fs->delete_area_files($contextid, 'qtype_calculatedmulti',
'incorrectfeedback', $questionid);
}
function check_file_access($question, $state, $options, $contextid, $component,
public function check_file_access($question, $state, $options, $contextid, $component,
$filearea, $args) {
$itemid = reset($args);
@@ -586,7 +520,8 @@ class question_calculatedmulti_qtype extends qtype_calculated {
$question->maxgrade = $question->defaultgrade;
}
if (in_array($filearea, array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'))) {
if (in_array($filearea, array('correctfeedback', 'partiallycorrectfeedback',
'incorrectfeedback'))) {
$result = $options->feedback && ($itemid == $question->id);
if (!$result) {
return false;
@@ -603,16 +538,10 @@ class question_calculatedmulti_qtype extends qtype_calculated {
}
return true;
} else if ($component == 'question' && $filearea == 'answerfeedback') {
return $options->feedback && (array_key_exists($itemid, $question->options->answers));
return $options->feedback && array_key_exists($itemid, $question->options->answers);
} else {
return parent::check_file_access($question, $state, $options, $contextid, $component,
$filearea, $args);
}
}
}
//// END OF CLASS ////
if ( ! defined ("CALCULATEDMULTI")) {
define("CALCULATEDMULTI", "calculatedmulti");
}