Giter Site home page Giter Site logo

middlebury / moodle-mod_adaptivequiz Goto Github PK

View Code? Open in Web Editor NEW
33.0 18.0 40.0 392 KB

Moodle Adaptive Quiz Module (archived). See https://moodle.org/plugins/mod_adaptivequiz for active forks and releases.

Home Page: https://moodle.org/plugins/mod_adaptivequiz

PHP 98.70% JavaScript 1.16% CSS 0.14%
moodle moodle-plugin moodle-quiz

moodle-mod_adaptivequiz's Introduction

This repository is now archived: The sponsor of this plugin, Middlebury College, is no longer using Moodle. Development is continuing on other forks of the project. See https://moodle.org/plugins/mod_adaptivequiz for more information and latest releases.

Moodle Adaptive Test Activity

The Adaptive Test activity enables a teacher to create tests that efficiently measure the takers' abilities. Adaptive tests are comprised of questions selected from the question bank that are tagged with a score of their difficulty. The questions are chosen to match the estimated ability level of the current test-taker. If the test-taker succeeds on a question, a more challenging question is presented next. If the test-taker answers a question incorrectly, a less-challenging question is presented next. This technique will develop into a sequence of questions converging on the test-taker's effective ability level. The test stops when the test-taker's ability is determined to the required accuracy.

The Adaptive Test activity uses the "Practical Adaptive Testing CAT Algorithm" by B.D. Wright published in Rasch Measurement Transactions, 1988, 2:2 p.24 and discussed in John Linacre's "Computer-Adaptive Testing: A Methodology Whose Time Has Come." MESA Memorandum No. 69 (2000).

This Moodle activity module was created as a collaborative effort between Middlebury College and Remote Learner. The latest code, documentation, and bug-tracker can be found at https://github.com/middlebury/moodle-mod_adaptivequiz.

The Question Bank

To begin with, questions to be used with this activity are added or imported into Moodle's question bank. Only questions that can automatically be graded may be used. As well, questions should not award partial credit. The questions can be placed in one or more categories.

This activity is best suited to determining an ability measure along a unidimensional scale. While the scale can be very broad, the questions must all provide a measure of ability or aptitude on the same scale. In a placement test for example, questions low on the scale that novices are able to answer correctly should also be answerable by experts, while questions higher on the scale should only be answerable by experts or a lucky guess. Questions that do not discriminate between takers of different abilities on will make the test ineffective and may provide inconclusive results.

Take for example a language placement test. Low-difficulty vocabulary and reading-comprehension questions would likely be answerable by all but the most novice test-takers. Likewise, high-difficulty questions involving advanced gramatical constructs and nuanced reading-comprehension would be likely only be correctly answered by advanced, high-level test-takers. Such questions would all be good candidates for usage in an Adaptive Test. In contrast, a question like "Is 25¥ a good price for a sandwich?" would not measure language ability but rather local knowledge and would be as likely to be answered correctly by a novice speaker who has recently been to China as it would be answered incorrectly by an advanced speaker who comes from Taiwan -- where a different currency is used. Such questions should not be included in the question-pool.

Questions must be tagged tagged with a 'difficulty score' using the format 'adpq_n' where n is a positive integer, e.g. 'adpq_1' or 'adpq_57'. The range of the scale is arbitrary (e.g. 1-10, 0-99, 1-1000), but should have enough levels to distinguish between question difficulties.

The Testing Process

The Adaptive Test activity is configured with a fixed starting level. The test will begin by presenting the test-taker with a random question from that starting level. As described in Linacre (2000), it often makes sense to have the starting level be in the lower part of the difficulty range so that most test-takers get to answer at least one of the first few questions correctly, helping their moral.

After the test-taker submits their answer, the system calculates the target question difficulty it will select next. If the last question was answered correctly, the next question will be harder; if the last question was answered incorrectly, the next question will be easier. The system also calculates a measure of the test-taker's ability and the standard error for that measure. A next random question at or near the target difficulty is selected and presented to the user.

This process of alternating harder questions following correct answers and easier questions following wrong answers continues until one of the stopping conditions is met. The possible stopping conditions are as follows:

  • There are no remaining easier questions to ask after a wrong answer.
  • There are no remaining harder questions to ask after a correct answer.
  • The standard error in the measure has become precise enough to stop.
  • The maximum number of questions has been exceeded.

Graph of an attempt

Test Parameters and Operation

The primary parameters for tuning the operation of the test are:

  • The starting level
  • The minimum number of questions
  • The maximum number of questions
  • The standard error to stop

Relationship between maximum number of questions and Standard Error

As discussed in Wright (1988), the formula for calculating the standard error is given by:

Standard Error (± logits) = sqrt((R+W)/(R*W))

where R is the number of right answers and W is the number of wrong answers. This value is on a logit scale, so we can apply the inverse-logit function to convert it to an percentage scale:

Standard Error (± %) = ((1 / ( 1 + e^( -1 * sqrt((R+W)/(R*W)) ) ) ) - 0.5) * 100

Looking at the Standard Error function, it is important to note that it depends only on the difference between the number of right and wrong answers and the total number of answers, not on any other features such as which answers were right and which answers were wrong. For a given number of questions asked, the Standard Error will be smallest when half the answers are right and half are wrong. From this, we can deduce the minimum standard error possible to achieve for any number of questions asked:

  • 10 questions (5 right, 5 wrong) → Minimum Standard Error = ± 15.30%
  • 20 questions (10 right, 10 wrong) → Minimum Standard Error = ± 11.00%
  • 30 questions (15 right, 15 wrong) → Minimum Standard Error = ± 9.03%
  • 40 questions (20 right, 20 wrong) → Minimum Standard Error = ± 7.84%
  • 50 questions (25 right, 25 wrong) → Minimum Standard Error = ± 7.02%
  • 60 questions (30 right, 30 wrong) → Minimum Standard Error = ± 6.42%
  • 70 questions (35 right, 35 wrong) → Minimum Standard Error = ± 5.95%
  • 80 questions (40 right, 40 wrong) → Minimum Standard Error = ± 5.57%
  • 90 questions (45 right, 45 wrong) → Minimum Standard Error = ± 5.25%
  • 100 questions (50 right, 50 wrong) → Minimum Standard Error = ± 4.98%
  • 110 questions (55 right, 55 wrong) → Minimum Standard Error = ± 4.75%
  • 120 questions (60 right, 60 wrong) → Minimum Standard Error = ± 4.55%
  • 130 questions (65 right, 65 wrong) → Minimum Standard Error = ± 4.37%
  • 140 questions (70 right, 70 wrong) → Minimum Standard Error = ± 4.22%
  • 150 questions (75 right, 75 wrong) → Minimum Standard Error = ± 4.07%
  • 160 questions (80 right, 80 wrong) → Minimum Standard Error = ± 3.94%
  • 170 questions (85 right, 85 wrong) → Minimum Standard Error = ± 3.83%
  • 180 questions (90 right, 90 wrong) → Minimum Standard Error = ± 3.72%
  • 190 questions (95 right, 95 wrong) → Minimum Standard Error = ± 3.62%
  • 200 questions (100 right, 100 wrong) → Minimum Standard Error = ± 3.53%

What this listing indicates is that for a test configured with a maximum of 50 questions and a "standard error to stop" of 7%, the maximum number of questions will always be encountered first and stop the test. Conversely, if you are looking for a standard error of 5% or better, the test must ask at least 100 questions.

Note that these are best-case scenarios for the number of questions asked. If a test-taker answers a lopsided run of questions right or wrong the test will require more questions to reach a target standard of error.

