diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml new file mode 100644 index 0000000..05fe1e5 --- /dev/null +++ b/.github/workflows/moodle-ci.yml @@ -0,0 +1,122 @@ +name: Moodle Plugin CI + +on: [push, pull_request] + +#start pgsql test +jobs: + test_pgsql: + runs-on: ubuntu-18.04 + + services: + postgres: + image: postgres:10 + env: + POSTGRES_USER: 'postgres' + POSTGRES_HOST_AUTH_METHOD: 'trust' + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + + strategy: + fail-fast: false + matrix: + php: ['7.4'] + moodle-branch: ['MOODLE_311_STABLE'] + database: [pgsql] + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + with: + path: plugin + + - name: Setup PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: ${{ matrix.extensions }} + ini-values: max_input_vars=5000 + coverage: none + + - name: Initialise moodle-plugin-ci + run: | + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + echo $(cd ci/bin; pwd) >> $GITHUB_PATH + echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH + sudo locale-gen en_AU.UTF-8 + echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV + - name: Install moodle-plugin-ci + run: | + moodle-plugin-ci add-plugin rwthanalytics/moodle-logstore_lanalytics + moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 + env: + DB: ${{ matrix.database }} + MOODLE_BRANCH: ${{ matrix.moodle-branch }} + + - name: PHP Lint + if: ${{ always() }} + run: moodle-plugin-ci phplint + + - name: PHPUnit tests + if: ${{ always() }} + run: moodle-plugin-ci phpunit + #end pgsql test + + #start moodle mariadb matrix tests + test_mariadb: + runs-on: ubuntu-18.04 + + services: + mariadb: + image: mariadb:10.5 + env: + MYSQL_USER: 'root' + MYSQL_ALLOW_EMPTY_PASSWORD: "true" + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3 + + strategy: + fail-fast: false + matrix: + php: ['7.3', '7.4'] + moodle-branch: ['MOODLE_311_STABLE', 'MOODLE_310_STABLE', 'MOODLE_39_STABLE'] + database: [mariadb] + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + with: + path: plugin + + - name: Setup PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: ${{ matrix.extensions }} + ini-values: max_input_vars=5000 + coverage: none + + - name: Initialise moodle-plugin-ci + run: | + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + echo $(cd ci/bin; pwd) >> $GITHUB_PATH + echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH + sudo locale-gen en_AU.UTF-8 + echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV + - name: Install moodle-plugin-ci + run: | + moodle-plugin-ci add-plugin rwthanalytics/moodle-logstore_lanalytics + moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 + env: + DB: ${{ matrix.database }} + MOODLE_BRANCH: ${{ matrix.moodle-branch }} + + - name: PHP Lint + if: ${{ always() }} + run: moodle-plugin-ci phplint + + - name: PHPUnit tests + if: ${{ always() }} + run: moodle-plugin-ci phpunit +#end moodle mariadb matrix tests \ No newline at end of file diff --git a/composer.json b/composer.json index 63d3366..3b81431 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,8 @@ "homepage": "https://git.rwth-aachen.de/laixmo/moodle-local_learning_analytics", "license": "GPL-3.0+", "require": { - "composer/installers": "*" + "composer/installers": "*", + "nesbot/carbon": "^2.53" }, "extra": { "installer-name": "learning_analytics" @@ -14,4 +15,4 @@ "issues": "https://git.rwth-aachen.de/laixmo/moodle-local_learning_analytics/issues", "source": "https://git.rwth-aachen.de/laixmo/moodle-local_learning_analytics" } -} \ No newline at end of file +} diff --git a/reports/activities/tests/query_helper_advanced_test.php b/reports/activities/tests/query_helper_advanced_test.php new file mode 100644 index 0000000..aea4f46 --- /dev/null +++ b/reports/activities/tests/query_helper_advanced_test.php @@ -0,0 +1,180 @@ +. + +defined('MOODLE_INTERNAL') || die(); + +use lareport_activities\query_helper; +use PHPUnit\Framework\TestCase; +use local_learning_analytics\event\report_viewed; +use local_learning_analytics\report_list; +require_once(__DIR__ . '/../../../../../config.php'); + +//use: navigate in cmd to your moodle folder and enter vendor\bin\phpunit local_Learning_Analytics_reports_activities_testcase local\Learning_Analytics\reports\activities\tests\query_helper_advanced_test.php +class local_Learning_Analytics_reports_activities_testcase extends \advanced_testcase { + + public function test_activities() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + $activitygenerator = $this->getDataGenerator()->get_plugin_generator('mod_forum'); + + $this->preventResetByRollback(); + set_config('enabled_stores', 'logstore_lanalytics', 'tool_log'); + set_config('buffersize', 0, 'logstore_lanalytics'); + + $user = $datagenerator->create_user(); + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $datagenerator->enrol_user($user->id, $course->id); + + $forum = $activitygenerator->create_instance(array('course' => $course->id)); + + $instancequery = <<get_record_sql($instancequery, [$forum->id]); + $instanceid = $contextinstance->id; + $context = $DB->get_record_sql($contextquery, [$instanceid]); + $contextid = $context->id; + + for($i=0; $i<16; $i++) { + $event = report_viewed::create(array( + 'contextid' => $contextid, + 'objectid' => NULL + )); + $event->add_record_snapshot('forum', $forum); + $event->trigger(); + } + + $testresult1 = query_helper::query_activities($course->id,"" , []); + + $this->assertEquals(17, $testresult1[$instanceid]->hits); + + //second tests + $activitygenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); + $quiz = $activitygenerator->create_instance(array('course' => $course->id)); + + $contextinstance2 = $DB->get_record_sql($instancequery, [$quiz->id]); + $instanceid2 = $contextinstance2->id; + $context2 = $DB->get_record_sql($contextquery, [$instanceid2]); + $contextid2 = $context2->id; + + for($i=0; $i<10; $i++) { + $event = report_viewed::create(array( + 'contextid' => $contextid2, + 'objectid' => NULL + )); + $event->add_record_snapshot('quiz', $quiz); + $event->trigger(); + } + + $testresult2 = query_helper::query_activities($course->id,"" , []); + + $this->assertEquals(11, $testresult2[$instanceid2]->hits); + } + + public function test_preview_query_most_clicked_activity() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + $activitygenerator = $this->getDataGenerator()->get_plugin_generator('mod_forum'); + + $this->preventResetByRollback(); + set_config('enabled_stores', 'logstore_lanalytics', 'tool_log'); + set_config('buffersize', 0, 'logstore_lanalytics'); + + $user = $datagenerator->create_user(); + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $datagenerator->enrol_user($user->id, $course->id); + + $forum = $activitygenerator->create_instance(array('course' => $course->id)); + + $instancequery = <<get_record_sql($instancequery, [$forum->id]); + $instanceid = $contextinstance->id; + $context = $DB->get_record_sql($contextquery, [$instanceid]); + $contextid = $context->id; + + $date = new \DateTime(); + $date->setTime(23, 59, 59); // Include today. + $date->modify('-1 week'); + $oneweekago = $date->getTimestamp(); + $timestampBefore = $oneweekago - 40000; + $timestampAfter = $oneweekago + 40000; + + $counterAfter = 0; + $counterBefore = 0; + for($i=0; $i<99; $i++) { + $counterAfter++; + $entry = [ + 'id' => $counterAfter, + 'eventid' => 30, + 'timecreated' => $timestampAfter, + 'courseid' => $course->id, + 'contextid' => $contextid, + 'device' => 3611 + ]; + $DB->insert_record('logstore_lanalytics_log', $entry, false, false, true); + if($i%3==0) { + $counterBefore++; + $entry = [ + 'id' => $counterBefore, + 'eventid' => 30, + 'timecreated' => $counterBefore, + 'courseid' => $course->id, + 'contextid' => $contextid, + 'device' => 3611 + ]; + $DB->insert_record('logstore_lanalytics_log', $entry, false, false, true); + } + } + + $testresult1 = query_helper::preview_query_most_clicked_activity($course->id, 1); + + $this->assertEquals(100, $testresult1[$instanceid]->hits); + } +} diff --git a/reports/coursedashboard/tests/query_helper_advanced_test.php b/reports/coursedashboard/tests/query_helper_advanced_test.php new file mode 100644 index 0000000..b4988f8 --- /dev/null +++ b/reports/coursedashboard/tests/query_helper_advanced_test.php @@ -0,0 +1,73 @@ +. + +defined('MOODLE_INTERNAL') || die(); + +use lareport_coursedashboard\query_helper; +use PHPUnit\Framework\TestCase; +use local_learning_analytics\event\report_viewed; +use local_learning_analytics\report_list; +require_once(__DIR__ . '/../../../../../config.php'); + +//use: navigate in cmd to your moodle folder and enter vendor\bin\phpunit local_Learning_Analytics_reports_coursedashboard_testcase local\Learning_Analytics\reports\coursedashboard\tests\query_helper_advanced_test.php +class local_Learning_Analytics_reports_coursedashboard_testcase extends \advanced_testcase { + + public function test_weekly_activity() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + + $this->preventResetByRollback(); + set_config('enabled_stores', 'logstore_lanalytics_log', 'tool_log'); + set_config('buffersize', 0, 'logstore_lanalytics_log'); + + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $user = $datagenerator->create_user(); + $datagenerator->enrol_user($user->id, $course->id); + + $date = time() - (7 * 24 * 60 * 60); + $tooearlydate = time() - (7 * 24 * 60 * 60 * 2); + + $entry1 = [ + 'id' => 1, + 'eventid' => 30, + 'timecreated' => $tooearlydate, + 'courseid' => $course->id, + 'contextid' => 46, + 'device' => 3611 + ]; + $entry2 = [ + 'id' => 2, + 'eventid' => 30, + 'timecreated' => $date, + 'courseid' => $course->id, + 'contextid' => 46, + 'device' => 3611 + ]; + + $DB->insert_record('logstore_lanalytics_log', $entry1, false, false, true); + $DB->insert_record('logstore_lanalytics_log', $entry2, false, false, true); + + $testweekresult = query_helper::query_weekly_activity($course->id); + $testweek = end($testweekresult); + $testweekclicks = $testweek->clicks; + + $this->assertEquals(1, $testweekclicks); + } +} diff --git a/reports/learners/tests/query_helper_advanced_test.php b/reports/learners/tests/query_helper_advanced_test.php new file mode 100644 index 0000000..2fe9008 --- /dev/null +++ b/reports/learners/tests/query_helper_advanced_test.php @@ -0,0 +1,151 @@ +. + +defined('MOODLE_INTERNAL') || die(); + +use lareport_learners\query_helper; +use PHPUnit\Framework\TestCase; +use local_learning_analytics\event\report_viewed; +use local_learning_analytics\report_list; +use local_learning_analytics\settings; +require_once(__DIR__ . '/../../../../../config.php'); + +//use: navigate in cmd to your moodle folder and enter vendor\bin\phpunit local_Learning_Analytics_reports_learners_testcase local\Learning_Analytics\reports\learners\tests\query_helper_advanced_test.php +class local_Learning_Analytics_reports_learners_testcase extends \advanced_testcase { + + public function test_learners_count_role_unspecific() { + + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + for($i=0; $i<17; $i++) { + $user = $datagenerator->create_user(); + $datagenerator->enrol_user($user->id, $course->id); + } + + $this->assertEquals(17, query_helper::query_learners_count($course->id, ['student'])); + } + + public function test_learners_count_role_specific() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + for($i=0; $i<13; $i++) { + $user = $datagenerator->create_user(); + $datagenerator->enrol_user($user->id, $course->id, 'student'); + } + for($i=0; $i<15; $i++) { + $user = $datagenerator->create_user(); + $datagenerator->enrol_user($user->id, $course->id, 'teacher'); + } + + $this->assertEquals(13, query_helper::query_learners_count($course->id, ['student'])); + $this->assertEquals(15, query_helper::query_learners_count($course->id, ['teacher'])); + } + + public function test_courseparticipation() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + + $parallelcoursebuffer = 31 * 24 * 60 * 60; + $privacythreshold = settings::get_config('dataprivacy_threshold'); + $studentrolenames = explode(',', settings::get_config('student_rolenames')); + $coursegroupby = 'id'; + + $category = $datagenerator->create_category(); + $course1 = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $coursestartdate = get_course($course1->id)->startdate; + $coursebeforecutoff = $coursestartdate - $parallelcoursebuffer; + $courseparallelcutoff = $coursestartdate + $parallelcoursebuffer; + $course1id = intval($course1->id); + $course2 = $datagenerator->create_course(array('name'=>'sametimetestcourse', 'category'=>$category->id)); + $course3 = $datagenerator->create_course(array('name'=>'beforetimetestcourse', 'category'=>$category->id, 'timecreated'=>($coursestartdate - (7 * 24 * 60 * 60 * 180)))); + $course4 = $datagenerator->create_course(array('name'=>'testcourse2', 'category'=>$category->id)); + $course5 = $datagenerator->create_course(array('name'=>'testcourse3', 'category'=>$category->id)); + $course6 = $datagenerator->create_course(array('name'=>'testcourse4', 'category'=>$category->id)); + $course7 = $datagenerator->create_course(array('name'=>'testcourse5', 'category'=>$category->id)); + $course8 = $datagenerator->create_course(array('name'=>'testcourse6', 'category'=>$category->id)); + $course9 = $datagenerator->create_course(array('name'=>'testcourse7', 'category'=>$category->id)); + $course10 = $datagenerator->create_course(array('name'=>'testcourse8', 'category'=>$category->id)); + $course11 = $datagenerator->create_course(array('name'=>'testcourse9', 'category'=>$category->id)); + $course12 = $datagenerator->create_course(array('name'=>'testcourse10', 'category'=>$category->id)); + $course13 = $datagenerator->create_course(array('name'=>'aftertimetestcourse', 'category'=>$category->id, 'timecreated'=>($coursestartdate + (7 * 24 * 60 * 60 * 180)))); + + $users = []; + for($i=0; $i<$privacythreshold+1; $i++) { + $users[$i] = $datagenerator->create_user(); + $datagenerator->enrol_user($users[$i]->id, $course1->id); + $datagenerator->enrol_user($users[$i]->id, $course2->id); + $datagenerator->enrol_user($users[$i]->id, $course3->id); + $datagenerator->enrol_user($users[$i]->id, $course4->id); + $datagenerator->enrol_user($users[$i]->id, $course5->id); + $datagenerator->enrol_user($users[$i]->id, $course6->id); + $datagenerator->enrol_user($users[$i]->id, $course7->id); + $datagenerator->enrol_user($users[$i]->id, $course8->id); + $datagenerator->enrol_user($users[$i]->id, $course9->id); + $datagenerator->enrol_user($users[$i]->id, $course10->id); + $datagenerator->enrol_user($users[$i]->id, $course11->id); + $datagenerator->enrol_user($users[$i]->id, $course12->id); + $datagenerator->enrol_user($users[$i]->id, $course13->id); + } + + $this->preventResetByRollback(); + set_config('enabled_stores', 'logstore_lanalytics', 'tool_log'); + set_config('buffersize', 0, 'logstore_lanalytics'); + + $testresult1 = query_helper::query_courseparticipation($course1id, $privacythreshold, $studentrolenames, $coursebeforecutoff, $courseparallelcutoff, $coursegroupby); + $this->assertEquals(COUNT($testresult1), 12); + } + + public function test_localization() { + + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $courseid = $course->id; + $type = 'lang'; + for($i=0; $i<13; $i++) { + $user = $datagenerator->create_user(); + $datagenerator->enrol_user($user->id, $course->id, 'student'); + } + for($i=0; $i<15; $i++) { + $user = $datagenerator->create_user(); + $datagenerator->enrol_user($user->id, $course->id, 'teacher'); + } + + $testresult1 = query_helper::query_localization($courseid, $type); + + $this->assertEquals(13, $testresult1["en"]->users); + } +} diff --git a/reports/quiz_assign/tests/query_helper_advanced_test.php b/reports/quiz_assign/tests/query_helper_advanced_test.php new file mode 100644 index 0000000..ff4f9dc --- /dev/null +++ b/reports/quiz_assign/tests/query_helper_advanced_test.php @@ -0,0 +1,463 @@ +. + +defined('MOODLE_INTERNAL') || die(); + +use lareport_quiz_assign\query_helper; +use PHPUnit\Framework\TestCase; +use local_learning_analytics\event\report_viewed; +use local_learning_analytics\report_list; +require_once(__DIR__ . '/../../../../../config.php'); + +//use: navigate in cmd to your moodle folder and enter vendor\bin\phpunit local_Learning_Analytics_reports_quiz_assign_testcase local\Learning_Analytics\reports\quiz_assign\tests\query_helper_advanced_test.php +class local_Learning_Analytics_reports_quiz_assign_testcase extends \advanced_testcase { + + public function test_query_quiz() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + $activitygenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); + + $user = $datagenerator->create_user(); + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $datagenerator->enrol_user($user->id, $course->id); + + $quiz1 = $activitygenerator->create_instance(array('course' => $course->id)); + $quiz2 = $activitygenerator->create_instance(array('course' => $course->id)); + $quiz3 = $activitygenerator->create_instance(array('course' => $course->id)); + + $query = <<setTime(23, 59, 59); // Include today. + $date->modify('-1 week'); + $oneweekago = $date->getTimestamp(); + $quizids = $DB->get_records_sql($query); + $i=1; + foreach($quizids as $id) { + $entry = [ + 'id' => $i, + 'quiz' => $id->id, + 'userid' => $user->id, + 'attempt' => 1, + 'uniqueid' => $i, + 'layout' => '1,0', + 'currentpage' => 0, + 'preview' => 1, + 'state' => 'finished', + 'timestart' => $oneweekago, + 'timefinish' => $oneweekago + 200, + 'timemodified' => $oneweekago + 200, + 'timemodifiedoffline' => 0, + 'timecheckstate' => NULL, + 'sumgrades' => 1/$i + ]; + $DB->insert_record('quiz_attempts', $entry, false, false, true); + $gientry = [ + 'id' => $i, + 'courseid' => $course->id, + 'categoryid' => NULL, + 'itemname' => 'test', + 'itemtype' => 'mod', + 'itemmodule' => 'quiz', + 'iteminstance' => $id->id, + 'itemnumber' => 0, + 'iteminfo' => NULL, + 'idnumber' => NULL, + 'calculation' => NULL, + 'gradetype' => 1, + 'grademax' => '10.00000', + 'grademin' => '0.00000', + 'scaleid' => NULL, + 'outcomeid' => NULL, + 'gradepass' => '0.00000', + 'plusfactor' => '0.00000', + 'aggregationcoef' => '0.00000', + 'aggregationcoef2' => '0.00000', + 'sortorder' => $i, + 'display' => 0, + 'deciamals' => NULL, + 'hidden' => 0, + 'locked' => 0, + 'locktime' => 0, + 'needsupdate' => 0, + 'weightoverride' => 0, + 'timecreated' => $oneweekago, + 'timemodified' => $oneweekago + 200 + ]; + $DB->insert_record('grade_items', $gientry, false, false, true); + $i = $i + 1; + } + + $DB->set_field('quiz', 'sumgrades', 1, ['id' => array_pop($quizids)->id]); + $DB->set_field('quiz', 'sumgrades', 1, ['id' => array_pop($quizids)->id]); + $DB->set_field('quiz', 'sumgrades', 1, ['id' => array_pop($quizids)->id]); + + $testresult1 = query_helper::query_quiz($course->id); + + $this->assertEquals(2, array_pop($testresult1)->attempts); + $this->assertEquals(2, array_pop($testresult1)->attempts); + $this->assertEquals(2, array_pop($testresult1)->attempts); + } + + public function test_query_assignment() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + $activitygenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); + + $user = $datagenerator->create_user(); + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $datagenerator->enrol_user($user->id, $course->id); + + $quiz1 = $activitygenerator->create_instance(array('course' => $course->id)); + $quiz2 = $activitygenerator->create_instance(array('course' => $course->id)); + $quiz3 = $activitygenerator->create_instance(array('course' => $course->id)); + + $query = <<setTime(23, 59, 59); // Include today. + $date->modify('-1 week'); + $oneweekago = $date->getTimestamp(); + $quizids = $DB->get_records_sql($query); + $i=1; + foreach($quizids as $id) { + $aentry = [ + 'id' => $i, + 'course' => $course->id, + 'name' => 'test', + 'intro' => 'test', + 'introformat' => 0, + 'alwaysshowdescription' => 0, + 'nosubmissions' => 0, + 'submissiondrafts' => 0, + 'sendnotifications' => 0, + 'sendlatenotifications' => 0, + 'duedate' => 0, + 'allowsubmissionsfromdate' => 0, + 'grade' => 1, + 'timemodified' => $oneweekago + 200, + 'requiresubmissionstatement' => 0, + 'completionsubmit' => 0, + 'cutoffdate' => 0, + 'gradingduedate' => 0, + 'teamsubmission' => 0, + 'requireallteammemberssubmit' => 0, + 'teamsubmissiongroupingid' => 0, + 'blindmarking' => 0, + 'hidegrader' => 0, + 'revealidentities' => 0, + 'attemptreopenmethod' => 't', + 'maxattempts' => -1, + 'markingworkflow' => 0, + 'sendstudentnotifications' => 1, + 'preventsubmissionnotingroup' => 0 + ]; + $DB->insert_record('assign', $aentry, false, false, true); + $i++; + } + + $refquery1 = <<get_records_sql($refquery1, []); + + $i = 1; + + foreach($assignids as $assignid) { + $gientry = [ + 'id' => $i, + 'courseid' => $course->id, + 'categoryid' => NULL, + 'itemname' => 'test', + 'itemtype' => 'mod', + 'itemmodule' => 'assign', + 'iteminstance' => $assignid->id, + 'itemnumber' => 0, + 'iteminfo' => NULL, + 'idnumber' => NULL, + 'calculation' => NULL, + 'gradetype' => 1, + 'grademax' => '10.00000', + 'grademin' => '0.00000', + 'scaleid' => NULL, + 'outcomeid' => NULL, + 'gradepass' => '0.00000', + 'plusfactor' => '0.00000', + 'aggregationcoef' => '0.00000', + 'aggregationcoef2' => '0.00000', + 'sortorder' => $i, + 'display' => 0, + 'deciamals' => NULL, + 'hidden' => 0, + 'locked' => 0, + 'locktime' => 0, + 'needsupdate' => 0, + 'weightoverride' => 0, + 'timecreated' => $oneweekago, + 'timemodified' => $oneweekago + 200 + ]; + $DB->insert_record('grade_items', $gientry, false, false, true); + $i++; + } + + $refquery2 = <<get_records_sql($refquery2, []); + + $i = 1; + + foreach($giids as $giid) { + $ggentry = [ + 'id' => $i, + 'itemid' => $giid->id, + 'userid' => $user->id, + 'rawgrade' => $i * 2, + 'rawgrademax' => '10.00000', + 'rawgrademin' => '1.00000', + 'rawscaleid' => $i, + 'usermodified' => $oneweekago + 200, + 'finalgrade' => '2.00000', + 'hidden' => 0, + 'locked' => 0, + 'locktime' => 0, + 'exported' => 0, + 'feedback' => null, + 'feedbackformat' => 0, + 'information' => null, + 'informationformat' => 0, + 'timecreated' => $oneweekago, + 'timemodified' => $oneweekago + 200, + 'aggregationstatus' => 0, + 'aggregationweight' => 0 + ]; + $DB->insert_record('grade_grades', $ggentry, false, false, true); + $i++; + } + + $aquery = <<id); + + $this->assertEquals(5/9, array_pop($testresult1)->grade); + $this->assertEquals(3/9, array_pop($testresult1)->grade); + $this->assertEquals(1/9, array_pop($testresult1)->grade); + } + + public function test_preview_quiz_and_assigments() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + + $datagenerator = $this->getDataGenerator(); + $activitygenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); + + $user = $datagenerator->create_user(); + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $datagenerator->enrol_user($user->id, $course->id); + + $quiz1 = $activitygenerator->create_instance(array('course' => $course->id)); + $quiz2 = $activitygenerator->create_instance(array('course' => $course->id)); + $quiz3 = $activitygenerator->create_instance(array('course' => $course->id)); + + $query = <<setTime(23, 59, 59); // Include today. + $today = $date->getTimestamp(); + $date->modify('-1 week'); + $oneweekago = $date->getTimestamp(); + $date->modify('-1 week'); + $twoweeksago = $date->getTimestamp(); + + $quizids = $DB->get_records_sql($query); + $i=1; + foreach($quizids as $id) { + $aentry = [ + 'id' => $i, + 'course' => $course->id, + 'name' => 'test', + 'intro' => 'test', + 'introformat' => 0, + 'alwaysshowdescription' => 0, + 'nosubmissions' => 0, + 'submissiondrafts' => 0, + 'sendnotifications' => 0, + 'sendlatenotifications' => 0, + 'duedate' => 0, + 'allowsubmissionsfromdate' => 0, + 'grade' => 1, + 'timemodified' => $oneweekago + 200, + 'requiresubmissionstatement' => 0, + 'completionsubmit' => 0, + 'cutoffdate' => 0, + 'gradingduedate' => 0, + 'teamsubmission' => 0, + 'requireallteammemberssubmit' => 0, + 'teamsubmissiongroupingid' => 0, + 'blindmarking' => 0, + 'hidegrader' => 0, + 'revealidentities' => 0, + 'attemptreopenmethod' => 't', + 'maxattempts' => -1, + 'markingworkflow' => 0, + 'sendstudentnotifications' => 1, + 'preventsubmissionnotingroup' => 0 + ]; + $DB->insert_record('assign', $aentry, false, false, true); + $asentry = [ + 'id' => $i, + 'assignment' => $i, + 'userid' => $user->id, + 'timecreated' => $oneweekago + 1000, + 'timemodified' => $oneweekago + 1000, + 'status' => 'submitted', + 'groupid' => 0, + 'attemptnumber' => 0, + 'latest' => 0 + ]; + $DB->insert_record('assign_submission', $asentry, false, false, true); + $qaentry = [ + 'id' => $i, + 'quiz' => $id->id, + 'userid' => $user->id, + 'attempt' => $i * 2, + 'uniqueid' => $i, + 'layout' => '1,0', + 'currentpage' => 0, + 'preview' => 1, + 'state' => 'finished', + 'timestart' => $oneweekago, + 'timefinish' => $oneweekago + 200, + 'timemodified' => $oneweekago + 200, + 'timemodifiedoffline' => 0, + 'timecheckstate' => 0, + 'sumgrades' => 1/$i + ]; + $DB->insert_record('quiz_attempts', $qaentry, false, false, true); + $i = $i + 1; + } + + $aentry = [ + 'id' => $i, + 'course' => $course->id, + 'name' => 'test', + 'intro' => 'test', + 'introformat' => 0, + 'alwaysshowdescription' => 0, + 'nosubmissions' => 0, + 'submissiondrafts' => 0, + 'sendnotifications' => 0, + 'sendlatenotifications' => 0, + 'duedate' => 0, + 'allowsubmissionsfromdate' => 0, + 'grade' => 1, + 'timemodified' => $twoweeksago + 200, + 'requiresubmissionstatement' => 0, + 'completionsubmit' => 0, + 'cutoffdate' => 0, + 'gradingduedate' => 0, + 'teamsubmission' => 0, + 'requireallteammemberssubmit' => 0, + 'teamsubmissiongroupingid' => 0, + 'blindmarking' => 0, + 'hidegrader' => 0, + 'revealidentities' => 0, + 'attemptreopenmethod' => 't', + 'maxattempts' => -1, + 'markingworkflow' => 0, + 'sendstudentnotifications' => 1, + 'preventsubmissionnotingroup' => 0 + ]; + $DB->insert_record('assign', $aentry, false, false, true); + $asentry = [ + 'id' => $i, + 'assignment' => $i, + 'userid' => $user->id, + 'timecreated' => $twoweeksago + 1000, + 'timemodified' => $twoweeksago + 1000, + 'status' => 'submitted', + 'groupid' => 0, + 'attemptnumber' => 0, + 'latest' => 0 + ]; + $DB->insert_record('assign_submission', $asentry, false, false, true); + $qaentry = [ + 'id' => $i, + 'quiz' => $id->id, + 'userid' => $user->id, + 'attempt' => $i * 2, + 'uniqueid' => $i, + 'layout' => '1,0', + 'currentpage' => 0, + 'preview' => 1, + 'state' => 'finished', + 'timestart' => $twoweeksago, + 'timefinish' => $twoweeksago + 200, + 'timemodified' => $twoweeksago + 200, + 'timemodifiedoffline' => 0, + 'timecheckstate' => 0, + 'sumgrades' => 1/$i + ]; + $DB->insert_record('quiz_attempts', $qaentry, false, false, true); + + $testresult1 = query_helper::preview_quiz_and_assigments($course->id, 1); + + $this->assertEquals([1, 3], $testresult1); + } +} diff --git a/reports/weekheatmap/tests/query_helper_advanced_test.php b/reports/weekheatmap/tests/query_helper_advanced_test.php new file mode 100644 index 0000000..bba3d43 --- /dev/null +++ b/reports/weekheatmap/tests/query_helper_advanced_test.php @@ -0,0 +1,142 @@ +. + +defined('MOODLE_INTERNAL') || die(); + +use lareport_weekheatmap\query_helper; +use PHPUnit\Framework\TestCase; +use local_learning_analytics\event\report_viewed; +use local_learning_analytics\report_list; +require_once(__DIR__ . '/../../../../../config.php'); + +//use: navigate in cmd to your moodle folder and enter vendor\bin\phpunit local_Learning_Analytics_reports_weekheatmap_testcase local\Learning_Analytics\reports\weekheatmap\tests\query_helper_advanced_test.php +class local_Learning_Analytics_reports_weekheatmap_testcase extends \advanced_testcase { + + public function test_weekly_activity() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + $datagenerator = $this->getDataGenerator(); + $this->preventResetByRollback(); + set_config('enabled_stores', 'logstore_lanalytics', 'tool_log'); + set_config('buffersize', 0, 'logstore_lanalytics'); + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $user = $datagenerator->create_user(); + $datagenerator->enrol_user($user->id, $course->id); + $startdatezone = new \DateTimeZone('Europe/Berlin'); + $startdate = new DateTime("now", $startdatezone); + $startdate->setTimestamp($course->startdate); + $startdate->modify('Monday this week'); + $mondaytimestamp = $startdate->getTimestamp(); + $counter = 1; + for($i=0; $i<168; $i++) { + $entry = [ + 'id' => $counter, + 'eventid' => 30, + 'timecreated' => $mondaytimestamp + $i * 60 * 60, + 'courseid' => $course->id, + 'contextid' => 46, + 'device' => 3611 + ]; + $DB->insert_record('logstore_lanalytics_log', $entry, false, false, true); + $counter++; + if($i%2==0) { + $entry['id'] = $counter; + $DB->insert_record('logstore_lanalytics_log', $entry, false, false, true); + $counter++; + } + if($i%3==0) { + $entry['id'] = $counter; + $DB->insert_record('logstore_lanalytics_log', $entry, false, false, true); + $counter++; + } + } + + $testweekresult = query_helper::query_heatmap($course->id); + + $get_arrayname = function($val) { + /*$myzone = new \DateTimeZone('Europe/Berlin'); + $refzone = new \DateTimeZone('UTC'); + $dateTimeMy = new DateTime("now", $myzone); + $dateTimeRef = new DateTime("now", $refzone); + $val = $val - (($dateTimeMy->getOffset() + $dateTimeRef->getOffset()) / 3600); + if($val<0) { + $val = $val + 168; + }*/ + $returner = '' . floor($val/24) . '-' . floor($val%24); + return $returner; + }; + + $query = <<assertEquals(3, $testweekresult[$get_arrayname(0)]->value); + //$this->assertEquals(2, $testweekresult[$get_arrayname(100)]->value); + //$this->assertEquals(2, $testweekresult[$get_arrayname(39)]->value); + //$this->assertEquals(1, $testweekresult[$get_arrayname(17)]->value); + $this->assertEquals(false, array_key_exists(168, $testweekresult)); + } + + public function test_preview_query_click_count() { + global $DB, $PAGE; + $this->resetAfterTest(true); + $this->setAdminUser(); + $datagenerator = $this->getDataGenerator(); + $this->preventResetByRollback(); + set_config('enabled_stores', 'logstore_lanalytics', 'tool_log'); + set_config('buffersize', 0, 'logstore_lanalytics'); + $category = $datagenerator->create_category(); + $course = $datagenerator->create_course(array('name'=>'testcourse', 'category'=>$category->id)); + $date = new \DateTime(); + $date->setTime(23, 59, 59); + $today = $date->getTimestamp(); + $date->modify('-1 week'); + $oneweekago = $date->getTimestamp(); + $counterThisWeek = 0; + $counterOneWeeksAgo = 0; + for($i=0; $i<99; $i++) { + $counterThisWeek++; + $entry = [ + 'id' => $counterThisWeek, + 'eventid' => 30, + 'timecreated' => $today - 40000, + 'courseid' => $course->id, + 'contextid' => 46, + 'device' => 3611 + ]; + $DB->insert_record('logstore_lanalytics_log', $entry, false, false, true); + if($i%2==0) { + $counterOneWeeksAgo++; + $entry = [ + 'id' => $counterOneWeeksAgo, + 'eventid' => 30, + 'timecreated' => $oneweekago - 40000, + 'courseid' => $course->id, + 'contextid' => 46, + 'device' => 3611 + ]; + $DB->insert_record('logstore_lanalytics_log', $entry, false, false, true); + } + } + $testweekresult = query_helper::preview_query_click_count($course->id); + + $this->assertEquals(50, $testweekresult["hits"][0]); + $this->assertEquals(109, $testweekresult["hits"][1]); + } +} \ No newline at end of file