MDL-24503 recoding unit grading options
This commit is contained in:
@@ -17,11 +17,20 @@
|
||||
<div class="answer">
|
||||
<fieldset class="answer" id="generalheader">
|
||||
<legend class="ftoggler">
|
||||
<?php echo get_string('datasetnumber', 'quiz') ; ?>
|
||||
<?php
|
||||
echo $OUTPUT->help_icon('validnumberformats', 'qtype_numerical', '');
|
||||
echo get_string('datasetnumber', 'quiz') ;
|
||||
?>
|
||||
</legend>
|
||||
<input type="text" class="<?php echo $class; ?>" <?php echo "$readonly $nameanswer $valueanswer"; //
|
||||
?> size="<?php echo $textlength;?>" />
|
||||
<?php echo $feedbackimg; ?>
|
||||
<?php echo $feedbackimg;
|
||||
if(! $answerasterisk && $question->options->unitgradingtype != 0 && $unit_in_numerical_answer){
|
||||
print_string('nonvalidcharactersinnumber', 'qtype_numerical');
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
@@ -44,27 +53,37 @@
|
||||
<div class="answer numerical ">
|
||||
<fieldset class="clearfix" id="generalheader">
|
||||
<legend class="ftoggler">
|
||||
<?php echo get_string('unit', 'quiz'); ?>
|
||||
<?php
|
||||
if ( $question->options->unitgradingtype == 0 ){
|
||||
echo $OUTPUT->help_icon('unitoptional', 'qtype_numerical', '');
|
||||
}else { // unitgradingtype == 1
|
||||
echo $OUTPUT->help_icon('unitmandatory', 'qtype_numerical', '');
|
||||
}
|
||||
echo get_string('unit', 'quiz'); ?>
|
||||
</legend>
|
||||
<input type="text" class="<?php echo $classunit; ?>" <?php echo "$readonly $nameunit $valueunit"; //
|
||||
?> size="<?php echo $textlength;?>"/>
|
||||
<?php echo $feedbackimgunit;
|
||||
if ($options->feedback && $classunitvalue == 0 && ! $answerasterisk ){
|
||||
if(isset($question->options->units) && count($question->options->units) > 0){
|
||||
$found = 0 ;
|
||||
foreach($question->options->units as $key => $unit){
|
||||
if($state->responses['unit'] == $unit->unit){
|
||||
print_string('unitnotvalid', 'qtype_numerical');
|
||||
$found = 1 ;
|
||||
break;
|
||||
if ($options->feedback && $question->options->unitgradingtype == 1 && ! $valid_numerical_unit && ! $answerasterisk ){
|
||||
if ( $empty_unit) {
|
||||
print_string('unitmandatory', 'qtype_numerical');
|
||||
}else {
|
||||
if(isset($question->options->units) && count($question->options->units) > 0){
|
||||
$found = 0 ;
|
||||
$valid_unit_found = 0 ;
|
||||
foreach($question->options->units as $key => $unit){
|
||||
if($state->responses['unit'] == $unit->unit){
|
||||
print_string('unitnotvalid', 'qtype_numerical');
|
||||
$valid_unit_found = 1 ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($valid_unit_found == 0) {
|
||||
print_string('unitunknown', 'qtype_numerical');
|
||||
}
|
||||
}
|
||||
if ($found == 0) {
|
||||
print_string('unitunknown', 'qtype_numerical');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
</fieldset>
|
||||
</div>
|
||||
@@ -106,65 +125,98 @@
|
||||
<div class="answer">
|
||||
<fieldset class="clearfix" id="generalheader">
|
||||
<legend class="ftoggler">
|
||||
<?php echo get_string('unit', 'quiz');
|
||||
<?php
|
||||
echo get_string('selectunit', 'qtype_numerical');
|
||||
?>
|
||||
</legend>
|
||||
<!-- <div class="que multichoice clearfix">
|
||||
<div class="content"> class="answer"
|
||||
<div class="ablock clearfix"> -->
|
||||
<table >
|
||||
<table >
|
||||
|
||||
<?php
|
||||
// the order is not shuffled
|
||||
//however the unitvalue is related to the number value
|
||||
// if the response/unit->multiplier is true then
|
||||
// the
|
||||
|
||||
// if(isset($state->responses['unit']) && $state->responses['unit'] != '' ){
|
||||
$valid_numerical_unit_index = -1;
|
||||
foreach ($question->options->units as $key => $unit) {
|
||||
$checked = '';
|
||||
$chosen = false;
|
||||
$classunitvalue = 0 ;
|
||||
$checked = '';
|
||||
$chosen = false;
|
||||
$classunit = 0 ;
|
||||
$feedbackimgunit = question_get_feedback_image(0);
|
||||
$valid_numerical_unit = false ;
|
||||
$validunit = false ;
|
||||
$type = 'type="radio"';
|
||||
// $nameunit = "name=\"".$question->name_prefix;//."unit\"";
|
||||
if ($response != '' && isset($state->responses['unit']) && $state->responses['unit'] != '' ){
|
||||
// we have a unit response
|
||||
// this unit is the one chosen
|
||||
// test if the unit give a valid response
|
||||
$testresponse = $response /$unit->multiplier ;
|
||||
if($answerasterisk || ($answer->min <= $testresponse && $testresponse <= $answer->max)) {
|
||||
$classunitvalue = $answer->fraction ;
|
||||
}
|
||||
// echo "<p> dans display classunitvalue $classunitvalue response $response $unit->multiplier $unit->unit state <pre>";print_r($answer);echo "</pre></p>";
|
||||
if ($state->responses['unit'] == $unit->unit) {
|
||||
$checked = 'checked="checked"';
|
||||
$chosen = true;
|
||||
|
||||
// echo "<p> boucle unit $key $unit->unit answerfraction $answer->fraction classunit $classunit index $valid_numerical_unit_index $key response $response $unit->multiplier $unit->unit state <pre>";print_r($answer);echo "</pre></p>";
|
||||
if(isset($state->responses['unit']) && $state->responses['unit'] != '' ){
|
||||
// $nameunit = "name=\"".$question->name_prefix;//."unit\"";
|
||||
// if (isset($response->number) && $response->number != false && isset($state->responses['unit']) && $state->responses['unit'] != '' ){
|
||||
// if ($unit->unit == $state->responses['unit']){
|
||||
// test if the numerical value as is or as multiplied by this unit
|
||||
// could give a good response
|
||||
// we need to extract the numerical and apply it with this unit
|
||||
// as if it was used
|
||||
$testresponse = $state->responses['answer']/$unit->multiplier ;
|
||||
/* if(isset($state->responses['unit'])){
|
||||
$testresponse .= $state->responses['unit'] ;
|
||||
} */
|
||||
$response = $this->apply_unit($testresponse, array($question->options->units[$key])) ;
|
||||
$invalid_unit_found = 0 ;
|
||||
if ($response !== false) {
|
||||
$this->get_tolerance_interval($answer);
|
||||
if($answer->min <= $response && $response <= $answer->max){
|
||||
// then it could give a good response
|
||||
// has it been used ?
|
||||
$classunit = 1; // or max response i.e. 1
|
||||
$feedbackimgunit = question_get_feedback_image($rawgrade);
|
||||
$valid_numerical_unit = true ;
|
||||
$validunit = true ;
|
||||
|
||||
$valid_numerical_unit_index = $key ;
|
||||
}
|
||||
}
|
||||
}else if ($key == 0) {
|
||||
}
|
||||
// if ($unit->unit == $state->responses['unit']){
|
||||
// we have a valid unit response
|
||||
if($answerasterisk || $valid_numerical_unit_index == $key ){
|
||||
$classunit = $rawgrade ; //question_get_feedback_class(1) ; // ;
|
||||
}
|
||||
// we have a unit response
|
||||
// this unit is the one chosen
|
||||
// test if the unit give a valid response
|
||||
// $testresponse = $response->number /$unit->multiplier ;
|
||||
// if($answerasterisk || ($answer->min <= $testresponse && $testresponse <= $answer->max)) {
|
||||
// $classunitvalue = $answer->fraction ;
|
||||
// }
|
||||
// echo "<p> dans display $answer->fraction classunit $classunit index $valid_numerical_unit_index $key response $response $unit->multiplier $unit->unit state <pre>";print_r($answer);echo "</pre></p>";
|
||||
// if ($state->responses['unit'] == $unit->unit) {
|
||||
if (isset($state->responses['unit']) && $unit->unit == $state->responses['unit']){
|
||||
$checked = 'checked="checked"';
|
||||
$chosen = true;
|
||||
}else {
|
||||
$checked = '';
|
||||
}
|
||||
|
||||
$aid = $question->id ;
|
||||
$a = new stdClass;
|
||||
$a->id = $question->name_prefix."unit" ;//. "2"
|
||||
$a->class = '' ;
|
||||
$a->feedbackimg = '';
|
||||
|
||||
$a->control = "<input $readonly $nameunit $checked $type value=\"$key\" />";
|
||||
|
||||
if ($options->correct_responses && $classunitvalue > 0 ) { //$answer->fraction
|
||||
$a->class = question_get_feedback_class($classunitvalue);
|
||||
}
|
||||
if (($options->feedback && $chosen) || $options->correct_responses) {
|
||||
$a->feedbackimg = question_get_feedback_image($classunitvalue, $chosen && $options->feedback);
|
||||
}
|
||||
|
||||
// Print the control
|
||||
// Print the answer text
|
||||
$a->text = format_text($unit->unit, FORMAT_MOODLE, $formatoptions, $cmoptions->course);
|
||||
$row = 0 ;
|
||||
|
||||
|
||||
|
||||
$aid = $question->id ;
|
||||
$a = new stdClass;
|
||||
$a->id = $question->name_prefix."unit" ;//. "2"
|
||||
$a->class = '' ;
|
||||
$a->feedbackimg = '';
|
||||
|
||||
$a->control = "<input $readonly $nameunit $checked $type value=\"$key\" />";
|
||||
|
||||
if ($options->correct_responses && $classunit > 0 ) { //$answer->fraction
|
||||
$a->class = question_get_feedback_class($classunit);
|
||||
}
|
||||
if (($options->feedback && $chosen) || $options->correct_responses) {
|
||||
$a->feedbackimg = question_get_feedback_image($classunit, $chosen && $options->feedback);
|
||||
}
|
||||
|
||||
// Print the control
|
||||
// Print the answer text
|
||||
$a->text = format_text($unit->unit, FORMAT_MOODLE, $formatoptions, $cmoptions->course);
|
||||
$row = 0 ;
|
||||
|
||||
?>
|
||||
<tr class="<?php echo 'r'.$row = $row ? 0 : 1; ?>">
|
||||
<td class="c0 control " style=" ">
|
||||
@@ -174,22 +226,24 @@
|
||||
<label for="<?php echo $a->id ?>">
|
||||
<?php echo $a->text.'<br />'; ?>
|
||||
<?php echo $a->feedbackimg;
|
||||
if ($options->feedback && $classunitvalue == 0 && $chosen && !$answerasterisk){
|
||||
if ($options->feedback && $classunit == 0 && $chosen && !$answerasterisk){
|
||||
print_string('unitnotvalid', 'qtype_numerical');
|
||||
}else {
|
||||
echo ' ';
|
||||
}
|
||||
?>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
|
||||
</table>
|
||||
<!-- </div>
|
||||
</div>
|
||||
</div> -->
|
||||
</fieldset>
|
||||
|
||||
|
||||
<?php if ($options->feedback && isset($state->responses['answer'])&& $state->responses['answer'] != '' && (!isset($state->responses['unit']) || $state->responses['unit'] == '') && ! $answerasterisk ){
|
||||
|
||||
print_string('unitnotselected', 'qtype_numerical');
|
||||
}
|
||||
?>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
<?php } // end unit choices
|
||||
// display intructions
|
||||
@@ -201,7 +255,10 @@
|
||||
<div class="answer">
|
||||
<fieldset class="clearfix" id="generalheader">
|
||||
<legend class="ftoggler">
|
||||
<?php echo get_string('datasetnumber', 'quiz'); ?>
|
||||
<?php
|
||||
echo $OUTPUT->help_icon('validnumberformats', 'qtype_numerical', '');
|
||||
echo get_string('datasetnumber', 'quiz');
|
||||
?>
|
||||
</legend>
|
||||
<input type="text" class="<?php echo $class; ?>" <?php echo "$readonly $nameanswer $valueanswer"; //
|
||||
?> size="<?php echo $textlength;?>"/>
|
||||
@@ -215,29 +272,18 @@
|
||||
</div>
|
||||
|
||||
|
||||
<?php if (!empty($question->options->instructions)){?>
|
||||
<div class="feedback">
|
||||
<fieldset class="clearfix" id="generalheader">
|
||||
<legend class="ftoggler">
|
||||
<?php echo get_string('instructions', 'auth'); ?>
|
||||
</legend>
|
||||
<div class="feedback">
|
||||
<fieldset class="clearfix" id="generalheader">
|
||||
<legend class="ftoggler">
|
||||
<?php echo get_string('validnumberformats', 'qtype_numerical');?>
|
||||
</legend>
|
||||
<?php echo get_string('validnumbers', 'qtype_numerical');
|
||||
|
||||
?>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
<?php if (!empty($question->options->instructions)){?>
|
||||
<div>
|
||||
<?php echo format_text($question->options->instructions, $question->options->instructionsformat, $formatoptions, $cmoptions->course);?>
|
||||
</div>
|
||||
<?php }?>
|
||||
</fieldset>
|
||||
</div>
|
||||
<?php }?>
|
||||
|
||||
<?php if ($feedback) { ?>
|
||||
<div class="feedback">
|
||||
|
||||
@@ -86,15 +86,6 @@ class question_edit_numerical_form extends question_edit_form {
|
||||
}
|
||||
$QTYPES['numerical']->set_numerical_unit_data($this, $question, $default_values);
|
||||
|
||||
/* if (isset($question->options->units)){
|
||||
$units = array_values($question->options->units);
|
||||
if (!empty($units)) {
|
||||
foreach ($units as $key => $unit){
|
||||
$default_values['unit['.$key.']'] = $unit->unit;
|
||||
$default_values['multiplier['.$key.']'] = $unit->multiplier;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
$question = (object)((array)$question + $default_values);
|
||||
}
|
||||
return $question;
|
||||
|
||||
@@ -37,6 +37,7 @@ $string['errorrepeatedunit'] = 'You cannot have two units with the same name.';
|
||||
$string['instructions'] = 'Instructions ';
|
||||
$string['leftexample'] = 'LEFT as $1.00';
|
||||
$string['noneditableunittext'] = 'NON editable text of Unit No1';
|
||||
$string['nonvalidcharactersinnumber'] = 'NON valid characters in number';
|
||||
$string['notenoughanswers'] = 'You must enter at least one answer.';
|
||||
$string['nounitdisplay'] = 'No unit grading';
|
||||
$string['numerical'] = 'Numerical';
|
||||
@@ -56,22 +57,62 @@ The first unit (Unit 1) has a default multiplier of 1. Thus if the correct numer
|
||||
If you add the unit kW with a multiplier of 0.001, this will add a correct response of 5.5 kW. This means that the answers 5500W or 5.5kW would be marked correct.
|
||||
|
||||
Note that the accepted error is also multiplied, so an allowed error of 100W would become an error of 0.1kW.';
|
||||
$string['onlynumerical'] = 'Only NUMERICAL ANSWER will be graded';
|
||||
$string['manynumerical'] = 'Only the NUMERICAL ANSWER will be graded using optional units ';
|
||||
$string['onlynumerical'] = 'Only the NUMERICAL ANSWER will be graded, no units allowed';
|
||||
$string['oneunitshown'] = 'Only the NUMERICAL ANSWER will be graded, Unit1 will be shown';
|
||||
$string['rightexample'] = 'RIGHT as 1.00cm';
|
||||
$string['selectunits'] = 'Select units';
|
||||
$string['selectunit'] = 'Select one unit';
|
||||
$string['studentunitanswer'] = 'UNIT ANSWER displayed as a ';
|
||||
$string['unitchoice'] = 'Multichoice (radio elements)';
|
||||
$string['unitdisplay'] = 'Display Unit1';
|
||||
$string['unitdisplay'] = '<STRONG>Unit 1 displayed </STRONG>';
|
||||
$string['unitedit'] = 'Edit unit';
|
||||
$string['unitgraded'] = ' NUMERICAL ANSWER and UNIT ANSWER will be graded ';
|
||||
$string['unitgraded'] = ' NUMERICAL ANSWER and UNIT ANSWER will be graded ';
|
||||
$string['unitgraded1'] = '<STRONG>UNIT GRADED</STRONG>';
|
||||
$string['unitsused'] = '<STRONG>UNIT USED</STRONG>';
|
||||
$string['unithdr'] = 'Unit {$a}';
|
||||
$string['unitmandatory'] = 'Mandatory';
|
||||
$string['unitmandatory_help'] = '
|
||||
|
||||
* The response will be graded using the unit written.
|
||||
|
||||
* The unit penalty will be applied if the unit field is empty
|
||||
|
||||
';
|
||||
$string['unitnotgraded'] = '<STRONG>UNIT NOT GRADED</STRONG>';
|
||||
$string['unitnotused'] = '<STRONG>UNIT NOT USED</STRONG>';
|
||||
$string['unitoptional'] = 'Optional unit';
|
||||
$string['unitoptional_help'] = '
|
||||
* If the unit field is not empty, the response will be graded using this unit.
|
||||
|
||||
* If the unit is badly written or unknown, the response will be considered as non valid.
|
||||
';
|
||||
$string['unitused'] = '<STRONG>UNIT USED</STRONG>';
|
||||
$string['unituses'] = 'Unit uses';
|
||||
$string['unituses_help'] = 'The unit(s) are uses as in pre 2,0 Moodle version
|
||||
|
||||
* The student can answer using units predefined by the teacher
|
||||
* in which case the constant will be applied to the student value.
|
||||
* If the student does not add any unit, his numerical answer is used as is.';
|
||||
$string['unitnotvalid'] = ' Unit not valid with this numerical value';
|
||||
$string['unitunknown'] = ' Undefined unit ';
|
||||
$string['unitpenalty'] = 'Penalty for bad unit';
|
||||
$string['unitpenalty'] = 'Unit penalty';
|
||||
$string['unitpenalty_help'] = 'The penalty is applied if
|
||||
|
||||
* An undefined unit name is put in the Unit answer element or
|
||||
* An unit name is put in the Number answer element ';
|
||||
$string['unitappliedpenalty'] = 'These marks include a penalty of {$a} for bad unit.';
|
||||
$string['unitposition'] = 'Unit position';
|
||||
$string['unitnotselected'] = 'No unit selected';
|
||||
$string['unitshandling'] = 'Units handling';
|
||||
$string['validnumberformats'] = 'Valid number formats';
|
||||
$string['validnumberformats_help'] = '
|
||||
* regular numbers 13500.67 : 13 500.67 : 13500,67: 13 500,67
|
||||
|
||||
* if you use , as thousand separator *always* put the decimal . as in
|
||||
13,500.67 : 13,500.
|
||||
|
||||
* for exponent form, say 1.350067 * 10<sup>4</sup>, use
|
||||
1.350067 E4 : 1.350067 E04 ';
|
||||
|
||||
$string['validnumbers'] = ' 13500.67 : 13 500.67 : 13,500.67 : 13500,67: 13 500,67 : 1.350067 E4 : 1.350067 E04 ';
|
||||
|
||||
@@ -87,35 +87,6 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
|
||||
return true;
|
||||
}
|
||||
function get_numerical_options(&$question) {
|
||||
global $DB;
|
||||
if (!$options = $DB->get_record('question_numerical_options', array('question' => $question->id))) {
|
||||
$question->options->unitgradingtype = 0; // total grade
|
||||
$question->options->unitpenalty = 0;
|
||||
// the default
|
||||
if ($defaultunit = $this->get_default_numerical_unit($question)) {
|
||||
// so units can be graded
|
||||
$question->options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
|
||||
$question->options->unitpenalty = 1;
|
||||
}else {
|
||||
// only numerical will be graded
|
||||
$question->options->showunits = NUMERICALQUESTIONUNITNODISPLAY ;
|
||||
}
|
||||
$question->options->unitsleft = 0 ;
|
||||
$question->options->instructions = '';
|
||||
$question->options->instructionsformat = editors_get_preferred_format();
|
||||
} else {
|
||||
$question->options->unitgradingtype = $options->unitgradingtype;
|
||||
$question->options->unitpenalty = $options->unitpenalty;
|
||||
$question->options->showunits = $options->showunits;
|
||||
$question->options->unitsleft = $options->unitsleft;
|
||||
$question->options->instructions = $options->instructions;
|
||||
$question->options->instructionsformat = $options->instructionsformat;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function get_numerical_units(&$question) {
|
||||
global $DB;
|
||||
if ($units = $DB->get_records('question_numerical_units', array('question' => $question->id), 'id ASC')) {
|
||||
@@ -141,6 +112,35 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_numerical_options(&$question) {
|
||||
global $DB;
|
||||
if (!$options = $DB->get_record('question_numerical_options', array('question' => $question->id))) {
|
||||
$question->options->unitgradingtype = 0; // total grade
|
||||
$question->options->unitpenalty = 0.1; // default for old questions
|
||||
// the default
|
||||
if ($defaultunit = $this->get_default_numerical_unit($question)) {
|
||||
// so units can be graded
|
||||
$question->options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
|
||||
}else {
|
||||
// only numerical will be graded
|
||||
$question->options->showunits = NUMERICALQUESTIONUNITNODISPLAY ;
|
||||
}
|
||||
$question->options->unitsleft = 0 ;
|
||||
$question->options->instructions = '';
|
||||
$question->options->instructionsformat = editors_get_preferred_format();
|
||||
} else {
|
||||
$question->options->unitgradingtype = $options->unitgradingtype;
|
||||
$question->options->unitpenalty = $options->unitpenalty;
|
||||
$question->options->showunits = $options->showunits;
|
||||
$question->options->unitsleft = $options->unitsleft;
|
||||
$question->options->instructions = $options->instructions;
|
||||
$question->options->instructionsformat = $options->instructionsformat;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the units and the answers associated with this question.
|
||||
*/
|
||||
@@ -178,7 +178,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
if (trim($dataanswer) === '*') {
|
||||
$answer->answer = '*';
|
||||
} else {
|
||||
$answer->answer = $this->apply_unit_old($dataanswer, $units);
|
||||
$answer->answer = $this->apply_unit($dataanswer, $units);
|
||||
if ($answer->answer === false) {
|
||||
$result->notice = get_string('invalidnumericanswer', 'quiz');
|
||||
}
|
||||
@@ -212,7 +212,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
if (trim($question->tolerance[$key]) == '') {
|
||||
$options->tolerance = '';
|
||||
} else {
|
||||
$options->tolerance = $this->apply_unit_old($question->tolerance[$key], $units);
|
||||
$options->tolerance = $this->apply_unit($question->tolerance[$key], $units);
|
||||
if ($options->tolerance === false) {
|
||||
$result->notice = get_string('invalidnumerictolerance', 'quiz');
|
||||
}
|
||||
@@ -249,8 +249,17 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The numerical options control the display and the grading of the unit
|
||||
* part of the numerical question and related types (calculateds)
|
||||
* Questions previous to 2,0 do not have this table as multianswer questions
|
||||
* in all versions including 2,0. The default values are set to give the same grade
|
||||
* as old question.
|
||||
*
|
||||
*/
|
||||
function save_numerical_options(&$question) {
|
||||
global $DB;
|
||||
// echo"<p> ".$question->id."question<pre>";print_r($question) ;echo"</pre></p>";
|
||||
|
||||
$result = new stdClass;
|
||||
// numerical options
|
||||
@@ -261,29 +270,36 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
$options = new stdClass;
|
||||
$options->question = $question->id;
|
||||
}
|
||||
if(isset($question->unitgradingtype)){
|
||||
$options->unitgradingtype = $question->unitgradingtype;
|
||||
if(isset($question->options->unitgradingtype)){
|
||||
$options->unitgradingtype = $question->options->unitgradingtype;
|
||||
}else {
|
||||
$options->unitgradingtype = 0 ;
|
||||
}
|
||||
if(isset($question->unitpenalty)){
|
||||
$options->unitpenalty = $question->unitpenalty;
|
||||
}else {
|
||||
$options->unitpenalty = 0 ;
|
||||
}else { //so this is either an old question or a close question type
|
||||
$options->unitpenalty = 1 ;
|
||||
}
|
||||
// if we came from the form then 'unitrole' exists
|
||||
if(isset($question->unitrole)){
|
||||
if ($question->unitrole == 0 ){
|
||||
$options->showunits = $question->showunits0;
|
||||
}else {
|
||||
$options->showunits = $question->showunits1;
|
||||
switch ($question->unitrole){
|
||||
case '0' : $options->showunits = NUMERICALQUESTIONUNITNODISPLAY ;
|
||||
break ;
|
||||
case '1' : $options->showunits = NUMERICALQUESTIONUNITTEXTDISPLAY ;
|
||||
break ;
|
||||
case '2' : $options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
|
||||
$options->unitgradingtype = 0 ;
|
||||
break ;
|
||||
case '3' : $options->showunits = $question->multichoicedisplay ;
|
||||
$options->unitgradingtype = $question->unitgradingtypes ;
|
||||
break ;
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
if(isset($question->showunits)){
|
||||
$options->showunits = $question->showunits;
|
||||
}else {
|
||||
if ($defaultunit = $this->get_default_numerical_unit($question)) {
|
||||
// so units can be graded
|
||||
// so units can be used
|
||||
$options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
|
||||
}else {
|
||||
// only numerical will be graded
|
||||
@@ -342,7 +358,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
$unitalreadyinsert[$question->unit[$i]] = 1 ;
|
||||
$units[$i] = new stdClass;
|
||||
$units[$i]->question = $question->id;
|
||||
$units[$i]->multiplier = $this->apply_unit_old($question->multiplier[$i], array());
|
||||
$units[$i]->multiplier = $this->apply_unit($question->multiplier[$i], array());
|
||||
$units[$i]->unit = $question->unit[$i];
|
||||
$DB->insert_record('question_numerical_units', $units[$i]);
|
||||
}
|
||||
@@ -438,7 +454,10 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
* the separate rendering of number and unit
|
||||
*/
|
||||
function print_question_formulation_and_controls(&$question, &$state, $cmoptions, $options) {
|
||||
global $CFG;
|
||||
global $CFG, $OUTPUT;
|
||||
//echo"<p> ".$question->id."question->options<pre>";print_r($question->options) ;echo"</pre></p>";
|
||||
//echo"<p> ".$question->id."state<pre>";print_r($state) ;echo"</pre></p>";
|
||||
|
||||
$context = $this->get_context_by_category_id($question->category);
|
||||
$readonly = empty($options->readonly) ? '' : 'readonly="readonly"';
|
||||
$formatoptions = new stdClass;
|
||||
@@ -466,9 +485,11 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
// before i.e. at left or after at rigth of the unit variants.
|
||||
$nameanswer = "name=\"".$question->name_prefix."answer\"";
|
||||
$nameunit = "name=\"".$question->name_prefix."unit\"";
|
||||
// put old answer data in $state->responses['answer'] and $state->responses['unit']
|
||||
if (isset($state->responses['']) && $state->responses[''] != '' && !isset($state->responses['answer'])){
|
||||
$this->split_old_answer($state->responses[''], $question->options->units, $state->responses['answer'] ,$state->responses['unit'] );
|
||||
}
|
||||
// prepare the values of the input elements to be dispalyed answer i.e. number and unit
|
||||
if (isset($state->responses['answer']) && $state->responses['answer']!='') {
|
||||
$valueanswer = ' value="'.s($state->responses['answer']).'" ';
|
||||
} else {
|
||||
@@ -492,6 +513,8 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
$answerasterisk = false ;
|
||||
$response = '' ;
|
||||
$valid_numerical_unit = false ;
|
||||
$valid_numerical_unit_index = -1 ;
|
||||
$unit_in_numerical_answer = false ;
|
||||
$rawgrade = 0 ;
|
||||
if ($options->feedback) {
|
||||
$class = question_get_feedback_class(0);
|
||||
@@ -499,71 +522,129 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
$feedbackimg = question_get_feedback_image(0);
|
||||
$feedbackimgunit = question_get_feedback_image(0);
|
||||
$classunitvalue = 0 ;
|
||||
$valid_numerical_unit_index = -1 ;
|
||||
// if there is unit in answer and unitgradingtype = 0
|
||||
// the grade is 0
|
||||
//this is OK for the first answer with a good response
|
||||
// having to test for * so response as long as not empty
|
||||
$response = $this->extract_numerical_response($state->responses['answer']);
|
||||
$break = 0 ;
|
||||
// $response = $this->extract_numerical_response($state->responses['answer']);
|
||||
// test for a greater than 0 grade
|
||||
foreach($question->options->answers as $answer) {
|
||||
// if * then everything has the $answer->fraction value
|
||||
if ($answer->answer !== '*' ) {
|
||||
$this->get_tolerance_interval($answer);
|
||||
}
|
||||
|
||||
$answer->feedback = quiz_rewrite_question_urls($answer->feedback, 'pluginfile.php', $context->id, 'question', 'answerfeedback', array($state->attempt, $state->question), $answer->id);
|
||||
if ($answer->answer === '*') {
|
||||
$answerasterisk = true ;
|
||||
$rawgrade = $answer->fraction ;
|
||||
if ($this->test_response($question, $state, $answer)) {
|
||||
// Answer was correct or partially correct.
|
||||
if ( $answer->answer === '*'){
|
||||
$answerasterisk = true ;
|
||||
}
|
||||
// in all cases
|
||||
$class = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimg = question_get_feedback_image($answer->fraction);
|
||||
$classunitvalue = $class ;
|
||||
$classunit = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimgunit = question_get_feedback_image($answer->fraction, $options->feedback);
|
||||
if ($question->options->unitgradingtype == 0 || ($question->options->unitgradingtype == 0 && $answer->answer === '*')){
|
||||
// if * then unit has the $answer->fraction value
|
||||
// if $question->options->unitgradingtype == 0 everything has been checked
|
||||
// if $question->options->showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
// then number - unit combination has been used to test response
|
||||
// so the unit should have same color
|
||||
$classunit = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimgunit = question_get_feedback_image($answer->fraction);
|
||||
$rawgrade = $answer->fraction ;
|
||||
|
||||
|
||||
}else {
|
||||
// so we need to apply unit grading i.e. to check if the number-unit combination
|
||||
// was the rigth one
|
||||
// on NUMERICALQUESTIONUNITTEXTINPUTDISPLAY we need only to ckeck if applyunit will test OK
|
||||
// with the $state->responses['unit'] value which cannot be empty
|
||||
// if $state->responses['unit']
|
||||
// if apply-unit is true with a specific unit as long as the unit as been written either in the
|
||||
// we need the numerical response and test it with the available units
|
||||
// if the unit used is good then it should be set OK
|
||||
// however the unit could have been put in the number element in this case
|
||||
// the unit penalty should be apllied.
|
||||
// testing apply_unit with no units will get us a false response if there is any text in it
|
||||
// testing apply_unit with a given unit will get a good value if the number is good with this unit
|
||||
// apply unit will return the numerical if
|
||||
// we need to know which conditions let to a good numerical value that were done in the
|
||||
//
|
||||
// echo"<p> unit grading > 0 asterisk <pre>";print_r($answer) ;echo"</pre></p>";
|
||||
$valid_numerical_unit = false ;
|
||||
$validunit = false ;
|
||||
$rawgrade = $answer->fraction ;
|
||||
$valid_numerical_unit_index = -1 ;
|
||||
$invalid_unit_in_numerical_answer = false ;
|
||||
if ( $answerasterisk ) {
|
||||
$classunit = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimgunit = question_get_feedback_image($answer->fraction);
|
||||
$valid_numerical_unit = true ;//everything is true with *
|
||||
//echo"<p> answer asterisk <pre>";print_r($answer) ;echo"</pre></p>";
|
||||
} else {
|
||||
//echo"<p> else after answer asterisk <pre>";print_r($answer) ;echo"</pre></p>";
|
||||
// if( isset($state->responses['unit']) && $state->responses['unit'] != '' ){// unit should be written in the unit input or checked in multichoice
|
||||
// we need to see if something was written in the answer field that was not in the number
|
||||
// although we cannot actually detect units put before the number which will cause bad numerical.
|
||||
// use extract response
|
||||
$response = $this->extract_numerical_response($state->responses['answer']);
|
||||
if(isset($response->unit ) && $response->unit != ''){
|
||||
$unit_in_numerical_answer = true ;
|
||||
}else {
|
||||
$unit_in_numerical_answer = false ;
|
||||
}
|
||||
|
||||
// the we let the testing to the two cases either
|
||||
// NUMERICALQUESTIONUNITTEXTINPUTDISPLAY or
|
||||
// NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
|
||||
if( !isset($state->responses['unit']) || $state->responses['unit'] == '' ){
|
||||
// unit should be written in the unit input or checked in multichoice
|
||||
$valid_numerical_unit = false ;
|
||||
$classunit = question_get_feedback_class(0);
|
||||
$feedbackimgunit = question_get_feedback_image(0);
|
||||
$empty_unit = true ;
|
||||
} else {
|
||||
// echo"<p> some unit answer <pre>";print_r($answer) ;echo"</pre></p>";
|
||||
// echo"<p> some unit answer <pre>";print_r($answer) ;echo"</pre></p>";
|
||||
$empty_unit = false ;
|
||||
$valid_numerical_unit = false ;
|
||||
|
||||
foreach ($question->options->units as $key => $unit) {
|
||||
if ($unit->unit == $state->responses['unit']){
|
||||
// $response = $this->apply_unit($state->responses['answer'].$unit->unit, array($question->options->units[$key])) ;
|
||||
// echo "<p> avant false valid_numerical_unit_index $valid_numerical_unit_index ".$state->responses['answer']."</p>";
|
||||
$invalid_unit_found = 0 ;
|
||||
if ($response->number !== false) {
|
||||
//echo "<p> avanr get valid_numerical_unit_index $valid_numerical_unit_index </p>";
|
||||
// $this->get_tolerance_interval($answer);
|
||||
$testresponse = $response->number /$unit->multiplier ;
|
||||
if($answer->min <= $testresponse && $testresponse <= $answer->max){
|
||||
//echo "<p> apres min max valid_numerical_unit_index $valid_numerical_unit_index </p>";
|
||||
$classunit = question_get_feedback_class($answer->fraction) ; //question_get_feedback_class(1);
|
||||
$feedbackimgunit = question_get_feedback_image($rawgrade);
|
||||
$valid_numerical_unit = true ;
|
||||
$validunit = true ;
|
||||
$valid_numerical_unit_index = $key ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
} // else
|
||||
|
||||
// }
|
||||
}
|
||||
//echo "<p> apres la boucle valid_numerical_unit $valid_numerical_unit valid_numerical_unit_index $valid_numerical_unit_index </p>";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// echo "<p> dans valid_numerical_unit_index $valid_numerical_unit_index </p>";
|
||||
if ($answer->feedback) {
|
||||
$answer->feedback = quiz_rewrite_question_urls($answer->feedback, 'pluginfile.php', $context->id, 'question', 'answerfeedback', array($state->attempt, $state->question), $answer->id);
|
||||
$feedback = format_text($answer->feedback, true, $formatoptions, $cmoptions->course);
|
||||
}
|
||||
if ( isset($question->options->units))
|
||||
{
|
||||
$valid_numerical_unit = true ;
|
||||
}
|
||||
$break = 1 ;
|
||||
} else if ($response !== false && isset($question->options->units) && count($question->options->units) > 0) {
|
||||
$hasunits = 1 ;
|
||||
foreach($question->options->units as $key => $unit){
|
||||
// The student did type a number, so check it with tolerances.
|
||||
$testresponse = $response /$unit->multiplier ;
|
||||
if($answer->min <= $testresponse && $testresponse <= $answer->max) {
|
||||
$unittested = $unit->unit ;
|
||||
$rawgrade = $answer->fraction ;
|
||||
$class = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimg = question_get_feedback_image($answer->fraction);
|
||||
if ($answer->feedback) {
|
||||
$feedback = format_text($answer->feedback, true, $formatoptions, $cmoptions->course);
|
||||
}
|
||||
if($state->responses['unit'] == $unit->unit){
|
||||
$classunitvalue = $answer->fraction ;
|
||||
}else {
|
||||
$classunitvalue == 0 ;
|
||||
}
|
||||
$classunit = question_get_feedback_class($classunitvalue);
|
||||
$feedbackimgunit = question_get_feedback_image($classunitvalue, $options->feedback);
|
||||
$break = 1 ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if($response !== false && ($answer->min <= $response && $response <= $answer->max) ) {
|
||||
$rawgrade = $answer->fraction ;
|
||||
$class = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimg = question_get_feedback_image($answer->fraction);
|
||||
if ($answer->feedback) {
|
||||
$feedback = format_text($answer->feedback, $answer->feedbackformat, $formatoptions, $cmoptions->course);
|
||||
}
|
||||
$break = 1 ;
|
||||
}
|
||||
if ($break) {
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// echo "<p> rawgrade $rawgrade classunit $classunit valid_numerical_unit_index $valid_numerical_unit_index ".$feedbackimgunit."</p>";
|
||||
$state->options->raw_unitpenalty = 0 ;
|
||||
$raw_unitpenalty = 0 ;
|
||||
if( $question->options->showunits == NUMERICALQUESTIONUNITNODISPLAY ||
|
||||
@@ -571,8 +652,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
$classunitvalue = 1 ;
|
||||
}
|
||||
|
||||
|
||||
if($classunitvalue == 0){
|
||||
if(! $answerasterisk && $question->options->unitgradingtype != 0 && (! $valid_numerical_unit || $unit_in_numerical_answer)){
|
||||
if($question->options->unitgradingtype == 1){
|
||||
$raw_unitpenalty = $question->options->unitpenalty * $rawgrade ;
|
||||
}else {
|
||||
@@ -588,7 +668,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
|
||||
function compare_responses(&$question, $state, $teststate) {
|
||||
|
||||
if ($question->options->showunits == NUMERICALQUESTIONUNITMULTICHOICEDISPLAY && isset($question->options->units) && isset($question->options->units[$state->responses['unit']] )){
|
||||
if ($question->options->showunits == NUMERICALQUESTIONUNITMULTICHOICEDISPLAY && isset($question->options->units) && isset($state->responses['unit']) && isset($question->options->units[$state->responses['unit']] )){
|
||||
$state->responses['unit']=$question->options->units[$state->responses['unit']]->unit;
|
||||
};
|
||||
|
||||
@@ -624,43 +704,84 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
*/
|
||||
function test_response(&$question, &$state, $answer ) {
|
||||
// Deal with the match anything answer.
|
||||
// echo"<p> test_response answer <pre>";print_r($answer) ;echo"</pre></p>";
|
||||
// echo"<p>test_response state <pre>";print_r($state) ;echo"</pre></p>";
|
||||
if ($answer->answer === '*') {
|
||||
return true;
|
||||
}
|
||||
/* To be able to test (old) questions that do not have an unit
|
||||
* input element the test is done using the $state->responses['']
|
||||
* which contains the response which is analyzed by extract_numerical_response()
|
||||
* If the data comes from the numerical or calculated display
|
||||
* the $state->responses['unit'] comes from either
|
||||
* a multichoice radio element NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
|
||||
* where the $state->responses['unit'] value is the key => unit object
|
||||
* in the the $question->options->units array
|
||||
* or an input text element NUMERICALUNITTEXTINPUTDISPLAY
|
||||
* which contains the student response
|
||||
* for NUMERICALQUESTIONUNITTEXTDISPLAY and NUMERICALQUESTIONUNITNODISPLAY
|
||||
*
|
||||
*/
|
||||
|
||||
if (!isset($state->responses['answer']) && isset($state->responses[''])){
|
||||
$state->responses['answer'] = $state->responses[''];
|
||||
}
|
||||
$response = $this->extract_numerical_response($state->responses['answer']);
|
||||
if ($response === false) {
|
||||
return false; // The student did not type a number.
|
||||
}
|
||||
// The student did type a number, so check it with tolerances.
|
||||
$this->get_tolerance_interval($answer);
|
||||
if ($answer->min <= $response && $response <= $answer->max){
|
||||
return true;
|
||||
}
|
||||
// testing for other units
|
||||
if ( isset($question->options->units) && count($question->options->units) > 0) {
|
||||
foreach($question->options->units as $key =>$unit){
|
||||
$testresponse = $response /$unit->multiplier ;
|
||||
if($answer->min <= $testresponse && $testresponse<= $answer->max) {
|
||||
return true;
|
||||
}
|
||||
// using old grading process if $question->unitgradingtype == 0
|
||||
// and adding unit1 for the new option NUMERICALQUESTIONUNITTEXTDISPLAY
|
||||
if ($question->options->unitgradingtype == 0 ){
|
||||
// values coming form old question stored in attempts
|
||||
if (!isset($state->responses['answer']) && isset($state->responses[''])){
|
||||
$state->responses['answer'] = $state->responses[''];
|
||||
}
|
||||
$answertotest = $state->responses['answer'];
|
||||
// values coming from NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
// or NUMERICALQUESTIONUNITTEXTDISPLAY as unit hidden HTML element
|
||||
if(isset($state->responses['unit'])) {
|
||||
$answertotest .= $state->responses['unit'] ;
|
||||
}
|
||||
// if ($question->options->showunits == NUMERICALQUESTIONUNITTEXTDISPLAY && isset($question->options->units[0])){
|
||||
// $answertotest .= $question->options->units[0]->unit ;
|
||||
// }
|
||||
// test OK if only numerical or numerical with known unit names with the unit mltiplier applied
|
||||
$response = $this->apply_unit($answertotest, $question->options->units);
|
||||
// echo"<p> dans response apres apply <pre>";print_r($response) ;echo"</pre></p>";
|
||||
|
||||
if ($response === false) {
|
||||
return false; // The student did not type a number.
|
||||
}
|
||||
|
||||
// The student did type a number, so check it with tolerances.
|
||||
$this->get_tolerance_interval($answer);
|
||||
// echo"<p> test_response apres get tolerance interval answer <pre>";print_r($answer) ;echo"</pre></p>";
|
||||
return ($answer->min <= $response && $response <= $answer->max);
|
||||
}else { // $question->options->unitgradingtype > 0
|
||||
/* testing with unitgradingtype $question->options->unitgradingtype > 0
|
||||
* if the response is at least patially true
|
||||
* if the numerical value agree in the interval
|
||||
* if so the only non valid case will be a bad unit and a unity penalty.
|
||||
|
||||
To be able to test (old) questions that do not have an unit
|
||||
* input element the test is done using the $state->responses['']
|
||||
* which contains the response which is analyzed by extract_numerical_response()
|
||||
* If the data comes from the numerical or calculated display
|
||||
* the $state->responses['unit'] comes from either
|
||||
* a multichoice radio element NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
|
||||
* where the $state->responses['unit'] value is the key => unit object
|
||||
* in the the $question->options->units array
|
||||
* or an input text element NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
* which contains the student response
|
||||
* for NUMERICALQUESTIONUNITTEXTDISPLAY and NUMERICALQUESTIONUNITNODISPLAY
|
||||
*
|
||||
*/
|
||||
|
||||
$response = $this->extract_numerical_response($state->responses['answer']);
|
||||
|
||||
// echo"<p> response <pre>";print_r($response) ;echo"</pre></p>";
|
||||
// echo"<p> response <pre>";print_r($response) ;echo"</pre></p>";
|
||||
|
||||
if ($response->number === false ) {
|
||||
return false; // The student did not type a number.
|
||||
}
|
||||
|
||||
// The student did type a number, so check it with tolerances.
|
||||
$this->get_tolerance_interval($answer);
|
||||
if ($answer->min <= $response->number && $response->number <= $answer->max){
|
||||
// echo"<p> response true <pre>";print_r($response) ;echo"</pre></p>";
|
||||
return true;
|
||||
}
|
||||
// testing for other units
|
||||
if ( isset($question->options->units) && count($question->options->units) > 0) {
|
||||
foreach($question->options->units as $key =>$unit){
|
||||
$testresponse = $response->number /$unit->multiplier ;
|
||||
if($answer->min <= $testresponse && $testresponse<= $answer->max) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -689,75 +810,67 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
* @param object $cmoptions
|
||||
*/
|
||||
function grade_responses(&$question, &$state, $cmoptions) {
|
||||
if (!isset($state->responses['answer']) && isset($state->responses[''])){
|
||||
// echo"<p>grade question->options<pre>";print_r($question->options) ;echo"</pre></p>";
|
||||
// echo"<p>grade state response<pre>";print_r($state->responses) ;echo"</pre></p>";
|
||||
/* if (!isset($state->responses['answer']) && isset($state->responses[''])){
|
||||
$state->responses['answer'] = $state->responses[''];
|
||||
}*/
|
||||
if ( isset($state->responses['']) && $state->responses[''] != '' && !isset($state->responses['answer'])){
|
||||
$this->split_old_answer($state->responses[''], $question->options->units, $state->responses['answer'] ,$state->responses['unit'] );
|
||||
}
|
||||
|
||||
//to apply the unit penalty we need to analyse the response in a more complex way
|
||||
//the apply_unit() function analysis could be used to obtain the infos
|
||||
// however it is used to detect good or bad numbers but also
|
||||
// gives false
|
||||
// gives false if there is a unit
|
||||
$state->raw_grade = 0;
|
||||
$valid_numerical_unit = false ;
|
||||
$break = 0 ;
|
||||
$unittested = '';
|
||||
$hasunits = 0 ;
|
||||
$response = $this->extract_numerical_response($state->responses['answer']);
|
||||
// $response = $this->extract_numerical_response($state->responses['answer']);
|
||||
$answerasterisk = false ;
|
||||
|
||||
$break = 0 ;
|
||||
foreach($question->options->answers as $answer) {
|
||||
if ($answer->answer !== '*' ) {
|
||||
// The student did type a number, so check it with tolerances.
|
||||
$this->get_tolerance_interval($answer);
|
||||
}
|
||||
|
||||
// if * then everything is OK even unit
|
||||
if ($answer->answer === '*') {
|
||||
$state->raw_grade = $answer->fraction;
|
||||
if ( isset($question->options->units)){
|
||||
$valid_numerical_unit = true ;
|
||||
}
|
||||
$answerasterisk = true ;
|
||||
$break = 1 ;
|
||||
}else if ($response !== false && isset($question->options->units) && count($question->options->units) > 0) {
|
||||
$hasunits = 1 ;
|
||||
foreach($question->options->units as $key => $unit){
|
||||
$testresponse = $response /$unit->multiplier ;
|
||||
|
||||
if($answer->min <= $testresponse && $testresponse <= $answer->max) {
|
||||
$state->raw_grade = $answer->fraction;
|
||||
$unittested = $unit->unit ;
|
||||
$break = 1 ;
|
||||
break;
|
||||
if ($this->test_response($question, $state, $answer)) {
|
||||
// Answer was correct or partially correct.
|
||||
$state->raw_grade = $answer->fraction ;
|
||||
if ($question->options->unitgradingtype == 0 || $answer->answer === '*'){
|
||||
// if * then unit has the $answer->fraction value
|
||||
// if $question->options->unitgradingtype == 0 everything has been checked
|
||||
// if $question->options->showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
// then number - unit combination has been used to test response
|
||||
// so the unit should have same color
|
||||
|
||||
}else {
|
||||
// so we need to apply unit grading i.e. to check if the number-unit combination
|
||||
// was the rigth one
|
||||
$valid_numerical_unit = false ;
|
||||
$class = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimg = question_get_feedback_image($answer->fraction);
|
||||
if(isset($state->responses['unit']) && $state->responses['unit'] != '' ){
|
||||
foreach ($question->options->units as $key => $unit) {
|
||||
if ($unit->unit == $state->responses['unit']){
|
||||
|
||||
$response = $this->apply_unit($state->responses['answer'].$state->responses['unit'], array($question->options->units[$key])) ;
|
||||
if ($response !== false) {
|
||||
$this->get_tolerance_interval($answer);
|
||||
if($answer->min <= $response && $response <= $answer->max){
|
||||
$valid_numerical_unit = true ;
|
||||
}
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if ($response !== false) {
|
||||
if($this->test_response($question, $state, $answer)) {
|
||||
$state->raw_grade = $answer->fraction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($break) break;
|
||||
} //foreach($question->options
|
||||
|
||||
// in all cases the unit should be tested
|
||||
if( $question->options->showunits == NUMERICALQUESTIONUNITNODISPLAY ||
|
||||
$question->options->showunits == NUMERICALQUESTIONUNITTEXTDISPLAY ) {
|
||||
$valid_numerical_unit = true ;
|
||||
}else {
|
||||
// $valid_numerical_unit means that the grading was done with the unit defined
|
||||
//
|
||||
if ($hasunits && !$answerasterisk ){
|
||||
$valid_numerical_unit = ($state->responses['unit'] == $unittested) ;
|
||||
} else {
|
||||
$valid_numerical_unit = true ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
// apply unit penalty
|
||||
$raw_unitpenalty = 0 ;
|
||||
if(!empty($question->options->unitpenalty)&& $valid_numerical_unit != true ){
|
||||
if($question->options->unitgradingtype != 0 && !empty($question->options->unitpenalty)&& $valid_numerical_unit != true ){
|
||||
if($question->options->unitgradingtype == 1){
|
||||
$raw_unitpenalty = $question->options->unitpenalty * $state->raw_grade ;
|
||||
}else {
|
||||
@@ -765,11 +878,11 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
}
|
||||
$state->raw_grade -= $raw_unitpenalty ;
|
||||
}
|
||||
|
||||
|
||||
// Make sure we don't assign negative or too high marks.
|
||||
$state->raw_grade = min(max((float) $state->raw_grade,
|
||||
0.0), 1.0) * $question->maxgrade;
|
||||
|
||||
|
||||
// Update the penalty.
|
||||
$state->penalty = $question->penalty * $question->maxgrade;
|
||||
|
||||
@@ -892,6 +1005,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
* account as a float.
|
||||
*/
|
||||
function extract_numerical_response($rawresponse) {
|
||||
$extractedresponse = new stdClass() ;
|
||||
$rawresponse = trim($rawresponse) ;
|
||||
$search = array(' ', ',');
|
||||
// test if a . is present or there are multiple , (i.e. 2,456,789 ) so that we don't need spaces and ,
|
||||
@@ -904,10 +1018,19 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
|
||||
if (preg_match('~^([+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)?)([^0-9].*)?$~',
|
||||
$rawresponse, $responseparts)) {
|
||||
return (float)$responseparts[1] ;
|
||||
//return (float)$responseparts[1] ;
|
||||
$extractedresponse->number = (float)$responseparts[1] ;
|
||||
}else {
|
||||
$extractedresponse->number = false ;
|
||||
}
|
||||
if (!empty($responseparts[5])) {
|
||||
$extractedresponse->unit = $responseparts[5] ;
|
||||
}else {
|
||||
$extractedresponse->unit = '';
|
||||
}
|
||||
|
||||
// Invalid number. Must be wrong.
|
||||
return false;
|
||||
return clone($extractedresponse) ;
|
||||
}
|
||||
/**
|
||||
* Checks if the $rawresponse has a unit and applys it if appropriate.
|
||||
@@ -918,7 +1041,9 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
* @return float The rawresponse with the unit taken into
|
||||
* account as a float.
|
||||
*/
|
||||
function apply_unit_old($rawresponse, $units) {
|
||||
function apply_unit($rawresponse, $units) {
|
||||
// echo"<p> rawresponse $rawresponse <pre>";print_r($units) ;echo"</pre></p>";
|
||||
|
||||
// Make units more useful
|
||||
$tmpunits = array();
|
||||
foreach ($units as $unit) {
|
||||
@@ -939,6 +1064,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
// Apply any unit that is present.
|
||||
if (ereg('^([+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)?)([^0-9].*)?$',
|
||||
$rawresponse, $responseparts)) {
|
||||
// echo"<p> responseparts <pre>";print_r($responseparts) ;echo"</pre></p>";
|
||||
|
||||
if (!empty($responseparts[5])) {
|
||||
|
||||
@@ -965,47 +1091,63 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
* numerical, calculated, calculatedsimple
|
||||
*/
|
||||
function add_units_options(&$mform, &$that){
|
||||
$mform->addElement('header', 'unithandling', get_string('unitshandling', 'qtype_numerical'));
|
||||
// Units are graded
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitgraded1', 'qtype_numerical'), get_string('unitgraded', 'qtype_numerical'),0);
|
||||
$mform->addElement('header', 'unithandling', get_string('unitshandling', 'qtype_numerical'));
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitnotused', 'qtype_numerical'), get_string('onlynumerical', 'qtype_numerical'),0);
|
||||
// $mform->addElement('header', 'unithandling1', get_string('unitnotgraded', 'qtype_numerical'));
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitdisplay', 'qtype_numerical'), get_string('oneunitshown', 'qtype_numerical'),1);
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitsused', 'qtype_numerical'), get_string('manynumerical', 'qtype_numerical'),2);
|
||||
/* $showunits1grp = array();
|
||||
$showunits1grp[] = & $mform->createElement('radio', 'showunits1', '', get_string('no', 'moodle'),3);
|
||||
$showunits1grp[] = & $mform->createElement('radio', 'showunits1', '', get_string('yes', 'moodle'),2);*/
|
||||
// $mform->addGroup($showunits1grp, 'showunits1grp', get_string('unitdisplay', 'qtype_numerical'),' ' , false);
|
||||
$mform->addElement('static', 'separator2', '', '<HR/>');
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitgraded1', 'qtype_numerical'), get_string('unitgraded', 'qtype_numerical'),3);
|
||||
$penaltygrp = array();
|
||||
$penaltygrp[] =& $mform->createElement('text', 'unitpenalty', get_string('unitpenalty', 'qtype_numerical') ,
|
||||
array('size' => 6));
|
||||
$unitgradingtypes = array('1' => get_string('decfractionofquestiongrade', 'qtype_numerical'), '2' => get_string('decfractionofresponsegrade', 'qtype_numerical'));
|
||||
$penaltygrp[] =& $mform->createElement('select', 'unitgradingtype', '' , $unitgradingtypes );
|
||||
$penaltygrp[] =& $mform->createElement('select', 'unitgradingtypes', '' , $unitgradingtypes );
|
||||
$mform->addGroup($penaltygrp, 'penaltygrp', get_string('unitpenalty', 'qtype_numerical'),' ' , false);
|
||||
$showunits0grp = array();
|
||||
$showunits0grp[] =& $mform->createElement('radio', 'showunits0', get_string('unitedit', 'qtype_numerical'), get_string('editableunittext', 'qtype_numerical'),0);
|
||||
$showunits0grp[] =& $mform->createElement('radio', 'showunits0', get_string('selectunits', 'qtype_numerical') , get_string('unitchoice', 'qtype_numerical'),1);
|
||||
$mform->addGroup($showunits0grp, 'showunits0grp', get_string('studentunitanswer', 'qtype_numerical'),' OR ' , false);
|
||||
$mform->addElement('editor', 'instructions', get_string('instructions', 'qtype_numerical'), null, $that->editoroptions);
|
||||
$mform->addElement('static', 'separator1', '<HR/>', '<HR/>');
|
||||
// Units are not graded
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitnotgraded', 'qtype_numerical'), get_string('onlynumerical', 'qtype_numerical'),1);
|
||||
$showunits1grp = array();
|
||||
$showunits1grp[] = & $mform->createElement('radio', 'showunits1', '', get_string('no', 'moodle'),3);
|
||||
$showunits1grp[] = & $mform->createElement('radio', 'showunits1', '', get_string('yes', 'moodle'),2);
|
||||
$mform->addGroup($showunits1grp, 'showunits1grp', get_string('unitdisplay', 'qtype_numerical'),' ' , false);
|
||||
$multichoicedisplaygrp = array();
|
||||
$multichoicedisplaygrp[] =& $mform->createElement('radio', 'multichoicedisplay', get_string('unitedit', 'qtype_numerical'), get_string('editableunittext', 'qtype_numerical'),0);
|
||||
$multichoicedisplaygrp[] =& $mform->createElement('radio', 'multichoicedisplay', get_string('selectunits', 'qtype_numerical') , get_string('unitchoice', 'qtype_numerical'),1);
|
||||
$mform->addGroup($multichoicedisplaygrp, 'multichoicedisplaygrp', get_string('studentunitanswer', 'qtype_numerical'),' OR ' , false);
|
||||
|
||||
|
||||
|
||||
$unitslefts = array('0' => get_string('rightexample', 'qtype_numerical'),'1' => get_string('leftexample', 'qtype_numerical'));
|
||||
$mform->addElement('static', 'separator2', '<HR/>', '<HR/>');
|
||||
$mform->addElement('select', 'unitsleft', get_string('unitposition', 'qtype_numerical') , $unitslefts );
|
||||
$currentgrp1 = array();
|
||||
|
||||
$mform->addElement('static', 'separator2', '<HR/>', '<HR/>');
|
||||
|
||||
|
||||
$mform->addElement('editor', 'instructions', get_string('instructions', 'qtype_numerical'), null, $that->editoroptions);
|
||||
// $mform->addElement('static', 'separator1', '<HR/>', '<HR/>');
|
||||
// Units are not graded
|
||||
$showunits1grp = array();
|
||||
$mform->addElement('static', 'separator2', '<HR/>', '<HR/>');
|
||||
|
||||
$mform->setType('unitpenalty', PARAM_NUMBER);
|
||||
$mform->setDefault('unitpenalty', 0.1);
|
||||
$mform->setDefault('unitgradingtype', 1);
|
||||
// $mform->addHelpButton('penaltygrp', 'unitpenalty', 'qtype_numerical'); // TODO help did not exist before MDL-21695
|
||||
$mform->setDefault('showunits0', 0);
|
||||
$mform->setDefault('showunits1', 3);
|
||||
$mform->setDefault('unitgradingtypes', 1);
|
||||
$mform->addHelpButton('penaltygrp', 'unitpenalty', 'qtype_numerical'); // TODO help did not exist before MDL-21695
|
||||
// $mform->setDefault('multichoicedisplay', 1);
|
||||
// $mform->setDefault('showunits1', 3);
|
||||
$mform->setDefault('unitsleft', 0);
|
||||
$mform->setType('instructions', PARAM_RAW);
|
||||
// $mform->addHelpButton('instructions', 'unituses', 'qtype_numerical');
|
||||
$mform->addHelpButton('instructions', 'numericalinstructions', 'qtype_numerical');
|
||||
$mform->disabledIf('penaltygrp', 'unitrole','eq','0');
|
||||
$mform->disabledIf('penaltygrp', 'unitrole','eq','1');
|
||||
$mform->disabledIf('unitgradingtype', 'unitrole','eq','1');
|
||||
$mform->disabledIf('instructions', 'unitrole','eq','1');
|
||||
$mform->disabledIf('unitsleft', 'showunits1','eq','3');
|
||||
$mform->disabledIf('showunits1','unitrole','eq','0');
|
||||
$mform->disabledIf('showunits0','unitrole','eq','1');
|
||||
$mform->disabledIf('penaltygrp', 'unitrole','eq','2');
|
||||
// $mform->disabledIf('unitgradingtype', 'unitrole','eq','1');
|
||||
// $mform->disabledIf('instructions', 'unitrole','eq','1');
|
||||
$mform->disabledIf('unitsleft', 'unitrole','eq','0');
|
||||
// $mform->disabledIf('showunits1','unitrole','eq','0');
|
||||
$mform->disabledIf('multichoicedisplay','unitrole','eq','0');
|
||||
$mform->disabledIf('multichoicedisplay','unitrole','eq','1');
|
||||
$mform->disabledIf('multichoicedisplay','unitrole','eq','2');
|
||||
|
||||
|
||||
}
|
||||
@@ -1056,21 +1198,39 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
$context = $this->get_context_by_category_id($categoryid);
|
||||
|
||||
if (isset($question->options)){
|
||||
$default_values['unitgradingtype'] = $question->options->unitgradingtype ;
|
||||
$default_values['unitgradingtypes'] = 1 ;
|
||||
if ($question->options->unitgradingtype == 2 ) {
|
||||
$default_values['unitgradingtypes'] = 1 ;
|
||||
}
|
||||
if ($question->options->unitgradingtype == 0 ) {
|
||||
$default_values['unitgradingtypes'] = 0 ;
|
||||
}
|
||||
$default_values['unitpenalty'] = $question->options->unitpenalty ;
|
||||
switch ($question->options->showunits){
|
||||
case 'O' :
|
||||
case '1' :
|
||||
$default_values['showunits0'] = $question->options->showunits ;
|
||||
$default_values['unitrole'] = 0 ;
|
||||
case 0 :// NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
if($question->options->unitgradingtype == 0 ){
|
||||
$default_values['unitrole'] = 2 ;
|
||||
$default_values['multichoicedisplay'] = 0 ;
|
||||
}else { // 1 or 2
|
||||
$default_values['unitrole'] = 3 ;
|
||||
$default_values['multichoicedisplay'] = 0 ;
|
||||
$default_values['unitgradingtypes'] = $question->options->unitgradingtype ;
|
||||
}
|
||||
break;
|
||||
case 1 : // NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
|
||||
$default_values['unitrole'] = 3 ;
|
||||
$default_values['multichoicedisplay'] = $question->options->unitgradingtype ;
|
||||
$default_values['unitgradingtypes'] = $question->options->unitgradingtype ;
|
||||
break;
|
||||
case '2' :
|
||||
case '3' :
|
||||
$default_values['showunits1'] = $question->options->showunits ;
|
||||
case 2 : // NUMERICALQUESTIONUNITTEXTDISPLAY
|
||||
$default_values['unitrole'] = 1 ;
|
||||
case 3 : // NUMERICALQUESTIONUNITNODISPLAY
|
||||
$default_values['unitrole'] = 0 ;
|
||||
// $default_values['showunits1'] = $question->options->showunits ;
|
||||
break;
|
||||
}
|
||||
$default_values['unitsleft'] = $question->options->unitsleft ;
|
||||
// $question->unitrole = $default_values['unitrole'] ;
|
||||
|
||||
// processing files
|
||||
$component = 'qtype_' . $question->qtype;
|
||||
@@ -1108,11 +1268,16 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
|
||||
function validate_numerical_options(& $data, & $errors){
|
||||
$units = $data['unit'];
|
||||
if ($data['unitrole'] == 0 ){
|
||||
$showunits = $data['showunits0'];
|
||||
}else {
|
||||
$showunits = $data['showunits1'];
|
||||
}
|
||||
switch ($data['unitrole']){
|
||||
case '0' : $showunits = NUMERICALQUESTIONUNITNODISPLAY ;
|
||||
break ;
|
||||
case '1' : $showunits = NUMERICALQUESTIONUNITTEXTDISPLAY ;
|
||||
break ;
|
||||
case '2' : $showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
|
||||
break ;
|
||||
case '3' : $showunits = $data['multichoicedisplay'] ;
|
||||
break ;
|
||||
}
|
||||
|
||||
if (($showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY) ||
|
||||
($showunits == NUMERICALQUESTIONUNITMULTICHOICEDISPLAY ) ||
|
||||
@@ -1168,7 +1333,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function valid_unit($rawresponse, $units) {
|
||||
// Make units more useful
|
||||
|
||||
Reference in New Issue
Block a user