Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/mod/lesson/pagetypes/shortanswer.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00027 defined('MOODLE_INTERNAL') || die();
00028 
00030 define("LESSON_PAGE_SHORTANSWER",   "1");
00031 
00032 class lesson_page_type_shortanswer extends lesson_page {
00033 
00034     protected $type = lesson_page::TYPE_QUESTION;
00035     protected $typeidstring = 'shortanswer';
00036     protected $typeid = LESSON_PAGE_SHORTANSWER;
00037     protected $string = null;
00038 
00039     public function get_typeid() {
00040         return $this->typeid;
00041     }
00042     public function get_typestring() {
00043         if ($this->string===null) {
00044             $this->string = get_string($this->typeidstring, 'lesson');
00045         }
00046         return $this->string;
00047     }
00048     public function get_idstring() {
00049         return $this->typeidstring;
00050     }
00051     public function display($renderer, $attempt) {
00052         global $USER, $CFG, $PAGE;
00053         $mform = new lesson_display_answer_form_shortanswer($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents(), 'lessonid'=>$this->lesson->id));
00054         $data = new stdClass;
00055         $data->id = $PAGE->cm->id;
00056         $data->pageid = $this->properties->id;
00057         if (isset($USER->modattempts[$this->lesson->id])) {
00058             $data->answer = s($attempt->useranswer);
00059         }
00060         $mform->set_data($data);
00061         return $mform->display();
00062     }
00063     public function check_answer() {
00064         global $CFG;
00065         $result = parent::check_answer();
00066 
00067         $mform = new lesson_display_answer_form_shortanswer($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents()));
00068         $data = $mform->get_data();
00069         require_sesskey();
00070 
00071         $studentanswer = trim($data->answer);
00072         if ($studentanswer === '') {
00073             $result->noanswer = true;
00074             return $result;
00075         }
00076 
00077         $i=0;
00078         $answers = $this->get_answers();
00079         foreach ($answers as $answer) {
00080             $i++;
00081             $expectedanswer  = $answer->answer; // for easier handling of $answer->answer
00082             $ismatch         = false;
00083             $markit          = false;
00084             $useregexp       = ($this->qoption);
00085 
00086             if ($useregexp) { //we are using 'normal analysis', which ignores case
00087                 $ignorecase = '';
00088                 if (substr($expectedanswer, -2) == '/i') {
00089                     $expectedanswer = substr($expectedanswer, 0, -2);
00090                     $ignorecase = 'i';
00091                 }
00092             } else {
00093                 $expectedanswer = str_replace('*', '#####', $expectedanswer);
00094                 $expectedanswer = preg_quote($expectedanswer, '/');
00095                 $expectedanswer = str_replace('#####', '.*', $expectedanswer);
00096             }
00097             // see if user typed in any of the correct answers
00098             if ((!$this->lesson->custom && $this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) or ($this->lesson->custom && $answer->score > 0) ) {
00099                 if (!$useregexp) { // we are using 'normal analysis', which ignores case
00100                     if (preg_match('/^'.$expectedanswer.'$/i',$studentanswer)) {
00101                         $ismatch = true;
00102                     }
00103                 } else {
00104                     if (preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$studentanswer)) {
00105                         $ismatch = true;
00106                     }
00107                 }
00108                 if ($ismatch == true) {
00109                     $result->correctanswer = true;
00110                 }
00111             } else {
00112                if (!$useregexp) { //we are using 'normal analysis'
00113                     // see if user typed in any of the wrong answers; don't worry about case
00114                     if (preg_match('/^'.$expectedanswer.'$/i',$studentanswer)) {
00115                         $ismatch = true;
00116                     }
00117                 } else { // we are using regular expressions analysis
00118                     $startcode = substr($expectedanswer,0,2);
00119                     switch ($startcode){
00120                         //1- check for absence of required string in $studentanswer (coded by initial '--')
00121                         case "--":
00122                             $expectedanswer = substr($expectedanswer,2);
00123                             if (!preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$studentanswer)) {
00124                                 $ismatch = true;
00125                             }
00126                             break;
00127                         //2- check for code for marking wrong strings (coded by initial '++')
00128                         case "++":
00129                             $expectedanswer=substr($expectedanswer,2);
00130                             $markit = true;
00131                             //check for one or several matches
00132                             if (preg_match_all('/'.$expectedanswer.'/'.$ignorecase,$studentanswer, $matches)) {
00133                                 $ismatch   = true;
00134                                 $nb        = count($matches[0]);
00135                                 $original  = array();
00136                                 $marked    = array();
00137                                 $fontStart = '<span class="incorrect matches">';
00138                                 $fontEnd   = '</span>';
00139                                 for ($i = 0; $i < $nb; $i++) {
00140                                     array_push($original,$matches[0][$i]);
00141                                     array_push($marked,$fontStart.$matches[0][$i].$fontEnd);
00142                                 }
00143                                 $studentanswer = str_replace($original, $marked, $studentanswer);
00144                             }
00145                             break;
00146                         //3- check for wrong answers belonging neither to -- nor to ++ categories
00147                         default:
00148                             if (preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$studentanswer, $matches)) {
00149                                 $ismatch = true;
00150                             }
00151                             break;
00152                     }
00153                     $result->correctanswer = false;
00154                 }
00155             }
00156             if ($ismatch) {
00157                 $result->newpageid = $answer->jumpto;
00158                 if (trim(strip_tags($answer->response))) {
00159                     $result->response = $answer->response;
00160                 }
00161                 $result->answerid = $answer->id;
00162                 break; // quit answer analysis immediately after a match has been found
00163             }
00164         }
00165         $result->userresponse = $studentanswer;
00166         //clean student answer as it goes to output.
00167         $result->studentanswer = s($studentanswer);
00168         return $result;
00169     }
00170 
00171     public function option_description_string() {
00172         if ($this->properties->qoption) {
00173             return " - ".get_string("casesensitive", "lesson");
00174         }
00175         return parent::option_description_string();
00176     }
00177 
00178     public function display_answers(html_table $table) {
00179         $answers = $this->get_answers();
00180         $options = new stdClass;
00181         $options->noclean = true;
00182         $options->para = false;
00183         $i = 1;
00184         foreach ($answers as $answer) {
00185             $cells = array();
00186             if ($this->lesson->custom && $answer->score > 0) {
00187                 // if the score is > 0, then it is correct
00188                 $cells[] = '<span class="labelcorrect">'.get_string("answer", "lesson")." $i</span>: \n";
00189             } else if ($this->lesson->custom) {
00190                 $cells[] = '<span class="label">'.get_string("answer", "lesson")." $i</span>: \n";
00191             } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) {
00192                 // underline correct answers
00193                 $cells[] = '<span class="correct">'.get_string("answer", "lesson")." $i</span>: \n";
00194             } else {
00195                 $cells[] = '<span class="labelcorrect">'.get_string("answer", "lesson")." $i</span>: \n";
00196             }
00197             $cells[] = format_text($answer->answer, $answer->answerformat, $options);
00198             $table->data[] = new html_table_row($cells);
00199 
00200             $cells = array();
00201             $cells[] = "<span class=\"label\">".get_string("response", "lesson")." $i</span>";
00202             $cells[] = format_text($answer->response, $answer->responseformat, $options);
00203             $table->data[] = new html_table_row($cells);
00204 
00205             $cells = array();
00206             $cells[] = "<span class=\"label\">".get_string("score", "lesson").'</span>';
00207             $cells[] = $answer->score;
00208             $table->data[] = new html_table_row($cells);
00209 
00210             $cells = array();
00211             $cells[] = "<span class=\"label\">".get_string("jump", "lesson").'</span>';
00212             $cells[] = $this->get_jump_name($answer->jumpto);
00213             $table->data[] = new html_table_row($cells);
00214             if ($i === 1){
00215                 $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;';
00216             }
00217             $i++;
00218         }
00219         return $table;
00220     }
00221     public function stats(array &$pagestats, $tries) {
00222         if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt
00223             $temp = $tries[$this->lesson->maxattempts - 1];
00224         } else {
00225             // else, user attempted the question less than the max, so grab the last one
00226             $temp = end($tries);
00227         }
00228         if (isset($pagestats[$temp->pageid][$temp->useranswer])) {
00229             $pagestats[$temp->pageid][$temp->useranswer]++;
00230         } else {
00231             $pagestats[$temp->pageid][$temp->useranswer] = 1;
00232         }
00233         if (isset($pagestats[$temp->pageid]["total"])) {
00234             $pagestats[$temp->pageid]["total"]++;
00235         } else {
00236             $pagestats[$temp->pageid]["total"] = 1;
00237         }
00238         return true;
00239     }
00240 
00241     public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) {
00242         $answers = $this->get_answers();
00243         $formattextdefoptions = new stdClass;
00244         $formattextdefoptions->para = false;  //I'll use it widely in this page
00245         foreach ($answers as $answer) {
00246             if ($useranswer == null && $i == 0) {
00247                 // I have the $i == 0 because it is easier to blast through it all at once.
00248                 if (isset($pagestats[$this->properties->id])) {
00249                     $stats = $pagestats[$this->properties->id];
00250                     $total = $stats["total"];
00251                     unset($stats["total"]);
00252                     foreach ($stats as $valentered => $ntimes) {
00253                         $data = '<input type="text" size="50" disabled="disabled" readonly="readonly" value="'.s($valentered).'" />';
00254                         $percent = $ntimes / $total * 100;
00255                         $percent = round($percent, 2);
00256                         $percent .= "% ".get_string("enteredthis", "lesson");
00257                         $answerdata->answers[] = array($data, $percent);
00258                     }
00259                 } else {
00260                     $answerdata->answers[] = array(get_string("nooneansweredthisquestion", "lesson"), " ");
00261                 }
00262                 $i++;
00263             } else if ($useranswer != null && ($answer->id == $useranswer->answerid || $answer == end($answers))) {
00264                  // get in here when what the user entered is not one of the answers
00265                 $data = '<input type="text" size="50" disabled="disabled" readonly="readonly" value="'.s($useranswer->useranswer).'">';
00266                 if (isset($pagestats[$this->properties->id][$useranswer->useranswer])) {
00267                     $percent = $pagestats[$this->properties->id][$useranswer->useranswer] / $pagestats[$this->properties->id]["total"] * 100;
00268                     $percent = round($percent, 2);
00269                     $percent .= "% ".get_string("enteredthis", "lesson");
00270                 } else {
00271                     $percent = get_string("nooneenteredthis", "lesson");
00272                 }
00273                 $answerdata->answers[] = array($data, $percent);
00274 
00275                 if ($answer->id == $useranswer->answerid) {
00276                     if ($answer->response == NULL) {
00277                         if ($useranswer->correct) {
00278                             $answerdata->response = get_string("thatsthecorrectanswer", "lesson");
00279                         } else {
00280                             $answerdata->response = get_string("thatsthewronganswer", "lesson");
00281                         }
00282                     } else {
00283                         $answerdata->response = $answer->response;
00284                     }
00285                     if ($this->lesson->custom) {
00286                         $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score;
00287                     } elseif ($useranswer->correct) {
00288                         $answerdata->score = get_string("receivedcredit", "lesson");
00289                     } else {
00290                         $answerdata->score = get_string("didnotreceivecredit", "lesson");
00291                     }
00292                 } else {
00293                     $answerdata->response = get_string("thatsthewronganswer", "lesson");
00294                     if ($this->lesson->custom) {
00295                         $answerdata->score = get_string("pointsearned", "lesson").": 0";
00296                     } else {
00297                         $answerdata->score = get_string("didnotreceivecredit", "lesson");
00298                     }
00299                 }
00300             }
00301             $answerpage->answerdata = $answerdata;
00302         }
00303         return $answerpage;
00304     }
00305 }
00306 
00307 
00308 class lesson_add_page_form_shortanswer extends lesson_add_page_form_base {
00309     public $qtype = 'shortanswer';
00310     public $qtypestring = 'shortanswer';
00311 
00312     public function custom_definition() {
00313 
00314         $this->_form->addElement('checkbox', 'qoption', get_string('options', 'lesson'), get_string('casesensitive', 'lesson')); //oh my, this is a regex option!
00315         $this->_form->setDefault('qoption', 0);
00316         $this->_form->addHelpButton('qoption', 'casesensitive', 'lesson');
00317 
00318         for ($i = 0; $i < $this->_customdata['lesson']->maxanswers; $i++) {
00319             $this->_form->addElement('header', 'answertitle'.$i, get_string('answer').' '.($i+1));
00320             $this->add_answer($i);
00321             $this->add_response($i);
00322             $this->add_jumpto($i, NULL, ($i == 0 ? LESSON_NEXTPAGE : LESSON_THISPAGE));
00323             $this->add_score($i, null, ($i===0)?1:0);
00324         }
00325     }
00326 }
00327 
00328 class lesson_display_answer_form_shortanswer extends moodleform {
00329 
00330     public function definition() {
00331         global $OUTPUT, $USER;
00332         $mform = $this->_form;
00333         $contents = $this->_customdata['contents'];
00334 
00335         $hasattempt = false;
00336         $attrs = array('size'=>'50', 'maxlength'=>'200');
00337         if (isset($this->_customdata['lessonid'])) {
00338             $lessonid = $this->_customdata['lessonid'];
00339             if (isset($USER->modattempts[$lessonid]->useranswer)) {
00340                 $attrs['readonly'] = 'readonly';
00341                 $hasattempt = true;
00342             }
00343         }
00344 
00345         $mform->addElement('header', 'pageheader');
00346 
00347         $mform->addElement('html', $OUTPUT->container($contents, 'contents'));
00348 
00349         $options = new stdClass;
00350         $options->para = false;
00351         $options->noclean = true;
00352 
00353         $mform->addElement('hidden', 'id');
00354         $mform->setType('id', PARAM_INT);
00355 
00356         $mform->addElement('hidden', 'pageid');
00357         $mform->setType('pageid', PARAM_INT);
00358 
00359         $mform->addElement('text', 'answer', get_string('youranswer', 'lesson'), $attrs);
00360         $mform->setType('answer', PARAM_TEXT);
00361 
00362         if ($hasattempt) {
00363             $this->add_action_buttons(null, get_string("nextpage", "lesson"));
00364         } else {
00365             $this->add_action_buttons(null, get_string("submit", "lesson"));
00366         }
00367     }
00368 
00369 }
 All Data Structures Namespaces Files Functions Variables Enumerations