questiontype.php

来自「很棒的在线教学系统」· PHP 代码 · 共 364 行

PHP
364
字号
<?php  // $Id: questiontype.php,v 1.4.4.1 2007/11/02 16:20:48 tjhunt Exp $//////////////////////// RANDOMSAMATCH /////////////////////////// TODO: Make sure short answer questions chosen by a randomsamatch question/// can not also be used by a random question/// QUESTION TYPE CLASS ///////////////////** * @package questionbank * @subpackage questiontypes*/class question_randomsamatch_qtype extends question_match_qtype {/// Extends 'match' as there are quite a few simularities...    function name() {        return 'randomsamatch';    }    function is_usable_by_random() {        return false;    }    function get_question_options(&$question) {        if (!$question->options = get_record('question_randomsamatch', 'question', $question->id)) {            notify('Error: Missing question options for random short answer question '.$question->id.'!');            return false;        }        // This could be included as a flag in the database. It's already        // supported by the code.        // Recurse subcategories: 0 = no recursion, 1 = recursion        $question->options->subcats = 1;        return true;    }    function save_question_options($question) {        $options->question = $question->id;        $options->choose = $question->choose;        if (2 > $question->choose) {            $result->error = "At least two shortanswer questions need to be chosen!";            return $result;        }        if ($existing = get_record("question_randomsamatch",                                   "question", $options->question)) {            $options->id = $existing->id;            if (!update_record("question_randomsamatch", $options)) {                $result->error = "Could not update quiz randomsamatch options!";                return $result;            }        } else {            if (!insert_record("question_randomsamatch", $options)) {                $result->error = "Could not insert quiz randomsamatch options!";                return $result;            }        }        return true;    }    /**    * Deletes question from the question-type specific tables    *    * @return boolean Success/Failure    * @param object $question  The question being deleted    */    function delete_question($questionid) {        delete_records("question_randomsamatch", "question", $questionid);        return true;    }    function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) {        // Choose a random shortanswer question from the category:        // We need to make sure that no question is used more than once in the        // quiz. Therfore the following need to be excluded:        // 1. All questions that are explicitly assigned to the quiz        // 2. All random questions        // 3. All questions that are already chosen by an other random question        global $QTYPES;        if (!isset($cmoptions->questionsinuse)) {            $cmoptions->questionsinuse = $cmoptions->questions;        }        if ($question->options->subcats) {            // recurse into subcategories            $categorylist = question_categorylist($question->category);        } else {            $categorylist = $question->category;        }        $saquestions = $this->get_sa_candidates($categorylist, $cmoptions->questionsinuse);        $count  = count($saquestions);        $wanted = $question->options->choose;        $errorstr = '';        if ($count < $wanted && isteacherinanycourse()) {            if ($count >= 2) {                $errorstr =  "Error: could not get enough Short-Answer questions!                 Got $count Short-Answer questions, but wanted $wanted.                 Reducing number to choose from to $count!";                $wanted = $question->options->choose = $count;            } else {                $errorstr = "Error: could not get enough Short-Answer questions!                 This can happen if all available Short-Answer questions are already                 taken up by other Random questions or Random Short-Answer question.                 Another possible cause for this error is that Short-Answer                 questions were deleted after this Random Short-Answer question was                 created.";            }            notify($errorstr);            $errorstr = '<span class="notifyproblem">' . $errorstr . '</span>';        }        if ($count < $wanted) {            $question->questiontext = "$errorstr<br /><br />Insufficient selection options are             available for this question, therefore it is not available in  this             quiz. Please inform your teacher.";            // Treat this as a description from this point on            $question->qtype = DESCRIPTION;            return true;        }        $saquestions =         draw_rand_array($saquestions, $question->options->choose); // from bug 1889        foreach ($saquestions as $key => $wrappedquestion) {            if (!$QTYPES[$wrappedquestion->qtype]             ->get_question_options($wrappedquestion)) {                return false;            }            // Now we overwrite the $question->options->answers field to only            // *one* (the first) correct answer. This loop can be deleted to            // take all answers into account (i.e. put them all into the            // drop-down menu.            $foundcorrect = false;            foreach ($wrappedquestion->options->answers as $answer) {                if ($foundcorrect || $answer->fraction != 1.0) {                    unset($wrappedquestion->options->answers[$answer->id]);                } else if (!$foundcorrect) {                    $foundcorrect = true;                }            }            if (!$QTYPES[$wrappedquestion->qtype]             ->create_session_and_responses($wrappedquestion, $state, $cmoptions,             $attempt)) {                return false;            }            $wrappedquestion->name_prefix = $question->name_prefix;            $wrappedquestion->maxgrade    = $question->maxgrade;            $cmoptions->questionsinuse .= ",$wrappedquestion->id";            $state->options->subquestions[$key] = clone($wrappedquestion);        }        // Shuffle the answers (Do this always because this is a random question type)        $subquestionids = array_values(array_map(create_function('$val',         'return $val->id;'), $state->options->subquestions));        $subquestionids = swapshuffle($subquestionids);        // Create empty responses        foreach ($subquestionids as $val) {            $state->responses[$val] = '';        }        return true;    }    function restore_session_and_responses(&$question, &$state) {        global $QTYPES;        if (empty($state->responses[''])) {            $question->questiontext = "Insufficient selection options are             available for this question, therefore it is not available in  this             quiz. Please inform your teacher.";            // Treat this as a description from this point on            $question->qtype = DESCRIPTION;        } else {            $responses = explode(',', $state->responses['']);            $responses = array_map(create_function('$val',             'return explode("-", $val);'), $responses);            // Restore the previous responses            $state->responses = array();            foreach ($responses as $response) {                $state->responses[$response[0]] = $response[1];                if (!$wrappedquestion = get_record('question', 'id',                 $response[0])) {                    notify("Couldn't get question (id=$response[0])!");                    return false;                }                if (!$QTYPES[$wrappedquestion->qtype]                 ->get_question_options($wrappedquestion)) {                    notify("Couldn't get question options (id=$response[0])!");                    return false;                }                // Now we overwrite the $question->options->answers field to only                // *one* (the first) correct answer. This loop can be deleted to                // take all answers into account (i.e. put them all into the                // drop-down menu.                $foundcorrect = false;                foreach ($wrappedquestion->options->answers as $answer) {                    if ($foundcorrect || $answer->fraction != 1.0) {                        unset($wrappedquestion->options->answers[$answer->id]);                    } else if (!$foundcorrect) {                        $foundcorrect = true;                    }                }                if (!$QTYPES[$wrappedquestion->qtype]                 ->restore_session_and_responses($wrappedquestion, $state)) {                    notify("Couldn't restore session of question (id=$response[0])!");                    return false;                }                $wrappedquestion->name_prefix = $question->name_prefix;                $wrappedquestion->maxgrade    = $question->maxgrade;                $state->options->subquestions[$wrappedquestion->id] =                 clone($wrappedquestion);            }        }        return true;    }    function extract_response($rawresponse, $nameprefix) {    /// Simple implementation that does not check with the database    /// and thus - does not bother to check whether there has been    /// any changes to the question options.        $response = array();        $rawitems = explode(',', $rawresponse->answer);        foreach ($rawitems as $rawitem) {            $splits = explode('-', $rawitem, 2);            $response[$nameprefix.$splits[0]] = $splits[1];        }        return $response;    }    function get_sa_candidates($categorylist, $questionsinuse=0) {        return get_records_select('question',         "qtype = '".'shortanswer'."' " .         "AND category IN ($categorylist) " .         "AND parent = '0' " .         "AND hidden = '0'" .         "AND id NOT IN ($questionsinuse)");    }    /// BACKUP FUNCTIONS ////////////////////////////    /*     * Backup the data in the question     *     * This is used in question/backuplib.php     */    function backup($bf,$preferences,$question,$level=6) {        $status = true;        $randomsamatchs = get_records("question_randomsamatch","question",$question,"id");        //If there are randomsamatchs        if ($randomsamatchs) {            //Iterate over each randomsamatch            foreach ($randomsamatchs as $randomsamatch) {                $status = fwrite ($bf,start_tag("RANDOMSAMATCH",6,true));                //Print randomsamatch contents                fwrite ($bf,full_tag("CHOOSE",7,false,$randomsamatch->choose));                $status = fwrite ($bf,end_tag("RANDOMSAMATCH",6,true));            }        }        return $status;    }/// RESTORE FUNCTIONS /////////////////    /*     * Restores the data in the question     *     * This is used in question/restorelib.php     */    function restore($old_question_id,$new_question_id,$info,$restore) {        $status = true;        //Get the randomsamatchs array        $randomsamatchs = $info['#']['RANDOMSAMATCH'];        //Iterate over randomsamatchs        for($i = 0; $i < sizeof($randomsamatchs); $i++) {            $ran_info = $randomsamatchs[$i];            //Now, build the question_randomsamatch record structure            $randomsamatch->question = $new_question_id;            $randomsamatch->choose = backup_todb($ran_info['#']['CHOOSE']['0']['#']);            //The structure is equal to the db, so insert the question_randomsamatch            $newid = insert_record ("question_randomsamatch",$randomsamatch);            //Do some output            if (($i+1) % 50 == 0) {                if (!defined('RESTORE_SILENTLY')) {                    echo ".";                    if (($i+1) % 1000 == 0) {                        echo "<br />";                    }                }                backup_flush(300);            }            if (!$newid) {                $status = false;            }        }        return $status;    }    function restore_recode_answer($state, $restore) {        //The answer is a comma separated list of hypen separated question_id and answer_id. We must recode them        $answer_field = "";        $in_first = true;        $tok = strtok($state->answer,",");        while ($tok) {            //Extract the question_id and the answer_id            $exploded = explode("-",$tok);            $question_id = $exploded[0];            $answer_id = $exploded[1];            //Get the question from backup_ids            if (!$que = backup_getid($restore->backup_unique_code,"question",$question_id)) {                echo 'Could not recode randomsamatch question '.$question_id.'<br />';            }                        if ($answer_id == 0) { // no response yet                $ans->new_id = 0;            } else {                //Get the answer from backup_ids                if (!$ans = backup_getid($restore->backup_unique_code,"question_answers",$answer_id)) {                    echo 'Could not recode randomsamatch answer '.$answer_id.'<br />';                }            }            if ($in_first) {                $answer_field .= $que->new_id."-".$ans->new_id;                $in_first = false;            } else {                $answer_field .= ",".$que->new_id."-".$ans->new_id;            }            //check for next            $tok = strtok(",");        }        return $answer_field;    }}//// END OF CLASS ////////////////////////////////////////////////////////////////////////////////// INITIATION - Without this line the question type is not in use... /////////////////////////////////////////////////////////////////////////////question_register_questiontype(new question_randomsamatch_qtype());?>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?