Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
b68ceb3
added distributor code and changed code style
Stazer Sep 22, 2017
306a83a
added moodle license notices
Stazer Sep 22, 2017
86a9ca9
replaced require loop
Stazer Sep 22, 2017
a4290be
fixed this related syntax issues
Stazer Sep 22, 2017
712b093
added include file for lp related classes
Stazer Sep 22, 2017
0625471
added missing dirname(__FILE__)
Stazer Sep 22, 2017
255b885
user class refactoring, renaming chosen_groups to selected_groups and…
Stazer Sep 26, 2017
71709dd
removed engine::get_engines
Stazer Sep 28, 2017
5f8d2bb
added utility class
Stazer Sep 28, 2017
7e4dcdd
added solver configuration
Stazer Sep 28, 2017
ceb3f6c
created utility class and removed linear_program_engine
Stazer Oct 5, 2017
060150d
added executor skeletons
Stazer Oct 5, 2017
7d7194b
removed description and useless constructors from engines
Stazer Oct 5, 2017
e6558d0
added executors include file
Stazer Oct 5, 2017
2a38cd9
added basic code for ssh and local executor
Stazer Oct 5, 2017
24d05a2
renamed distrubute choices and fixed get_solver
Stazer Oct 12, 2017
d705e0c
added another two utility functions
Stazer Oct 12, 2017
61e8ef4
fixed get_priority
Stazer Oct 12, 2017
14bc9c4
added missing requires
Stazer Oct 12, 2017
6ba2017
removed engine name and fixed solve_objects
Stazer Oct 12, 2017
380a2f0
added missing requires, removed name from executors and fixed syntax …
Stazer Oct 12, 2017
afbf82e
fixed str_replace call
Stazer Oct 12, 2017
9dce810
fixed syntax issues
Stazer Oct 12, 2017
d9f9a7c
fixed syntax errors
Stazer Oct 13, 2017
f59549f
moved none_authentication into authentication
Stazer Oct 13, 2017
d9effa1
added public_key authentication
Stazer Oct 13, 2017
7ae9820
changed order of constructor parameter
Stazer Oct 18, 2017
0316db6
added default value for fingerprint
Stazer Oct 18, 2017
064446a
added working ssh executor implementation
Stazer Oct 19, 2017
5e757c0
added missing method documentation
Stazer Oct 19, 2017
21e5494
moved solve methods into executor
Stazer Oct 19, 2017
d24e7d3
changed access of solve to public
Stazer Oct 19, 2017
dc6443e
added working webservice executor implementation
Stazer Oct 19, 2017
7a568e5
added working local executor implementation
Stazer Oct 19, 2017
2b6a00d
crated webservice backend
Stazer Oct 24, 2017
4698084
changed description of loction of local_path
Stazer Oct 24, 2017
81b2488
splitted webservice into backend and connector and added secret
Stazer Oct 24, 2017
6935f0d
removed old code and added includes
Stazer Oct 24, 2017
35c6b14
added missing backend class
Stazer Oct 24, 2017
e344347
added missing setters
Stazer Oct 24, 2017
a75d702
added missing setters
Stazer Oct 24, 2017
0ed4f33
added missing set_engine
Stazer Oct 24, 2017
dc97788
changed Exception to exception
Stazer Oct 25, 2017
e916fe1
removed debugging output and added error checking for fopen
Stazer Oct 25, 2017
143fd1b
removed getter for and added secret verification
Stazer Oct 25, 2017
38cb001
replaced fopen with curl
Stazer Oct 25, 2017
54a23de
added missign newlines
Stazer Oct 25, 2017
974f2f3
added group assignment
Stazer Oct 25, 2017
15d8b72
added
Stazer Oct 25, 2017
2511be7
added directory for webservice and its config file
Stazer Oct 25, 2017
9f2067f
fixed issue in creating the allocation array
Stazer Oct 25, 2017
3e8b622
fixed syntax error
Stazer Oct 25, 2017
44c1aea
changed argument names of receive and send file
Stazer Oct 26, 2017
cd59ab0
added lp-solver
Stazer Oct 26, 2017
1d7bacd
added some lp solver documentation
Stazer Nov 1, 2017
bf39921
changed Algorithm section
Stazer Nov 1, 2017
8063de7
fixed reference issues
Stazer Nov 3, 2017
76192cc
fixed running issues on algorithm error
Stazer Nov 3, 2017
7dd4bb8
algorithm status is now set to failure if errors occur
Stazer Nov 3, 2017
185f42f
moved lib into classes/local for autoloading purposes
Stazer Nov 3, 2017
382bb54
added settings for lp configuration
Stazer Nov 6, 2017
9c0a58b
renamed ssh hostname to ssh address
Stazer Nov 6, 2017
a5b0900
changed setting type for ssh password
Stazer Nov 8, 2017
39729e0
added another test data helper function
Stazer Nov 9, 2017
9f5257e
added error message for cases where users > choices
Stazer Nov 13, 2017
045701c
some readme changes
Stazer Nov 13, 2017
c9cc4ad
added line and variable name limits
Stazer Nov 14, 2017
be76962
replaced tabs with spaces
Stazer Nov 17, 2017
64cae36
removed group size check
Stazer Nov 17, 2017
cef4274
replaces static lp file paths with temporary paths
Stazer Nov 17, 2017
8ab91d2
added missing string
Stazer Nov 17, 2017
c525bef
added tests for user and group and fixed some issues
Stazer Nov 27, 2017
560af9c
added test_from_transformation
Stazer Nov 27, 2017
a0a8ec5
replaced class names with full class paths for @covers
Stazer Nov 28, 2017
106fb0c
added tests for lp utility and weighter
Stazer Nov 28, 2017
bbcf62b
renamed class names
Stazer Jan 2, 2018
e144b2a
improved weighters formular readability
Stazer Jan 8, 2018
e7b949b
added check for existence of active
Stazer Jan 8, 2018
c349fae
added test for to group transofrmation
Stazer Jan 8, 2018
cd0f1b4
added missing utility tests
Stazer Feb 5, 2018
4e8edee
added missing newlines
Stazer Feb 5, 2018
1feb36b
added get_variable_names method
Stazer Feb 5, 2018
a49ff0f
added linear program test
Stazer Feb 5, 2018
5f0c715
added write_objective_function method
Stazer Feb 5, 2018
ee4468e
added missing test classes
Stazer Feb 5, 2018
2f5f511
fixed solution value parsing break
Stazer Feb 5, 2018
cdf7dbf
added engine tests
Stazer Feb 5, 2018
359693e
fixed syntax error
Stazer Feb 5, 2018
d110e75
added some executor tests
Stazer Feb 5, 2018
3295767
replaced t function with an anonymous function
Stazer Feb 8, 2018
ddbb1a3
Type error fix
Stazer Apr 10, 2018
ac2fc3d
Fixed type errors
Stazer Apr 10, 2018
73b6df6
Fixed plus issues
Stazer Apr 11, 2018
aa32159
added CURL timeout
Stazer Apr 11, 2018
ddc8f63
Fixed namespace naming error
Stazer Apr 11, 2018
0d51d74
Removed local path from the backend of the webservice executor
Stazer Apr 11, 2018
e972641
Fixed tmpfile issues
Stazer Apr 11, 2018
66bfbe1
Replaced lib.php import and added configuration varaible for enable t…
Stazer Apr 11, 2018
bd17a5b
Merge branch 'feature/lp-support' of github.com:Stazer/moodle-mod_rat…
Stazer Apr 11, 2018
5ba71f4
fixed webservice issues
Stazer Apr 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ Next you can add choices, which the users will have to rate later on.
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 allocated to.
For more information please visit the [moodle wiki](https://docs.moodle.org/31/en/Ratingallocate).

Configuration
=============
General
---------
You can configure ``mod/ratingallocate`` using moodles administration interface. Three different solvers are available for selection. For LP it is necessary to configure the way it will use the external LP solver by selecting an executor.


Webservice backend
------------
Using the webservice executor mod_ratingallocate can use an external lp solver which is not on the same machine as the moodle instance.
A working webserver with PHP is needed. Clone the mod_ratingallocate into the document root and take a look into ``webservice/config.php`` for configuring the executors backend. A strong secret and HTTPS are recommended.


Moodle version
======================
The plugin is continously tested with all moodle versions, which are security supported by the moodle headquarter.
Expand All @@ -30,8 +43,8 @@ In addition to all stable branches the version is also tested against the master

Algorithm
=========
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 -1 first.

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.
Using the Edmonds-Karp algorithm the 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.
Distributing 500 users to 21 choices takes around 11sec.

Measurements for using the LP solver or Ford-Fulkerson are not available.

153 changes: 153 additions & 0 deletions classes/local/group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace mod_ratingallocate\local;

class group {

private $id = '';
private $limit = 0;
private $assigned_users = [];

/**
* Creates a new group
*
* @param $id Id of the group
* @param $limit Group limit
*/
public function __construct($id, $limit = 0) {
$this->id = $id;
$this->set_limit($limit);
}

/**
* Returns the group id
*
* @return Id of the group
*/
public function get_id() {
return $this->id;
}

/**
* Checks if the group has a limit (limit is zero)
*
* @return True if the group has a limit
*/
public function has_limit() {
return $this->limit != 0;
}

/**
* Returns the group limit
*
* @return Group limit
*/

public function get_limit() {
return $this->limit;
}

/**
* Checks if the group is empty
*
* @return True if the group is empty
*/
public function is_empty() {
return empty($this->assigned_users);
}

/**
* Checks if the group is full (limit has been reached)
*
* @return True if the group is full
*/
public function is_full() {
if($this->limit == 0)
return false;

return count($this->assigned_users) == $this->limit;
}

/**
* Sets the group limit (zero for no limit)
*
* @param $limit The new group limit
* @throws exception if the group limit is negative
*/
public function set_limit($limit) {
if($limit < 0)
throw new \exception('Limit cannot be negative!');

$this->limit = $limit;
}

/**
* Returns an array of users which are assigned to the group
*
* @return Array of users which are assigned to the group
*/
public function get_assigned_users() {
return $this->assigned_users;
}

/**
* Adds an assigned user to the group
*
* @param $user User that gets added to the group
*
* @throws exception if the group limit has been reached or the user has been already assigned to a group
*/
public function add_assigned_user(&$user) {
if($this->exists_assigned_user($user))
return;

if($this->is_full())
throw new \exception('Limit has been reached!');

if($user->get_assigned_group() && $user->get_assigned_group() != $this)
throw new \exception('User has been already assigned to another group!');

$user->set_assigned_group($this);
$this->assigned_users[$user->get_id()] = $user;
}

/**
* Checks if user belongs to this group
*
* @param $user User that gets checked
*
* @return True if user belongs to this group
*/
public function exists_assigned_user($user) {
return isset($this->assigned_users[$user->get_id()]);
}

/**
* Removes a user from the group
*
* @param $user User that gets removed from the group
*
* @throws exception If user was not assigned from the group
*/
public function remove_assigned_user($user) {
if(!$this->exists_assigned_user($user))
throw new \exception('User has not been assigned to this group!');

unset($this->assigned_users[$user->get_id()]);
}

}
39 changes: 39 additions & 0 deletions classes/local/lp/engine.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace mod_ratingallocate\local\lp;

abstract class engine {

/**
* Reads the content of the stream and returns the variables and their optimized values
*
* @param $stream Output stream of the program that was executed
*
* @return Array of variables and their values
*/
abstract public function read($stream);

/**
* Returns the command that gets executed
*
* @param $input_file Name of the input file
*
* @returns Command as a string
*/
abstract public function get_command($input_file);

};
55 changes: 55 additions & 0 deletions classes/local/lp/engines/cplex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace mod_ratingallocate\local\lp\engines;

class cplex extends \mod_ratingallocate\local\lp\engine {

/**
* Returns the command that gets executed
*
* @param $input_file Name of the input file
*
* @returns Command as a string
*/
public function get_command($input_file) {
return "cplex -c \"read $input_file\" \"optimize\" \"display solution variables -\"";
}

/**
* Reads the content of the stream and returns the variables and their optimized values
*
* @param $stream Output stream of the program that was executed
*
* @return Array of variables and their values
*/
public function read($stream) {
$content = stream_get_contents($stream);
$solution = [];

foreach(array_slice(explode("\n", substr($content, strpos($content, "Solution Value"))), 1) as $variable) {
$parts = explode(' ', preg_replace('!\s+!', ' ', $variable));

if(count($parts) < 2)
break;

$solution[$parts[0]] = intval($parts[1]);
}

return $solution;
}

}
55 changes: 55 additions & 0 deletions classes/local/lp/engines/scip.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace mod_ratingallocate\local\lp\engines;

class scip extends \mod_ratingallocate\local\lp\engine {

/**
* Returns the command that gets executed
*
* @param $input_file Name of the input file
*
* @returns Command as a string
*/
public function get_command($input_file) {
return "scip -f $input_file";
}

/**
* Reads the content of the stream and returns the variables and their optimized values
*
* @param $stream Output stream of the program that was executed
*
* @return Array of variables and their values
*/
public function read($stream) {
$content = stream_get_contents($stream);
$solution = [];

foreach(array_slice(explode("\n", substr($content, strpos($content, 'objective value:'))), 1) as $variable) {
$parts = explode(' ', preg_replace('!\s+!', ' ', $variable));

if(empty($parts[0]))
break;

$solution[$parts[0]] = $parts[1];
}

return $solution;
}

}
Loading