Minimum number of questions

For most purposes this value can be set to 1 since the standard of error to stop will generally set a base-line for the number of questions required. This could be configured to be greater than the minimum number of questions needed to achieve the standard of error to stop if you wish to ensure that all test-takers answer additional questions.

Starting level

As mentioned above, this usually will be set in the lower part of the difficulty range (about 1/3 of the way up from the bottom) so that most test takers will be able answer one of the first two questions correctly and get a moral boost from their correct answers. If the starting level is too high, low-ability users would be asked several questions they can't answer before the test begins asking them questions at a level they can answer.

Scoring

As discussed in Wright (1988), the formula for calculating the ability measure is given by:

Ability Measure = H/L + ln(R/W)

where H is the sum of all question difficulties answered, L is the number of questions answered, R is the number of right answers, and W is the number of wrong answers.

Note that this measure is not affected by the order of answers, just the total difficulty and number of right and wrong answers. This measure is dependent on the test algorithm presenting alternating easier/harder questions as the user answers wrong/right and may not be applicable to other algorithms. In practice, this means that the ability measure should not greatly affected by a small number of spurrious right or wrong answers.

As discussed in Linacre (2000), the ability measure of the test taker aligns with the question-difficulty at which the test-taker has a 50% probability of answering a question correctly.

For example, given a test with levels 1-10 and a test-taker that answered every question 5 and below correctly and every question 6 and up wrong, the test-taker's ability measure would fall close to 5.5.

Remember that the ability measure does have error associated with it. Be sure to take the standard error ammount into account when acting on the score.

moodle-mod_adaptivequiz's People

Contributors

adamfranco avatar benit avatar semteacher avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

moodle-mod_adaptivequiz's Issues

SQL error when clicking the 'Start attempt' button with Moodle 3.0.6

Hello,
I am encountering an SQL error when starting an attempt in adaptive quiz.
Details:

  • Adaptive quiz version: 1.2.3
  • Moodle version: 3.0.6
  • Database: PostgreSQL 9.4.10

Steps to reproduce:

  • Create a course named: "test course for adaptive quiz"

  • Go to the course page

  • Create 3 "true/false" questions with category set to 'Default for test course for adaptive quiz'.
    ` Dashboard / ► Courses / ► test course for adaptive quiz / ► Question bank / ► Questions /

  • According to this answer, question 1 is tagged as "adpq_1", question 2 is tagged as"adpq_2",question 3 tagged as"adpq_3".

  • Get back to course page and click "Add an activity or resource", then add an Adaptive Quiz named "test adaptive quiz".

  • This test will be feed configured as follow:
    -Question pool:'Default for test course for adaptive quiz'.
    -Starting level of difficulty: 1
    -Lowest level of difficulty: 1
    -Highest level of difficulty: 1
    -Minimum number of questions: 1
    -Maximum number of questions: 3
    -Standard Error to stop: 5

  • Go to the 'test course for adaptive quiz' page, and click on the quiz.

  • Click on the 'Start attempt' button

  • The following error will appear:

  Debug info: ERROR: column "t.id" must appear in the GROUP BY clause or be used in an aggregate function

        LINE 9: ORDER BY t.id ASC
        ^
        SELECT SUBSTR(t.name, 6) AS difflevel, count(*) AS numofquest
        FROM mdl_tag t
        JOIN mdl_tag_instance ti ON t.id = ti.tagid
        JOIN mdl_question q ON q.id = ti.itemid
        WHERE ti.itemtype = $1
        AND ti.tagid IN ($2,$3,$4)
        AND q.category = $5
        GROUP BY t.name
        ORDER BY t.id ASC
        [array (
        0 => 'question',
        1 => '4',
        2 => '5',
        3 => '6',
        4 => '7',
        )]
        Error code: dmlreadexception
        Stack trace:

            line 443 of /lib/dml/moodle_database.php: dml_read_exception thrown
            line 244 of /lib/dml/pgsql_native_moodle_database.php: call to moodle_database->query_end()
            line 785 of /lib/dml/pgsql_native_moodle_database.php: call to pgsql_native_moodle_database->query_end()
            line 1404 of /lib/dml/moodle_database.php: call to pgsql_native_moodle_database->get_records_sql()
            line 436 of /mod/adaptivequiz/fetchquestion.class.php: call to moodle_database->get_records_sql_menu()
            line 259 of /mod/adaptivequiz/fetchquestion.class.php: call to fetchquestion->retrieve_tags_with_question_count()
            line 287 of /mod/adaptivequiz/fetchquestion.class.php: call to fetchquestion->initalize_tags_with_quest_count()
            line 373 of /mod/adaptivequiz/adaptiveattempt.class.php: call to fetchquestion->fetch_questions()
            line 352 of /mod/adaptivequiz/adaptiveattempt.class.php: call to adaptiveattempt->get_question_ready()
            line 211 of /mod/adaptivequiz/attempt.php: call to adaptiveattempt->start_attempt()

Need customizable message at the end of the test.

Reported by @JoeAntonioli :

The adaptive placement module does not have a way to change the message at the end of the exam, all the student sees is what is in the attached screen shot. In the quiz module this is done by changing the overall feedback in the quiz settings, but that setting is not available in the adaptive quiz.

screen shot 2014-01-02 at 10 34 39 am

Error trying to complete attempt record

I have set up a new Moodle install, set up the tags, and added at least one question to all the three difficulty levels. After creating the Adaptive Quiz, when I press the "Start Quiz" button this error shows up:

Error trying to complete attempt record

Report score into gradebook

Report the user's best score into the gradebook so that other modules can access it for workflow purposes.

Issues with unit test: mod_adaptivequiz_locallib_testcase for Moodle v3.6

Hello!

My name is Sebastián and I work as a developer for Blackboard - Open LMS Moodle team.

Recently we have discovered a strange behaviour with one of the test in mod_adaptivequiz. Please read the following comment:

The test mod_adaptivequiz_locallib_testcase::test_adaptivequiz_complete_attempt is giving the following output:

########################################################################
vendor/bin/phpunit mod/adaptivequiz/tests/locallib_test.php
Moodle 3.6.3 (Build: 20190311), 953c924510701d711300aace97762eb41d7b20b6
Php: 7.1.20.1.16.04.1.1, mysqli: 5.7.23-0ubuntu0.16.04.1, OS: Linux 4.4.0-116-generic x86_64
PHPUnit 6.5.8 by Sebastian Bergmann and contributors.

..............RThe instance of this module does not exist
.......... 25 / 25 (100%)

Time: 36.63 seconds, Memory: 82.00MB

There was 1 risky test:

  1. mod_adaptivequiz_locallib_testcase::test_adaptivequiz_complete_attempt
    This test printed output: The instance of this module does not exist

To re-run:
vendor/bin/phpunit "mod_adaptivequiz_locallib_testcase" mod/adaptivequiz/tests/locallib_test.php

OK, but incomplete, skipped, or risky tests!
Tests: 25, Assertions: 37, Risky: 1.`
########################################################################

If you have any questions or concerns, feel free to reach out to me at [email protected] :)

Error fetching question from the database

When "start attempt" is clicked, the course throws the following error:

