├── .github
└── workflows
│ ├── moodle-ci.yml
│ └── moodle-release.yml
├── README.md
├── amd
├── build
│ ├── radiobuttondeselect.min.js
│ └── radiobuttondeselect.min.js.map
└── src
│ └── radiobuttondeselect.js
├── backup
└── moodle2
│ ├── backup_ratingallocate_activity_stepslib.php
│ ├── backup_ratingallocate_activity_task.class.php
│ ├── backup_restore_helper.php
│ ├── restore_ratingallocate_activity_stepslib.php
│ └── restore_ratingallocate_activity_task.class.php
├── classes
├── algorithm_status.php
├── allocations_table.php
├── choice_importer.php
├── completion
│ └── custom_completion.php
├── dates.php
├── event
│ ├── all_ratings_deleted.php
│ ├── allocation_published.php
│ ├── allocation_statistics_viewed.php
│ ├── allocation_table_viewed.php
│ ├── distribution_triggered.php
│ ├── index_viewed.php
│ ├── manual_allocation_saved.php
│ ├── rating_deleted.php
│ ├── rating_saved.php
│ ├── rating_viewed.php
│ ├── ratingallocate_viewed.php
│ └── ratings_and_allocation_table_viewed.php
├── privacy
│ └── provider.php
├── ratingallocate_observer.php
├── ratings_and_allocations_table.php
└── task
│ ├── cron_task.php
│ ├── distribute_unallocated_task.php
│ └── send_distribution_notification.php
├── db
├── access.php
├── db_structure.php
├── events.php
├── install.php
├── install.xml
├── log.php
├── messages.php
├── tasks.php
├── uninstall.php
└── upgrade.php
├── form_manual_allocation.php
├── form_modify_choice.php
├── form_upload_choices.php
├── grade.php
├── index.php
├── lang
└── en
│ └── ratingallocate.php
├── lib.php
├── locallib.php
├── mod_form.php
├── pix
├── checkbox-selected.svg
├── checkbox.svg
├── icon.png
├── icon.svg
└── monologo.svg
├── renderable.php
├── renderer.php
├── settings.php
├── solver
├── edmonds-karp.php
├── export_lp_solve.php
├── ford-fulkerson-koegel.php
└── solver-template.php
├── strategy
├── strategy01_yes_no.php
├── strategy02_yes_maybe_no.php
├── strategy03_lickert.php
├── strategy04_points.php
├── strategy05_order.php
├── strategy06_tickyes.php
├── strategy_template.php
└── strategy_template_options.php
├── styles.css
├── tests
├── backup_restore_test.php
├── behat
│ ├── allocation_status.feature
│ ├── behat_mod_ratingallocate.php
│ ├── completion_condition_allocation.feature
│ ├── completion_condition_vote.feature
│ ├── completion_manual.feature
│ ├── defaultratings.feature
│ ├── manual_allocation.feature
│ ├── mod_form.feature
│ ├── ratings.feature
│ ├── select_strategy.feature
│ ├── validate_rating.feature
│ └── visibile_calendar_events.feature
├── cron_test.php
├── generator
│ └── lib.php
├── locallib_test.php
├── mod_generator_test.php
├── mod_ratingallocate_allocate_unrated_test.php
├── mod_ratingallocate_choice_groups_test.php
├── mod_ratingallocate_choice_importer_test.php
├── mod_ratingallocate_notification_test.php
├── mod_ratingallocate_privacy_provider_test.php
├── mod_ratingallocate_processor_test.php
├── mod_ratingallocate_solver_test.php
├── mod_ratingallocate_status_test.php
└── mod_ratingallocate_strategy_test.php
├── version.php
└── view.php
/.github/workflows/moodle-ci.yml:
--------------------------------------------------------------------------------
1 | name: Moodle Plugin CI
2 |
3 | on: [ push, pull_request ]
4 |
5 | jobs:
6 | static:
7 | runs-on: ubuntu-latest
8 |
9 | strategy:
10 | matrix:
11 | php: ['8.3']
12 | moodle-branch: ['MOODLE_405_STABLE']
13 | database: ['pgsql']
14 |
15 | steps:
16 | - name: Start PostgreSQL
17 | run: docker run -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:14
18 |
19 | - name: Check out repository code
20 | uses: actions/checkout@v4
21 | with:
22 | path: plugin
23 |
24 | - name: Setup PHP ${{ matrix.php }}
25 | uses: shivammathur/setup-php@v2
26 | with:
27 | php-version: ${{ matrix.php }}
28 | ini-values: max_input_vars=5000
29 | coverage: none
30 |
31 | - name: Initialise moodle-plugin-ci
32 | run: |
33 | composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4
34 | echo $(cd ci/bin; pwd) >> $GITHUB_PATH
35 | echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
36 | sudo locale-gen en_AU.UTF-8
37 | echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV
38 |
39 | - name: Install moodle-plugin-ci
40 | run: |
41 | moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 --no-init
42 | env:
43 | DB: ${{ matrix.database }}
44 | MOODLE_BRANCH: ${{ matrix.moodle-branch }}
45 |
46 | - name: PHP Lint
47 | if: ${{ always() }}
48 | run: moodle-plugin-ci phplint
49 |
50 | - name: PHP Mess Detector
51 | if: ${{ always() }}
52 | run: moodle-plugin-ci phpmd
53 |
54 | - name: Moodle Code Checker
55 | if: ${{ always() }}
56 | run: moodle-plugin-ci codechecker
57 |
58 | - name: Moodle PHPDoc Checker
59 | if: ${{ always() }}
60 | run: moodle-plugin-ci phpdoc
61 | continue-on-error: true
62 |
63 | - name: Validating
64 | if: ${{ always() }}
65 | run: moodle-plugin-ci validate
66 |
67 | - name: Check upgrade savepoints
68 | if: ${{ always() }}
69 | run: moodle-plugin-ci savepoints
70 |
71 | - name: Mustache Lint
72 | if: ${{ always() }}
73 | run: moodle-plugin-ci mustache
74 |
75 | - name: Grunt
76 | if: ${{ always() }}
77 | run: moodle-plugin-ci grunt
78 |
79 | test:
80 | runs-on: ubuntu-latest
81 | needs: static
82 |
83 | strategy:
84 | fail-fast: false
85 | matrix:
86 | php: ['8.0', '8.1', '8.2', '8.3']
87 | moodle-branch: [
88 | 'MOODLE_401_STABLE',
89 | 'MOODLE_402_STABLE',
90 | 'MOODLE_403_STABLE',
91 | 'MOODLE_404_STABLE',
92 | 'MOODLE_405_STABLE'
93 | ]
94 | database: ['mariadb', 'pgsql']
95 | exclude:
96 | - php: '8.0'
97 | moodle-branch: 'MOODLE_404_STABLE'
98 | - php: '8.0'
99 | moodle-branch: 'MOODLE_405_STABLE'
100 | - php: '8.2'
101 | moodle-branch: 'MOODLE_401_STABLE'
102 | - php: '8.3'
103 | moodle-branch: 'MOODLE_401_STABLE'
104 | - php: '8.3'
105 | moodle-branch: 'MOODLE_402_STABLE'
106 | - php: '8.3'
107 | moodle-branch: 'MOODLE_403_STABLE'
108 | include:
109 | - php: '7.4'
110 | moodle-branch: 'MOODLE_401_STABLE'
111 | database: 'pgsql'
112 | - php: '7.4'
113 | moodle-branch: 'MOODLE_401_STABLE'
114 | database: 'mariadb'
115 |
116 | steps:
117 | - name: Start MariaDB
118 | if: matrix.database == 'mariadb'
119 | run: docker run -p 3306:3306 -e MYSQL_USER=root -e MYSQL_ALLOW_EMPTY_PASSWORD=true -d mariadb:10
120 |
121 | - name: Start PostgreSQL
122 | if: matrix.database == 'pgsql'
123 | run: docker run -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:14
124 |
125 | - name: Check out repository code
126 | uses: actions/checkout@v4
127 | with:
128 | path: plugin
129 |
130 | - name: Setup PHP ${{ matrix.php }}
131 | uses: shivammathur/setup-php@v2
132 | with:
133 | php-version: ${{ matrix.php }}
134 | ini-values: max_input_vars=5000
135 | coverage: none
136 |
137 | - name: Initialise moodle-plugin-ci
138 | run: |
139 | composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4
140 | echo $(cd ci/bin; pwd) >> $GITHUB_PATH
141 | echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
142 | sudo locale-gen en_AU.UTF-8
143 | echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV
144 |
145 | - name: Install moodle-plugin-ci
146 | run: |
147 | moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1
148 | env:
149 | DB: ${{ matrix.database }}
150 | MOODLE_BRANCH: ${{ matrix.moodle-branch }}
151 |
152 | - name: PHPUnit tests
153 | if: ${{ always() }}
154 | run: moodle-plugin-ci phpunit
155 |
156 | - name: Behat features
157 | if: ${{ always() }}
158 | run: moodle-plugin-ci behat --profile chrome --auto-rerun 0
159 |
160 | # This step allows to upload Behat faildump (screenshots) as workflow artifact,
161 | # so it can be downloaded and inspected. You do not need this step if you
162 | # are not running Behat test. Artifact will be retained for 7 days.
163 | - name: Upload Behat Faildump
164 | if: ${{ failure() && steps.behat.outcome == 'failure' }}
165 | uses: actions/upload-artifact@v4
166 | with:
167 | name: Behat Faildump (${{ join(matrix.*, ', ') }})
168 | path: ${{ github.workspace }}/moodledata/behat_dump
169 | retention-days: 7
170 | if-no-files-found: ignore
171 |
--------------------------------------------------------------------------------
/.github/workflows/moodle-release.yml:
--------------------------------------------------------------------------------
1 | #
2 | # Whenever a new tag starting with "v" is pushed, add the tagged version
3 | # to the Moodle Plugins directory at https://moodle.org/plugins
4 | #
5 | # revision: 2021070201
6 | # Changed to be released on Github release with the release notes.
7 | #
8 | name: Releasing in the Plugins directory
9 |
10 | on:
11 | release:
12 | types: [ published ]
13 |
14 | defaults:
15 | run:
16 | shell: bash
17 |
18 | jobs:
19 | release-at-moodle-org:
20 | runs-on: ubuntu-latest
21 | env:
22 | PLUGIN: mod_ratingallocate
23 | CURL: curl -s
24 | ENDPOINT: https://moodle.org/webservice/rest/server.php
25 | TOKEN: ${{ secrets.MOODLE_ORG_TOKEN }}
26 | FUNCTION: local_plugins_add_version
27 |
28 | steps:
29 | - name: Call the service function
30 | id: add-version
31 | run: |
32 | TAGNAME="${{ github.event.release.tag_name }}"
33 | BODY="${{ github.event.release.body }}"
34 | ZIPURL="${{ github.event.release.zipball_url }}"
35 | RESPONSE=$(${CURL} ${ENDPOINT} --data-urlencode "wstoken=${TOKEN}" \
36 | --data-urlencode "wsfunction=${FUNCTION}" \
37 | --data-urlencode "moodlewsrestformat=json" \
38 | --data-urlencode "frankenstyle=${PLUGIN}" \
39 | --data-urlencode "zipurl=${ZIPURL}" \
40 | --data-urlencode "vcssystem=git" \
41 | --data-urlencode "vcsrepositoryurl=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" \
42 | --data-urlencode "vcstag=${TAGNAME}" \
43 | --data-urlencode "changelogurl=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/commits/${TAGNAME}" \
44 | --data-urlencode "altdownloadurl=${ZIPURL}" \
45 | --data-urlencode "releasenotes=${BODY}" \
46 | --data-urlencode "releasenotesformat=4")
47 | echo "response=${RESPONSE}" >> $GITHUB_OUTPUT
48 | - name: Evaluate the response
49 | id: evaluate-response
50 | env:
51 | RESPONSE: ${{ steps.add-version.outputs.response }}
52 | run: |
53 | jq <<< ${RESPONSE}
54 | jq --exit-status ".id" <<< ${RESPONSE} > /dev/null
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | moodle-mod_ratingallocate
2 | ============================
3 | [](https://codecov.io/gh/learnweb/moodle-mod_ratingallocate)
4 |
5 | Module which lets you add an activity to courses, in which users can rate choices. You may then distribute the users fairly to the choices by maximising overall 'hapiness' in terms
6 | of ratings.
7 | This may be an alternative to the choice activity or other first-come-first-served plugins.
8 |
9 | This plugin is based on previous work by Stefan Koegel and Alexander Bias, University of Ulm.
10 |
11 | Installation
12 | ============
13 | This is an activity plugin and should go into ``mod/ratingallocate``.
14 | Obtain this plugin from https://moodle.org/plugins/view/mod_ratingallocate.
15 |
16 | Usage
17 | ============
18 |
19 | Add an activity instance. Set mandatory parameters. These are timespan, in which users can give ratings, and the strategy,
20 | which form will be presented to the users to rate.
21 | Next you can add choices, which the users will have to rate later on.
22 | After the rating period has finished, you can allocate the users automatically or manually. Upon publishing the results, users will be able to see which choice they have been
23 | allocated to.
24 | For more information please visit the [moodle wiki](https://docs.moodle.org/31/en/Ratingallocate).
25 |
26 | Moodle version
27 | ======================
28 | The plugin is continously tested with all moodle versions, which are security supported by the moodle headquarter.
29 | Therefore, Travis uses the most current release to build a test instance and run the behat and unit tests on them.
30 | In addition to all stable branches the version is also tested against the master branch to support early adopters.
31 |
32 | Algorithm
33 | =========
34 | This module uses a modified Edmonds-karp algorithm to solve the minimum-cost flow problem. Augmenting paths are found using Bellman-Ford, but the user ratings are multiplied with
35 | -1 first.
36 |
37 | Worst-Case complexity is O(m^2n^2) with m,n being number of edges (#users+#choices+#ratings_users_gave) and nodes (2+#users+#choices) in the graph.
38 | Distributing 500 users to 21 choices takes around 11sec.
39 |
40 | Changelog
41 | =========
42 | The changes for every release are listed here: https://github.com/learnweb/moodle-mod_ratingallocate/wiki/Changelog.
43 |
--------------------------------------------------------------------------------
/amd/build/radiobuttondeselect.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This class manages the deselection of radiobuttons, which is necessary for deleting allocations
3 | *
4 | * @module mod_ratingallocate/radiobuttondeselect
5 | * @copyright 2017 Tobias Reischmann
6 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7 | */
8 | define("mod_ratingallocate/radiobuttondeselect",["jquery"],(function($){return{init:function(){$(".ratingallocate_checkbox_label:checked").on("click",this.deselect(this)),$(".ratingallocate_checkbox_label:not(:checked)").on("click",this.callrefresh(this))},deselect:function(that){return function(event){event.target.checked&&(event.target.checked=!1),that.refresh(that)}},refresh:function(that){$(".ratingallocate_checkbox_label").off("click"),$(".ratingallocate_checkbox_label:checked").on("click",that.deselect(that)),$(".ratingallocate_checkbox_label:not(:checked)").on("click",that.callrefresh(that))},callrefresh:function(that){return function(){that.refresh(that)}}}}));
9 |
10 | //# sourceMappingURL=radiobuttondeselect.min.js.map
--------------------------------------------------------------------------------
/amd/build/radiobuttondeselect.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"radiobuttondeselect.min.js","sources":["../src/radiobuttondeselect.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * This class manages the deselection of radiobuttons, which is necessary for deleting allocations\n *\n * @module mod_ratingallocate/radiobuttondeselect\n * @copyright 2017 Tobias Reischmann\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'], function ($) {\n\n /**\n * @alias module:mod_ratingallocate/radiobuttondeselect\n */\n var t = {\n\n /**\n * Create the click events for deselecting radiobuttons.\n */\n init: function () {\n $('.ratingallocate_checkbox_label:checked').on('click', this.deselect(this));\n $('.ratingallocate_checkbox_label:not(:checked)').on('click', this.callrefresh(this));\n },\n\n deselect: function (that) {\n return function (event) {\n if (event.target.checked) {\n event.target.checked = false;\n }\n that.refresh(that);\n };\n },\n\n refresh: function (that) {\n $('.ratingallocate_checkbox_label').off('click');\n $('.ratingallocate_checkbox_label:checked').on('click', that.deselect(that));\n $('.ratingallocate_checkbox_label:not(:checked)').on('click', that.callrefresh(that));\n },\n\n callrefresh: function (that) {\n return function () {\n that.refresh(that);\n };\n }\n };\n\n return t;\n});\n"],"names":["define","$","init","on","this","deselect","callrefresh","that","event","target","checked","refresh","off"],"mappings":";;;;;;;AAsBAA,gDAAO,CAAC,WAAW,SAAUC,SAKjB,CAKJC,KAAM,WACFD,EAAE,0CAA0CE,GAAG,QAASC,KAAKC,SAASD,OACtEH,EAAE,gDAAgDE,GAAG,QAASC,KAAKE,YAAYF,QAGnFC,SAAU,SAAUE,aACT,SAAUC,OACTA,MAAMC,OAAOC,UACbF,MAAMC,OAAOC,SAAU,GAE3BH,KAAKI,QAAQJ,QAIrBI,QAAS,SAAUJ,MACfN,EAAE,kCAAkCW,IAAI,SACxCX,EAAE,0CAA0CE,GAAG,QAASI,KAAKF,SAASE,OACtEN,EAAE,gDAAgDE,GAAG,QAASI,KAAKD,YAAYC,QAGnFD,YAAa,SAAUC,aACZ,WACHA,KAAKI,QAAQJ"}
--------------------------------------------------------------------------------
/amd/src/radiobuttondeselect.js:
--------------------------------------------------------------------------------
1 | // This file is part of Moodle - http://moodle.org/
2 | //
3 | // Moodle is free software: you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation, either version 3 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // Moodle is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Moodle. If not, see .
15 |
16 | /**
17 | * This class manages the deselection of radiobuttons, which is necessary for deleting allocations
18 | *
19 | * @module mod_ratingallocate/radiobuttondeselect
20 | * @copyright 2017 Tobias Reischmann
21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 | */
23 | define(['jquery'], function ($) {
24 |
25 | /**
26 | * @alias module:mod_ratingallocate/radiobuttondeselect
27 | */
28 | var t = {
29 |
30 | /**
31 | * Create the click events for deselecting radiobuttons.
32 | */
33 | init: function () {
34 | $('.ratingallocate_checkbox_label:checked').on('click', this.deselect(this));
35 | $('.ratingallocate_checkbox_label:not(:checked)').on('click', this.callrefresh(this));
36 | },
37 |
38 | deselect: function (that) {
39 | return function (event) {
40 | if (event.target.checked) {
41 | event.target.checked = false;
42 | }
43 | that.refresh(that);
44 | };
45 | },
46 |
47 | refresh: function (that) {
48 | $('.ratingallocate_checkbox_label').off('click');
49 | $('.ratingallocate_checkbox_label:checked').on('click', that.deselect(that));
50 | $('.ratingallocate_checkbox_label:not(:checked)').on('click', that.callrefresh(that));
51 | },
52 |
53 | callrefresh: function (that) {
54 | return function () {
55 | that.refresh(that);
56 | };
57 | }
58 | };
59 |
60 | return t;
61 | });
62 |
--------------------------------------------------------------------------------
/backup/moodle2/backup_ratingallocate_activity_task.class.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | defined('MOODLE_INTERNAL') || die();
18 |
19 | require_once($CFG->dirroot . '/mod/ratingallocate/backup/moodle2/backup_ratingallocate_activity_stepslib.php');
20 |
21 | /**
22 | * Ratingallocate backup task that provides all the settings and steps to perform one
23 | * complete backup of the activity.
24 | *
25 | * @package mod_ratingallocate
26 | * @copyright 2014 C. Usener
27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 | */
29 | class backup_ratingallocate_activity_task extends backup_activity_task {
30 |
31 | /**
32 | * Define (add) particular settings this activity can have
33 | */
34 | protected function define_my_settings() {
35 | // No particular settings for this activity.
36 | }
37 |
38 | /**
39 | * Define (add) particular steps this activity can have
40 | */
41 | protected function define_my_steps() {
42 | // Ratingallocate only has one structure step.
43 | $this->add_step(new backup_ratingallocate_activity_structure_step('ratingallocate_structure', 'ratingallocate.xml'));
44 | }
45 |
46 | /**
47 | * Code the transformations to perform in the activity in
48 | * order to get transportable (encoded) links
49 | */
50 | public static function encode_content_links($content) {
51 | return $content;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/backup/moodle2/backup_restore_helper.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Backup restore helper.
19 | *
20 | * @package mod_ratingallocate
21 | * @subpackage backup-moodle2
22 | * @copyright 2014 C. Usener
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | /**
27 | * Get fields for tableclass
28 | *
29 | * @param $class
30 | * @return array
31 | * @throws ReflectionException
32 | */
33 | function get_fields_for_tableclass($class) {
34 | $class = new ReflectionClass($class);
35 | $constants = $class->getConstants();
36 | $keystoremove = ['ID', 'TABLE'];
37 | foreach ($constants as $key => $value) {
38 | if (count(array_intersect([$key], $keystoremove)) > 0) {
39 | unset($constants[$key]);
40 | }
41 | }
42 | return array_values($constants);
43 | }
44 |
45 | /**
46 | * Get tablename for tableclass.
47 | *
48 | * @param $class
49 | * @return mixed
50 | * @throws ReflectionException
51 | */
52 | function get_tablename_for_tableclass($class) {
53 | $class = new ReflectionClass($class);
54 | $constants = $class->getConstants();
55 | return $constants['TABLE'];
56 | }
57 |
58 | /**
59 | * Get id for tableclass.
60 | *
61 | * @param $class
62 | * @return array
63 | * @throws ReflectionException
64 | */
65 | function get_id_for_tableclass($class) {
66 | $class = new ReflectionClass($class);
67 | $constants = $class->getConstants();
68 | return [$constants['ID']];
69 | }
70 |
--------------------------------------------------------------------------------
/backup/moodle2/restore_ratingallocate_activity_task.class.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | defined('MOODLE_INTERNAL') || die();
18 |
19 | /**
20 | * Ratingallocate restore task that provides all the settings and steps to perform one
21 | * complete restore of the activity.
22 | *
23 | * @package moodlecore
24 | * @subpackage backup-moodle2
25 | * @copyright 2014 C. Usener
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 | */
28 | require_once($CFG->dirroot . '/mod/ratingallocate/backup/moodle2/restore_ratingallocate_activity_stepslib.php');
29 |
30 | /**
31 | * Restore ratingallocate activity class
32 | *
33 | * @package mod_ratingallocate
34 | * @copyright 214 C. Usener
35 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 | */
37 | class restore_ratingallocate_activity_task extends restore_activity_task {
38 |
39 | /**
40 | * Define (add) particular settings this activity can have
41 | */
42 | protected function define_my_settings() {
43 | // No particular settings for this activity.
44 | }
45 |
46 | /**
47 | * Define (add) particular steps this activity can have
48 | */
49 | protected function define_my_steps() {
50 | // Ratingallocate only has one structure step.
51 | $this->add_step(new restore_ratingallocate_activity_structure_step('ratingallocate_structure', 'ratingallocate.xml'));
52 | }
53 |
54 | /**
55 | * Define the contents in the activity that must be
56 | * processed by the link decoder
57 | */
58 | public static function define_decode_contents() {
59 | $contents = [];
60 |
61 | return $contents;
62 | }
63 |
64 | /**
65 | * Define the decoding rules for links belonging
66 | * to the activity to be executed by the link decoder
67 | */
68 | public static function define_decode_rules() {
69 | $rules = [];
70 |
71 | return $rules;
72 | }
73 |
74 | /**
75 | * Define the restore log rules that will be applied
76 | * by the {@link restore_logs_processor} when restoring
77 | * ratingallocate logs.
78 | * It must return one array
79 | * of {@link restore_log_rule} objects
80 | */
81 | public static function define_restore_log_rules() {
82 | $rules = [];
83 |
84 | return $rules;
85 | }
86 |
87 | /**
88 | * Define the restore log rules that will be applied
89 | * by the {@link restore_logs_processor} when restoring
90 | * course logs.
91 | * It must return one array
92 | * of {@link restore_log_rule} objects
93 | *
94 | * Note this rules are applied when restoring course logs
95 | * by the restore final task, but are defined here at
96 | * activity level. All them are rules not linked to any module instance (cmid = 0)
97 | */
98 | public static function define_restore_log_rules_for_course() {
99 | $rules = [];
100 | return $rules;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/classes/algorithm_status.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | namespace mod_ratingallocate;
18 | /**
19 | * The different status a ratingallocate object can be in according to its algorithm run.
20 | *
21 | * @package mod_ratingallocate
22 | * @copyright 2015 Tobias Reischmann
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 | class algorithm_status {
26 | /**
27 | * Algorithm did not finish correctly.
28 | */
29 | const FAILURE = -1;
30 | /**
31 | * Default status for new instances.
32 | */
33 | const NOTSTARTED = 0;
34 | /**
35 | * Algorithm is currently running.
36 | */
37 | const RUNNING = 1;
38 | /**
39 | * Algorithm finished correctly.
40 | */
41 | const FINISHED = 2;
42 | }
43 |
--------------------------------------------------------------------------------
/classes/completion/custom_completion.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | declare(strict_types=1);
18 |
19 | namespace mod_ratingallocate\completion;
20 |
21 | use context_module;
22 | use core_completion\activity_custom_completion;
23 |
24 | /**
25 | * Activity custom completion subclass for the ratingallocate activity.
26 | *
27 | * Class for defining the custom completion rules of ratingallocate and fetching the completion statuses
28 | * of the custom completion rules for a given ratingallocate instance and a user.
29 | *
30 | * @package mod_ratingallocate
31 | * @copyright Irina Hoppe Uni Münster
32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 | */
34 | class custom_completion extends activity_custom_completion {
35 |
36 | /**
37 | * Fetches the completion state for a given completion rule.
38 | *
39 | * @param string $rule The completion rule.
40 | * @return int The completion state.
41 | * @throws \moodle_exception
42 | */
43 | public function get_state(string $rule): int {
44 | global $DB;
45 | $status = false;
46 | $this->validate_rule($rule);
47 |
48 | $userid = $this->userid;
49 | $instance = $this->cm->instance;
50 |
51 | if (!$DB->get_record('ratingallocate', ['id' => $instance])) {
52 | throw new \moodle_exception('Unable to find ratingallocate instance with id ' . $instance);
53 | }
54 |
55 | if ($rule == 'completionvote') {
56 | $sql = "SELECT * FROM {ratingallocate_ratings} r INNER JOIN {ratingallocate_choices} c on r.choiceid=c.id " .
57 | "WHERE r.userid= :userid AND c.ratingallocateid= :ratingallocateid AND c.active=1";
58 | $votesofuser = $DB->get_records_sql($sql, ['userid' => $userid, 'ratingallocateid' => $instance]);
59 | $status = count($votesofuser) > 0;
60 | } else if ($rule == 'completionallocation') {
61 | $sql = "SELECT * FROM {ratingallocate_allocations} a INNER JOIN {ratingallocate_choices} c
62 | ON a.choiceid = c.id WHERE userid= :userid AND a.ratingallocateid= :ratingallocateid AND c.active=1";
63 | $allocationsofuser = $DB->get_records_sql($sql, ['userid' => $userid, 'ratingallocateid' => $instance]);
64 | $status = count($allocationsofuser) > 0;
65 | }
66 |
67 | return $status ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE;
68 | }
69 |
70 | /**
71 | * Fetch the list of custom completion rules that this module defines.
72 | *
73 | * @return array
74 | */
75 | public static function get_defined_custom_rules(): array {
76 | return [
77 | 'completionvote',
78 | 'completionallocation',
79 | ];
80 | }
81 |
82 | /**
83 | * Returns an associative array of the descriptions of custom completion rules.
84 | *
85 | * @return array
86 | */
87 | public function get_custom_rule_descriptions(): array {
88 | return [
89 | 'completionvote' => get_string('completionvote_desc', RATINGALLOCATE_MOD_NAME),
90 | 'completionallocation' => get_string('completionallocation_desc', RATINGALLOCATE_MOD_NAME),
91 | ];
92 | }
93 |
94 | /**
95 | * Returns an array of all completion rules, in the order they should be displayed to users.
96 | *
97 | * @return array
98 | */
99 | public function get_sort_order(): array {
100 | return [
101 | 'completionview',
102 | 'completionvote',
103 | 'completionallocation',
104 | ];
105 | }
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/classes/dates.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Contains the class for fetching the important dates in mod_ratingallocate for a given module instance and a user.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2022 University of Vienna
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | declare(strict_types=1);
26 |
27 | namespace mod_ratingallocate;
28 |
29 | use core\activity_dates;
30 |
31 | /**
32 | * Class for fetching the important dates in mod_ratingallocate for a given module instance and a user.
33 | *
34 | * @copyright 2022 Jakob Mischke
35 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 | */
37 | class dates extends activity_dates {
38 | /**
39 | * Returns a list of important dates in mod_ratingallocate
40 | *
41 | * @return array
42 | */
43 | protected function get_dates(): array {
44 | global $DB;
45 |
46 | $timeopen = $this->cm->customdata['accesstimestart'] ?? null;
47 | $timeclose = $this->cm->customdata['accesstimestop'] ?? null;
48 |
49 | $now = time();
50 | $dates = [];
51 |
52 | if ($timeopen) {
53 | $openlabelid = $timeopen > $now ? 'activitydate:opens' : 'activitydate:opened';
54 | $dates[] = [
55 | 'label' => get_string($openlabelid, 'core_course'),
56 | 'timestamp' => (int) $timeopen,
57 | ];
58 | }
59 |
60 | if ($timeclose) {
61 | $closelabelid = $timeclose > $now ? 'activitydate:closes' : 'activitydate:closed';
62 | $dates[] = [
63 | 'label' => get_string($closelabelid, 'core_course'),
64 | 'timestamp' => (int) $timeclose,
65 | ];
66 | }
67 |
68 | return $dates;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/classes/event/all_ratings_deleted.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate rating_deleted event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2020 Robin Tschudi
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 | namespace mod_ratingallocate\event;
25 |
26 | /**
27 | * The mod_ratingallocate rating_deleted event class.
28 | *
29 | * @copyright 2020 Robin Tschudi
30 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31 | **/
32 | class all_ratings_deleted extends \core\event\base {
33 |
34 | /**
35 | * Create simple all_ratings_deleted event.
36 | * @param $modulecontext
37 | * @param $ratingallocateid
38 | * @return \core\event\base
39 | * @throws \coding_exception
40 | */
41 | public static function create_simple($modulecontext, $ratingallocateid) {
42 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
43 | }
44 |
45 | /**
46 | * Initialize data.
47 | * @return void
48 | */
49 | protected function init() {
50 | $this->data['crud'] = 'd';
51 | $this->data['edulevel'] = self::LEVEL_TEACHING;
52 | $this->data['objecttable'] = 'ratingallocate_ratings';
53 | }
54 |
55 | /**
56 | * Get event name.
57 | * @return \lang_string|string
58 | * @throws \coding_exception
59 | */
60 | public static function get_name() {
61 | return get_string('log_all_ratings_deleted', 'mod_ratingallocate');
62 | }
63 |
64 | /**
65 | * Get event description.
66 | * @return \lang_string|string|null
67 | * @throws \coding_exception
68 | */
69 | public function get_description() {
70 | return get_string('log_all_ratings_deleted_description', 'mod_ratingallocate',
71 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
72 | }
73 |
74 | /**
75 | * Get event url.
76 | * @return \moodle_url
77 | * @throws \moodle_exception
78 | */
79 | public function get_url() {
80 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
81 | }
82 |
83 | /**
84 | * Get event mapping.
85 | * @return string[]
86 | */
87 | public static function get_objectid_mapping() {
88 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
89 | }
90 |
91 | /**
92 | * No other mappings available.
93 | * @return false
94 | */
95 | public static function get_other_mapping() {
96 | return false;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/classes/event/allocation_published.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate allocation_published event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate allocation_published event class.
29 | *
30 | * @property-read array $other {
31 | * Extra information about event.
32 | *
33 | * - array allocations: published allocations
34 | * }
35 | *
36 | * @since Moodle 2.7
37 | * @copyright 2014 Tobias Reischmann
38 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 | **/
40 | class allocation_published extends \core\event\base {
41 |
42 | /**
43 | * Create simple allocation_published event.
44 | * @param $modulecontext
45 | * @param $ratingallocateid
46 | * @return \core\event\base
47 | * @throws \coding_exception
48 | */
49 | public static function create_simple($modulecontext, $ratingallocateid) {
50 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
51 | }
52 |
53 | /**
54 | * Initialize data.
55 | * @return void
56 | */
57 | protected function init() {
58 | $this->data['crud'] = 'r';
59 | $this->data['edulevel'] = self::LEVEL_TEACHING;
60 | $this->data['objecttable'] = 'ratingallocate';
61 | }
62 |
63 | /**
64 | * Get event name.
65 | * @return \lang_string|string
66 | * @throws \coding_exception
67 | */
68 | public static function get_name() {
69 | return get_string('log_allocation_published', 'mod_ratingallocate');
70 | }
71 |
72 | /**
73 | * Get event description.
74 | * @return \lang_string|string|null
75 | * @throws \coding_exception
76 | */
77 | public function get_description() {
78 | return get_string('log_allocation_published_description', 'mod_ratingallocate',
79 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
80 | }
81 |
82 | /**
83 | * Get event url.
84 | * @return \moodle_url
85 | * @throws \moodle_exception
86 | */
87 | public function get_url() {
88 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
89 | }
90 |
91 | /**
92 | * Get event mapping.
93 | * @return string[]
94 | */
95 | public static function get_objectid_mapping() {
96 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
97 | }
98 |
99 | /**
100 | * No other mappings available.
101 | * @return false
102 | */
103 | public static function get_other_mapping() {
104 | return false;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/classes/event/allocation_statistics_viewed.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate allocation_statistics_viewed event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate allocation_statistics_viewed event class.
29 | *
30 | * @since Moodle 2.7
31 | * @copyright 2015 Tobias Reischmann
32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 | **/
34 | class allocation_statistics_viewed extends \core\event\base {
35 |
36 | /**
37 | * Create simple allocation_statistics_viewed event.
38 | * @param $modulecontext
39 | * @param $ratingallocateid
40 | * @return \core\event\base
41 | * @throws \coding_exception
42 | */
43 | public static function create_simple($modulecontext, $ratingallocateid) {
44 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
45 | }
46 |
47 | /**
48 | * Initialize data.
49 | * @return void
50 | */
51 | protected function init() {
52 | $this->data['crud'] = 'r';
53 | $this->data['edulevel'] = self::LEVEL_TEACHING;
54 | $this->data['objecttable'] = 'ratingallocate';
55 | }
56 |
57 | /**
58 | * Get event name.
59 | * @return \lang_string|string
60 | * @throws \coding_exception
61 | */
62 | public static function get_name() {
63 | return get_string('log_allocation_statistics_viewed', 'mod_ratingallocate');
64 | }
65 |
66 | /**
67 | * Get event description.
68 | * @return \lang_string|string|null
69 | * @throws \coding_exception
70 | */
71 | public function get_description() {
72 | return get_string('log_allocation_statistics_viewed_description', 'mod_ratingallocate',
73 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
74 | }
75 |
76 | /**
77 | * Get event url.
78 | * @return \moodle_url
79 | * @throws \moodle_exception
80 | */
81 | public function get_url() {
82 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
83 | }
84 |
85 | /**
86 | * Get event mapping.
87 | * @return string[]
88 | */
89 | public static function get_objectid_mapping() {
90 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
91 | }
92 |
93 | /**
94 | * No other mappings available.
95 | * @return false
96 | */
97 | public static function get_other_mapping() {
98 | return false;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/classes/event/allocation_table_viewed.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate allocation_table_viewed event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate allocation_table_viewed event class.
29 | *
30 | * @since Moodle 2.7
31 | * @copyright 2014 Tobias Reischmann
32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 | **/
34 | class allocation_table_viewed extends \core\event\base {
35 |
36 | /**
37 | * Create simple allocation_table_viewed event.
38 | * @param $modulecontext
39 | * @param $ratingallocateid
40 | * @return \core\event\base
41 | * @throws \coding_exception
42 | */
43 | public static function create_simple($modulecontext, $ratingallocateid) {
44 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
45 | }
46 |
47 | /**
48 | * Initialize data.
49 | * @return void
50 | */
51 | protected function init() {
52 | $this->data['crud'] = 'r';
53 | $this->data['edulevel'] = self::LEVEL_TEACHING;
54 | $this->data['objecttable'] = 'ratingallocate';
55 | }
56 |
57 | /**
58 | * Get event name.
59 | * @return \lang_string|string
60 | * @throws \coding_exception
61 | */
62 | public static function get_name() {
63 | return get_string('log_allocation_table_viewed', 'mod_ratingallocate');
64 | }
65 |
66 | /**
67 | * Get event description.
68 | * @return \lang_string|string|null
69 | * @throws \coding_exception
70 | */
71 | public function get_description() {
72 | return get_string('log_allocation_table_viewed_description', 'mod_ratingallocate',
73 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
74 | }
75 |
76 | /**
77 | * Get event url.
78 | * @return \moodle_url
79 | * @throws \moodle_exception
80 | */
81 | public function get_url() {
82 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
83 | }
84 |
85 | /**
86 | * Get event mapping.
87 | * @return string[]
88 | */
89 | public static function get_objectid_mapping() {
90 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
91 | }
92 |
93 | /**
94 | * No other mappings available.
95 | * @return false
96 | */
97 | public static function get_other_mapping() {
98 | return false;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/classes/event/distribution_triggered.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate distribution_triggered event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate distribution_triggered event class.
29 | *
30 | * @property-read array $other {
31 | * Extra information about event.
32 | *
33 | * - array allocations: created allocations
34 | * - double time_needed: time needed to finish the distribution
35 | * }
36 | *
37 | * @since Moodle 2.7
38 | * @copyright 2014 Tobias Reischmann
39 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 | **/
41 | class distribution_triggered extends \core\event\base {
42 |
43 | /**
44 | * Create simple distribution_triggered event.
45 | * @param $modulecontext
46 | * @param $ratingallocateid
47 | * @param $timeneeded
48 | * @return \core\event\base
49 | * @throws \coding_exception
50 | */
51 | public static function create_simple($modulecontext, $ratingallocateid, $timeneeded) {
52 | $timeneededjsonvalid = json_decode(json_encode($timeneeded), true);
53 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid,
54 | 'other' => ['time_needed' => $timeneededjsonvalid]]);
55 | }
56 |
57 | /**
58 | * Initialize data.
59 | * @return void
60 | */
61 | protected function init() {
62 | $this->data['crud'] = 'u';
63 | $this->data['edulevel'] = self::LEVEL_TEACHING;
64 | $this->data['objecttable'] = 'ratingallocate_ratings';
65 | }
66 |
67 | /**
68 | * Get event name.
69 | * @return \lang_string|string
70 | * @throws \coding_exception
71 | */
72 | public static function get_name() {
73 | return get_string('log_distribution_triggered', 'mod_ratingallocate');
74 | }
75 |
76 | /**
77 | * Get event description.
78 | * @return \lang_string|string|null
79 | * @throws \coding_exception
80 | */
81 | public function get_description() {
82 | return get_string('log_distribution_triggered_description', 'mod_ratingallocate',
83 | ['userid' => $this->userid,
84 | 'ratingallocateid' => $this->objectid,
85 | 'time_needed' => $this->other['time_needed']]);
86 | }
87 |
88 | /**
89 | * Get event url.
90 | * @return \moodle_url
91 | * @throws \moodle_exception
92 | */
93 | public function get_url() {
94 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
95 | }
96 |
97 | /**
98 | * Get event mapping.
99 | * @return string[]
100 | */
101 | public static function get_objectid_mapping() {
102 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
103 | }
104 |
105 | /**
106 | * No other mappings available.
107 | * @return false
108 | */
109 | public static function get_other_mapping() {
110 | return false;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/classes/event/index_viewed.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate index_viewed event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2017 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate index_viewed event class.
29 | *
30 | * @copyright 2017 Tobias Reischmann
31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 | **/
33 | class index_viewed extends \core\event\base {
34 |
35 | /**
36 | * Create simple index_viewed event.
37 | * @param $coursecontext
38 | * @return \core\event\base
39 | * @throws \coding_exception
40 | */
41 | public static function create_simple($coursecontext) {
42 | return self::create(['context' => $coursecontext]);
43 | }
44 |
45 | /**
46 | * Initialize data.
47 | * @return void
48 | */
49 | protected function init() {
50 | $this->data['crud'] = 'r';
51 | $this->data['edulevel'] = self::LEVEL_OTHER;
52 | }
53 |
54 | /**
55 | * Get event name.
56 | * @return \lang_string|string
57 | * @throws \coding_exception
58 | */
59 | public static function get_name() {
60 | return get_string('log_index_viewed', 'mod_ratingallocate');
61 | }
62 |
63 | /**
64 | * Get event description.
65 | * @return \lang_string|string|null
66 | * @throws \coding_exception
67 | */
68 | public function get_description() {
69 | return get_string('log_index_viewed_description', 'mod_ratingallocate', ['userid' => $this->userid]);
70 | }
71 |
72 | /**
73 | * Get event url.
74 | * @return \moodle_url
75 | * @throws \moodle_exception
76 | */
77 | public function get_url() {
78 | return new \moodle_url('/mod/ratingallocate/index.php', ['id' => $this->courseid]);
79 | }
80 |
81 | /**
82 | * Get event mapping.
83 | * @return array
84 | */
85 | public static function get_objectid_mapping() {
86 | return [];
87 | }
88 |
89 | /**
90 | * No other mappings available.
91 | * @return false
92 | */
93 | public static function get_other_mapping() {
94 | return false;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/classes/event/manual_allocation_saved.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate manual_allocation_saved event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate manual_allocation_saved event class.
29 | *
30 | * @property-read array $other {
31 | * Extra information about event.
32 | *
33 | * - array allocations: changes of allocations
34 | * }
35 | *
36 | * @since Moodle 2.7
37 | * @copyright 2014 Tobias Reischmann
38 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 | **/
40 | class manual_allocation_saved extends \core\event\base {
41 |
42 | /**
43 | * Create simple manual_allocation_saved event.
44 | * @param $modulecontext
45 | * @param $ratingallocateid
46 | * @return \core\event\base
47 | * @throws \coding_exception
48 | */
49 | public static function create_simple($modulecontext, $ratingallocateid) {
50 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
51 | }
52 |
53 | /**
54 | * Initialize data.
55 | * @return void
56 | */
57 | protected function init() {
58 | $this->data['crud'] = 'u';
59 | $this->data['edulevel'] = self::LEVEL_TEACHING;
60 | $this->data['objecttable'] = 'ratingallocate_ratings';
61 | }
62 |
63 | /**
64 | * Get event name.
65 | * @return \lang_string|string
66 | * @throws \coding_exception
67 | */
68 | public static function get_name() {
69 | return get_string('log_manual_allocation_saved', 'mod_ratingallocate');
70 | }
71 |
72 | /**
73 | * Get event description.
74 | * @return \lang_string|string|null
75 | * @throws \coding_exception
76 | */
77 | public function get_description() {
78 | return get_string('log_manual_allocation_saved_description', 'mod_ratingallocate',
79 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
80 | }
81 |
82 | /**
83 | * Get event url.
84 | * @return \moodle_url
85 | * @throws \moodle_exception
86 | */
87 | public function get_url() {
88 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
89 | }
90 |
91 | /**
92 | * Get event mapping.
93 | * @return string[]
94 | */
95 | public static function get_objectid_mapping() {
96 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
97 | }
98 |
99 | /**
100 | * No other mappings available.
101 | * @return false
102 | */
103 | public static function get_other_mapping() {
104 | return false;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/classes/event/rating_deleted.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate rating_deleted event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2017 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate rating_deleted event class.
29 | *
30 | * @copyright 2017 Tobias Reischmann
31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 | **/
33 | class rating_deleted extends \core\event\base {
34 |
35 | /**
36 | * Create simple rating_deleted event.
37 | * @param $modulecontext
38 | * @param $ratingallocateid
39 | * @return \core\event\base
40 | * @throws \coding_exception
41 | */
42 | public static function create_simple($modulecontext, $ratingallocateid) {
43 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
44 | }
45 |
46 | /**
47 | * Initialize data.
48 | * @return void
49 | */
50 | protected function init() {
51 | $this->data['crud'] = 'd';
52 | $this->data['edulevel'] = self::LEVEL_PARTICIPATING;
53 | $this->data['objecttable'] = 'ratingallocate_ratings';
54 | }
55 |
56 | /**
57 | * Get event name.
58 | * @return \lang_string|string
59 | * @throws \coding_exception
60 | */
61 | public static function get_name() {
62 | return get_string('log_rating_deleted', 'mod_ratingallocate');
63 | }
64 |
65 | /**
66 | * Get event description.
67 | * @return \lang_string|string|null
68 | * @throws \coding_exception
69 | */
70 | public function get_description() {
71 | return get_string('log_rating_deleted_description', 'mod_ratingallocate',
72 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
73 | }
74 |
75 | /**
76 | * Get event url.
77 | * @return \moodle_url
78 | * @throws \moodle_exception
79 | */
80 | public function get_url() {
81 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
82 | }
83 |
84 | /**
85 | * Get event mapping.
86 | * @return string[]
87 | */
88 | public static function get_objectid_mapping() {
89 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
90 | }
91 |
92 | /**
93 | * No other mappings available.
94 | * @return false
95 | */
96 | public static function get_other_mapping() {
97 | return false;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/classes/event/rating_saved.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate rating_saved event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate rating_saved event class.
29 | *
30 | * @property-read array $other {
31 | * Extra information about event.
32 | *
33 | * - array rating: new values of rating
34 | * }
35 | *
36 | * @since Moodle 2.7
37 | * @copyright 2014 Tobias Reischmann
38 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 | **/
40 | class rating_saved extends \core\event\base {
41 |
42 | /**
43 | * Create simple rating_saved event.
44 | * @param $modulecontext
45 | * @param $ratingallocateid
46 | * @param $rating
47 | * @return \core\event\base
48 | * @throws \coding_exception
49 | */
50 | public static function create_simple($modulecontext, $ratingallocateid, $rating) {
51 | // The values of other need to be encoded since the base checks for equality
52 | // of a decoded encoded other instance with the original
53 | // this is not given for nested arrays.
54 | $ratingjsonvalid = json_decode(json_encode($rating), true);
55 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid,
56 | 'other' => ['ratings' => $ratingjsonvalid]]);
57 | }
58 |
59 | /**
60 | * Initialize data.
61 | * @return void
62 | */
63 | protected function init() {
64 | $this->data['crud'] = 'u';
65 | $this->data['edulevel'] = self::LEVEL_PARTICIPATING;
66 | $this->data['objecttable'] = 'ratingallocate_ratings';
67 | }
68 |
69 | /**
70 | * Get event name.
71 | * @return \lang_string|string
72 | * @throws \coding_exception
73 | */
74 | public static function get_name() {
75 | return get_string('log_rating_saved', 'mod_ratingallocate');
76 | }
77 |
78 | /**
79 | * Get event description.
80 | * @return \lang_string|string|null
81 | * @throws \coding_exception
82 | */
83 | public function get_description() {
84 | return get_string('log_rating_saved_description', 'mod_ratingallocate',
85 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
86 | }
87 |
88 | /**
89 | * Get event url.
90 | * @return \moodle_url
91 | * @throws \moodle_exception
92 | */
93 | public function get_url() {
94 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
95 | }
96 |
97 | /**
98 | * Get event mapping.
99 | * @return string[]
100 | */
101 | public static function get_objectid_mapping() {
102 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
103 | }
104 |
105 | /**
106 | * No other mappings available.
107 | * @return false
108 | */
109 | public static function get_other_mapping() {
110 | return false;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/classes/event/rating_viewed.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate rating_viewed event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate rating_viewed event class.
29 | *
30 | * @since Moodle 2.7
31 | * @copyright 2014 Tobias Reischmann
32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 | **/
34 | class rating_viewed extends \core\event\base {
35 |
36 | /**
37 | * Create simple rating_viewed event.
38 | * @param $modulecontext
39 | * @param $ratingallocateid
40 | * @return \core\event\base
41 | * @throws \coding_exception
42 | */
43 | public static function create_simple($modulecontext, $ratingallocateid) {
44 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
45 | }
46 |
47 | /**
48 | * Initialize data.
49 | * @return void
50 | */
51 | protected function init() {
52 | $this->data['crud'] = 'r';
53 | $this->data['edulevel'] = self::LEVEL_PARTICIPATING;
54 | $this->data['objecttable'] = 'ratingallocate';
55 | }
56 |
57 | /**
58 | * Get event name.
59 | * @return \lang_string|string
60 | * @throws \coding_exception
61 | */
62 | public static function get_name() {
63 | return get_string('log_rating_viewed', 'mod_ratingallocate');
64 | }
65 |
66 | /**
67 | * Get event description.
68 | * @return \lang_string|string|null
69 | * @throws \coding_exception
70 | */
71 | public function get_description() {
72 | return get_string('log_rating_viewed_description', 'mod_ratingallocate',
73 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
74 | }
75 |
76 | /**
77 | * Get event url.
78 | * @return \moodle_url
79 | * @throws \moodle_exception
80 | */
81 | public function get_url() {
82 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
83 | }
84 |
85 | /**
86 | * Get event mapping.
87 | * @return string[]
88 | */
89 | public static function get_objectid_mapping() {
90 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
91 | }
92 |
93 | /**
94 | * No other mappings available.
95 | * @return false
96 | */
97 | public static function get_other_mapping() {
98 | return false;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/classes/event/ratingallocate_viewed.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate ratingallocate_viewed event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 | /**
28 | * The mod_ratingallocate ratingallocate_viewed event class.
29 | *
30 | * @since Moodle 2.7
31 | * @copyright 2014 Tobias Reischmann
32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 | **/
34 | class ratingallocate_viewed extends \core\event\base {
35 |
36 | /**
37 | * Create simple ratingallocate_viewed event.
38 | * @param $modulecontext
39 | * @param $ratingallocateid
40 | * @return \core\event\base
41 | * @throws \coding_exception
42 | */
43 | public static function create_simple($modulecontext, $ratingallocateid) {
44 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
45 | }
46 |
47 | /**
48 | * Initialize data.
49 | * @return void
50 | */
51 | protected function init() {
52 | $this->data['crud'] = 'r';
53 | $this->data['edulevel'] = self::LEVEL_TEACHING;
54 | $this->data['objecttable'] = 'ratingallocate';
55 | }
56 |
57 | /**
58 | * Get event name.
59 | * @return \lang_string|string
60 | * @throws \coding_exception
61 | */
62 | public static function get_name() {
63 | return get_string('log_ratingallocate_viewed', 'mod_ratingallocate');
64 | }
65 |
66 | /**
67 | * Get event description.
68 | * @return \lang_string|string|null
69 | * @throws \coding_exception
70 | */
71 | public function get_description() {
72 | return get_string('log_ratingallocate_viewed_description', 'mod_ratingallocate',
73 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
74 | }
75 |
76 | /**
77 | * Get event url.
78 | * @return \moodle_url
79 | * @throws \moodle_exception
80 | */
81 | public function get_url() {
82 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
83 | }
84 |
85 | /**
86 | * Get event mapping.
87 | * @return string[]
88 | */
89 | public static function get_objectid_mapping() {
90 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
91 | }
92 |
93 | /**
94 | * No other mappings available.
95 | * @return false
96 | */
97 | public static function get_other_mapping() {
98 | return false;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/classes/event/ratings_and_allocation_table_viewed.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * The mod_ratingallocate ratings_and_allocation_table_viewed event.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\event;
26 |
27 |
28 | /**
29 | * The mod_ratingallocate ratings_and_allocation_table_viewed event class.
30 | *
31 | * @since Moodle 2.7
32 | * @copyright 2014 Tobias Reischmann
33 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34 | **/
35 | class ratings_and_allocation_table_viewed extends \core\event\base {
36 |
37 | /**
38 | * Create simple ratings_and_allocation_table_viewed event.
39 | * @param $modulecontext
40 | * @param $ratingallocateid
41 | * @return \core\event\base
42 | * @throws \coding_exception
43 | */
44 | public static function create_simple($modulecontext, $ratingallocateid) {
45 | return self::create(['context' => $modulecontext, 'objectid' => $ratingallocateid]);
46 | }
47 |
48 | /**
49 | * Initialize data.
50 | * @return void
51 | */
52 | protected function init() {
53 | $this->data['crud'] = 'r';
54 | $this->data['edulevel'] = self::LEVEL_TEACHING;
55 | $this->data['objecttable'] = 'ratingallocate';
56 | }
57 |
58 | /**
59 | * Get event name.
60 | * @return \lang_string|string
61 | * @throws \coding_exception
62 | */
63 | public static function get_name() {
64 | return get_string('log_ratings_and_allocation_table_viewed', 'mod_ratingallocate');
65 | }
66 |
67 | /**
68 | * Get event description.
69 | * @return \lang_string|string|null
70 | * @throws \coding_exception
71 | */
72 | public function get_description() {
73 | return get_string('log_ratings_and_allocation_table_viewed_description', 'mod_ratingallocate',
74 | ['userid' => $this->userid, 'ratingallocateid' => $this->objectid]);
75 | }
76 |
77 | /**
78 | * Get event url.
79 | * @return \moodle_url
80 | * @throws \moodle_exception
81 | */
82 | public function get_url() {
83 | return new \moodle_url('/mod/ratingallocate/view.php', ['m' => $this->objectid]);
84 | }
85 |
86 | /**
87 | * Get event mapping.
88 | * @return string[]
89 | */
90 | public static function get_objectid_mapping() {
91 | return ['db' => 'ratingallocate', 'restore' => 'ratingallocate'];
92 | }
93 |
94 | /**
95 | * No other mappings available.
96 | * @return false
97 | */
98 | public static function get_other_mapping() {
99 | return false;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/classes/ratingallocate_observer.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Event observer for ratingallocate.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2023 I Hoppe
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate;
26 | use coding_exception;
27 | use dml_exception;
28 |
29 | /**
30 | * Ratingallocate observer.
31 | *
32 | * @package mod_ratingallocate
33 | */
34 | class ratingallocate_observer {
35 |
36 | /**
37 | * Triggered if group_deleted event is triggered.
38 | *
39 | * @param \core\event\group_deleted $event
40 | * @return void
41 | * @throws coding_exception
42 | * @throws dml_exception
43 | */
44 | public static function ch_gengroups_delete(\core\event\group_deleted $event) {
45 | global $DB;
46 |
47 | $eventdata = $event->get_record_snapshot('groups', $event->objectid);
48 | if ($DB->record_exists(
49 | 'ratingallocate_ch_gengroups',
50 | ['groupid' => $eventdata->id])) {
51 |
52 | // Delete the group from ratingallocate_ch_gengroups table.
53 | $DB->delete_records(
54 | 'ratingallocate_ch_gengroups',
55 | ['groupid' => $eventdata->id]
56 | );
57 | }
58 |
59 | }
60 |
61 | /**
62 | * Triggered if grouping_deleted event is triggered.
63 | *
64 | * @param \core\event\grouping_deleted $event
65 | * @return void
66 | * @throws coding_exception
67 | * @throws dml_exception
68 | */
69 | public static function ra_groupings_delete(\core\event\grouping_deleted $event) {
70 | global $DB;
71 |
72 | $eventdata = $event->get_record_snapshot('groupings', $event->objectid);
73 | if ($DB->record_exists(
74 | 'ratingallocate_groupings',
75 | ['groupingid' => $eventdata->id])) {
76 |
77 | // Delete the grouping from the ratingallocate_groupings table.
78 | $DB->delete_records(
79 | 'ratingallocate_groupings',
80 | ['groupingid' => $eventdata->id]
81 | );
82 |
83 | }
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/classes/task/cron_task.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | namespace mod_ratingallocate\task;
18 |
19 | use mod_ratingallocate\db as this_db;
20 |
21 | defined('MOODLE_INTERNAL') || die();
22 |
23 | require_once(__DIR__ . '/../../locallib.php');
24 |
25 | /**
26 | * A scheduled task for ratingallocate cron.
27 | *
28 | * @package mod_ratingallocate
29 | * @copyright 2015 Tobias Reischmann
30 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31 | */
32 | class cron_task extends \core\task\scheduled_task {
33 |
34 | /**
35 | * Get a descriptive name for this task (shown to admins).
36 | *
37 | * @return string
38 | */
39 | public function get_name() {
40 | return get_string('crontask', 'mod_ratingallocate');
41 | }
42 |
43 | /**
44 | * Run forum cron.
45 | */
46 | public function execute() {
47 | global $DB, $CFG;
48 |
49 | $currenttime = time();
50 | $statement = 'SELECT R.* FROM {ratingallocate} R
51 | LEFT JOIN {ratingallocate_allocations} A
52 | ON R.' . this_db\ratingallocate::ID . '=A.' . this_db\ratingallocate_allocations::RATINGALLOCATEID . '
53 | WHERE A.' . this_db\ratingallocate_allocations::ID . ' IS NULL AND R.' . this_db\ratingallocate::ACCESSTIMESTOP . '<' .
54 | $currenttime;
55 | $records = $DB->get_records_sql($statement);
56 | $course = null;
57 | foreach ($records as $record) {
58 | $cm = get_coursemodule_from_instance(this_db\ratingallocate::TABLE, $record->{this_db\ratingallocate::ID});
59 | // Fetch the data for the course, if is has changed.
60 | if (!$course || $course->id != $record->{this_db\ratingallocate::COURSE}) {
61 | $course = $DB->get_record('course', ['id' => $record->{this_db\ratingallocate::COURSE}], '*', MUST_EXIST);
62 | }
63 | // Create ratingallocate instance from record.
64 | $ratingallocate = new \ratingallocate($record, $course, $cm, \context_module::instance($cm->id));
65 | $currenttime = time();
66 | $timetoterminate = $CFG->ratingallocate_algorithm_timeout + $ratingallocate->ratingallocate->algorithmstarttime;
67 |
68 | // If last execution exeeds timeout limit assume failure of algorithm run.
69 | if ($ratingallocate->ratingallocate->algorithmstarttime &&
70 | $currenttime >= $timetoterminate &&
71 | $ratingallocate->get_algorithm_status() === \mod_ratingallocate\algorithm_status::RUNNING) {
72 | $ratingallocate->set_algorithm_failed();
73 | return true;
74 | }
75 |
76 | // Only start the algorithm, if it should be run by the cron and hasn't been started somehow, yet.
77 | if ($ratingallocate->ratingallocate->runalgorithmbycron === "1" &&
78 | $ratingallocate->get_algorithm_status() === \mod_ratingallocate\algorithm_status::NOTSTARTED) {
79 | // Clear eventually scheduled distribution of unallocated users.
80 | $ratingallocate->clear_distribute_unallocated_tasks();
81 | // Run allocation.
82 | $ratingallocate->distrubute_choices();
83 | }
84 | }
85 | return true;
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/classes/task/distribute_unallocated_task.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Task for distributing unallocated users in the background.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2023 ISB Bayern
22 | * @author Philipp Memmel
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | namespace mod_ratingallocate\task;
27 |
28 | use context_module;
29 | use core\task\adhoc_task;
30 | use moodle_exception;
31 | use ratingallocate;
32 |
33 | /**
34 | * Task for distributing unallocated users in the background.
35 | *
36 | * @copyright 2023 ISB Bayern
37 | * @author Philipp Memmel
38 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 | */
40 | class distribute_unallocated_task extends adhoc_task {
41 |
42 | /**
43 | * Executes the distribution of unallocated users.
44 | *
45 | * @throws moodle_exception
46 | */
47 | public function execute(): void {
48 | global $CFG, $DB;
49 | // Make sure to include the global definitions of constants defined in locallib.
50 | require_once($CFG->dirroot . '/mod/ratingallocate/locallib.php');
51 |
52 | $data = $this->get_custom_data();
53 | if (empty($data->distributionalgorithm) ||
54 | !in_array($data->distributionalgorithm, [ACTION_DISTRIBUTE_UNALLOCATED_EQUALLY, ACTION_DISTRIBUTE_UNALLOCATED_FILL])) {
55 | mtrace('No distribution algorithm has been specified, exiting.');
56 | return;
57 | }
58 | if (empty($data->courseid)) {
59 | mtrace('No course ID has been found, exiting.');
60 | return;
61 | }
62 | if (empty($data->cmid)) {
63 | mtrace('No course module ID has been found, exiting.');
64 | return;
65 | }
66 |
67 | $modinfo = get_fast_modinfo($data->courseid);
68 | $cm = $modinfo->get_cm($data->cmid);
69 | $course = $modinfo->get_course();
70 | $ratingallocatedb = $DB->get_record('ratingallocate', ['id' => $cm->instance]);
71 | if (empty($ratingallocatedb)) {
72 | mtrace('Could not find database record of ratingallocate instance for course module id ' . $cm->id
73 | . '. Nothing to do.');
74 | return;
75 | }
76 | $context = context_module::instance($cm->id);
77 | $ratingallocate = new ratingallocate($ratingallocatedb, $course, $cm, $context);
78 |
79 | mtrace('Distributing unallocated users for ratingallocate with course module id ' . $cm->id);
80 | $ratingallocate->distribute_users_without_choice($data->distributionalgorithm);
81 | mtrace('Distribution of unallocated users for ratingallocate instance with course module id ' . $cm->id . ' done.');
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/classes/task/send_distribution_notification.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Send distibution notification.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 M Schulze
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 |
25 | namespace mod_ratingallocate\task;
26 |
27 | defined('MOODLE_INTERNAL') || die();
28 |
29 | require_once(dirname(__FILE__) . '/../../db/db_structure.php');
30 |
31 | use mod_ratingallocate\db as this_db;
32 |
33 | /**
34 | * Send distribution notification
35 | *
36 | * @package mod_ratingallocate
37 | */
38 | class send_distribution_notification extends \core\task\adhoc_task {
39 |
40 | /**
41 | * Gets executed by the task runner. Will lookup the ratingallocation object and command it
42 | * to notify users.
43 | * @return void
44 | * @throws \coding_exception
45 | * @throws \dml_exception
46 | * @throws \moodle_exception
47 | */
48 | public function execute() {
49 | global $CFG, $DB;
50 |
51 | require_once($CFG->dirroot . '/mod/ratingallocate/locallib.php');
52 |
53 | $site = get_site();
54 | // Parse customdata passed.
55 | $customdata = $this->get_custom_data();
56 | $ratingallocateid = $customdata->ratingallocateid;
57 |
58 | // Get instance of ratingallocate.
59 | $ratingallocate =
60 | $DB->get_record(this_db\ratingallocate::TABLE, [this_db\ratingallocate::ID => $ratingallocateid], '*',
61 | MUST_EXIST);
62 |
63 | $courseid = $ratingallocate->course;
64 | $course = get_course($courseid);
65 | $cm = get_coursemodule_from_instance('ratingallocate', $ratingallocate->id, $courseid);
66 | $context = \context_module::instance($cm->id);
67 |
68 | $ratingallocateobj = new \ratingallocate($ratingallocate, $course, $cm, $context);
69 |
70 | $ratingallocateobj->notify_users_distribution();
71 |
72 | }
73 | }
74 |
75 |
--------------------------------------------------------------------------------
/db/access.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Capability definitions for the ratingallocate module
19 | *
20 | * The capabilities are loaded into the database table when the module is
21 | * installed or updated. Whenever the capability definitions are updated,
22 | * the module version number should be bumped up.
23 | *
24 | * The system has four possible values for a capability:
25 | * CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT, and inherit (not set).
26 | *
27 | * It is important that capability names are unique. The naming convention
28 | * for capabilities that are specific to modules and blocks is as follows:
29 | * [mod/block]/:
30 | *
31 | * component_name should be the same as the directory name of the mod or block.
32 | *
33 | * Core moodle capabilities are defined thus:
34 | * moodle/:
35 | *
36 | * Examples: mod/forum:viewpost
37 | * block/recent_activity:view
38 | * moodle/site:deleteuser
39 | *
40 | * The variable name for the capability definitions array is $capabilities
41 | *
42 | * @package mod_ratingallocate
43 | * @copyright 2014 M Schulze
44 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
45 | */
46 | defined('MOODLE_INTERNAL') || die();
47 |
48 | $capabilities = [
49 |
50 | 'mod/ratingallocate:addinstance' => [
51 | 'riskbitmask' => RISK_XSS | RISK_PERSONAL,
52 | 'contextlevel' => CONTEXT_COURSE,
53 | 'captype' => 'write',
54 | 'archetypes' => [
55 | 'editingteacher' => CAP_ALLOW,
56 | 'manager' => CAP_ALLOW,
57 | ],
58 | 'clonepermissionsfrom' => 'moodle/course:manageactivities',
59 | ],
60 | 'mod/ratingallocate:view' => [
61 | 'captype' => 'read',
62 | 'contextlevel' => CONTEXT_MODULE,
63 | 'legacy' => [
64 | 'guest' => CAP_ALLOW,
65 | 'student' => CAP_ALLOW,
66 | 'teacher' => CAP_ALLOW,
67 | 'editingteacher' => CAP_ALLOW,
68 | 'manager' => CAP_ALLOW,
69 | ],
70 | ],
71 | 'mod/ratingallocate:give_rating' => [
72 | 'contextlevel' => CONTEXT_MODULE,
73 | 'captype' => 'write',
74 | 'archetypes' => [
75 | 'student' => CAP_ALLOW,
76 | ],
77 | ],
78 | 'mod/ratingallocate:start_distribution' => [
79 | 'contextlevel' => CONTEXT_MODULE,
80 | 'riskbitmask' => RISK_PERSONAL,
81 | 'captype' => 'write',
82 | 'archetypes' => [
83 | 'editingteacher' => CAP_ALLOW,
84 | 'manager' => CAP_ALLOW,
85 | ],
86 | ],
87 | 'mod/ratingallocate:modify_choices' => [
88 | 'contextlevel' => CONTEXT_MODULE,
89 | 'captype' => 'write',
90 | 'archetypes' => [
91 | 'editingteacher' => CAP_ALLOW,
92 | 'manager' => CAP_ALLOW,
93 | ],
94 | ],
95 | 'mod/ratingallocate:export_ratings' => [
96 | 'contextlevel' => CONTEXT_MODULE,
97 | 'riskbitmask' => RISK_PERSONAL,
98 | 'captype' => 'read',
99 | 'archetypes' => [
100 | 'editingteacher' => CAP_ALLOW,
101 | 'manager' => CAP_ALLOW,
102 | ],
103 | ],
104 | 'mod/ratingallocate:distribute_unallocated' => [
105 | 'contextlevel' => CONTEXT_MODULE,
106 | 'riskbitmask' => RISK_PERSONAL,
107 | 'captype' => 'write',
108 | 'archetypes' => [
109 | 'editingteacher' => CAP_ALLOW,
110 | 'manager' => CAP_ALLOW,
111 | ],
112 | ],
113 | ];
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/db/db_structure.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Database structure of the table needed by the ratingallocate module
19 | * Grants easier acces to database fields
20 | *
21 | * @package mod_ratingallocate
22 | * @copyright 2014 T Reischmann, M Schulze
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | namespace mod_ratingallocate\db;
27 |
28 | defined('MOODLE_INTERNAL') || die();
29 |
30 | /**
31 | * Ratingallocate.
32 | *
33 | * @package mod_ratingallocate
34 | */
35 | class ratingallocate {
36 | /**
37 | * The ratingallocate table.
38 | */
39 | const TABLE = 'ratingallocate';
40 | /**
41 | * Ratingallocateid.
42 | */
43 | const ID = 'id';
44 | /**
45 | * The course.
46 | */
47 | const COURSE = 'course';
48 | /**
49 | * Name of the instance.
50 | */
51 | const NAME = 'name';
52 | /**
53 | * Intro.
54 | */
55 | const INTRO = 'intro';
56 | /**
57 | * The introformat.
58 | */
59 | const INTROFORMAT = 'introformat';
60 | /**
61 | * When the instance was created.
62 | */
63 | const TIMECREATED = 'timecreated';
64 | /**
65 | * Time it was modified.
66 | */
67 | const TIMEMODIFIED = 'timemodified';
68 | /**
69 | * Beginning voting.
70 | */
71 | const ACCESSTIMESTART = 'accesstimestart';
72 | /**
73 | * End of voting.
74 | */
75 | const ACCESSTIMESTOP = 'accesstimestop';
76 | /**
77 | * Setting.
78 | */
79 | const SETTING = 'setting';
80 | /**
81 | * The strategy used.
82 | */
83 | const STRATEGY = 'strategy';
84 | /**
85 | * Date to publish allocation.
86 | */
87 | const PUBLISHDATE = 'publishdate';
88 | /**
89 | * Wether its published.
90 | */
91 | const PUBLISHED = 'published';
92 | /**
93 | * Send notification to users.
94 | */
95 | const NOTIFICATIONSEND = 'notificationsend';
96 | /**
97 | * Strat time of algorithm.
98 | */
99 | const ALGORITHMSTARTTIME = 'algorithmstarttime';
100 | /**
101 | * Wether algorithm is run by cron task.
102 | */
103 | const RUNALGORITHMBYCRON = 'runalgorithmbycron';
104 | /**
105 | * Status of the most recent algorithm run.
106 | */
107 | const ALGORITHMSTATUS = 'algorithmstatus';
108 | }
109 |
110 | /**
111 | * Ratingallocate choices.
112 | *
113 | * @package mod_ratingallocate
114 | */
115 | class ratingallocate_choices {
116 | /**
117 | * Table.
118 | */
119 | const TABLE = 'ratingallocate_choices';
120 | /**
121 | * ID.
122 | */
123 | const ID = 'id';
124 | /**
125 | * Ratingallocateid.
126 | */
127 | const RATINGALLOCATEID = 'ratingallocateid';
128 | /**
129 | * Title of choice.
130 | */
131 | const TITLE = 'title';
132 | /**
133 | * Explanation.
134 | */
135 | const EXPLANATION = 'explanation';
136 | /**
137 | * Max number of users.
138 | */
139 | const MAXSIZE = 'maxsize';
140 | /**
141 | * If its active.
142 | */
143 | const ACTIVE = 'active';
144 | /**
145 | * Restrict visibility by groups.
146 | */
147 | const USEGROUPS = 'usegroups';
148 | }
149 |
150 | /**
151 | * Ratingallocate group choices.
152 | *
153 | * @package mod_ratingallocate
154 | */
155 | class ratingallocate_group_choices {
156 | /**
157 | * Table.
158 | */
159 | const TABLE = 'ratingallocate_group_choices';
160 | /**
161 | * Id.
162 | */
163 | const ID = 'id';
164 | /**
165 | * Choiceid.
166 | */
167 | const CHOICEID = 'choiceid';
168 | /**
169 | * Groupid.
170 | */
171 | const GROUPID = 'groupid';
172 | }
173 |
174 | /**
175 | * Ratingallocate generated groups of choices
176 | *
177 | * @package mod_ratingallocate
178 | */
179 | class ratingallocate_ch_gengroups {
180 | /**
181 | * Table.
182 | */
183 | const TABLE = 'ratingallocate_ch_gengroups';
184 | /**
185 | * Id.
186 | */
187 | const ID = 'id';
188 | /**
189 | * Groupid.
190 | */
191 | const GROUPID = 'groupid';
192 | /**
193 | * Choiceid.
194 | */
195 | const CHOICEID = 'choiceid';
196 | }
197 |
198 | /**
199 | * Ratingallocate groupings
200 | *
201 | * @package mod_ratingallocate
202 | */
203 | class ratingallocate_groupings {
204 | /**
205 | * Table.
206 | */
207 | const TABLE = 'ratingallocate_groupings';
208 | /**
209 | * Id.
210 | */
211 | const ID = 'id';
212 | /**
213 | * Ratingallocateid.
214 | */
215 | const RATINGALLOCATEID = 'ratingallocateid';
216 | /**
217 | * Groupingid.
218 | */
219 | const GROUPINGID = 'groupingid';
220 | }
221 |
222 | /**
223 | * Ratingallocate ratings
224 | *
225 | * @package mod_ratingallocate
226 | */
227 | class ratingallocate_ratings {
228 | /**
229 | * Table.
230 | */
231 | const TABLE = 'ratingallocate_ratings';
232 | /**
233 | * Id.
234 | */
235 | const ID = 'id';
236 | /**
237 | * The choiceid.
238 | */
239 | const CHOICEID = 'choiceid';
240 | /**
241 | * The userid.
242 | */
243 | const USERID = 'userid';
244 | /**
245 | * How the user rated the choice.
246 | */
247 | const RATING = 'rating';
248 | }
249 |
250 | /**
251 | * Ratingallocate allocations.
252 | *
253 | * @package mod_ratingallocate
254 | */
255 | class ratingallocate_allocations {
256 | /**
257 | * Table.
258 | */
259 | const TABLE = 'ratingallocate_allocations';
260 | /**
261 | * Id.
262 | */
263 | const ID = 'id';
264 | /**
265 | * Userid.
266 | */
267 | const USERID = 'userid';
268 | /**
269 | * Id of ratingallocate instance.
270 | */
271 | const RATINGALLOCATEID = 'ratingallocateid';
272 | /**
273 | * Choiceid.
274 | */
275 | const CHOICEID = 'choiceid';
276 | }
277 |
--------------------------------------------------------------------------------
/db/events.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Definition of ratingallocate event observers.
19 | *
20 | * The observers defined in this file are notified when respective events are triggered.
21 | *
22 | * @package mod_ratingallocate
23 | * @category event
24 | * @copyright 2023 I Hoppe
25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 | *
27 | */
28 |
29 | defined('MOODLE_INTERNAL') || die();
30 |
31 |
32 | $handlers = [];
33 |
34 | // List of observers for group_deleted and grouping_deleted.
35 |
36 | $observers = [
37 | [
38 | 'eventname' => '\core\event\group_deleted',
39 | 'callback' => 'mod_ratingallocate\ratingallocate_observer::ch_gengroups_delete',
40 | ],
41 | [
42 | 'eventname' => '\core\event\grouping_deleted',
43 | 'callback' => 'mod_ratingallocate\ratingallocate_observer::ra_groupings_delete',
44 | ],
45 | ];
46 |
--------------------------------------------------------------------------------
/db/install.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * This file replaces the legacy STATEMENTS section in db/install.xml,
19 | * lib.php/modulename_install() post installation hook and partially defaults.php
20 | *
21 | * @package mod_ratingallocate
22 | * @copyright 2014 M Schulze
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | /**
27 | * Post installation procedure
28 | *
29 | * @see upgrade_plugins_modules()
30 | */
31 | function xmldb_ratingallocate_install() {
32 | }
33 |
34 | /**
35 | * Post installation recovery procedure
36 | *
37 | * @see upgrade_plugins_modules()
38 | */
39 | function xmldb_ratingallocate_install_recovery() {
40 | }
41 |
--------------------------------------------------------------------------------
/db/log.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Definition of log events
19 | *
20 | * NOTE: this is an example how to insert log event during installation/update.
21 | * It is not really essential to know about it, but these logs were created as example
22 | * in the previous 1.9 NEWMODULE.
23 | *
24 | * @package mod_ratingallocate
25 | * @copyright 2014 M Schulze
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 | */
28 | defined('MOODLE_INTERNAL') || die();
29 |
30 | global $DB;
31 |
32 | $logs = [
33 | ['module' => 'ratingallocate', 'action' => 'add', 'mtable' => 'ratingallocate', 'field' => 'name'],
34 | ['module' => 'ratingallocate', 'action' => 'update', 'mtable' => 'ratingallocate', 'field' => 'name'],
35 | ['module' => 'ratingallocate', 'action' => 'view', 'mtable' => 'ratingallocate', 'field' => 'name'],
36 | ['module' => 'ratingallocate', 'action' => 'view all', 'mtable' => 'ratingallocate', 'field' => 'name'],
37 | ];
38 |
--------------------------------------------------------------------------------
/db/messages.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Definition of Ratingallocate messages.
19 | *
20 | * @package mod_ratingallocate
21 | * @category message
22 | * @copyright 2018 Tobias Reischmann
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | defined('MOODLE_INTERNAL') || die();
27 |
28 | $messageproviders = [
29 | // Notify student about published allocation.
30 | 'allocation' => [
31 | 'capability' => 'mod/ratingallocate:give_rating',
32 | ],
33 | ];
34 |
--------------------------------------------------------------------------------
/db/tasks.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Definition of Ratingallocate scheduled tasks.
19 | *
20 | * @package mod_ratingallocate
21 | * @category task
22 | * @copyright 2015 Tobias Reischmann
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | defined('MOODLE_INTERNAL') || die();
27 |
28 | $tasks = [
29 | [
30 | 'classname' => 'mod_ratingallocate\task\cron_task',
31 | 'blocking' => 0,
32 | 'minute' => '*',
33 | 'hour' => '*',
34 | 'day' => '*',
35 | 'month' => '*',
36 | 'dayofweek' => '*',
37 | 'faildelay' => 1,
38 | ],
39 | ];
40 |
--------------------------------------------------------------------------------
/db/uninstall.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Db uninstall.
19 | *
20 | * @see uninstall_plugin()
21 | *
22 | * @package mod_ratingallocate
23 | * @copyright 2014 M Schulze
24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 | */
26 |
27 | /**
28 | * Uninstall.
29 | *
30 | * @package mod_ratingallocate
31 | */
32 | function xmldb_ratingallocate_uninstall() {
33 | return true;
34 | }
35 |
--------------------------------------------------------------------------------
/form_upload_choices.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Bulk upload one or more choices for the ratingallocate instance via CSV file.
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2021 Catalyst IT
22 | * @author David Thompson
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 | defined('MOODLE_INTERNAL') || die();
26 | global $CFG;
27 | require_once($CFG->dirroot . '/course/moodleform_mod.php');
28 | require_once(dirname(__FILE__) . '/locallib.php');
29 |
30 | /**
31 | * A form to upload multiple choices
32 | */
33 | class upload_choices_form extends moodleform {
34 |
35 | /** @var $ratingallocate ratingallocate */
36 | private $ratingallocate;
37 |
38 | /**
39 | * Constructor
40 | * @param string $url
41 | * @param ratingallocate $ratingallocate
42 | */
43 | public function __construct($url, ratingallocate $ratingallocate) {
44 | $this->ratingallocate = $ratingallocate;
45 | parent::__construct($url);
46 | }
47 |
48 | /**
49 | * Defines forms elements
50 | */
51 | public function definition() {
52 | $mform = $this->_form;
53 |
54 | $requiredfields = \mod_ratingallocate\choice_importer::print_fields();
55 | $elementname = 'description';
56 | $mform->addElement('static', $elementname, get_string('upload_choices_required_fields', 'ratingallocate'),
57 | get_string('upload_choices_fields_desc', 'ratingallocate', $requiredfields));
58 |
59 | $elementname = 'uploadfile';
60 | $mform->addElement('filepicker', $elementname, get_string('csvupload', 'ratingallocate'), null,
61 | ['accepted_types' => 'text/csv']
62 | );
63 | $mform->addRule($elementname, get_string('err_required', 'form') , 'required', null, 'server');
64 |
65 | $elementname = 'testimport';
66 | $mform->addElement('advcheckbox', $elementname, get_string('csvupload_test_upload', 'ratingallocate'),
67 | null, null, [0, 1]);
68 | $mform->addHelpButton($elementname, 'csvupload_test_upload', 'ratingallocate');
69 |
70 | $this->add_buttons();
71 | }
72 |
73 | /**
74 | * Add button group.
75 | * @return void
76 | * @throws coding_exception
77 | */
78 | public function add_buttons() {
79 | $mform =& $this->_form;
80 |
81 | $buttonarray = [];
82 | $buttonarray[] = &$mform->createElement('submit', 'submitbutton', get_string('csvupload', 'ratingallocate'));
83 | $buttonarray[] = &$mform->createElement('cancel');
84 | $mform->addGroup($buttonarray, 'buttonar', '', [' '], false);
85 | $mform->closeHeaderBefore('buttonar');
86 | }
87 |
88 |
89 | /**
90 | * Returns the forms HTML code.
91 | * So we don't have to call display().
92 | */
93 | public function to_html() {
94 | $o = '';
95 | $o .= $this->_form->getValidationScript();
96 | $o .= $this->_form->toHtml();
97 | return $o;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/grade.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Redirect the user to the appropriate submission related page
19 | *
20 | * @package mod_ratingallocate
21 | * @category grade
22 | * @copyright 2014 C Usener
23 | * @copyright based on code by M Schulze copyright (C) 2014 M Schulze
24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 | */
26 |
27 | require_once(__DIR__ . "/../../config.php");
28 | require_login();
29 |
30 | $id = required_param('id', PARAM_INT); // Course module ID.
31 | $itemnumber = optional_param('itemnumber', 0,
32 | PARAM_INT); // Item number, may be != 0 for activities that allow more than one grade per user.
33 | $userid = optional_param('userid', 0, PARAM_INT); // Graded user ID (optional).
34 |
35 | // In the simplest case just redirect to the view page.
36 | redirect('view.php?id=' . $id);
37 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * This is a one-line short description of the file
19 | *
20 | * You can have a rather longer description of the file as well,
21 | * if you like, and it can span multiple lines.
22 | *
23 | * @package mod_ratingallocate
24 | * @copyright 2014 M Schulze, C Usener
25 | * @copyright based on code by Stefan Koegel copyright (C) 2013 Stefan Koegel
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 | */
28 |
29 | require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
30 | require_once(dirname(__FILE__) . '/lib.php');
31 | require_once(dirname(__FILE__) . '/locallib.php');
32 |
33 | $id = required_param('id', PARAM_INT); // Courseid.
34 |
35 | $course = get_course($id);
36 |
37 | require_course_login($course);
38 |
39 | $coursecontext = context_course::instance($course->id);
40 |
41 | $PAGE->set_pagelayout('incourse');
42 | $PAGE->set_url('/mod/ratingallocate/index.php', ['id' => $id]);
43 | $PAGE->set_title(format_string($course->fullname));
44 | $PAGE->set_heading(format_string($course->fullname));
45 | $PAGE->set_context($coursecontext);
46 |
47 | echo $OUTPUT->header();
48 | echo $OUTPUT->heading(get_string('modulenameplural', RATINGALLOCATE_MOD_NAME), 2);
49 |
50 | require_capability('mod/ratingallocate:view', $coursecontext);
51 |
52 | $event = \mod_ratingallocate\event\index_viewed::create_simple(
53 | context_course::instance($course->id));
54 | $event->trigger();
55 |
56 | if (!$ratingallocates = get_all_instances_in_course('ratingallocate', $course, $USER->id)) {
57 | notice(get_string('noratingallocates', RATINGALLOCATE_MOD_NAME),
58 | new moodle_url('/course/view.php', ['id' => $course->id]));
59 | }
60 |
61 | $table = new html_table();
62 | $table->head = [
63 | get_string('name'),
64 | get_string('rating_begintime', 'mod_ratingallocate'),
65 | get_string('rating_endtime', 'mod_ratingallocate'),
66 | get_string('is_published', 'mod_ratingallocate')];
67 | $table->align = ['left', 'left', 'left', 'left'];
68 |
69 | foreach ($ratingallocates as $ratingallocate) {
70 | $ratingallocateinstance = $DB->get_record('ratingallocate', ['id' => $ratingallocate->id]);
71 | if (!$ratingallocate->visible) {
72 | $link = html_writer::link(
73 | new moodle_url('/mod/ratingallocate/view.php', ['id' => $ratingallocate->coursemodule]),
74 | format_string($ratingallocate->name, true),
75 | ['class' => 'dimmed']);
76 | } else {
77 | $link = html_writer::link(
78 | new moodle_url('/mod/ratingallocate/view.php', ['id' => $ratingallocate->coursemodule]),
79 | format_string($ratingallocate->name, true));
80 | }
81 | $table->data[] = [$link, userdate($ratingallocateinstance->accesstimestart),
82 | userdate($ratingallocateinstance->accesstimestop),
83 | $ratingallocateinstance->published == 0 ? get_string('no') : get_string('yes')];
84 |
85 | }
86 |
87 | echo html_writer::table($table);
88 | echo $OUTPUT->footer();
89 |
--------------------------------------------------------------------------------
/pix/checkbox-selected.svg:
--------------------------------------------------------------------------------
1 |
2 |
44 |
--------------------------------------------------------------------------------
/pix/checkbox.svg:
--------------------------------------------------------------------------------
1 |
2 |
44 |
--------------------------------------------------------------------------------
/pix/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learnweb/moodle-mod_ratingallocate/3798407ec44256f717ac72ec1a4dedf92e6a00e9/pix/icon.png
--------------------------------------------------------------------------------
/pix/monologo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/renderable.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * This file contains the definition for the renderable classes for the ratingallocate module
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 C Usener, T Reischmann
22 | * @copyright based on code by M Schulze copyright (C) 2014 M Schulze
23 | *
24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 | *
26 | */
27 | defined('MOODLE_INTERNAL') || die();
28 |
29 | /**
30 | * Renderable header
31 | * @package mod_ratingallocate
32 | */
33 | class ratingallocate_header implements renderable {
34 | /** @var ratingallocate_db_wrapper the ratingallocate class */
35 | public $ratingallocate = null;
36 | /** @var mixed context|null the context record */
37 | public $context = null;
38 | /** @var bool $showintro - show or hide the intro */
39 | public $showintro = false;
40 | /** @var int coursemoduleid - The course module id */
41 | public $coursemoduleid = 0;
42 |
43 | /**
44 | * Construct.
45 | *
46 | * @param ratingallocate_db_wrapper $ratingallocate
47 | * @param $context
48 | * @param $showintro
49 | * @param $coursemoduleid
50 | */
51 | public function __construct(ratingallocate_db_wrapper $ratingallocate, $context, $showintro, $coursemoduleid) {
52 | $this->ratingallocate = $ratingallocate;
53 | $this->context = $context;
54 | $this->showintro = $showintro;
55 | $this->coursemoduleid = $coursemoduleid;
56 | }
57 | }
58 |
59 | /**
60 | * Choice status
61 | *
62 | * @package mod_ratingallocate
63 | */
64 | class ratingallocate_choice_status implements renderable {
65 |
66 | /** @var $accesstimestop */
67 | public $accesstimestop;
68 | /** @var $accesstimestart */
69 | public $accesstimestart;
70 | /** @var $ispublished */
71 | public $ispublished;
72 | /** @var $publishdate */
73 | public $publishdate;
74 | /** @var $availablechoices */
75 | public $availablechoices;
76 | /** @var $necessarychoices */
77 | public $necessarychoices;
78 | /** @var $ownchoices */
79 | public $ownchoices;
80 | /** @var $allocations */
81 | public $allocations;
82 | /** @var $strategy */
83 | public $strategy;
84 | /** @var bool show_distribution_info specifies if the info regarding the distribution should be displayed. * */
85 | public $showdistributioninfo;
86 | /** @var bool show_user_info specifies if the current ratings of the user shoulld be renderer. * */
87 | public $showuserinfo;
88 | /** @var $algorithmstarttime */
89 | public $algorithmstarttime;
90 | /** @var $algorithmstatus */
91 | public $algorithmstatus;
92 | }
93 |
--------------------------------------------------------------------------------
/settings.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Admin settings for mod_ratingallocate
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2015 Tobias Reischmann
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 | */
24 | defined('MOODLE_INTERNAL') || die;
25 |
26 | if ($ADMIN->fulltree) {
27 | $settings->add(new admin_setting_configtext('ratingallocate_algorithm_timeout',
28 | get_string('algorithmtimeout', 'ratingallocate'),
29 | get_string('configalgorithmtimeout', 'ratingallocate'), 600, PARAM_INT));
30 |
31 | $settings->add(new admin_setting_configmulticheckbox('ratingallocate_download_userfields',
32 | new lang_string('downloaduserfields', 'ratingallocate'),
33 | new lang_string('configdownloaduserfields', 'ratingallocate'),
34 | [
35 | 'id' => 1,
36 | 'username' => 1,
37 | 'department' => 0,
38 | 'institution' => 0,
39 | 'email' => 1,
40 | ],
41 | [
42 | 'id' => new lang_string('userid', 'ratingallocate'),
43 | 'username' => new lang_string('username'),
44 | 'idnumber' => new lang_string('idnumber'),
45 | 'department' => new lang_string('department'),
46 | 'institution' => new lang_string('institution'),
47 | 'email' => new lang_string('email'),
48 | ]));
49 |
50 | $settings->add(new admin_setting_configcheckbox('ratingallocate_algorithm_force_background_execution',
51 | new lang_string('algorithmforcebackground', 'ratingallocate'),
52 | new lang_string('configalgorithmforcebackground', 'ratingallocate'), 0));
53 | }
54 |
--------------------------------------------------------------------------------
/solver/edmonds-karp.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | *
19 | * Contains the algorithm for the distribution
20 | *
21 | * @package mod_ratingallocate
22 | * @subpackage mod_ratingallocate
23 | * @copyright 2014 M Schulze
24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 | */
26 | defined('MOODLE_INTERNAL') || die();
27 |
28 | require_once(dirname(__FILE__) . '/../locallib.php');
29 | require_once(dirname(__FILE__) . '/solver-template.php');
30 |
31 | /**
32 | * Solver edmonds-karp.
33 | *
34 | * @package mod_ratingallocate
35 | */
36 | class solver_edmonds_karp extends distributor {
37 |
38 | /**
39 | * Return name.
40 | *
41 | * @return string
42 | */
43 | public function get_name() {
44 | return 'edmonds_karp';
45 | }
46 |
47 | /**
48 | * Compute distribution.
49 | *
50 | * @param $choicerecords
51 | * @param $ratings
52 | * @param $usercount
53 | * @return an|array
54 | * @throws moodle_exception
55 | */
56 | public function compute_distribution($choicerecords, $ratings, $usercount) {
57 | $choicedata = [];
58 | foreach ($choicerecords as $record) {
59 | $choicedata[$record->id] = $record;
60 | }
61 |
62 | $choicecount = count($choicedata);
63 | // Index of source and sink in the graph.
64 | $source = 0;
65 | $sink = $choicecount + $usercount + 1;
66 |
67 | list($fromuserid, $touserid, $fromchoiceid, $tochoiceid) = $this->setup_id_conversions($usercount, $ratings);
68 |
69 | $this->setup_graph($choicecount, $usercount, $fromuserid, $fromchoiceid, $ratings, $choicedata, $source, $sink, -1);
70 |
71 | // Now that the datastructure is complete, we can start the algorithm
72 | // This is an adaptation of the Ford-Fulkerson algorithm
73 | // with Bellman-Ford as search function (see: Edmonds-Karp in Introduction to Algorithms)
74 | // http://stackoverflow.com/questions/6681075/while-loop-in-php-with-assignment-operator
75 | // Look for an augmenting path (a shortest path from the source to the sink).
76 | while ($path = $this->find_shortest_path_bellf($source, $sink)) { // If the function returns null, the while will stop.
77 | // Reverse the augmentin path, thereby distributing a user into a group.
78 | $this->augment_flow($path);
79 | unset($path); // Clear up old path.
80 | }
81 | return $this->extract_allocation($touserid, $tochoiceid);
82 | }
83 |
84 | /**
85 | * Bellman-Ford acc. to Cormen
86 | *
87 | * @param $from index of starting node
88 | * @param $to index of end node
89 | * @return array with the of the nodes in the path
90 | */
91 | private function find_shortest_path_bellf($from, $to) {
92 | // Table of distances known so far.
93 | $dists = [];
94 | // Table of predecessors (used to reconstruct the shortest path later).
95 | $preds = [];
96 |
97 | // Number of nodes in the graph.
98 | $count = $this->graph['count'];
99 |
100 | // Step 1: initialize graph.
101 | for ($i = 0; $i < $count; $i++) { // For each vertex v in vertices.
102 | if ($i == $from) {// If v is source then weight[v] := 0.
103 | $dists[$i] = 0;
104 | } else {// Else set weight[v] to infinity.
105 | $dists[$i] = INF;
106 | }
107 | $preds[$i] = null; // Set predecessor[v] to null.
108 | }
109 |
110 | // Step 2: relax edges repeatedly.
111 | for ($i = 0; $i < $count; $i++) { // For i from 1 to size(vertices)-1:.
112 | $updatedsomething = false;
113 | foreach ($this->graph as $key => $edges) { // For each edge (u, v) with weight w in edges:.
114 | if (is_array($edges)) {
115 | foreach ($edges as $key2 => $edge) {
116 | if ($dists[$edge->from] + $edge->weight < $dists[$edge->to]) { // If weight[u] + w < weight[v]:.
117 | $dists[$edge->to] = $dists[$edge->from] + $edge->weight; // Set weight[v] := weight[u] + w.
118 | $preds[$edge->to] = $edge->from; // Set predecessor[v] := u.
119 | $updatedsomething = true;
120 | }
121 | }
122 | }
123 | }
124 | if (!$updatedsomething) {
125 | break; // Leave.
126 | }
127 | }
128 |
129 | // If there is no path to $to, return null.
130 | if (is_null($preds[$to])) {
131 | return null;
132 | }
133 |
134 | // Cleanup dists to save some space.
135 | unset($dists);
136 |
137 | // Use the preds table to reconstruct the shortest path.
138 | $path = [];
139 | $p = $to;
140 | while ($p != $from) {
141 | $path[] = $p;
142 | $p = $preds[$p];
143 | }
144 | $path[] = $from;
145 | return $path;
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/solver/ford-fulkerson-koegel.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Internal library of functions for module groupdistribution.
19 | *
20 | * Contains the algorithm for the group distribution
21 | *
22 | * @package mod_ratingallocate
23 | * @subpackage mod_ratingallocate originally mod_groupdistribution
24 | * @copyright 2014 M Schulze
25 | * @copyright based on code by Stefan Koegel copyright (C) 2013 Stefan Koegel
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 | */
28 | defined('MOODLE_INTERNAL') || die();
29 |
30 | require_once(dirname(__FILE__) . '/../locallib.php');
31 | require_once(dirname(__FILE__) . '/solver-template.php');
32 |
33 | /**
34 | * Solver Ford-fulkerson.
35 | *
36 | * @package mod_ratingallocate
37 | */
38 | class solver_ford_fulkerson extends distributor {
39 |
40 | /**
41 | * Starts the distribution algorithm.
42 | * Uses the users' ratings and a minimum-cost maximum-flow algorithm
43 | * to distribute the users fairly into the groups.
44 | * (see http://en.wikipedia.org/wiki/Minimum-cost_flow_problem)
45 | * After the algorithm is done, users are removed from their current
46 | * groups (see clear_all_groups_in_course()) and redistributed
47 | * according to the computed distriution.
48 | *
49 | */
50 | public function compute_distribution($choicerecords, $ratings, $usercount) {
51 | $groupdata = [];
52 | foreach ($choicerecords as $record) {
53 | $groupdata[$record->id] = $record;
54 | }
55 |
56 | $groupcount = count($groupdata);
57 | // Index of source and sink in the graph.
58 | $source = 0;
59 | $sink = $groupcount + $usercount + 1;
60 | list($fromuserid, $touserid, $fromgroupid, $togroupid) = $this->setup_id_conversions($usercount, $ratings);
61 |
62 | $this->setup_graph($groupcount, $usercount, $fromuserid, $fromgroupid, $ratings, $groupdata, $source, $sink);
63 |
64 | // Now that the datastructure is complete, we can start the algorithm
65 | // This is an adaptation of the Ford-Fulkerson algorithm
66 | // (http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm).
67 | for ($i = 1; $i <= $usercount; $i++) {
68 | // Look for an augmenting path (a shortest path from the source to the sink).
69 | $path = $this->find_shortest_path_bellmanf_koegel($source, $sink);
70 | // If there is no such path, it is impossible to fit any more users into groups.
71 | if (is_null($path)) {
72 | // Stop the algorithm.
73 | continue;
74 | }
75 | // Reverse the augmenting path, thereby distributing a user into a group.
76 | $this->augment_flow($path);
77 | }
78 |
79 | return $this->extract_allocation($touserid, $togroupid);
80 | }
81 |
82 | /**
83 | * Uses a modified Bellman-Ford algorithm to find a shortest path
84 | * from $from to $to in $graph. We can't use Dijkstra here, because
85 | * the graph contains edges with negative weight.
86 | *
87 | * @param $from index of starting node
88 | * @param $to index of end node
89 | * @return array with the of the nodes in the path
90 | * @throws moodle_exception
91 | */
92 | public function find_shortest_path_bellmanf_koegel($from, $to) {
93 |
94 | // Table of distances known so far.
95 | $dists = [];
96 | // Table of predecessors (used to reconstruct the shortest path later).
97 | $preds = [];
98 | // Stack of the edges we need to test next.
99 | $edges = $this->graph[$from];
100 | // Number of nodes in the graph.
101 | $count = $this->graph['count'];
102 |
103 | // To prevent the algorithm from getting stuck in a loop with
104 | // with negative weight, we stop it after $count ^ 3 iterations.
105 | $counter = 0;
106 | $limit = $count * $count * $count;
107 |
108 | // Initialize dists and preds.
109 | for ($i = 0; $i < $count; $i++) {
110 | if ($i == $from) {
111 | $dists[$i] = 0;
112 | } else {
113 | $dists[$i] = -INF;
114 | }
115 | $preds[$i] = null;
116 | }
117 |
118 | while (!empty($edges) && $counter < $limit) {
119 | $counter++;
120 |
121 | /* @var e edge */
122 | $e = array_pop($edges);
123 |
124 | $f = $e->from;
125 | $t = $e->to;
126 | $dist = $e->weight + $dists[$f];
127 |
128 | // If this edge improves a distance update the tables and the edges stack.
129 | if ($dist > $dists[$t]) {
130 | $dists[$t] = $dist;
131 | $preds[$t] = $f;
132 | foreach ($this->graph[$t] as $newedge) {
133 | $edges[] = $newedge;
134 | }
135 | }
136 | }
137 |
138 | // A valid groupdistribution graph can't contain a negative edge.
139 | if ($counter == $limit) {
140 | throw new \moodle_exception('negative_cycle', 'ratingallocate');
141 | }
142 |
143 | // If there is no path to $to, return null.
144 | if (is_null($preds[$to])) {
145 | return null;
146 | }
147 |
148 | // Use the preds table to reconstruct the shortest path.
149 | $path = [];
150 | $p = $to;
151 | while ($p != $from) {
152 | $path[] = $p;
153 | $p = $preds[$p];
154 | }
155 | $path[] = $from;
156 |
157 | return $path;
158 | }
159 |
160 | /**
161 | * Return name.
162 | *
163 | * @return string
164 | */
165 | public function get_name() {
166 | return "ford-fulkerson Koegel2014";
167 | }
168 |
169 | }
170 |
--------------------------------------------------------------------------------
/strategy/strategy01_yes_no.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Internal library of functions for module ratingallocate
19 | *
20 | * All the ratingallocate specific functions, needed to implement the module
21 | * logic, should go here. Never include this file from your lib.php!
22 | *
23 | * @package mod_ratingallocate
24 | * @copyright 2014 T Reischmann, C Usener
25 | * @copyright based on code by M Schulze copyright (C) 2014 M Schulze
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 | */
28 |
29 | namespace mod_ratingallocate\strategy_yesno;
30 |
31 | defined('MOODLE_INTERNAL') || die();
32 | require_once($CFG->libdir . '/formslib.php');
33 | require_once(dirname(__FILE__) . '/../locallib.php');
34 | require_once(dirname(__FILE__) . '/strategy_template_options.php');
35 |
36 | /**
37 | * Strategy
38 | *
39 | * @package mod_ratingallocate
40 | */
41 | class strategy extends \strategytemplate_options {
42 |
43 | /**
44 | * Strategyid.
45 | */
46 | const STRATEGYID = 'strategy_yesno';
47 | /**
48 | * Maximum to deny.
49 | */
50 | const MAXCROSSOUT = 'maxcrossout';
51 |
52 | /**
53 | * Get strategy id.
54 | * @return string
55 | */
56 | public function get_strategyid() {
57 | return self::STRATEGYID;
58 | }
59 |
60 | /**
61 | * Get static settingfields.
62 | * @return array|array[]
63 | * @throws \coding_exception
64 | */
65 | public function get_static_settingfields() {
66 | $output = [
67 | self::MAXCROSSOUT => [
68 | 'int',
69 | get_string(self::STRATEGYID . '_setting_crossout', RATINGALLOCATE_MOD_NAME),
70 | $this->get_settings_value(self::MAXCROSSOUT),
71 | null,
72 | ],
73 | ];
74 | foreach (array_keys($this->get_choiceoptions()) as $id) {
75 | $output[$id] = [
76 | 'text',
77 | get_string('strategy_settings_label', RATINGALLOCATE_MOD_NAME, $this->get_settings_default_value($id)),
78 | null,
79 | $this->get_settings_default_value($id),
80 | ];
81 | }
82 | $output += $this->get_default_strategy_option();
83 | return $output;
84 | }
85 |
86 | /**
87 | * Get dynamic settingfields.
88 | * @return array
89 | */
90 | public function get_dynamic_settingfields() {
91 | return [];
92 | }
93 |
94 | /**
95 | * Get choice options.
96 | * @return array
97 | */
98 | public function get_choiceoptions() {
99 | $options = [
100 | 0 => $this->get_settings_value(0),
101 | 1 => $this->get_settings_value(1),
102 | ];
103 | return $options;
104 | }
105 |
106 | /**
107 | * Get default settings.
108 | * @return array
109 | * @throws \coding_exception
110 | */
111 | public function get_default_settings() {
112 | return [
113 | self::MAXCROSSOUT => 3,
114 | 0 => get_string(self::STRATEGYID . '_rating_crossout', RATINGALLOCATE_MOD_NAME),
115 | 1 => get_string(self::STRATEGYID . '_rating_choose', RATINGALLOCATE_MOD_NAME),
116 | 'default' => 1,
117 | ];
118 | }
119 |
120 | /**
121 | * Get validation information.
122 | * @return array[]
123 | */
124 | protected function getvalidationinfo() {
125 | return [self::MAXCROSSOUT => [true, 0]];
126 | }
127 | }
128 |
129 | // Register with the strategymanager.
130 | \strategymanager::add_strategy(strategy::STRATEGYID);
131 |
132 | /**
133 | * View form
134 | *
135 | * @package mod_ratingallocate
136 | */
137 | class mod_ratingallocate_view_form extends \ratingallocate_options_strategyform {
138 | // Already specified by parent class.
139 |
140 | /**
141 | * Create new strategy.
142 | * @param $strategyoptions
143 | * @return strategy
144 | */
145 | protected function construct_strategy($strategyoptions) {
146 | return new strategy($strategyoptions);
147 | }
148 |
149 | /**
150 | * Get choice options.
151 | * @return mixed
152 | */
153 | public function get_choiceoptions() {
154 | return $this->get_strategy()->get_choiceoptions();
155 | }
156 |
157 | /**
158 | * Get maximal amount how many times a user is allowed to rate a choice with "NO".
159 | * @return mixed|\the|null
160 | */
161 | protected function get_max_amount_of_nos() {
162 | return $this->get_strategysetting(strategy::MAXCROSSOUT);
163 | }
164 |
165 | /**
166 | * Get string identifier of max_nos.
167 | * @return string
168 | */
169 | protected function get_max_nos_string_identyfier() {
170 | return strategy::STRATEGYID . '_max_no';
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/strategy/strategy02_yes_maybe_no.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Internal library of functions for module ratingallocate
19 | *
20 | * All the ratingallocate specific functions, needed to implement the module
21 | * logic, should go here. Never include this file from your lib.php!
22 | *
23 | * @package mod_ratingallocate
24 | * @copyright 2014 T Reischmann, C Usener
25 | * @copyright based on code by M Schulze copyright (C) 2014 M Schulze
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 | */
28 |
29 | // Namespace is mandatory!
30 | namespace mod_ratingallocate\strategy_yesmaybeno;
31 |
32 | defined('MOODLE_INTERNAL') || die();
33 | require_once($CFG->libdir . '/formslib.php');
34 | require_once(dirname(__FILE__) . '/../locallib.php');
35 | require_once(dirname(__FILE__) . '/strategy_template_options.php');
36 |
37 | /**
38 | * Strategy.
39 | *
40 | * @package mod_ratingallocate
41 | */
42 | class strategy extends \strategytemplate_options {
43 |
44 | /**
45 | * Strategyid.
46 | */
47 | const STRATEGYID = 'strategy_yesmaybeno';
48 | /**
49 | * Maximal votes for no.
50 | */
51 | const MAXNO = 'maxno';
52 |
53 | /**
54 | * Get strategy id.
55 | * @return string
56 | */
57 | public function get_strategyid() {
58 | return self::STRATEGYID;
59 | }
60 |
61 | /**
62 | * Get static settingfields of strategy.
63 | * @return array|array[]
64 | * @throws \coding_exception
65 | */
66 | public function get_static_settingfields() {
67 | $output = [
68 | self::MAXNO => [// Maximum count of 'No'.
69 | 'int',
70 | get_string(self::STRATEGYID . '_setting_maxno', RATINGALLOCATE_MOD_NAME),
71 | $this->get_settings_value(self::MAXNO),
72 | null,
73 | ],
74 | ];
75 | foreach (array_keys($this->get_choiceoptions()) as $id) {
76 | $output[$id] = [
77 | 'text',
78 | get_string('strategy_settings_label', RATINGALLOCATE_MOD_NAME, $this->get_settings_default_value($id)),
79 | null,
80 | $this->get_settings_default_value($id),
81 | ];
82 | }
83 | $output += $this->get_default_strategy_option();
84 | return $output;
85 | }
86 |
87 | /**
88 | * Get dynamic settingfields.
89 | *
90 | * @return array
91 | */
92 | public function get_dynamic_settingfields() {
93 | return [];
94 | }
95 |
96 | /**
97 | * Get choiceoptions.
98 | *
99 | * @return array
100 | */
101 | public function get_choiceoptions() {
102 | $options = [
103 | 0 => $this->get_settings_value(0),
104 | 3 => $this->get_settings_value(3),
105 | 5 => $this->get_settings_value(5),
106 | ];
107 | return $options;
108 | }
109 |
110 | /**
111 | * Get default settings.
112 | *
113 | * @return array
114 | * @throws \coding_exception
115 | */
116 | public function get_default_settings() {
117 | return [
118 | self::MAXNO => 3,
119 | 0 => get_string(self::STRATEGYID . '_rating_no', RATINGALLOCATE_MOD_NAME),
120 | 3 => get_string(self::STRATEGYID . '_rating_maybe', RATINGALLOCATE_MOD_NAME),
121 | 5 => get_string(self::STRATEGYID . '_rating_yes', RATINGALLOCATE_MOD_NAME),
122 | 'default' => 3,
123 | ];
124 | }
125 |
126 | /**
127 | * Get validation info.
128 | *
129 | * @return array[]
130 | */
131 | protected function getvalidationinfo() {
132 | return [self::MAXNO => [true, 0]];
133 | }
134 | }
135 |
136 | // Register with the strategymanager.
137 | \strategymanager::add_strategy(strategy::STRATEGYID);
138 |
139 | /**
140 | * View form.
141 | *
142 | * @package mod_ratingallocate
143 | */
144 | class mod_ratingallocate_view_form extends \ratingallocate_options_strategyform {
145 | // Already specified by parent class.
146 |
147 | /**
148 | * Create new strategy.
149 | * @param $strategyoptions
150 | * @return strategy
151 | */
152 | protected function construct_strategy($strategyoptions) {
153 | return new strategy($strategyoptions);
154 | }
155 |
156 | /**
157 | * Get all choice options.
158 | * @return mixed
159 | */
160 | public function get_choiceoptions() {
161 | return $this->get_strategy()->get_choiceoptions();
162 | }
163 |
164 | /**
165 | * Get maximal amount how many times a user is allowed to rate a choice with "NO".
166 | * @return \the|null
167 | */
168 | protected function get_max_amount_of_nos() {
169 | return $this->get_strategysetting(strategy::MAXNO);
170 | }
171 |
172 | /**
173 | * Get string identifier of max_nos.
174 | * @return string
175 | */
176 | protected function get_max_nos_string_identyfier() {
177 | return strategy::STRATEGYID . '_max_no';
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/strategy/strategy03_lickert.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Internal library of functions for module ratingallocate
19 | *
20 | * All the ratingallocate specific functions, needed to implement the module
21 | * logic, should go here. Never include this file from your lib.php!
22 | *
23 | * @package mod_ratingallocate
24 | * @copyright 2014 M Schulze
25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 | */
27 |
28 | // Namespace is mandatory!
29 | namespace mod_ratingallocate\strategy_lickert;
30 |
31 | defined('MOODLE_INTERNAL') || die();
32 | require_once($CFG->libdir . '/formslib.php');
33 | require_once(dirname(__FILE__) . '/../locallib.php');
34 | require_once(dirname(__FILE__) . '/strategy_template_options.php');
35 |
36 | /**
37 | * Strategy
38 | *
39 | * @package mod_ratingallocate
40 | */
41 | class strategy extends \strategytemplate_options {
42 |
43 | /**
44 | * Strategyid.
45 | */
46 | const STRATEGYID = 'strategy_lickert';
47 | /**
48 | * Max NO.
49 | */
50 | const MAXNO = 'maxno';
51 | /**
52 | * Countlickert.
53 | */
54 | const COUNTLICKERT = 'countlickert';
55 | /** @var mixed $maxlickert */
56 | private $maxlickert;
57 |
58 | /**
59 | * Constructor.
60 | * @param array|null $strategysettings
61 | * @throws \coding_exception
62 | */
63 | public function __construct(?array $strategysettings = null) {
64 | parent::__construct($strategysettings);
65 | if (isset($strategysettings) && array_key_exists(self::COUNTLICKERT, $strategysettings)) {
66 | $this->maxlickert = $strategysettings[self::COUNTLICKERT];
67 | } else {
68 | $this->maxlickert = $this->get_default_settings()[self::COUNTLICKERT];
69 | }
70 | }
71 |
72 | /**
73 | * Get strategy id.
74 | * @return string
75 | */
76 | public function get_strategyid() {
77 | return self::STRATEGYID;
78 | }
79 |
80 | /**
81 | * Get static settingfields of strategy.
82 | * @return array[]
83 | * @throws \coding_exception
84 | */
85 | public function get_static_settingfields() {
86 | return [
87 | self::MAXNO => [// Maximum count of 'No'.
88 | 'int',
89 | get_string(self::STRATEGYID . '_setting_maxno', RATINGALLOCATE_MOD_NAME),
90 | $this->get_settings_value(self::MAXNO),
91 | null,
92 | ],
93 | self::COUNTLICKERT => [// How many fields there are.
94 | 'int',
95 | get_string(self::STRATEGYID . '_setting_maxlickert', RATINGALLOCATE_MOD_NAME),
96 | $this->get_settings_value(self::COUNTLICKERT),
97 | null,
98 | ],
99 | ];
100 | }
101 |
102 | /**
103 | * Get dynamic settingfields of strategy.
104 | * @return array|array[]
105 | * @throws \coding_exception
106 | */
107 | public function get_dynamic_settingfields() {
108 | $output = [];
109 | foreach (array_keys($this->get_choiceoptions()) as $id) {
110 | $output[$id] = [
111 | 'text',
112 | get_string('strategy_settings_label', RATINGALLOCATE_MOD_NAME, $this->get_settings_default_value($id)),
113 | null,
114 | $this->get_settings_default_value($id),
115 | ];
116 | }
117 | $output += $this->get_default_strategy_option();
118 | return $output;
119 | }
120 |
121 | /**
122 | * Get choiceoptions.
123 | *
124 | * @return array
125 | */
126 | public function get_choiceoptions() {
127 | $options = [];
128 | for ($i = 0; $i <= $this->maxlickert; $i++) {
129 | $options[$i] = $this->get_settings_value($i);
130 | }
131 | return $options;
132 | }
133 |
134 | /**
135 | * Get default settings.
136 | *
137 | * @return array
138 | * @throws \coding_exception
139 | */
140 | public function get_default_settings() {
141 | $defaults = [
142 | self::MAXNO => 3,
143 | self::COUNTLICKERT => 4,
144 | 0 => get_string(self::STRATEGYID . '_rating_exclude', RATINGALLOCATE_MOD_NAME, "0"),
145 | 'default' => $this->maxlickert,
146 | ];
147 |
148 | for ($i = 1; $i <= $this->maxlickert; $i++) {
149 | if ($i == $this->maxlickert) {
150 | $defaults[$i] = get_string(self::STRATEGYID . '_rating_biggestwish', RATINGALLOCATE_MOD_NAME, "$i");
151 | } else {
152 | $defaults[$i] = $i;
153 | }
154 | }
155 | return $defaults;
156 | }
157 |
158 | /**
159 | * Get validation info.
160 | *
161 | * @return array[]
162 | */
163 | protected function getvalidationinfo() {
164 | return [self::MAXNO => [true, 0],
165 | self::COUNTLICKERT => [true, 2],
166 | ];
167 | }
168 | }
169 |
170 | // Register with the strategymanager.
171 | \strategymanager::add_strategy(strategy::STRATEGYID);
172 |
173 | /**
174 | * View form.
175 | *
176 | * @package mod_ratingallocate
177 | */
178 | class mod_ratingallocate_view_form extends \ratingallocate_options_strategyform {
179 | // Already specified by parent class.
180 |
181 | /**Get maximal amount how many times a user is allowed to rate a choice with "NO".
182 | * Create new strategy.
183 | * @param $strategyoptions
184 | * @return strategy
185 | * @throws \coding_exception
186 | */
187 | protected function construct_strategy($strategyoptions) {
188 | return new strategy($strategyoptions);
189 | }
190 |
191 | /**
192 | * Get choice options.
193 | * @return mixed
194 | */
195 | public function get_choiceoptions() {
196 | $params = $this->get_strategysetting(strategy::COUNTLICKERT);
197 | return $this->get_strategy()->get_choiceoptions($params);
198 | }
199 |
200 | /**
201 | *
202 | * @return \the|null
203 | */
204 | protected function get_max_amount_of_nos() {
205 | return $this->get_strategysetting(strategy::MAXNO);
206 | }
207 |
208 | /**
209 | * Get string identifier of max_nos.
210 | * @return string
211 | */
212 | protected function get_max_nos_string_identyfier() {
213 | return strategy::STRATEGYID . '_max_no';
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | .path-mod-ratingallocate ul.horizontal.choices {
2 | margin: 0;
3 | }
4 |
5 | .path-mod-ratingallocate .horizontal.choices .option {
6 | padding-right: 20px;
7 | display: inline-block;
8 | white-space: normal;
9 | }
10 |
11 | .ratingallocate_ratings_table tr.ratingallocate_summary,
12 | .ratingallocate_ratings_table span.ratingallocate_member {
13 | font-weight: bold;
14 | }
15 |
16 | .ratingallocate_ratings_table span.ratingallocate_member {
17 | display: flex;
18 | align-items: center;
19 | }
20 |
21 | /* Indicate selected choice in non-writeable tables */
22 | .ratingallocate_ratings_table span.ratingallocate_member::before {
23 | content: url('[[pix:i/checked]]');
24 | display: inline-block;
25 | width: 1em;
26 | height: 1em;
27 | margin-right: 5px;
28 | }
29 |
30 | .ratingallocate_ratings_table span input[type=radio] ~ label {
31 | display: flex;
32 | align-items: center;
33 | margin-bottom: 0;
34 | }
35 |
36 | /* Show a tickmark for a selected choice */
37 | .ratingallocate_ratings_table span input[type=radio]:checked ~ label {
38 | /* necessary for containing absolute position values */
39 | position: relative;
40 | }
41 |
42 | .ratingallocate_ratings_table span input[type=radio]:checked ~ label::before {
43 | content: url('[[pix:i/checked]]');
44 | position: absolute;
45 | top: 1px;
46 | left: 2px;
47 | width: 12px;
48 | height: 12px;
49 | }
50 |
51 | /* Special highlight for values that were checked *initially* */
52 | .ratingallocate_ratings_table span input[type=radio][checked] ~ label > span.ratingallocate_checkbox {
53 | background: url('[[pix:ratingallocate|checkbox-selected]]');
54 | background-size: 13px 13px;
55 | }
56 |
57 | .ratingallocate_ratings_table span input[type=radio][checked] ~ label {
58 | font-weight: bold;
59 | }
60 |
61 | /* Checkbox/radio replacement */
62 | .ratingallocate_ratings_table span input[type=radio] ~ label > span.ratingallocate_checkbox {
63 | display: inline-flex;
64 | height: 13px;
65 | width: 13px;
66 | margin-right: 5px;
67 | vertical-align: text-top;
68 | background: url('[[pix:ratingallocate|checkbox]]');
69 | background-size: 13px 13px;
70 | }
71 |
72 | .ratingallocate_ratings_table span input[type=radio] {
73 | display: none;
74 | }
75 |
76 | .ratingallocate_ratings_box {
77 | overflow: auto; /* Scrolling tables */
78 | }
79 |
80 | .path-mod-ratingallocate .mod-ratingallocate-choice-maxno {
81 | text-align: right;
82 | }
83 |
84 | .ratingallocate_distribute_unallocated {
85 | margin: 1em 1em 0 0;
86 | }
87 |
88 | .ratingallocate_ratings_table {
89 | border-collapse: separate;
90 | border-spacing: 0;
91 | }
92 |
93 | .ratingallocate_ratings_table thead th:first-child,
94 | .ratingallocate_ratings_table tbody td:first-child {
95 | position: sticky;
96 | left: 0;
97 | min-width: 10rem;
98 | max-width: 10rem;
99 | }
100 |
101 | .ratingallocate_ratings_table.includegroups tbody td:nth-child(2),
102 | .ratingallocate_ratings_table.includegroups thead th:nth-child(2) {
103 | position: sticky;
104 | left: 10rem;
105 | border-right: 2px solid #dee2e6;
106 | }
107 |
108 | .ratingallocate_ratings_table:not(.includegroups) tbody td:first-child,
109 | .ratingallocate_ratings_table:not(.includegroups) thead th:first-child {
110 | border-right: 2px solid #dee2e6;
111 | }
112 |
113 | .ratingallocate_ratings_table thead th:first-child,
114 | .ratingallocate_ratings_table.includegroups thead th:nth-child(2) {
115 | z-index: 3;
116 | }
117 |
118 | .ratingallocate_ratings_table .groupsinchoiceheadings {
119 | font-size: xx-small;
120 | }
121 |
122 | .ratingallocate_ratings_table tr.ratingallocate_summary td {
123 | position: sticky;
124 | bottom: 0;
125 | background-color: #fff;
126 | }
127 |
128 | .ratingallocate_ratings_table thead th {
129 | background-color: #fff;
130 | position: sticky;
131 | top: 0;
132 | z-index: 2;
133 | }
134 |
135 | .ratingallocate_ratings_table tbody td:first-child,
136 | .ratingallocate_ratings_table.includegroups tbody td:nth-child(2) {
137 | background-color: #fff;
138 | z-index: 1;
139 | font-weight: bold;
140 | }
141 |
142 | .ratingallocate_ratings_table_container .no-overflow {
143 | overflow: unset;
144 | }
145 |
146 | .ratingallocate_front_page_table_1 {
147 | margin: auto;
148 | width: 40%;
149 | }
150 |
151 | .ratingallocate_front_page_table_23 {
152 | margin: auto;
153 | width: 30%;
154 | padding-left: 50px;
155 | padding-right: 50px;
156 | }
157 |
158 | .ratingallocate_front_page_buttons {
159 | margin: auto;
160 | }
161 |
--------------------------------------------------------------------------------
/tests/behat/allocation_status.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @javascript
2 | Feature: Students should get status information according to their rating and their allocation.
3 |
4 | Background:
5 | Given the following "courses" exist:
6 | | fullname | shortname | category | groupmode |
7 | | Course 1 | C1 | 0 | 1 |
8 | And the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | teacher1 | Theo | Teacher | teacher1@example.com |
11 | | student1 | Steve | Student | student1@example.com |
12 | | student2 | Sophie | Student | student2@example.com |
13 | | student3 | Steffanie | Student | student3@example.com |
14 | And the following "course enrolments" exist:
15 | | user | course | role |
16 | | teacher1 | C1 | editingteacher |
17 | | student1 | C1 | student |
18 | | student2 | C1 | student |
19 | | student3 | C1 | student |
20 | And the following "activities" exist:
21 | | activity | course | idnumber | name | accesstimestart |
22 | | ratingallocate | C1 | ra1 | My Fair Allocation | ##yesterday## |
23 | And I log in as "teacher1"
24 | And I am on the "My Fair Allocation" "mod_ratingallocate > Choices" page
25 | And I add a new choice with the values:
26 | | title | My only choice |
27 | | Description (optional) | Test |
28 | | maxsize | 1 |
29 | And I log out
30 | And I log in as "student1"
31 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
32 | And I press "Edit Rating"
33 | And I press "Save changes"
34 | And I log out
35 | And I log in as "student2"
36 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
37 | And I press "Edit Rating"
38 | And I click on "Deny" "radio"
39 | And I press "Save changes"
40 | And I log out
41 | And I log in as "teacher1"
42 | And I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
43 | And I set the following fields to these values:
44 | | Rating begins at | ##2 days ago## |
45 | | Rating ends at | ##yesterday## |
46 | And I press "id_submitbutton"
47 | And I run the scheduled task "mod_ratingallocate\task\cron_task"
48 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
49 | And I press "Publish Allocation"
50 | And I log out
51 |
52 | @javascript
53 | Scenario: As a user, who rated and was allocated, I should see my allocated choice.
54 | When I log in as "student1"
55 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
56 | Then I should see "My only choice" in the "//*[contains(@class, 'allocation')]" "xpath_element"
57 | And I should see "My only choice" in the "//*[contains(@class, 'alert-success')]" "xpath_element"
58 |
59 | @javascript
60 | Scenario: As a user, who rated and was not allocated, I should see a warning.
61 | When I log in as "student2"
62 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
63 | Then I should see "You were not allocated to any choice!" in the "//*[contains(@class, 'allocation')]" "xpath_element"
64 | And I should see "You could not be allocated to any choice." in the "//*[contains(@class, 'alert-danger')]" "xpath_element"
65 |
66 | @javascript
67 | Scenario: As a user, who did not rate, I should not see my allocated choice
68 | When I log in as "student3"
69 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
70 | Then I should not see "Your Allocation"
71 | And I should see "The rating is over." in the "//*[contains(@class, 'alert-info')]" "xpath_element"
72 |
--------------------------------------------------------------------------------
/tests/behat/completion_condition_allocation.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @core_completion
2 | Feature: Set a ratingallocate activity marked as completed when a user has been allocated
3 | In order to ensure a student has been allocated
4 | As a teacher
5 | I need to set the ratingallocate to complete when the student has an allocation
6 |
7 | Background:
8 | Given the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | student1 | Student | 1 | student1@example.com |
11 | | student2 | Student | 2 | student2@example.com |
12 | | teacher1 | Teacher | 1 | teacher1@example.com |
13 | And the following "courses" exist:
14 | | fullname | shortname | category | enablecompletion |
15 | | Course 1 | C1 | 0 | 1 |
16 | And the following "course enrolments" exist:
17 | | user | course | role |
18 | | teacher1 | C1 | editingteacher |
19 | | student1 | C1 | student |
20 | | student2 | C1 | student |
21 | And the following "activities" exist:
22 | | activity | course | idnumber | name | completion | completionallocation | accesstimestart | accesstimestop |
23 | | ratingallocate | C1 | ra1 | My Fair Allocation | 2 | 1 | ##2 days ago## | ##yesterday## |
24 | And the following choices exist:
25 | | title | explanation | maxsize | ratingallocate |
26 | | C1 | Test | 1 | My Fair Allocation |
27 | | C2 | Test | 0 | My Fair Allocation |
28 | And the following ratings exist:
29 | | choice | user | rating |
30 | | C1 | student1 | 1 |
31 | | C1 | student2 | 0 |
32 | | C2 | student1 | 0 |
33 | | C2 | student2 | 0 |
34 | And I log in as "teacher1"
35 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
36 | And I run the scheduled task "mod_ratingallocate\task\cron_task"
37 | And I press "Publish Allocation"
38 | And I wait "1" seconds
39 | And I run the scheduled task "core\task\completion_regular_task"
40 | And I wait "1" seconds
41 | And I log out
42 |
43 | @javascript
44 | Scenario: User completes ratingallocate only if they have been allocated
45 | When I log in as "teacher1"
46 | And I am on "Course 1" course homepage
47 | Then "Student 1" user has completed "My Fair Allocation" activity
48 | And "Student 2" user has not completed "My Fair Allocation" activity
49 |
--------------------------------------------------------------------------------
/tests/behat/completion_condition_vote.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @core_completion
2 | Feature: Set a ratingallocate activity marked as completed when a user submits a vote
3 | In order to ensure a student has voted in the activity
4 | As a teacher
5 | I need to set the ratingallocate to complete when the student has voted
6 |
7 | Background:
8 | Given the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | student1 | Student | 1 | student1@example.com |
11 | | student2 | Student | 2 | student2@example.com |
12 | | teacher1 | Teacher | 1 | teacher1@example.com |
13 | And the following "courses" exist:
14 | | fullname | shortname | category | enablecompletion |
15 | | Course 1 | C1 | 0 | 1 |
16 | And the following "course enrolments" exist:
17 | | user | course | role |
18 | | teacher1 | C1 | editingteacher |
19 | | student1 | C1 | student |
20 | | student2 | C1 | student |
21 | And the following "activities" exist:
22 | | activity | course | idnumber | name | completion | completionvote |
23 | | ratingallocate | C1 | ra1 | My Fair Allocation | 2 | 1 |
24 | And I log in as "teacher1"
25 | And I am on the "My Fair Allocation" "mod_ratingallocate > Choices" page
26 | And I add a new choice with the values:
27 | | title | My first choice |
28 | | Description (optional) | Test 1 |
29 | | maxsize | 2 |
30 |
31 | @javascript
32 | Scenario: User completes ratingallocate only if they voted
33 | When I log in as "student1"
34 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
35 | And I press "Edit Rating"
36 | And I press "Save changes"
37 | And I log out
38 | And I log in as "teacher1"
39 | And I am on "Course 1" course homepage
40 | And I navigate to "Reports" in current page administration
41 | And I click on "Activity completion" "link"
42 | Then "Completed" "icon" should exist in the "Student 1" "table_row"
43 | And "Completed" "icon" should not exist in the "Student 2" "table_row"
44 |
--------------------------------------------------------------------------------
/tests/behat/completion_manual.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @core_completion
2 | Feature: Manually mark a ratingallocate activity as completed
3 | In order to meet manual ratingallocate completion requirements
4 | As a student
5 | I need to be able to view and modify my ratingallocate manual completion status
6 |
7 | Background:
8 | Given the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | student1 | Student | 1 | student1@example.com |
11 | | teacher1 | Teacher | 1 | teacher1@example.com |
12 | And the following "courses" exist:
13 | | fullname | shortname | category | enablecompletion |
14 | | Course 1 | C1 | 0 | 1 |
15 | And the following "course enrolments" exist:
16 | | user | course | role |
17 | | teacher1 | C1 | editingteacher |
18 | | student1 | C1 | student |
19 | And the following "activities" exist:
20 | | activity | course | idnumber | name | completion |
21 | | ratingallocate | C1 | ra1 | My Fair Allocation | 1 |
22 | And I log in as "teacher1"
23 | And I am on the "My Fair Allocation" "mod_ratingallocate > Choices" page
24 | And I add a new choice with the values:
25 | | title | My first choice |
26 | | Description (optional) | Test 1 |
27 | | maxsize | 2 |
28 |
29 | @javascript
30 | Scenario: Use manual completion as teacher
31 | When I log in as "teacher1"
32 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
33 | Then the manual completion button for "My Fair Allocation" should be disabled
34 |
35 | @javascript
36 | Scenario: Use manual completion student view
37 | When I log in as "student1"
38 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
39 | Then the manual completion button of "My Fair Allocation" is displayed as "Mark as done"
40 | And I toggle the manual completion state of "My Fair Allocation"
41 | And the manual completion button of "My Fair Allocation" is displayed as "Done"
42 |
--------------------------------------------------------------------------------
/tests/behat/defaultratings.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @javascript
2 | Feature: When a student starts a rating the default values of all choices
3 | are set according to the instance settings.
4 |
5 | Background:
6 | Given the following "courses" exist:
7 | | fullname | shortname | category | groupmode |
8 | | Course 1 | C1 | 0 | 1 |
9 | And the following "users" exist:
10 | | username | firstname | lastname | email |
11 | | teacher1 | Teacher | 1 | teacher1@example.com |
12 | | student1 | Student | 1 | student1@example.com |
13 | And the following "course enrolments" exist:
14 | | user | course | role |
15 | | teacher1 | C1 | editingteacher |
16 | | student1 | C1 | student |
17 | And the following "activities" exist:
18 | | activity | course | idnumber | name |
19 | | ratingallocate | C1 | ra1 | My Fair Allocation |
20 | And I log in as "teacher1"
21 | And I am on the "My Fair Allocation" "mod_ratingallocate > Choices" page
22 | And I add a new choice with the values:
23 | | title | My first choice |
24 | | Description (optional) | Test 1 |
25 | | maxsize | 2 |
26 | And I add a new choice with the values:
27 | | title | My second choice |
28 | | Description (optional) | Test 1 |
29 | | maxsize | 2 |
30 |
31 | @javascript
32 | Scenario: The default rating is the max rating
33 | And I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
34 | And I select "strategy_lickert" from the "strategy" singleselect
35 | And I press "id_submitbutton"
36 | And I log out
37 | When I log in as "student1"
38 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
39 | And I press "Edit Rating"
40 | Then I should see the following rating form:
41 | | My first choice | 4 |
42 | | My second choice | 4 |
43 |
44 | @javascript
45 | Scenario: The default rating should be changeable to a medium rating
46 | And I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
47 | And I select "strategy_lickert" from the "strategy" singleselect
48 | And I select "3" from the "strategyopt[strategy_lickert][default]" singleselect
49 | And I press "id_submitbutton"
50 | And I log out
51 | When I log in as "student1"
52 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
53 | And I press "Edit Rating"
54 | Then I should see the following rating form:
55 | | My first choice | 3 |
56 | | My second choice | 3 |
57 |
58 | @javascript
59 | Scenario: The default rating should be changeable to the lowest rating
60 | And I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
61 | And I select "strategy_lickert" from the "strategy" singleselect
62 | And I select "0" from the "strategyopt[strategy_lickert][default]" singleselect
63 | And I press "id_submitbutton"
64 | And I log out
65 | When I log in as "student1"
66 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
67 | And I press "Edit Rating"
68 | Then I should see the following rating form:
69 | | My first choice | 0 |
70 | | My second choice | 0 |
71 |
72 | @javascript
73 | Scenario: The default rating is the max rating
74 | And I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
75 | And I select "strategy_lickert" from the "strategy" singleselect
76 | And I press "id_submitbutton"
77 | And I log out
78 | When I log in as "student1"
79 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
80 | And I press "Edit Rating"
81 | And I set the rating form to the following values:
82 | | My first choice | 2 |
83 | | My second choice | 3 |
84 | And I press "Save changes"
85 | And I press "Edit Rating"
86 | Then I should see the following rating form:
87 | | My first choice | 2 |
88 | | My second choice | 3 |
89 |
--------------------------------------------------------------------------------
/tests/behat/manual_allocation.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate
2 | Feature: Teachers should be able to alter the allocations manually.
3 |
4 | Background:
5 | Given the following "courses" exist:
6 | | fullname | shortname | category | groupmode |
7 | | Course 1 | C1 | 0 | 1 |
8 | And the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | teacher1 | Theo | Teacher | teacher1@example.com |
11 | | student1 | Steve | Student | student1@example.com |
12 | | student2 | Sophie | Student | student2@example.com |
13 | | student3 | Stefanie | Student | student3@example.com |
14 | And the following "course enrolments" exist:
15 | | user | course | role |
16 | | teacher1 | C1 | editingteacher |
17 | | student1 | C1 | student |
18 | | student2 | C1 | student |
19 | | student3 | C1 | student |
20 | And the following "activities" exist:
21 | | activity | course | idnumber | name | accesstimestart | accesstimestop |
22 | | ratingallocate | C1 | ra1 | My Fair Allocation | ##yesterday## | ##yesterday## |
23 | And the following choices exist:
24 | | title | explanation | maxsize | ratingallocate |
25 | | C1 | Test | 1 | My Fair Allocation |
26 | | C2 | Test | 1 | My Fair Allocation |
27 | And the following ratings exist:
28 | | choice | user | rating |
29 | | C1 | student1 | 1 |
30 | | C1 | student2 | 0 |
31 | | C2 | student1 | 0 |
32 | | C2 | student2 | 1 |
33 | And I run the scheduled task "mod_ratingallocate\task\cron_task"
34 |
35 | Scenario: As a teacher, I want to allocate a so far not allocated user.
36 | And I log in as "teacher1"
37 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
38 | And I press "Manual Allocation Form"
39 | Then I should see "Steve" assigned to "C1"
40 | And I should see "Steve" not assigned to "C2"
41 | And I should see "Sophie" not assigned to "C1"
42 | And I should see "Sophie" assigned to "C2"
43 | And I should not see "Stefanie"
44 | When I assign "Steve" to choice "C2"
45 | And I press "Save and Continue"
46 | Then I should see "Steve" not assigned to "C1"
47 | And I should see "Steve" assigned to "C2"
48 | And I should see "Sophie" not assigned to "C1"
49 | And I should see "Sophie" assigned to "C2"
50 | When I assign "Sophie" to choice "C1"
51 | And I press "Save and Continue"
52 | Then I should see "Steve" not assigned to "C1"
53 | And I should see "Steve" assigned to "C2"
54 | And I should see "Sophie" assigned to "C1"
55 | And I should see "Sophie" not assigned to "C2"
56 |
--------------------------------------------------------------------------------
/tests/behat/mod_form.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @javascript
2 | Feature: Creating a new rating allocation, where new choices need to
3 | be added and if necessary deleted prior to submission.
4 |
5 | Background:
6 | Given the following "courses" exist:
7 | | fullname | shortname | category | groupmode |
8 | | Course 1 | C1 | 0 | 1 |
9 | And the following "users" exist:
10 | | username | firstname | lastname | email |
11 | | teacher1 | Teacher | 1 | teacher1@example.com |
12 | | student1 | Student | 1 | student1@example.com |
13 | And the following "course enrolments" exist:
14 | | user | course | role |
15 | | teacher1 | C1 | editingteacher |
16 | | student1 | C1 | student |
17 | And I log in as "teacher1"
18 | And I am on "Course 1" course homepage with editing mode on
19 | And I add a ratingallocate to course "Course 1" section "0" and I fill the form with:
20 | | id_name | My Fair Allocation |
21 | And I am on the "My Fair Allocation" "mod_ratingallocate > Choices" page
22 | And I add a new choice with the values:
23 | | title | My first choice |
24 | | Description (optional) | Test 1 |
25 | | maxsize | 2 |
26 | And I add a new choice with the values:
27 | | title | My second choice |
28 | | Description (optional) | Test 2 |
29 | | maxsize | 2 |
30 | And I add a new choice with the values:
31 | | title | My third choice |
32 | | Description (optional) | Test 3 |
33 | | maxsize | 2 |
34 | And the default editor is set to "textarea"
35 |
36 | Scenario: Create a new rating alloation and add an additonal new choice.
37 | Given I add a new choice with the values:
38 | | title | My fourth choice |
39 | | Description (optional) | Test 4 |
40 | | maxsize | 2 |
41 | Then I should see the choice with the title "My first choice"
42 | And I should see the choice with the title "My second choice"
43 | And I should see the choice with the title "My third choice"
44 | And I should see the choice with the title "My fourth choice"
45 |
46 | Scenario: Create a new rating alloation and add two additonal new choices using the add next button.
47 | Given I add new choices with the values:
48 | | title | Description (optional) | maxsize |
49 | | My fourth choice | Test 4 | 2 |
50 | | My fifth choice | Test 5 | 2 |
51 | Then I should see the choice with the title "My first choice"
52 | And I should see the choice with the title "My second choice"
53 | And I should see the choice with the title "My third choice"
54 | And I should see the choice with the title "My fourth choice"
55 | And I should see the choice with the title "My fifth choice"
56 |
57 | Scenario: Create a new rating alloation and add two additonal new choices, but delete two old and one new.
58 | When I add new choices with the values:
59 | | title | Description (optional) | maxsize |
60 | | My fourth choice | Test 4 | 2 |
61 | | My fifth choice | Test 5 | 2 |
62 | And I delete the choice with the title "My first choice"
63 | And I delete the choice with the title "My second choice"
64 | And I delete the choice with the title "My fifth choice"
65 |
66 | Then I should not see the choice with the title "My first choice"
67 | And I should not see the choice with the title "My second choice"
68 | And I should see the choice with the title "My third choice"
69 | And I should see the choice with the title "My fourth choice"
70 | And I should not see the choice with the title "My fifth choice"
71 |
72 | Scenario: Create a new rating alloation and add an additonal new active choice.
73 | When I add a new choice with the values:
74 | | title | My fourth choice |
75 | | Description (optional) | Test 4 |
76 | | maxsize | 1337 |
77 | | active | true |
78 | And I should see the choice with the title "My fourth choice"
79 | And the choice with name "My fourth choice" should have explanation being equal to "Test 4"
80 | And the choice with name "My fourth choice" should have maxsize being equal to 1337
81 | And the choice with name "My fourth choice" should be active
82 |
83 | Scenario: Create a new rating alloation and add an additonal new inactive choice.
84 | When I add a new choice with the values:
85 | | title | My fourth choice |
86 | | Description (optional) | Test 4 |
87 | | maxsize | 1337 |
88 | | active | false |
89 | And I should see the choice with the title "My fourth choice"
90 | And the choice with name "My fourth choice" should have explanation being equal to "Test 4"
91 | And the choice with name "My fourth choice" should have maxsize being equal to 1337
92 | And the choice with name "My fourth choice" should not be active
93 |
94 | Scenario: Create a new rating alloation and add an additonal new inactive choice. Change the the choice to active.
95 | When I add a new choice with the values:
96 | | title | My fourth choice |
97 | | Description (optional) | This is my discription |
98 | | maxsize | 1231243 |
99 | | active | false |
100 | Then I set the choice with the title "My fourth choice" to active
101 | And I should see "My fourth choice"
102 | And the choice with name "My fourth choice" should be active
103 |
104 | Scenario: Create a new rating alloation and add an additonal new active choice. Change the the choice to inactive.
105 | When I add a new choice with the values:
106 | | title | My fourth choice |
107 | | Description (optional) | This is my discription |
108 | | maxsize | 1231243 |
109 | | active | true |
110 | Then I set the choice with the title "My fourth choice" to inactive
111 | And I should see "My fourth choice"
112 | And the choice with name "My fourth choice" should not be active
113 |
114 | Scenario: Create a new rating alloation and check the field runalgorithmbycron. It should be saved as true.
115 | When I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
116 | And I set the field "runalgorithmbycron" to "1"
117 | And I press "id_submitbutton"
118 | And I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
119 | Then the field "runalgorithmbycron" matches value "1"
120 |
121 | Scenario: Create a new rating alloation and uncheck the field runalgorithmbycron. It should be saved as false.
122 | When I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
123 | And I set the field "runalgorithmbycron" to ""
124 | And I press "id_submitbutton"
125 | And I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
126 | Then the field "runalgorithmbycron" matches value ""
127 |
128 | Scenario: Create a new rating alloation and assume the default for the field runalgorithmbycron is true.
129 | When I am on the "My Fair Allocation" "mod_ratingallocate > Edit" page
130 | Then the field "runalgorithmbycron" matches value "1"
131 |
--------------------------------------------------------------------------------
/tests/behat/ratings.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @javascript
2 | Feature: When a student rates a rating should be saved and it should be possible to delete it again.
3 |
4 | Background:
5 | Given the following "courses" exist:
6 | | fullname | shortname | category | groupmode |
7 | | Course 1 | C1 | 0 | 1 |
8 | And the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | student1 | Student | 1 | student1@example.com |
11 | And the following "course enrolments" exist:
12 | | user | course | role |
13 | | student1 | C1 | student |
14 | And the following "activities" exist:
15 | | activity | course | idnumber | name |
16 | | ratingallocate | C1 | ra1 | My Fair Allocation |
17 | And the following choices exist:
18 | | title | maxsize | ratingallocate |
19 | | My first choice | 2 | My Fair Allocation |
20 | | My second choice | 2 | My Fair Allocation |
21 | | My third choice | 2 | My Fair Allocation |
22 |
23 | @javascript
24 | Scenario: The user can create a rating
25 | When I log in as "student1"
26 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
27 | And I press "Edit Rating"
28 | And I press "Save changes"
29 | Then the user "student1" should have ratings
30 |
31 | @javascript
32 | Scenario: The user can delete a rating
33 | When I log in as "student1"
34 | And I am on the "My Fair Allocation" "mod_ratingallocate > View" page
35 | And I press "Edit Rating"
36 | And I press "Save changes"
37 | Then the user "student1" should have ratings
38 | When I press "Delete Rating"
39 | Then the user "student1" should not have ratings
40 |
--------------------------------------------------------------------------------
/tests/behat/select_strategy.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @javascript
2 | Feature: When a teacher selects a strategy the appropriate options are displayed
3 |
4 | Background:
5 | Given the following "courses" exist:
6 | | fullname | shortname | category | groupmode |
7 | | Course 1 | CO1 | 0 | 1 |
8 | And the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | teacher1 | Teacher | 1 | teacher1@example.com |
11 | And the following "course enrolments" exist:
12 | | user | course | role |
13 | | teacher1 | CO1 | editingteacher |
14 | And I log in as "teacher1"
15 | And I am on "Course 1" course homepage with editing mode on
16 | And I add a ratingallocate to course "Course 1" section "1"
17 |
18 | @javascript
19 | Scenario: The correct options are displayed for the default strategy (Yes-No)
20 | Then the field "Rating strategy" matches value "Accept-Deny"
21 | And I should see "Maximum number of choices the user can rate with \"Deny\""
22 | And I should see "Designation for \"Deny\""
23 |
24 | @javascript
25 | Scenario: Selecting "Likert Scale" strategy should show the correct options.
26 | When I select "strategy_lickert" from the "strategy" singleselect
27 | Then I should see "Maximum number of choices the user can rate with 0"
28 | And I should see "Highest number on the likert scale"
29 | And I should see "Designation for \"0 - Exclude\""
30 | And I should not see "Maximum number of choices the user can rate with \"Deny\""
31 | And I should not see "Designation for \"Deny\""
32 |
33 | @javascript
34 | Scenario: Selecting "Give Points" then "Yes-No" shows only the correct options.
35 | When I select "strategy_points" from the "strategy" singleselect
36 | And I should see "Maximum number of choices to which the user can give 0 points"
37 | And I should see "Total number of points the user can assign"
38 | And I select "strategy_yesno" from the "strategy" singleselect
39 | Then I should see "Maximum number of choices the user can rate with \"Deny\""
40 | And I should see "Designation for \"Deny\""
41 | And I should not see "Maximum number of choices to which the user can give 0 points"
42 | And I should not see "Total number of points the user can assign"
43 |
--------------------------------------------------------------------------------
/tests/behat/validate_rating.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate @javascript
2 | Feature: When a student attempts to rate choices it should be validated prior to changing.
3 |
4 | Background:
5 | Given the following "courses" exist:
6 | | fullname | shortname | category | groupmode |
7 | | Course 1 | C1 | 0 | 1 |
8 | And the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | teacher1 | Teacher | 1 | teacher1@example.com |
11 | | student1 | Student | 1 | student1@example.com |
12 | And the following "course enrolments" exist:
13 | | user | course | role |
14 | | teacher1 | C1 | editingteacher |
15 | | student1 | C1 | student |
16 | And I log in as "teacher1"
17 | And I am on "Course 1" course homepage with editing mode on
18 | And I add a ratingallocate to course "Course 1" section "1" and I fill the form with:
19 | | id_name | Validated Rating |
20 | | strategy | strategy_points |
21 | | Rating begins at | ##2 days ago## |
22 | | strategyopt[strategy_points][maxzero] | 2 |
23 | And I am on the "Validated Rating" "mod_ratingallocate > Choices" page
24 | And I add a new choice with the values:
25 | | title | My first choice |
26 | | Description (optional) | Test 1 |
27 | | maxsize | 2 |
28 | And I add a new choice with the values:
29 | | title | My second choice |
30 | | Description (optional) | Test 2 |
31 | | maxsize | 2 |
32 | And I add a new choice with the values:
33 | | title | My third choice |
34 | | Description (optional) | Test 3 |
35 | | maxsize | 2 |
36 | And I add a new choice with the values:
37 | | title | My fourth choice |
38 | | Description (optional) | Test 4 |
39 | | maxsize | 2 |
40 | And I log out
41 |
42 | Scenario: The user cannot enter values less than 0.
43 | When I log in as "student1"
44 | And I am on the "Validated Rating" "mod_ratingallocate > View" page
45 | And I press "Edit Rating"
46 | And I rate choices with the following points:
47 | | My first choice | -1 |
48 | | My second choice | 1 |
49 | | My third choice | 1 |
50 | | My fourth choice | 99 |
51 | And I press "Save changes"
52 | Then I should see "The points that you assign to a choice must be between 0 and 100."
53 |
54 | Scenario: The values entered by the user must sum up to the (default) maximum.
55 | When I log in as "student1"
56 | And I am on the "Validated Rating" "mod_ratingallocate > View" page
57 | And I press "Edit Rating"
58 | And I rate choices with the following points:
59 | | My first choice | 1 |
60 | | My second choice | 2 |
61 | | My third choice | 3 |
62 | | My fourth choice | 4 |
63 | And I press "Save changes"
64 | Then I should see "Incorrect total number of points. The sum of all points has to be 100."
65 |
66 | Scenario: The user may not rate more than a (default) number of choices with 0.
67 | When I log in as "student1"
68 | And I am on the "Validated Rating" "mod_ratingallocate > View" page
69 | And I press "Edit Rating"
70 | And I rate choices with the following points:
71 | | My first choice | 0 |
72 | | My second choice | 0 |
73 | | My third choice | 0 |
74 | | My fourth choice | 100 |
75 | And I press "Save changes"
76 | Then I should see "You may give 0 points to at most 2 choice(s)."
77 |
--------------------------------------------------------------------------------
/tests/behat/visibile_calendar_events.feature:
--------------------------------------------------------------------------------
1 | @mod @mod_ratingallocate
2 | Feature: Students should only see the ratingallocate calendar events if they are able to rate.
3 |
4 | Background:
5 | Given the following "courses" exist:
6 | | fullname | shortname | category | groupmode |
7 | | Course 1 | C1 | 0 | 1 |
8 | And the following "users" exist:
9 | | username | firstname | lastname | email |
10 | | teacher1 | Theo | Teacher | teacher1@example.com |
11 | | student1 | Steve | Student | student1@example.com |
12 | | student2 | Sophie | Student | student2@example.com |
13 | And the following "course enrolments" exist:
14 | | user | course | role |
15 | | teacher1 | C1 | editingteacher |
16 | | student1 | C1 | student |
17 | | student2 | C1 | student |
18 | And the following "groups" exist:
19 | | name | course | idnumber |
20 | | group1 | C1 | G1 |
21 | | group2 | C1 | G2 |
22 | And the following "group members" exist:
23 | | user | group |
24 | | student1 | G1 |
25 | | student2 | G1 |
26 | And the following "activities" exist:
27 | | activity | course | idnumber | name | accesstimestart | accesstimestop | accesstype |
28 | | ratingallocate | C1 | ra1 | My Fair Allocation | ##1 May 2023## | ##2 May 2023## | group1 |
29 |
30 | @javascript
31 | Scenario: As a user that is able to rate, I should see the event
32 | Given I log in as "student1"
33 | And I view the calendar for "5" "2023"
34 | Then I should see "My Fair Allocation opens"
35 | And I should see "My Fair Allocation closes"
36 |
37 | Scenario: As a user that is not able to rate, I should not see the event
38 | Given I log in as "student2"
39 | And I view the calendar for "5" "2023"
40 | Then I should not see "My Fair Allocation begins"
41 | And I should not see "My Fair Allocation ends"
42 |
--------------------------------------------------------------------------------
/tests/mod_generator_test.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | namespace mod_ratingallocate;
18 | defined('MOODLE_INTERNAL') || die();
19 |
20 | global $CFG;
21 | require_once(dirname(__FILE__) . '/../locallib.php');
22 |
23 | /**
24 | * mod_ratingallocate generator tests
25 | *
26 | * @package mod_ratingallocate
27 | * @category test
28 | * @group mod_ratingallocate
29 | * @copyright usener
30 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
31 | * @covers \mod_ratingallocate_generator
32 | */
33 | final class mod_generator_test extends \advanced_testcase {
34 |
35 | public function test_create_instance(): void {
36 |
37 | global $DB, $USER;
38 | \core_php_time_limit::raise();
39 | $this->resetAfterTest();
40 | $this->setAdminUser();
41 |
42 | $course = $this->getDataGenerator()->create_course();
43 |
44 | // There should not be any module for that course first.
45 | $this->assertFalse(
46 | $DB->record_exists('ratingallocate', ['course' => $course->id,
47 | ]));
48 | $records = $DB->get_records('ratingallocate_choices', [], 'id');
49 | $this->assertEquals(0, count($records));
50 |
51 | // Create activity.
52 | $mod = \mod_ratingallocate_generator::create_instance_with_choices($this,
53 | ['course' => $course]);
54 | $records = $DB->get_records('ratingallocate', ['course' => $course->id,
55 | ], 'id');
56 | $this->assertEquals(1, count($records));
57 | $this->assertTrue(array_key_exists($mod->id, $records));
58 | $expectedvaluesdb = [
59 | 'id' => $mod->id,
60 | 'course' => $course->id,
61 | 'name' => 'Rating Allocation',
62 | 'intro' => 'Test ratingallocate 1',
63 | 'introformat' => '0',
64 | 'timecreated' => reset($records)->{'timecreated'},
65 | 'timemodified' => '0',
66 | 'accesstimestart' => reset($records)->{'accesstimestart'},
67 | 'accesstimestop' => reset($records)->{'accesstimestop'},
68 | 'setting' => '{"strategy_yesno":{"maxcrossout":"1"}}',
69 | 'strategy' => 'strategy_yesno',
70 | 'publishdate' => reset($records)->{'publishdate'},
71 | 'published' => '0',
72 | 'notificationsend' => '0',
73 | 'algorithmstarttime' => null,
74 | 'algorithmstatus' => '0',
75 | 'runalgorithmbycron' => '1',
76 | 'completionvote' => '0',
77 | 'completionallocation' => '0',
78 | ];
79 |
80 | $this->assertEquals(json_decode(json_encode($expectedvaluesdb, false)), reset($records));
81 | // Must have two choices.
82 | $records = $DB->get_records('ratingallocate_choices',
83 | ['ratingallocateid' => $mod->id,
84 | ], 'title');
85 | $this->assertEquals(2, count($records));
86 | $choiceids = array_keys($records);
87 | $expectedchoices = [
88 | $choiceids[0] => (object) [
89 | 'title' => 'Choice 1',
90 | 'id' => $choiceids[0],
91 | 'ratingallocateid' => $mod->id,
92 | 'explanation' => 'Some explanatory text for choice 1',
93 | 'maxsize' => '10',
94 | 'usegroups' => '0',
95 | 'active' => '1',
96 | ],
97 | $choiceids[1] => (object) [
98 | 'title' => 'Choice 2',
99 | 'id' => $choiceids[1],
100 | 'ratingallocateid' => $mod->id,
101 | 'explanation' => 'Some explanatory text for choice 2',
102 | 'maxsize' => '5',
103 | 'usegroups' => '0',
104 | 'active' => '0',
105 | ],
106 | ];
107 | $this->assertEquals($expectedchoices, $records);
108 |
109 | // Create an other mod_ratingallocate within the course.
110 | $params = ['course' => $course->id, 'name' => 'Another mod_ratingallocate',
111 | ];
112 | $mod = \mod_ratingallocate_generator::create_instance_with_choices($this, $params);
113 | $records = $DB->get_records('ratingallocate', ['course' => $course->id,
114 | ], 'id');
115 | // Are there 2 modules within the course?
116 | $this->assertEquals(2, count($records));
117 | // Is the name correct?
118 | $this->assertEquals('Another mod_ratingallocate', $records[$mod->id]->name);
119 |
120 | $records = $DB->get_records('ratingallocate_choices', [], 'id');
121 | $this->assertEquals(4, count($records));
122 |
123 | // Other tables.
124 | $records = $DB->get_records('ratingallocate_ratings', [], 'id');
125 | $this->assertEquals(0, count($records));
126 | $records = $DB->get_records('ratingallocate_allocations', [], 'id');
127 | $this->assertEquals(0, count($records));
128 | }
129 |
130 | public function test_mod_ratingallocate_generated_module(): void {
131 | $choicedata = \mod_ratingallocate_generator::get_default_choice_data();
132 | foreach ($choicedata as $id => $choice) {
133 | $choice['maxsize'] = 10;
134 | $choice['active'] = true;
135 | $choicedata[$id] = $choice;
136 | }
137 | $moduledata = \mod_ratingallocate_generator::get_default_values();
138 | $moduledata['num_students'] = 22;
139 | $testmodule = new \mod_ratingallocate_generated_module($this, $moduledata, $choicedata);
140 | $this->assertCount($moduledata['num_students'], $testmodule->students);
141 | $this->assertCount(20, $testmodule->allocations);
142 |
143 | $ratingallocate = \mod_ratingallocate_generator::get_ratingallocate_for_user(
144 | $this, $testmodule->moddb, $testmodule->teacher);
145 | foreach ($ratingallocate->get_choices_with_allocationcount() as $choice) {
146 | $this->assertEquals(10, $choice->{'usercount'});
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/tests/mod_ratingallocate_notification_test.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | namespace mod_ratingallocate;
18 | defined('MOODLE_INTERNAL') || die();
19 | require_once(__DIR__ . '/../locallib.php');
20 |
21 | /**
22 | * Tests the notifications when allocations are published.
23 | *
24 | * @package mod_ratingallocate
25 | * @category test
26 | * @group mod_ratingallocate
27 | * @copyright 2018 T Reischmann
28 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
29 | */
30 | final class mod_ratingallocate_notification_test extends \advanced_testcase {
31 |
32 | /**
33 | * Choice 1.
34 | */
35 | const CHOICE1 = 'Choice 1';
36 | /**
37 | * Choice 2.
38 | */
39 | const CHOICE2 = 'Choice 2';
40 |
41 | /**
42 | * Tests if publishing the allocation send messages with the right content to the right users.
43 | *
44 | * @covers ::send_distribution_notification()
45 | */
46 | public function test_allocation_notification(): void {
47 | $course = $this->getDataGenerator()->create_course();
48 | $students = [];
49 | for ($i = 1; $i <= 4; $i++) {
50 | $students[$i] = \mod_ratingallocate_generator::create_user_and_enrol($this, $course);
51 | }
52 | $choices = [
53 | [
54 | 'title' => self::CHOICE1,
55 | 'maxsize' => '1',
56 | 'active' => '1',
57 | ],
58 | [
59 | 'title' => self::CHOICE2,
60 | 'maxsize' => '1',
61 | 'active' => '1',
62 | ],
63 | ];
64 | $ratings = [
65 | $students[1]->id => [
66 | [
67 | 'choice' => self::CHOICE1,
68 | 'rating' => 1,
69 | ],
70 | [
71 | 'choice' => self::CHOICE2,
72 | 'rating' => 0,
73 | ],
74 | ],
75 | $students[2]->id => [
76 | [
77 | 'choice' => self::CHOICE1,
78 | 'rating' => 0,
79 | ],
80 | [
81 | 'choice' => self::CHOICE2,
82 | 'rating' => 1,
83 | ],
84 | ],
85 | $students[3]->id => [
86 | [
87 | 'choice' => self::CHOICE1,
88 | 'rating' => 0,
89 | ],
90 | [
91 | 'choice' => self::CHOICE2,
92 | 'rating' => 0,
93 | ],
94 | ],
95 | ];
96 |
97 | $ratingallocate = \mod_ratingallocate_generator::get_closed_ratingallocate_for_teacher($this, $choices,
98 | $course, $ratings);
99 | $allocations = $ratingallocate->get_allocations();
100 | $this->assertArrayHasKey($students[1]->id, $allocations);
101 | $this->assertArrayHasKey($students[2]->id, $allocations);
102 | $this->assertCount(2, $allocations);
103 | $choices = $ratingallocate->get_choices();
104 | $this->assertEquals(self::CHOICE1, $choices[$allocations[$students[1]->id]->choiceid]->title);
105 | $this->assertEquals(self::CHOICE2, $choices[$allocations[$students[2]->id]->choiceid]->title);
106 |
107 | $this->preventResetByRollback();
108 | $messagesink = $this->redirectMessages();
109 |
110 | // Create a notification task.
111 | $task = new \mod_ratingallocate\task\send_distribution_notification();
112 |
113 | // Add custom data.
114 | $task->set_component('mod_ratingallocate');
115 | $task->set_custom_data([
116 | 'ratingallocateid' => $ratingallocate->ratingallocate->id,
117 | ]);
118 |
119 | $this->setAdminUser();
120 | $task->execute();
121 |
122 | $messages = $messagesink->get_messages();
123 | $this->assertEquals(3, count($messages));
124 | $this->assert_message_contains($messages, $students[1]->id, self::CHOICE1);
125 | $this->assert_message_contains($messages, $students[2]->id, self::CHOICE2);
126 | $this->assert_message_contains($messages, $students[3]->id, 'could not');
127 | $this->assert_no_message_for_user($messages, $students[4]->id);
128 | }
129 |
130 | /**
131 | * Asserts that a message for a user exists and that it contains a certain search string
132 | * @param $messages \stdClass[] received messages
133 | * @param $userid int id of the user
134 | * @param $needle string search string
135 | */
136 | private function assert_message_contains($messages, $userid, $needle) {
137 | $messageexists = false;
138 | foreach ($messages as $message) {
139 | if ($message->useridto == $userid) {
140 | $messageexists = true;
141 | $this->assertStringContainsString($needle, $message->fullmessage);
142 | }
143 | }
144 | $this->assertTrue($messageexists, 'Message for userid ' . $userid . 'could not be found.');
145 | }
146 |
147 | /**
148 | * Asserts that there is no message for a certain user.
149 | * @param $messages \stdClass[] received messages
150 | * @param $userid int id of the user
151 | * @param $needle string search string
152 | */
153 | private function assert_no_message_for_user($messages, $userid) {
154 | $messageexists = false;
155 | foreach ($messages as $message) {
156 | if ($message->useridto == $userid) {
157 | $messageexists = true;
158 | }
159 | }
160 | $this->assertFalse($messageexists, 'There is a message for userid ' . $userid . '.');
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/tests/mod_ratingallocate_status_test.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | namespace mod_ratingallocate;
18 |
19 | use PHP_CodeSniffer\Generators\Generator;
20 | use PhpOffice\PhpSpreadsheet\Worksheet\Iterator;
21 |
22 | defined('MOODLE_INTERNAL') || die();
23 |
24 | require_once(__DIR__ . '/generator/lib.php');
25 | require_once(__DIR__ . '/../locallib.php');
26 |
27 | /**
28 | * Tests the method get_status()
29 | *
30 | * @package mod_ratingallocate
31 | * @category test
32 | * @group mod_ratingallocate
33 | * @copyright reischmann
34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 | */
36 | final class mod_ratingallocate_status_test extends \advanced_testcase {
37 |
38 | public function setUp(): void {
39 | global $PAGE;
40 | parent::setUp();
41 | $PAGE->set_url('/');
42 | $this->resetAfterTest();
43 | }
44 |
45 | /**
46 | * Provider
47 | *
48 | * @return array
49 | */
50 | public static function ratingallocate_provider(): array {
51 | return [
52 | 'Rating phase is not started.' => [
53 | 3, 6, false, false, \ratingallocate::DISTRIBUTION_STATUS_TOO_EARLY],
54 | 'Rating phase is not started, but some allocations exist.' => [
55 | 3, 6, false, true, \ratingallocate::DISTRIBUTION_STATUS_TOO_EARLY],
56 | 'Rating phase is not started, but allocation is published.' => [
57 | 3, 6, true, false, \ratingallocate::DISTRIBUTION_STATUS_TOO_EARLY],
58 | 'Rating phase is not started, but allocations exist and are published.' => [
59 | 3, 6, true, true, \ratingallocate::DISTRIBUTION_STATUS_TOO_EARLY],
60 | 'The rating phase is running' => [
61 | -1, 6, false, false, \ratingallocate::DISTRIBUTION_STATUS_RATING_IN_PROGRESS],
62 | 'The rating phase is running, but allocations exist.' => [
63 | -1, 6, false, true, \ratingallocate::DISTRIBUTION_STATUS_RATING_IN_PROGRESS],
64 | 'The rating phase is running, but allocation is published.' => [
65 | -1, 6, true, false, \ratingallocate::DISTRIBUTION_STATUS_RATING_IN_PROGRESS],
66 | 'The rating phase is running, but allocations exist and are published.' => [
67 | -1, 6, true, true, \ratingallocate::DISTRIBUTION_STATUS_RATING_IN_PROGRESS],
68 | 'The rating phase is running.' => [
69 | -7, -6, false, false, \ratingallocate::DISTRIBUTION_STATUS_READY],
70 | 'The rating phase is running and some allocations exist.' => [
71 | -7, -6, false, true, \ratingallocate::DISTRIBUTION_STATUS_READY_ALLOC_STARTED],
72 | 'The rating phase is running and allocation is published.' => [
73 | -7, -6, true, false, \ratingallocate::DISTRIBUTION_STATUS_PUBLISHED],
74 | 'The rating phase is running and allocations exist and are published.' => [
75 | -7, -6, true, true, \ratingallocate::DISTRIBUTION_STATUS_PUBLISHED],
76 | ];
77 | }
78 |
79 | /**
80 | * Tests under different conditions if the returned status object is correct.
81 | * @dataProvider ratingallocate_provider
82 | * @covers ::get_status()
83 | */
84 | public function test_get_status($addtostart, $addtostop, $published, $hasallocations, $expected): void {
85 | $record = [
86 | 'name' => 'Rating Allocation',
87 | 'accesstimestart' => time() + ($addtostart * 24 * 60 * 60),
88 | 'accesstimestop' => time() + ($addtostop * 24 * 60 * 60),
89 | 'strategyopt' => ['strategy_yesno' => ['maxcrossout' => '1']],
90 | 'strategy' => 'strategy_yesno'];
91 | if ($hasallocations) {
92 | $genmod = new \mod_ratingallocate_generated_module($this, $record);
93 | $moddb = $genmod->moddb;
94 | } else {
95 | $course = $this->getDataGenerator()->create_course();
96 | $record['course'] = $course;
97 | $moddb = $this->getDataGenerator()->create_module(RATINGALLOCATE_MOD_NAME, $record);
98 | }
99 |
100 | $ratingallocate = \mod_ratingallocate_generator::get_ratingallocate($moddb);
101 | $ratingallocate->ratingallocate->published = $published;
102 |
103 | $status = $ratingallocate->get_status();
104 | $this->assertEquals($expected, $status);
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/version.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Defines the version of ratingallocate
19 | *
20 | * @package mod_ratingallocate
21 | * @copyright 2014 T Reischmann, C Usener
22 | * @copyright based on code by M Schulze copyright (C) 2014 M Schulze
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 | */
25 |
26 | defined('MOODLE_INTERNAL') || die();
27 |
28 | $plugin->version = 2025021900; // The current module version (Date: YYYYMMDDXX).
29 | $plugin->requires = 2022112800; // Requires Moodle 4.1 and higher.
30 | $plugin->maturity = MATURITY_STABLE;
31 | $plugin->release = 'v4.5-r1';
32 | $plugin->component = 'mod_ratingallocate'; // To check on upgrade, that module sits in correct place.
33 |
--------------------------------------------------------------------------------
/view.php:
--------------------------------------------------------------------------------
1 | .
16 |
17 | /**
18 | * Prints a particular instance of ratingallocate
19 | *
20 | * You can have a rather longer description of the file as well,
21 | * if you like, and it can span multiple lines.
22 | *
23 | * @package mod_ratingallocate
24 | * @copyright 2014 T Reischmann, C Usener
25 | * @copyright based on code by M Schulze copyright (C) 2014 M Schulze
26 | * @copyright based on code by Stefan Koegel copyright (C) 2013 Stefan Koegel
27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 | */
29 |
30 | require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
31 | require_once(dirname(__FILE__) . '/locallib.php');
32 |
33 | require_once(dirname(__FILE__) . '/solver/ford-fulkerson-koegel.php');
34 |
35 | $id = optional_param('id', 0, PARAM_INT); // Course_module ID, or.
36 | $n = optional_param('m', 0, PARAM_INT); // Ratingallocate instance ID - it should be named as the first character of the module.
37 |
38 | if ($id) {
39 | $cm = get_coursemodule_from_id('ratingallocate', $id, 0, false, MUST_EXIST);
40 | $course = get_course($cm->course);
41 | $ratingallocate = $DB->get_record('ratingallocate', ['id' => $cm->instance], '*', MUST_EXIST);
42 | } else if ($n) {
43 | $ratingallocate = $DB->get_record('ratingallocate', ['id' => $n], '*', MUST_EXIST);
44 | $course = get_course($ratingallocate->course);
45 | $cm = get_coursemodule_from_instance('ratingallocate', $ratingallocate->id, $course->id, false, MUST_EXIST);
46 | } else {
47 | throw new \moodle_exception('no_id_or_m_error', RATINGALLOCATE_MOD_NAME);
48 | }
49 |
50 | require_login($course, true, $cm);
51 | $context = context_module::instance($cm->id);
52 | $PAGE->set_title($cm->name);
53 | $PAGE->set_context($context);
54 | $PAGE->set_url('/mod/ratingallocate/view.php', ['id' => $cm->id]);
55 |
56 | require_capability('mod/ratingallocate:view', $context);
57 |
58 | $ratingallocateobj = new ratingallocate($ratingallocate, $course, $cm, $context);
59 | echo $ratingallocateobj->handle_view();
60 |
--------------------------------------------------------------------------------