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 = '
'.get_string( 'common_problems', 'game').'';
+ foreach ($warnings as $line) {
+ $s .= '- '.$line.'
';
+ }
+
+ 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 = ''.get_string( 'common_problems', 'game');
- foreach( $warnings as $line) {
- $s .= '- '.$line.'
';
- }
- 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();