Debug info: ERROR: column "u.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT u.id, u.firstname, u.lastname, u.email, a.highestleve...
^
SELECT u.id, u.firstname, u.lastname, u.email, a.highestlevel, a.lowestlevel,
(SELECT COUNT(*)
FROM mdl_adaptivequiz_attempt caa
WHERE caa.userid = u.id
AND caa.instance = aa.instance
) AS attempts,
(SELECT maa.measure
FROM mdl_adaptivequiz_attempt maa
WHERE maa.instance = a.id
AND maa.userid = u.id
AND maa.attemptstate = $1
AND maa.standarderror > 0.0
ORDER BY measure DESC
LIMIT 1) AS measure,
(SELECT saa.standarderror
FROM mdl_adaptivequiz_attempt saa
WHERE saa.instance = a.id
AND saa.userid = u.id
AND saa.attemptstate = $2
AND saa.standarderror > 0.0
ORDER BY measure DESC
LIMIT 1) AS stderror,
(SELECT taa.timemodified
FROM mdl_adaptivequiz_attempt taa
WHERE taa.instance = a.id
AND taa.userid = u.id
AND taa.attemptstate = $3
AND taa.standarderror > 0.0
ORDER BY measure DESC
LIMIT 1) AS timemodified,
(SELECT iaa.uniqueid
FROM mdl_adaptivequiz_attempt iaa
WHERE iaa.instance = a.id
AND iaa.userid = u.id
AND iaa.attemptstate = $4
AND iaa.standarderror > 0.0
ORDER BY measure DESC
LIMIT 1) AS uniqueid
FROM mdl_adaptivequiz_attempt aa
JOIN mdl_user u ON u.id = aa.userid
JOIN mdl_adaptivequiz a ON a.id = aa.instance

WHERE aa.instance = $5

GROUP BY aa.userid
ORDER BY lastname ASC LIMIT 30 OFFSET 0
[array (
0 => 'complete',
1 => 'complete',
2 => 'complete',
3 => 'complete',
4 => '2',
)]
Error code: dmlreadexception
Stack trace:

line 443 of /lib/dml/moodle_database.php: dml_read_exception thrown
line 244 of /lib/dml/pgsql_native_moodle_database.php: call to moodle_database->query_end()
line 764 of /lib/dml/pgsql_native_moodle_database.php: call to pgsql_native_moodle_database->query_end()
line 145 of /mod/adaptivequiz/viewreport.php: call to pgsql_native_moodle_database->get_records_sql()

Time Limit

I am trying to use the "adaptive quiz" plug-in on moodle. I want to put a time limit on the test but I cant find an option to do so. Can anyone please help me?

Adaptive Quiz: Fix unit test failures

Hi Adam my name is Derek Henderson, and I work for remote learner. Part of my job is to evaluate plugins for newer versions of Moodle, and I was noticing that your Adaptive Quiz plugin fails a unit test in M30, and M31.

The details are below..

Just wondering if you are going to issuing a fix at any time - or if there is something that I am doing wrong with the tests etc.

The unit test failures look minor - like something is not being reset in the database...

Cheers

Derek Henderson
vendor/bin/phpunit mod_adaptivequiz_locallib_testcase mod/adaptivequiz/tests/locallib_test.php

  1. mod_adaptivequiz_locallib_testcase::test_adaptivequiz_complete_attempt
    dml_write_exception: Error writing to database (Duplicate entry '16' for key 'PRIMARY'
    INSERT INTO phpu2_context (id,contextlevel,instanceid,path,depth) VALUES(?,?,?,?,?)
    [array (
    0 => '16',
    1 => '50',
    2 => '2',
    3 => '/1/3/16',
    4 => '3',
    )])

/var/www/html/m31/lib/dml/moodle_database.php:446
/var/www/html/m31/lib/dml/mysqli_native_moodle_database.php:1164
/var/www/html/m31/lib/dml/mysqli_native_moodle_database.php:1353
/var/www/html/m31/lib/phpunit/classes/advanced_testcase.php:219
/var/www/html/m31/mod/adaptivequiz/tests/locallib_test.php:64
/var/www/html/m31/mod/adaptivequiz/tests/locallib_test.php:275
/var/www/html/m31/lib/phpunit/classes/advanced_testcase.php:80

To re-run:
vendor/bin/phpunit mod_adaptivequiz_locallib_testcase mod/adaptivequiz/tests/locallib_test.php

  1. mod_adaptivequiz_locallib_testcase::test_adaptivequiz_min_attempts_reached
    dml_write_exception: Error writing to database (Duplicate entry '16' for key 'PRIMARY'
    INSERT INTO phpu2_context (id,contextlevel,instanceid,path,depth) VALUES(?,?,?,?,?)
    [array (
    0 => '16',
    1 => '50',
    2 => '2',
    3 => '/1/3/16',
    4 => '3',
    )])

/var/www/html/m31/lib/dml/moodle_database.php:446
/var/www/html/m31/lib/dml/mysqli_native_moodle_database.php:1164
/var/www/html/m31/lib/dml/mysqli_native_moodle_database.php:1353
/var/www/html/m31/lib/phpunit/classes/advanced_testcase.php:219
/var/www/html/m31/mod/adaptivequiz/tests/locallib_test.php:64
/var/www/html/m31/mod/adaptivequiz/tests/locallib_test.php:293
/var/www/html/m31/lib/phpunit/classes/advanced_testcase.php:80

results of the quiz

Colleagues,
How can we interpret results of users?
For instance, we have English Placement Test with levels
1 - Elementary
2 - Pre-Intermediate
3 - Intermediate
4 - Upper-Intermediate
5 - Advanced
Every level has 20 questions: adpq_1, adpq_2, adpq_3, adpq_4 and adpq_5
After taking the quiz user gets 4.50 (87.55 %)
Which level it fits?
How can we grade results?

Quiz Navigation

Hi,
Is there any way to have "Quiz navigation" option in adaptive quiz also, just like we have in case of normal quiz?
If not then it can be added as enhancement.

Add graph of attempt to attempt report

Add a graph that charts the difficulty of the questions asked, the measured ability, and the standard error at each step of the attempt. This graph will provide important visual clues as to how the system is operating and will highlight cases where problems with the question bank (such as insufficient questions) cause the test to fail.

Screen shot 2013-04-24 at 10 22 51 AM

Image path corrupted by +1

The images are not visible, and the pathway seems to get corrupted on the way from draftfile.php to pluginfile.php

E.G; the image is visible on editing mode to the teacher, but when the students starts an attempt, the student doesnt see the image, but if i change the pathway i.e change the folder name. (Have -1 the original folder number) The image appears.

1
2
3

Adaptive Quiz Images Missing moodle 2.9

Images in the questions in the Question bank when previewed show OK
Running through the Adaptive Quiz with the questions the images show a red cross and a blank space
I set up a standard Moodle Quiz and images work in that fine on all Browsers.
Probably bug in the Adaptive Quiz code which we thought would be a possibility due to it being out of date.

Record question difficulty and test parameters for each attempt

Currently the attempt review summary has to look at the question's ability tags and setting on the test when displaying how the result was calculated. If a question's difficulty is modified or the test parameters change then the report will not match the summary score.

Unit tests fail with a dml_write_exception

I'm trying to get the unit tests to work with a Moodle 2.8 installation. Unfortunately they consistently fail with errors like this one:

mod_adaptivequiz_adaptiveattempt_testcase::test_get_all_questions_in_attempt
dml_write_exception: Error writing to database (Duplicate entry '70-2' for key 'phpu_cont_conins_uix'
INSERT INTO phpu_context (id,contextlevel,instanceid,path,depth) VALUES(?,?,?,?,?)
[array (
  0 => '330',
  1 => '70',
  2 => '2',
  3 => '/1/3/16/330',
  4 => '4',
)])

