diff --git a/CHANGES.md b/CHANGES.md index 5e1266a..2221e1a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,6 @@ +Changes in version 2017-07-03 (2017073001) +- New: Auto check for common problem (mod_form.php and view.php for teachers) + Changes in version 2017-06-30 (2017063002) - in mod_form.php shows the correct numbers of correspondings questions/glossaryentries - in showanswrs.php shows the correspondings questions/glossaryentries diff --git a/check.php b/check.php new file mode 100644 index 0000000..da6e3f5 --- /dev/null +++ b/check.php @@ -0,0 +1,280 @@ +. + +/** + * Basic library. + * + * @package mod_game + * @copyright 2007 Vasilis Daloukas + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Checks for common problems + * + * @param stdClass $context + * @param stdClass $game + */ +function game_check_common_problems($context, $game) { + if (!has_capability('mod/game:viewreports', $context)) { + return ''; + } + + $warnings = array(); + + switch( $game->gamekind) { + case 'millionaire': + game_check_common_problems_multichoice( $game, $warnings); + break; + case 'hangman': + case 'cross': + case 'cryptex': + game_check_common_problems_shortanswer( $game, $warnings); + break; + } + + if (count( $warnings) == 0) { + return ''; + } + + $s = ''; +} + +/** + * Checks for common problems on multichoice answers + * + * @param stdClass $game + * @param string $warnings + */ +function game_check_common_problems_multichoice($game, &$warnings) { + + if ($game->sourcemodule == 'question') { + game_check_common_problems_multichoice_question($game, $warnings); + } else if ( $game->sourcemodule == 'quiz') { + game_check_common_problems_multichoice_quiz($game, $warnings); + } +} + +/** + * Checks for common problems on multichoice answers (questions) + * + * @param stdClass $game + * @param string $warnings + */ +function game_check_common_problems_multichoice_question($game, &$warnings) { + global $CFG, $DB; + + if ($game->questioncategoryid == 0) { + $warnings[] = get_string( 'must_select_questioncategory', 'game'); + return; + } + + // Include subcategories. + $select = 'category='.$game->questioncategoryid; + if ($game->subcategories) { + $cats = question_categorylist( $game->questioncategoryid); + if (count( $cats)) { + $select = 'q.category in ('.implode(',', $cats).')'; + } + } + + if (game_get_moodle_version() < '02.06') { + $table = "{$CFG->prefix}question q, {$CFG->prefix}question_multichoice qmo"; + $select .= " AND qtype='multichoice' AND qmo.single <> 1 AND qmo.question=q.id"; + } else { + $table = "{$CFG->prefix}question q, {$CFG->prefix}qtype_multichoice_options qmo"; + $select .= " AND qtype='multichoice' AND qmo.single <> 1 AND qmo.questionid=q.id"; + } + + $sql = "SELECT COUNT(*) as c FROM $table WHERE $select"; + $rec = $DB->get_record_sql( $sql); + if ($rec->c != 0) { + $warnings[] = get_string( 'millionaire_also_multichoice', 'game').': '.$rec->c; + } +} + +/** + * Checks for common problems on multichoice answers (quiz) + * + * @param stdClass $game + * @param string $warnings + */ +function game_check_common_problems_multichoice_quiz($game, &$warnings) { + global $CFG, $DB; + + if (game_get_moodle_version() < '02.06') { + $select = "qtype='multichoice' AND quiz='$game->quizid' AND qmo.question=q.id". + " AND qqi.question=q.id"; + $table = "{quiz_question_instances} qqi,{question} q, {question_multichoice} qmo"; + } else if (game_get_moodle_version() < '02.07') { + $select = "qtype='multichoice' AND quiz='$game->quizid' AND qmo.questionid=q.id". + " AND qqi.question=q.id"; + $table = "{quiz_question_instances} qqi,{question} q, {qtype_multichoice_options} qmo"; + } else { + $select = "qtype='multichoice' AND qs.quizid='$game->quizid' AND qmo.questionid=q.id". + " AND qs.questionid=q.id"; + $table = "{quiz_slots} qs,{question} q, {qtype_multichoice_options} qmo"; + } + + $sql = "SELECT COUNT(*) as c FROM $table WHERE $select"; + $rec = $DB->get_record_sql( $sql); + if ($rec->c != 0) { + $warnings[] = get_string( 'millionaire_also_multichoice', 'game').': '.$rec->c; + } +} + +/** + * Checks for common problems on short answers + * + * @param stdClass $game + * @param string $warnings + */ +function game_check_common_problems_shortanswer($game, &$warnings) { + if ($game->sourcemodule == 'question') { + game_check_common_problems_shortanswer_question($game, $warnings); + } else if ( $game->sourcemodule == 'glossary') { + game_check_common_problems_shortanswer_glossary($game, $warnings); + } +} + +/** + * Checks for common problems on short answers (glossaries) + * + * @param stdClass $game + * @param string $warnings + */ +function game_check_common_problems_shortanswer_glossary($game, &$warnings) { + + global $CFG, $DB; + + $sql = "SELECT id,concept FROM {$CFG->prefix}glossary_entries WHERE glossaryid={$game->glossaryid}"; + $recs = $DB->get_records_sql( $sql); + $a = array(); + foreach ($recs as $rec) { + $a[] = $rec->concept; + } + + game_check_common_problems_shortanswer_allowspaces( $game, $warnings, $a); + if ($game->gamekind == 'hangman') { + game_check_common_problems_shortanswer_hangman( $game, $warnings, $a); + } +} + +/** + * Checks for common problems on short answers (questions) + * + * @param stdClass $game + * @param string $warnings + */ +function game_check_common_problems_shortanswer_question($game, &$warnings) { + + global $CFG, $DB; + + if ($game->questioncategoryid == 0) { + $warnings[] = get_string( 'must_select_questioncategory', 'game'); + return; + } + + $select = 'category='.$game->questioncategoryid; + if ($game->subcategories) { + $cats = question_categorylist( $game->questioncategoryid); + if (count( $cats) > 0) { + $s = implode( ',', $cats); + $select = 'category in ('.$s.')'; + } + } + $select .= " AND qtype='shortanswer'"; + + $sql = "SELECT id FROM {$CFG->prefix}question WHERE $select"; + if (($recs = $DB->get_records_sql( $sql)) === false) { + return; + } + $a = array(); + foreach ($recs as $rec) { + // Maybe there are more answers to one question. I use as correct the one with bigger fraction. + $sql = "SELECT DISTINCT answer FROM {$CFG->prefix}question_answers WHERE question={$rec->id} ORDER BY fraction DESC"; + if (($rec2 = $DB->get_record_sql( $sql, null, 0, 1)) != false) { + $a[] = $rec2->answer; + } + } + game_check_common_problems_shortanswer_allowspaces( $game, $warnings, $a); + if ($game->gamekind == 'hangman') { + game_check_common_problems_shortanswer_hangman( $game, $warnings, $a); + } +} + +/** + * Checks for common problems (check if are answers with spaces and the game doesn't allow spaces) + * + * @param stdClass $game + * @param string $warnings + * @param array $a the words contained + */ +function game_check_common_problems_shortanswer_allowspaces( $game, &$warnings, $a) { + if ($game->param7 != 0) { + // Allow spaces, so no check is needed. + return; + } + + $ret = array(); + foreach ($a as $word) { + if (strpos( $word, ' ') === false) { + continue; + } + $ret[] = $word; + } + + if (count( $ret) != 0) { + $warnings[] = get_string( 'common_problems_allowspaces', 'game').': '.count($ret).' ('.implode( ', ', $ret); + } +} + +/** + * Checks for common problems (check if are answers with spaces and the game doesn't allow spaces) + * + * @param stdClass $game + * @param string $warnings + * @param array $a the words contained + */ +function game_check_common_problems_shortanswer_hangman( $game, &$warnings, $a) { + $ret = array(); + foreach ($a as $word) { + + $word = game_upper( str_replace( ' ', '', $word), $game->language); + if ($game->language == '') { + $game->language = game_detectlanguage( $word); + $word = game_upper( $word, $game->language); + } + $allletters = game_getallletters( $word, $game->language, $game->userlanguage); + + if ($allletters != '') { + continue; + } + + $ret[] = $word; + } + + if (count( $ret) != 0) { + $warnings[] = get_string( 'common_problems_shortanswer_hangman', 'game').': '.count($ret).' ('.implode( ', ', $ret); + } +} diff --git a/db/upgrade.php b/db/upgrade.php index 4a4a8cb..f5ad12a 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1644,6 +1644,11 @@ function xmldb_game_upgrade($oldversion) { } } + if ($oldversion < ($ver = 2017070301)) { + $sql = "UPDATE {$CFG->prefix}game SET glossarycategoryid=0 WHERE glossarycategoryid < 0"; + $DB->execute( $sql); + } + return true; } diff --git a/lang/en/game.php b/lang/en/game.php index 314feed..bdb6839 100644 --- a/lang/en/game.php +++ b/lang/en/game.php @@ -36,6 +36,12 @@ $string[ 'bookquiz_categories'] = 'Categories'; $string[ 'bookquiz_chapters'] = 'Chapters'; $string[ 'bookquiz_numquestions'] = 'Questions'; +// Check.php. +$string[ 'common_problems'] = 'Common problems'; +$string[ 'millionaire_also_multichoice'] = 'Multichoice answers without single correct answer'; +$string[ 'common_problems_allowspaces'] = 'There are words with spaces but in the game, spaces are not allowed'; +$string[ 'common_problems_shortanswer_hangman'] = 'Not all characters are in the language of game'; + // Classes. $string[ 'eventgamecreated'] = 'Game created'; $string[ 'eventgamedeleted'] = 'Game deleted'; @@ -230,7 +236,6 @@ $string[ 'convertfrom'] = '-'; $string[ 'convertto'] = '-'; $string[ 'gradeaverage'] = 'Average grade'; $string[ 'gradehighest'] = 'Highest grade'; -$string[ 'common_problems'] = 'Common problems'; // File mod_form.php. $string[ 'bookquiz_layout'] = 'Layout'; @@ -342,7 +347,6 @@ $string[ 'clearrepetitions'] = 'Clear statistics'; $string[ 'computerepetitions'] = 'Compute statistics again'; $string[ 'feedbacks'] = 'Messages correct answer'; $string[ 'repetitions'] = 'Repetitions'; -$string[ 'millionaire_also_multichoice'] = 'Multichoice answers without single correct answer'; // File showattempts.php. $string[ 'lastip'] = 'IP student'; diff --git a/locallib.php b/locallib.php index f1b3791..9581374 100644 --- a/locallib.php +++ b/locallib.php @@ -2567,110 +2567,3 @@ function game_use_events() { function game_feedback_for_grade($grade, $gameid) { return ''; } - -/** - * Checks for common problems - * - * @param stdClass $context - * @param stdClass $game - */ -function game_check_common_problems($context, $game) { - if (!has_capability('mod/game:viewreports', $context)) { - return ''; - } - - $warnings = array(); - - switch( $game->gamekind) { - case 'millionaire': - game_check_common_problems_multichoice( $game, $warnings); - break; - case 'hangman': - case 'cross': - case 'cryptex': - game_check_common_problems_shortanswer( $game, $warnings); - break; - } - - if( count( $warnings) == 0) { - return ''; - } - - - $s = ''; -} - -/** - * Checks for common problems on multichoice answers - * - * @param stdClass $game - * @param string $warnings - */ -function game_check_common_problems_multichoice($game, &$warnings) { - - global $CFG, $DB; - - if ($game->questioncategoryid == 0) { - $warnings[] = get_string( 'must_select_questioncategory', 'game'); - return; - } - - // Include subcategories. - $select = 'category='.$game->questioncategoryid; - if ($game->subcategories) { - $cats = question_categorylist( $game->questioncategoryid); - if (count( $cats)) { - $select = 'q.category in ('.implode(',', $cats).')'; - } - } - - if (game_get_moodle_version() < '02.06') { - $table = "{$CFG->prefix}question q, {$CFG->prefix}question_multichoice qmo"; - $select .= " AND qtype='multichoice' AND qmo.single <> 1 AND qmo.question=q.id"; - } else { - $table = "{$CFG->prefix}question q, {$CFG->prefix}qtype_multichoice_options qmo"; - $select .= " AND qtype='multichoice' AND qmo.single <> 1 AND qmo.questionid=q.id"; - } - - $sql = "SELECT COUNT(*) as c FROM $table WHERE $select"; - $rec = $DB->get_record_sql( $sql); - if ($rec->c != 0) { - $warnings[] = get_string( 'millionaire_also_multichoice', 'game').': '.$rec->c; - } -} - -/** - * Checks for common problems on short answers - * - * @param stdClass $game - * @param string $warnings - */ -function game_check_common_problems_shortanswer($game, &$warnings) { - - global $CFG, $DB; - - if ($game->sourcemodule == 'question') { - if ($game->questioncategoryid == 0) { - $warnings[] = get_string( 'must_select_questioncategory', 'game'); - return; - } - - // Include subcategories. - $select = 'category='.$game->questioncategoryid; - if ($game->subcategories) { - $cats = question_categorylist( $game->questioncategoryid); - if (count( $cats)) { - $select = 'q.category in ('.implode(',', $cats).')'; - } - } - - $table = '{question} q'; - $select .= " AND q.qtype = 'shortanswer'"; - - $sql = "SELECT COUNT(*) as c FROM $table WHERE $select"; - } -} diff --git a/mod_form.php b/mod_form.php index 0347f91..3e3c138 100644 --- a/mod_form.php +++ b/mod_form.php @@ -421,12 +421,7 @@ class mod_game_mod_form extends moodleform_mod { $a = array(); // Fills with the count of entries in each glossary. - $sql2 = "SELECT COUNT(*) FROM {$CFG->prefix}glossary_entries ge WHERE ge.glossaryid=g.id"; - $sql = "SELECT id, name, ($sql2) as c FROM {$CFG->prefix}glossary g WHERE $select"; - $recs = $DB->get_records_sql( $sql); - foreach ($recs as $rec) { - $a[ - $rec->id] = $rec->name.' -> ('.$rec->c.')'; - } + $a[ 0] = ''; // Fills with the count of entries in each category. $sql2 = "SELECT COUNT(*) ". " FROM {$CFG->prefix}glossary_entries ge, {$CFG->prefix}glossary_entries_categories gec". diff --git a/showanswers.php b/showanswers.php index 9d38566..383e29d 100644 --- a/showanswers.php +++ b/showanswers.php @@ -24,6 +24,7 @@ require_once("../../config.php"); require_once( "headergame.php"); +require_once( "check.php"); require_login(); @@ -53,8 +54,9 @@ echo '

'; $existsbook = ($DB->get_record( 'modules', array( 'name' => 'book'), 'id,id')); game_showanswers( $game, $existsbook, $context); $s = game_check_common_problems( $context, $game); -if ($s != '') +if ($s != '') { echo '
'.$s; +} echo $OUTPUT->footer(); diff --git a/version.php b/version.php index 11da006..9fce04d 100644 --- a/version.php +++ b/version.php @@ -35,10 +35,10 @@ if (!isset( $plugin)) { } $plugin->component = 'mod_game'; // Full name of the plugin (used for diagnostics). -$plugin->version = 2017070201; // The current module version (Date: YYYYMMDDXX). +$plugin->version = 2017070301; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2010112400; // Requires Moodle 2.0. $plugin->cron = 0; // Period for cron to check this module (secs). -$plugin->release = '2017-07-02'; +$plugin->release = '2017-07-03'; $plugin->maturity = MATURITY_STABLE; if ($useplugin != 2) { diff --git a/view.php b/view.php index 89d93aa..3edbd1f 100644 --- a/view.php +++ b/view.php @@ -326,4 +326,12 @@ if ($buttontext) { } echo $OUTPUT->box_end(); +if (has_capability('mod/game:manage', $context)) { + require( 'check.php'); + $s = game_check_common_problems( $context, $game); + if ($s != '') { + echo '
'.$s; + } +} + echo $OUTPUT->footer();