/www/lib/dml/moodle_database.php:446
/www/lib/dml/mysqli_native_moodle_database.php:1164
/wwww/lib/dml/mysqli_native_moodle_database.php:1353
/www/lib/phpunit/classes/advanced_testcase.php:212
/www/mod/adaptivequiz/tests/adaptiveattempt_test.php:59
/www/mod/adaptivequiz/tests/adaptiveattempt_test.php:653
/www//lib/phpunit/classes/advanced_testcase.php:80

Could you please investigate why this is occurring? Also could you outline why the unit tests are trying to load data directly into core Moodle tables such as the context table?

"missing tag prefix" under Moodle 2.5.3

This plugin (although for version 2.3) installs under 2.5.3. However, I get athis error when trying to start an attempt on a quiz:

Missing tag prefix

More information about this error

Debug info:
Error code: missingtagprefix
Stack trace:
line 476 of /lib/setuplib.php: moodle_exception thrown
line 412 of /mod/adaptivequiz/fetchquestion.class.php: call to print_error()
line 238 of /mod/adaptivequiz/fetchquestion.class.php: call to fetchquestion->retrieve_tags_with_question_count()
line 266 of /mod/adaptivequiz/fetchquestion.class.php: call to fetchquestion->initalize_tags_with_quest_count()
line 358 of /mod/adaptivequiz/adaptiveattempt.class.php: call to fetchquestion->fetch_questions()
line 337 of /mod/adaptivequiz/adaptiveattempt.class.php: call to adaptiveattempt->get_question_ready()
line 209 of /mod/adaptivequiz/attempt.php: call to adaptiveattempt->start_attempt()

A number of small fixes.

The attached patch includes a number of small fixes that our internal code review process discovered. Including:

  • Using the new events API instead of the deprecated add_to_log function
  • A missing variable declaration
  • Other minor deprecated functions
  • An updated high resolution icon, using an icon already in the public domain
  • Incorrect paths
  • Missing optional_param function call.

I hope this patch proves useful.

From 89a81698c2706ee650221948efabf22d88c250d2 Mon Sep 17 00:00:00 2001
From: Corey Wallis <[email protected]>
Date: Tue, 23 Jun 2015 14:33:04 +0930
Subject: [PATCH] Various fixes

---
 .../event/course_module_instance_list_viewed.php   |  50 ++++++++++++
 classes/event/course_module_viewed.php             |  33 ++++++++
 index.php                                          |   9 ++-
 mod_form.php                                       |  14 +++-
 pix/icon.png                                       | Bin 0 -> 1026 bytes
 pix/icon.svg                                       |  85 +++++++++++++++++++++
 view.php                                           |  16 +++-
 7 files changed, 195 insertions(+), 12 deletions(-)
 create mode 100644 classes/event/course_module_instance_list_viewed.php
 create mode 100644 classes/event/course_module_viewed.php
 create mode 100644 pix/icon.png
 create mode 100644 pix/icon.svg

diff --git a/classes/event/course_module_instance_list_viewed.php b/classes/event/course_module_instance_list_viewed.php
new file mode 100644
index 0000000..e95b590
--- /dev/null
+++ b/classes/event/course_module_instance_list_viewed.php
@@ -0,0 +1,50 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * The mod_peerassess instance list viewed event.
+ *
+ * @package    mod_adaptivequiz
+ * @author     Corey Wallis <[email protected]>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_adaptivequiz\event;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * The mod_adaptivequiz instance list viewed event class.
+ *
+ * @package    mod_adaptivequiz
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
+    /**
+     * Create the event from course record.
+     *
+     * @param \stdClass $course
+     * @return course_module_instance_list_viewed
+     */
+    public static function create_from_course(\stdClass $course) {
+        $params = array(
+            'context' => \context_course::instance($course->id)
+        );
+        $event = self::create($params);
+        $event->add_record_snapshot('course', $course);
+        return $event;
+    }
+}
diff --git a/classes/event/course_module_viewed.php b/classes/event/course_module_viewed.php
new file mode 100644
index 0000000..20bbdb9
--- /dev/null
+++ b/classes/event/course_module_viewed.php
@@ -0,0 +1,33 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Defines the course module viewed event.
+ *
+ * @package    mod_adaptivequiz
+ * @author     Corey Wallis <[email protected]>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace mod_adaptivequiz\event;
+defined('MOODLE_INTERNAL') || die();
+
+class course_module_viewed extends \core\event\course_module_viewed {
+    protected function init() {
+        $this->data['objecttable'] = 'adaptivequiz';
+        parent::init();
+    }
+}
diff --git a/index.php b/index.php
index b4a4bb3..4766e5e 100644
--- a/index.php
+++ b/index.php
@@ -25,7 +25,7 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */

-require_once(dirname(__FILE__).'/../..config.php');
+require_once(dirname(__FILE__).'/../../config.php');
 require_once($CFG->dirroot.'/mod/adaptivequiz/lib.php');

 $id = required_param('id', PARAM_INT);   // Course.
@@ -34,7 +34,7 @@ $course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST);

 require_course_login($course);

-add_to_log($course->id, 'adaptivequiz', 'view all', 'index.php?id='.$course->id, '');
+\mod_adaptivequiz\event\course_module_instance_list_viewed::create_from_course($course)->trigger();

 $coursecontext = context_course::instance($course->id);

@@ -49,6 +49,7 @@ if (!$adaptivequizinstances = get_all_instances_in_course('adaptivequiz', $cours
     notice(get_string('nonewmodules', 'adaptivequiz'), new moodle_url('/course/view.php', array('id' => $course->id)));
 }

+$table = new html_table();
 if ($course->format == 'weeks') {
     $table->head  = array(get_string('week'), get_string('name'));
     $table->align = array('center', 'left');
@@ -63,12 +64,12 @@ if ($course->format == 'weeks') {
 foreach ($adaptivequizinstances as $adaptivequizinstance) {
     if (!$adaptivequizinstance->visible) {
         $link = html_writer::link(
-            new moodle_url('/mod/adaptivequiz.php', array('id' => $adaptivequizinstance->coursemodule)),
+            new moodle_url('/mod/adaptivequiz/view.php', array('id' => $adaptivequizinstance->coursemodule)),
             format_string($adaptivequizinstance->name, true),
             array('class' => 'dimmed'));
     } else {
         $link = html_writer::link(
-            new moodle_url('/mod/adaptivequiz.php', array('id' => $adaptivequizinstance->coursemodule)),
+            new moodle_url('/mod/adaptivequiz/view.php', array('id' => $adaptivequizinstance->coursemodule)),
             format_string($adaptivequizinstance->name, true));
     }

diff --git a/mod_form.php b/mod_form.php
index 24b4a9e..8f8b129 100644
--- a/mod_form.php
+++ b/mod_form.php
@@ -49,14 +49,20 @@ class mod_adaptivequiz_mod_form extends moodleform_mod {
         if (!empty($CFG->formatstringstriptags)) {
             $mform->setType('name', PARAM_TEXT);
         } else {
-            $mform->setType('name', PARAM_CLEAN);
+            $mform->setType('name', PARAM_CLEANHTML);
         }
         $mform->addRule('name', null, 'required', null, 'client');
         $mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
         $mform->addHelpButton('name', 'adaptivequizname', 'adaptivequiz');

-        // Adding the standard "intro" and "introformat" fields.
-        $this->add_intro_editor();
+        // Adding the standard "intro" and "introformat" fields...
+        // Use the non deprecated function if it exists.
+        if (method_exists($this, 'standard_intro_elements')) {
+            $this->standard_intro_elements();
+        } else {
+            // Deprecated as of Moodle 2.9
+            $this->add_intro_editor();
+        }

         // Number of attempts.
         $attemptoptions = array('0' => get_string('unlimited'));
@@ -137,7 +143,7 @@ class mod_adaptivequiz_mod_form extends moodleform_mod {
         $mform->addRule('standarderror', get_string('formelementempty', 'adaptivequiz'), 'required', null, 'client');
         $mform->addRule('standarderror', get_string('formelementdecimal', 'adaptivequiz'), 'numeric', null, 'client');
         $mform->setDefault('standarderror', 5.0);
-        $mform->setType('standarderror', PARAM_NUMBER);
+        $mform->setType('standarderror', PARAM_FLOAT);

         // Grade settings.
         $this->standard_grading_coursemodule_elements();
diff --git a/pix/icon.png b/pix/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ed0c6eca6501b1187188b03166bd95fa969f90e
GIT binary patch
literal 1026
zcmV+d1pWJoP)<h;3K|Lk000e1NJLTq000yK000;W1^@s6`b*t*00006VoOIv0RI60
z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_00W{)L_t(I%Z-%HPh4db#((eSGIQHu
zKFWu}U`(lvDO4Cuq#ATFn<lujRazHrL>F#c_&@j$xG*u%RilZ~Zj1|)sxc%sel(U$
zP^O_xpp~|Oq)r(q^Yy;xxVV>L1}gO==f3y8$@|>rdCzl>;UO{o&h)1zhlfvzI#5s)
zQAI^jRaAwA>o*FYUHE(&kk+$4z<a03W|HYw3>^mJ`@Olbw<aei{c5F(6Nj@F>m1@7
z);T(TpHw<CGFbll7pz!=Xr*5L_QOl8_yA829lLn$-47=IzQ0Ya=J@LS0(Vz(*hU>|
z9nRU^)j2%lvA9t1&zyVz<4(`g9SB#h{QNtYE|2>F@gR2S+O0K?KKClU@ffFLLwxb&
zMFz72Ac|9mh&1!|$|`TZah{<QC#cnHEd2Np>F$AKQ!*-4%n{P*6y=RFPYw=pe(E(!
zr42v{Z!vsLBog#J)<<@rA5|q0>moKV&V%wd+5}W5s0s!{@mi5T{+#2#;_R8TB$G*0
z6##<)6{OLig`tKCoEm?D@#n{*&u~w}Qb(&naYSff!pb|bEezG6Dk#eG?OUv^ukT<*
zu^;&OvEwAV4zqJ*xHdqEQrX(tV&(1~9u-d=9cundL~&wiD+&^Vj*L9R*yvabFPf~H
z*Pu$hQO7xl8bY(TF^s@el)~IBOG}IU<hI7d#7kt3WKh7Uq6p44b^#@lEUIJ&vIIeJ
zpxi_v5xGf2h9Zb<sj^1KRTY9mar*q;JrKJ4RHag_P^oN_=<32#FSJc7!_YQ@h%#R+
zQY_B%e`4zODdIsKQNg)ZhT<a0LN50#W23nPfug>_7*Nqro$RwsIF?pdS16TA2Lmef
z_diZ1lR@x66lt^-#f6epC~uTmTwHvl+)O%+W)###jp15+=%T?X%J9h%#&S7K^QhTV
zlyJ9JuhNJrE24<FcF8-|Db5$Ub9?zfb`9%LRl2*oiFNwi+jNMvv;m^wnD6Q72`9(_
zQLEMPIy^>4N12_yO6s2<SZ`$*>amD8lBq6I>13PWz5P<F*0_0diMhD~n^!*}YYVKl
z`4I5eX1H-ZN4%{|%tK9Mt>v%fWxCeB<B7&^cpV0fhJ(rH^TErhUoZ3|&4lX+d`#dg
z#sHpzr;67KXAELMFh;$4sR1gU!QFeHKV826;@fQ$^7*{Kxw#pu#$v%?YhyrX6*@g*
wB73O~paC?teZL;m>(yj3S)ZAiu{#+50s@Rrmo1+$?f?J)07*qoM6N<$f@2})mjD0&

literal 0
HcmV?d00001

diff --git a/pix/icon.svg b/pix/icon.svg
new file mode 100644
index 0000000..c5d2ac6
--- /dev/null
+++ b/pix/icon.svg
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--part of the rodentia icon theme by sixsixfive released under CC0 (https://creativecommons.org/publicdomain/zero/1.0/) on openclipart-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" width="24px" height="24px">
+ <defs id="0">
+  <linearGradient id="2">
+   <stop id="Y" stop-color="#888a85"/>
+   <stop id="Z" offset="1" stop-color="#2e3436"/>
+  </linearGradient>
+  <linearGradient id="3">
+   <stop id="a" stop-color="#eeeeec"/>
+   <stop id="b" offset="1" stop-color="#888a85"/>
+  </linearGradient>
+  <linearGradient id="4">
+   <stop id="c" stop-color="#2e3436"/>
+   <stop id="d" offset="1" stop-color="#2e3436" stop-opacity="0"/>
+  </linearGradient>
+  <linearGradient id="5">
+   <stop id="e" stop-color="#fff"/>
+   <stop id="f" offset="1" stop-color="#fff" stop-opacity="0"/>
+  </linearGradient>
+  <linearGradient id="6">
+   <stop id="g" stop-color="#fff" stop-opacity="0.8"/>
+   <stop id="h" offset="1" stop-color="#fff" stop-opacity="0"/>
+  </linearGradient>
+  <linearGradient id="7">
+   <stop id="i" stop-color="#e9b96e"/>
+   <stop id="j" offset="1" stop-color="#c17d11"/>
+  </linearGradient>
+  <filter x="-0.16" y="-0.151" width="1.321" height="1.302" color-interpolation-filters="sRGB" id="8">
+   <feGaussianBlur stdDeviation="0.5327" id="k"/>
+  </filter>
+  <linearGradient id="9">
+   <stop id="l" stop-color="#eeeeec"/>
+   <stop id="m" offset="1" stop-color="#d3d7cf"/>
+  </linearGradient>
+  <radialGradient cx="23.903" cy="47.23" r="23.442" id="A" xlink:href="#4" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,0.0852459,0,43.205123)"/>
+  <radialGradient cx="10.598" cy="14.524" r="18.475" id="B" xlink:href="#7" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.2047255,1.9462005,-2.6136959,0.2850988,46.782408,-21.224234)"/>
+  <linearGradient y1="3.333" x2="0" y2="46.667" id="C" xlink:href="#6" gradientUnits="userSpaceOnUse"/>
+  <linearGradient x1="-7.177" y1="-22.618" x2="17.775" y2="18.539" id="D" xlink:href="#5" gradientUnits="userSpaceOnUse"/>
+  <radialGradient cx="24.293" cy="13.388" r="16.219" id="E" xlink:href="#9" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.5533713,-2.2948164,-3.3955484,-0.8188024,46.75215,79.261928)"/>
+  <linearGradient y1="43.531" x2="0" y2="2.25" id="F" xlink:href="#6" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.896238,0,0,-0.896238,2.5072529,45.322604)"/>
+  <radialGradient cx="34.13" cy="8.609" r="3.03" id="G" xlink:href="#9" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.792476,-1.8567779e-7,-1.9429172e-7,-1.8756322,-28.076861,53.568907)"/>
+  <linearGradient x1="34.13" y1="8.75" x2="36.533" y2="6.363" id="H" xlink:href="#6" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.896238,0,0,-0.896238,2.5072529,45.262984)"/>
+  <linearGradient x1="55.936" y1="14.994" x2="59.847" y2="31.394" id="I" xlink:href="#3" gradientUnits="userSpaceOnUse"/>
+  <linearGradient y1="16.19" x2="0" y2="26.631" id="J" xlink:href="#6" gradientUnits="userSpaceOnUse"/>
+  <linearGradient y1="16.38" x2="0" y2="28.03" id="K" xlink:href="#2" gradientUnits="userSpaceOnUse"/>
+ </defs>
+ <g id="1">
+  <path d="m 47.345411,47.231407 a 23.442127,1.9983453 0 1 1 -46.88425415,0 23.442127,1.9983453 0 1 1 46.88425415,0 z" transform="matrix(0.9125654,0,0,0.963088,2.1866908,0.08741362)" id="L" opacity="0.8" fill="url(#A)"/>
+  <path d="m 7.40625,2.875 c -0.7554285,0 -1.375,0.7312174 -1.375,1.59375 l 0,41.0625 c 0,0.862533 0.6195719,1.593749 1.375,1.59375 l 33.1875,0 c 0.755428,0 1.374999,-0.731215 1.375,-1.59375 l 0,-41.0625 c 0,-0.8625327 -0.619571,-1.59375 -1.375,-1.59375 l -33.1875,0 z" transform="matrix(0.9593462,0,0,0.942101,0.9756909,1.1222877)" id="M" fill="url(#B)" fill-rule="evenodd" stroke="#683f00" stroke-width="1.013"/>
+  <path d="M 7.40625,3.84375 C 7.2707325,3.84375 7,4.0662537 7,4.46875 l 0,41.0625 c 0,0.402497 0.2707314,0.625 0.40625,0.625 l 33.1875,0 c 0.135519,0 0.40625,-0.222499 0.40625,-0.625 l 0,-41.0625 c 0,-0.4024968 -0.270732,-0.625 -0.40625,-0.625 l -33.1875,0 z" transform="matrix(0.9593462,0,0,0.942101,0.9756909,1.1222877)" id="N" opacity="0.8" fill="none" stroke="url(#C)" stroke-width="1.013"/>
+  <path d="m 7.46875,2.84375 c -0.4294846,-10e-8 -0.875,0.4682617 -0.875,1.0625 l 0,25.3125 c 9.489422,-5.867753 22.865809,-12.260207 34.8125,-17.3125 l 0,-8 c 10e-7,-0.5942378 -0.445514,-1.0625 -0.875,-1.0625 l -33.0625,0 z" transform="matrix(0.963088,0,0,0.963088,0.885888,1.5606998)" id="O" opacity="0.6" fill="url(#D)" fill-rule="evenodd"/>
+  <path d="m 11.329596,44.230313 c -1.5391991,0 -2.7727366,-1.233537 -2.7727366,-2.772736 l 0,-33.3008434 c 0,-1.5391995 1.2335375,-2.7727371 2.7727366,-2.7727361 l 25.374739,0 c 1.539199,0 2.772737,1.2335375 2.772737,2.7727361 l 0,29.7719064 -6.049608,6.301673 -22.097868,0 0,0 z" id="P" fill="#888a85"/>
+  <path d="m 11.329596,43.306068 c -1.038393,0 -1.8484909,-0.810098 -1.8484909,-1.848491 l 0,-33.3008434 c 0,-1.0383938 0.8100979,-1.8484924 1.8484909,-1.8484914 l 25.374739,0 c 1.038393,0 1.848491,0.8100995 1.848491,1.8484914 l 0,29.3798024 -5.517466,5.769532 -21.705764,0 z" id="Q" fill="url(#E)"/>
+  <g transform="matrix(0.896238,0,0,0.896238,2.5072535,3.7104971)" id="R">
+   <g transform="translate(0,0.9997506)" id="n" fill="#fff">
+    <rect width="21.968" height="3" x="11.5" y="12.539" id="t"/>
+    <rect width="17.353" height="3" x="11.5" y="6.539" id="u"/>
+    <rect width="19.726" height="3" x="11.5" y="18.539" id="v"/>
+    <rect width="23.813" height="3" x="11.5" y="24.539" id="w"/>
+    <rect width="22.363" height="3" x="11.5" y="30.539" id="x"/>
+    <rect width="25" height="3" x="11.5" y="36.539" id="y"/>
+   </g>
+   <g id="o" fill="#888a85">
+    <rect width="21.968" height="3" x="11.5" y="12.539" id="z"/>
+    <rect width="17.353" height="3" x="11.5" y="6.539" id="10"/>
+    <rect width="19.726" height="3" x="11.5" y="18.539" id="11"/>
+    <rect width="23.813" height="3" x="11.5" y="24.539" id="12"/>
+    <rect width="22.363" height="3" x="11.5" y="30.539" id="13"/>
+    <rect width="25" height="3" x="11.5" y="36.539" id="14"/>
+   </g>
+  </g>
+  <path d="m 11.329596,42.857949 c -0.80458,0 -1.4003719,-0.595792 -1.4003719,-1.400372 l 0,-33.3008434 c 0,-0.804582 0.5957919,-1.4003733 1.4003719,-1.4003723 l 25.374739,0 c 0.804581,0 1.400372,0.5957922 1.400372,1.4003723 l 0,29.2397654 -5.265399,5.46145 -21.509712,0 0,0 z" id="S" opacity="0.8" fill="none" stroke="url(#F)" stroke-linejoin="round" stroke-linecap="square" stroke-width="0.896"/>
+  <path d="m 77.133371,16.968067 0,6.875 c 0,0.956611 0.676661,1.593751 1.71875,1.59375 l 6.25,0 0,-1.8125 -6.9375,-6.65625 -1.03125,0 0,0 z" transform="matrix(0.896238,0,0,-0.8100394,-37.71893,56.964667)" id="T" opacity="0.16" fill="#2e3436" filter="url(#8)"/>
+  <path d="m 32.194916,44.127263 0,-5.657503 c -2e-6,-1.038393 0.810097,-1.848491 1.848491,-1.84849 l 5.433443,0 0,1.204319 -6.049607,6.301674 -1.232327,0 0,0 z" id="U" fill="#888a85"/>
+  <path d="m 33.091375,43.10639 0,-4.733258 c -10e-7,-0.574219 0.378033,-0.952253 0.952254,-0.952252 l 4.481189,0 -5.433443,5.68551 0,0 z" id="V" fill="url(#G)"/>
+  <path d="m 33.539495,41.958106 0,-3.584953 c -1e-6,-0.338155 0.165977,-0.504133 0.504134,-0.504133 l 3.444914,0 -3.949048,4.089086 z" id="W" opacity="0.8" fill="none" stroke="url(#H)" stroke-linecap="square" stroke-width="0.896"/>
+  <g transform="matrix(0.9180102,0,0,0.7524892,1.9677556,0.3657735)" id="X">
+   <path d="m 13.031712,3.3127153 1.924751,6.239505 c 0.36426,1.1075167 1.256004,1.5413677 2.198945,1.5392607 l 13.715919,0 c 1.007931,0.0023 1.839587,-0.474167 2.198945,-1.5667475 L 34.807069,3.8899382 C 34.633248,2.1321559 15.660167,1.5897175 13.031712,3.3127153 z" id="p" opacity="0.5" fill="#2e3436"/>
+   <path d="m 53.96875,16.40625 c -0.227234,0.03412 -1.169585,0.322383 -1.6875,0.96875 -0.508043,0.633965 -0.640226,0.979171 -0.5625,1.8125 0.02228,0.238917 0.08782,0.486655 0.15625,0.65625 0.03422,0.0848 0.04294,0.150533 0.0625,0.1875 l 2.09375,6.25 c 0.414131,1.259146 1.427962,1.752395 2.5,1.75 l 15.59375,0 c 1.145925,0.0026 2.091442,-0.539085 2.5,-1.78125 l 2.15625,-6.40625 C 76.877759,19.556327 76.99918,19.123868 76.9375,18.625 76.87582,18.126132 76.621473,17.629376 76.28125,17.25 75.923221,16.850594 75.438162,16.544609 75,16.4375 74.561838,16.330391 74.171214,16.406634 74.28125,16.40625 l -19.75,0 -0.125,0 c -0.01061,-7.09e-4 -0.02063,5.67e-4 -0.03125,0 -0.04246,-0.0023 -0.0825,0 -0.125,0 -0.05313,0 -0.103206,-0.0035 -0.15625,0 a 1.4526884,1.4526884 0 0 0 -0.125,0 z" transform="matrix(0.879578,0,0,0.879578,-32.568236,-14.229)" id="q" fill="url(#K)"/>
+   <path d="m 54.1875,17.84375 c -0.23626,0.03548 -0.487536,0.07094 -0.78125,0.4375 -0.169064,0.210968 -0.268989,0.577663 -0.25,0.78125 0.01899,0.203587 0.08524,0.287616 0.09375,0.3125 l 2.15625,6.40625 c 0.0048,0.0146 0.02578,0.017 0.03125,0.03125 0.182908,0.477016 0.696142,0.782138 1.09375,0.78125 l 15.59375,0 c 0.397612,8.88e-4 0.910837,-0.304231 1.09375,-0.78125 l 0.03125,0 c 0.0029,-0.0081 -0.0027,-0.02309 0,-0.03125 L 75.40625,19.375 c 0.125813,-0.374698 0.156742,-0.737546 -0.21875,-1.15625 -0.402647,-0.449181 -0.729514,-0.375617 -0.90625,-0.375 l -19.90625,0 c -0.0093,1.44e-4 -0.02192,1.44e-4 -0.03125,0 0.007,-5.4e-5 -0.03824,-5.4e-5 -0.03125,0 a 0.93763029,0.93763029 0 0 0 -0.125,0 z" transform="matrix(0.879578,0,0,0.879578,-32.576961,-14.229)" id="r" fill="url(#I)"/>
+   <path d="m 54.28125,18.625 c -0.09007,0.01353 -0.199043,0.05365 -0.28125,0.15625 -0.04601,0.05741 -0.03664,0.129698 -0.03125,0.1875 0.0044,0.04669 0.0209,0.0957 0.03125,0.125 l 0,0.03125 2.15625,6.40625 c 0.0536,0.162973 0.207402,0.281624 0.375,0.28125 l 15.59375,0 c 0.167596,3.75e-4 0.321397,-0.118276 0.375,-0.28125 l 2.15625,-6.4375 c 0.04088,-0.121739 0.03423,-0.23589 -0.0625,-0.34375 -0.100933,-0.112598 -0.213867,-0.125344 -0.3125,-0.125 l -19.90625,0 c -0.0125,1.93e-4 -0.01875,1.93e-4 -0.03125,0 -0.0044,3.5e-5 -0.02681,3.5e-5 -0.03125,0 a 0.14577079,0.14577079 0 0 0 -0.03125,0 z" transform="matrix(0.879578,0,0,0.879578,-32.583902,-14.229)" id="s" opacity="0.8" fill="none" stroke="url(#J)" stroke-width="1.41"/>
+  </g>
+ </g>
+</svg>
diff --git a/view.php b/view.php
index f8e6c6c..d23f3c7 100644
--- a/view.php
+++ b/view.php
@@ -29,8 +29,7 @@ require_once(dirname(__FILE__).'/../../config.php');
 require_once($CFG->dirroot.'/mod/adaptivequiz/locallib.php');

 $id = optional_param('id', 0, PARAM_INT);
-
-global $USER;
+$n  = optional_param('n', 0, PARAM_INT);

 if ($id) {
     $cm         = get_coursemodule_from_id('adaptivequiz', $id, 0, false, MUST_EXIST);
@@ -41,13 +40,22 @@ if ($id) {
     $course     = $DB->get_record('course', array('id' => $adaptivequiz->course), '*', MUST_EXIST);
     $cm         = get_coursemodule_from_instance('adaptivequiz', $adaptivequiz->id, $course->id, false, MUST_EXIST);
 } else {
-    error('You must specify a course_module ID or an instance ID');
+    print_error('invalidarguments');
 }

 require_login($course, true, $cm);
 $context = context_module::instance($cm->id);

-add_to_log($course->id, 'adaptivequiz', 'view', "view.php?id={$cm->id}", $adaptivequiz->name, $cm->id);
+$event = \mod_adaptivequiz\event\course_module_viewed::create(
+    array(
+        'objectid' => $PAGE->cm->instance,
+        'context' => $PAGE->context,
+    )
+);
+
+$event->add_record_snapshot('course', $PAGE->course);
+$event->add_record_snapshot($PAGE->cm->modname, $adaptivequiz);
+$event->trigger();

 // Print the page header.
 $PAGE->set_url('/mod/adaptivequiz/view.php', array('id' => $cm->id));
-- 
2.4.3

Renderer exception in questionanalysis/overview.php

When testing this new functionality in their sandbox, the client has come upon a coding error that breaks functionality:
Debug info: mod_adaptivequiz_questions
Error code: codingerror
Stack trace:

line 185 of /lib/outputfactories.php: coding_exception thrown
line 237 of /lib/outputfactories.php: call to renderer_factory_base->standard_renderer_classname()
line 1511 of /lib/outputlib.php: call to standard_renderer_factory->get_renderer()
line 779 of /lib/pagelib.php: call to theme_config->get_renderer()
line 60 of /mod/adaptivequiz/questionanalysis/overview.php: call to moodle_page->get_renderer()

Postgresql Group By error

There are two locations where a " GROUP BY clause or be used in an aggregate function" error occurs.
In fetchquestion.class.php -> function retrieve_tags_with_question_count(...)
(Approx ln 437) $records = $DB->get_records_sql_menu($sql, $params);
And....
In viewreport.php (Approx ln 142)

Will return the following error (this output is from fetchquestion) :
//===========================
Error reading from database

More information about this error
Debug info: ERROR: column "t.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 9: ORDER BY t.id ASC
^
SELECT SUBSTR(t.name, 6) AS difflevel, count(*) AS numofquest
FROM mdl_tag t
JOIN mdl_tag_instance ti ON t.id = ti.tagid
JOIN mdl_question q ON q.id = ti.itemid
WHERE ti.itemtype = $1
AND ti.tagid IN ($2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25)
AND q.category IN ($26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$40,$41,$42,$43,$44,$45)
GROUP BY t.name
ORDER BY t.id ASC
[array (
0 => 'question',
1 => '407',
2 => '408',
3 => '409',
4 => '410',
5 => '411',
6 => '412',
7 => '413',
8 => '414',
9 => '415',
10 => '416',
11 => '417',
12 => '418',
13 => '419',
14 => '420',
15 => '421',
16 => '422',
17 => '423',
18 => '424',
19 => '425',
20 => '426',
21 => '427',
22 => '428',
23 => '429',
24 => '430',
25 => '2431',
26 => '2432',
27 => '2433',
28 => '2434',
29 => '2435',
30 => '2436',
31 => '2437',
32 => '2438',
33 => '2439',
34 => '2440',
35 => '2441',
36 => '2442',
37 => '2443',
38 => '2444',
39 => '2445',
40 => '2446',
41 => '2447',
42 => '2448',
43 => '2449',
44 => '2450',
)]
Error code: dmlreadexception
Stack trace:

line 443 of /lib/dml/moodle_database.php: dml_read_exception thrown
line 239 of /lib/dml/pgsql_native_moodle_database.php: call to moodle_database->query_end()
line 744 of /lib/dml/pgsql_native_moodle_database.php: call to pgsql_native_moodle_database->query_end()
line 1352 of /lib/dml/moodle_database.php: call to pgsql_native_moodle_database->get_records_sql()
line 437 of /mod/adaptivequiz/fetchquestion.class.php: call to moodle_database->get_records_sql_menu()
line 259 of /mod/adaptivequiz/fetchquestion.class.php: call to fetchquestion->retrieve_tags_with_question_count()
line 288 of /mod/adaptivequiz/fetchquestion.class.php: call to fetchquestion->initalize_tags_with_quest_count()
line 373 of /mod/adaptivequiz/adaptiveattempt.class.php: call to fetchquestion->fetch_questions()
line 352 of /mod/adaptivequiz/adaptiveattempt.class.php: call to adaptiveattempt->get_question_ready()
line 211 of /mod/adaptivequiz/attempt.php: call to adaptiveattempt->start_attempt()

//===========================

I added t.id and it works but I'm not sure how that affects everything else
"GROUP BY t.id,t.name"

Thoughts?
Thx.

Immediate feedback (enchancement)

Hi, @adamfranco
I have read in previous topics that you cannot pay a lot of attention to this plugin. So, I have tried to make some customization of it. I got task to implement feature like "immediate feedback" in general quiz module:

  • student got, and submit question answer (Submit button)
  • instead of new question - he returned to same question page where is shown is his answer was correct or not (and show correct answer - depend to other settings).
  • to move forward to the next question - student must press "next" button
    Could you provide me some recommendations / hints / docs about how this could be implemented?

Error reading from database - after choosing "View report"

Adaptive quizes work with levels well, but when a student finish a test, there is an error of database, and the test starts again! "Question Analysis" shows right statistics, but "View report" shows "Error reading from database".
Pls - where is a problem? (Moodle 2.5)

Images still not loading!

Hello there.

First of all, its a brilliant plugin - Been using since a year and the staff loves it. Using Moodle 2.9, i am still having problem with quiz images being fetched from Question Bank? The version report said it had been fixed, so i uninstalled plugin completely, and reinstalled and made a new quiz - Still the problem resides... We are using workarounds to attach images from a source outside Moodle to be able to work, but our new question bank has images uploaded through file manager. Attached screenshots.

screen shot 2017-01-12 at 2 02 20 pm

screen shot 2017-01-12 at 2 01 45 pm

Error: "Missing Tag Prefix"

Installed version the adaptive quiz plugin version "2013022800" under Moodle version 2.5.2+ (Build: 20130913)

Whenever I start an attempt on an Adaptive Quiz, I get the following error:

Missing tag prefix
More information about this error
Debug info:
Error code: missingtagprefix
Stack trace:
line 476 of /lib/setuplib.php: moodle_exception thrown
line 412 of /mod/adaptivequiz/fetchquestion.class.php: call to print_error()
line 238 of /mod/adaptivequiz/fetchquestion.class.php: call to fetchquestion->retrieve_tags_with_question_count()
line 266 of /mod/adaptivequiz/fetchquestion.class.php: call to fetchquestion->initalize_tags_with_quest_count()
line 358 of /mod/adaptivequiz/adaptiveattempt.class.php: call to fetchquestion->fetch_questions()
line 337 of /mod/adaptivequiz/adaptiveattempt.class.php: call to adaptiveattempt->get_question_ready()
line 209 of /mod/adaptivequiz/attempt.php: call to adaptiveattempt->start_attempt()

SQL error when clicking the 'View report' button with Moodle 3.0.6

Hello,
I am encountering an SQL error when viewing a report in adaptive quiz.
Details:

  • Adaptive quiz version: 1.2.3
  • Moodle version: 3.0.6
  • Database: PostgreSQL 9.4.10

Steps to reproduce:

  • Create a course named: "test course for adaptive quiz"

  • Go to the course page

  • Create 3 "true/false" questions with category set to 'Default for test course for adaptive quiz'.
    ` Dashboard / ► Courses / ► test course for adaptive quiz / ► Question bank / ► Questions /

  • According to this answer, question 1 is tagged as "adpq_1", question 2 is tagged as"adpq_2",question 3 tagged as"adpq_3".

  • Get back to course page and click "Add an activity or resource", then add an Adaptive Quiz named "test adaptive quiz".

  • This test will be feed configured as follow:
    -Question pool:'Default for test course for adaptive quiz'.
    -Starting level of difficulty: 1
    -Lowest level of difficulty: 1
    -Highest level of difficulty: 1
    -Minimum number of questions: 1
    -Maximum number of questions: 3
    -Standard Error to stop: 5

  • Go to the 'test course for adaptive quiz' page, and click on the quiz.

  • Click on the 'View Report' button

  • The following error will appear:

Debug info: ERROR: column "u.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT u.id, u.firstname, u.lastname, u.email, a.highestleve...
^
SELECT u.id, u.firstname, u.lastname, u.email, a.highestlevel, a.lowestlevel,
(SELECT COUNT(*)
FROM mdl_adaptivequiz_attempt caa
WHERE caa.userid = u.id
AND caa.instance = aa.instance
) AS attempts,
(SELECT maa.measure
FROM mdl_adaptivequiz_attempt maa
WHERE maa.instance = a.id
AND maa.userid = u.id
AND maa.attemptstate = $1
AND maa.standarderror > 0.0
ORDER BY measure DESC
LIMIT 1) AS measure,
(SELECT saa.standarderror
FROM mdl_adaptivequiz_attempt saa
WHERE saa.instance = a.id
AND saa.userid = u.id
AND saa.attemptstate = $2
AND saa.standarderror > 0.0
ORDER BY measure DESC
LIMIT 1) AS stderror,
(SELECT taa.timemodified
FROM mdl_adaptivequiz_attempt taa
WHERE taa.instance = a.id
AND taa.userid = u.id
AND taa.attemptstate = $3
AND taa.standarderror > 0.0
ORDER BY measure DESC
LIMIT 1) AS timemodified,
(SELECT iaa.uniqueid
FROM mdl_adaptivequiz_attempt iaa
WHERE iaa.instance = a.id
AND iaa.userid = u.id
AND iaa.attemptstate = $4
AND iaa.standarderror > 0.0
ORDER BY measure DESC
LIMIT 1) AS uniqueid
FROM mdl_adaptivequiz_attempt aa
JOIN mdl_user u ON u.id = aa.userid
JOIN mdl_adaptivequiz a ON a.id = aa.instance

WHERE aa.instance = $5

GROUP BY aa.userid
ORDER BY lastname ASC LIMIT 30 OFFSET 0
[array (
0 => 'complete',
1 => 'complete',
2 => 'complete',
3 => 'complete',
4 => '1',
)]
Error code: dmlreadexception

Report of question usage and efficacy

A report is needed that lists the questions in the bank along with their tagged level, a better estimate of their level based the levels of test-takers that answered them right/wrong, a measure of how well the question discriminated between more-able and less-able test takers.

This report will allow test administrators to evaluate and improve their question bank.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.