mirror of
https://github.com/moodle/moodle.git
synced 2025-01-19 14:27:22 +01:00
MDL-25526 Workshop: fixed random allocation of reviews
The patch wraps that foreach ($circles as $circleid => $circle) loop by yet another one for() loop. Reviews are allocated iteratively now. During the first iteration, we try to make sure that at least one circle link exists. During the second iteration, we try to allocate two, etc. Circles are shuffled at the beginning of each iteration. This is supposed to improve the randomness of the allocation. The patch also fixes shuffle_assoc() implementation. The previous implementation actually did not work at all. Also, that removed called to shuffle_assoc() was redundant here.
This commit is contained in:
parent
5a7f931ee5
commit
47ce9385e8
@ -428,76 +428,82 @@ class workshop_random_allocator implements workshop_allocator {
|
|||||||
// all users will be processed at once
|
// all users will be processed at once
|
||||||
$circlegroups = array(0);
|
$circlegroups = array(0);
|
||||||
}
|
}
|
||||||
$this->shuffle_assoc($circlegroups);
|
|
||||||
// $o[] = 'debug::circle groups = ' . json_encode($circlegroups);
|
// $o[] = 'debug::circle groups = ' . json_encode($circlegroups);
|
||||||
foreach ($circlegroups as $circlegroupid) {
|
foreach ($circlegroups as $circlegroupid) {
|
||||||
$o[] = 'debug::processing circle group id ' . $circlegroupid;
|
$o[] = 'debug::processing circle group id ' . $circlegroupid;
|
||||||
$circles = $allcircles[$circlegroupid];
|
$circles = $allcircles[$circlegroupid];
|
||||||
$this->shuffle_assoc($circles);
|
// iterate over all circles in the group until the requested number of links per circle exists
|
||||||
foreach ($circles as $circleid => $circle) {
|
// or it is not possible to fulfill that requirment
|
||||||
$o[] = 'debug::processing circle id ' . $circleid;
|
// during the first iteration, we try to make sure that at least one circlelink exists. during the
|
||||||
if (!isset($circlelinks[$circleid])) {
|
// second iteration, we try to allocate two, etc.
|
||||||
$circlelinks[$circleid] = array();
|
for ($requiredreviews = 1; $requiredreviews <= $numofreviews; $requiredreviews++) {
|
||||||
}
|
$this->shuffle_assoc($circles);
|
||||||
$keeptrying = true; // is there a chance to find a square for this circle?
|
$o[] = 'debug::iteration ' . $requiredreviews;
|
||||||
$failedgroups = array(); // array of groupids where the square should be chosen from (because
|
foreach ($circles as $circleid => $circle) {
|
||||||
// of their group workload) but it was not possible (for example there
|
$o[] = 'debug::processing circle id ' . $circleid;
|
||||||
// was the only square and it had been already connected
|
if (!isset($circlelinks[$circleid])) {
|
||||||
while ($keeptrying && (count($circlelinks[$circleid]) < $numofreviews)) {
|
$circlelinks[$circleid] = array();
|
||||||
// firstly, choose a group to pick the square from
|
}
|
||||||
if (NOGROUPS == $gmode) {
|
$keeptrying = true; // is there a chance to find a square for this circle?
|
||||||
if (in_array(0, $failedgroups)) {
|
$failedgroups = array(); // array of groupids where the square should be chosen from (because
|
||||||
|
// of their group workload) but it was not possible (for example there
|
||||||
|
// was the only square and it had been already connected
|
||||||
|
while ($keeptrying && (count($circlelinks[$circleid]) < $requiredreviews)) {
|
||||||
|
// firstly, choose a group to pick the square from
|
||||||
|
if (NOGROUPS == $gmode) {
|
||||||
|
if (in_array(0, $failedgroups)) {
|
||||||
|
$keeptrying = false;
|
||||||
|
$o[] = 'error::indent::No more peers available'; // todo translate
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$targetgroup = 0;
|
||||||
|
} elseif (SEPARATEGROUPS == $gmode) {
|
||||||
|
if (in_array($circlegroupid, $failedgroups)) {
|
||||||
|
$keeptrying = false;
|
||||||
|
$o[] = 'error::indent::No more peers available in this separate group'; // todo translate
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$targetgroup = $circlegroupid;
|
||||||
|
} elseif (VISIBLEGROUPS == $gmode) {
|
||||||
|
$trygroups = array_diff_key($squaregroupsworkload, array(0 => null)); // all but [0]
|
||||||
|
$trygroups = array_diff_key($trygroups, array_flip($failedgroups)); // without previous failures
|
||||||
|
$targetgroup = $this->get_element_with_lowest_workload($trygroups);
|
||||||
|
}
|
||||||
|
if ($targetgroup === false) {
|
||||||
$keeptrying = false;
|
$keeptrying = false;
|
||||||
$o[] = 'error::indent::No more peers available'; // todo translate
|
$o[] = 'error::indent::Not enough peers available'; // todo translate
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$targetgroup = 0;
|
$o[] = 'debug::indent::next square should be from group id ' . $targetgroup;
|
||||||
} elseif (SEPARATEGROUPS == $gmode) {
|
// now, choose a square from the target group
|
||||||
if (in_array($circlegroupid, $failedgroups)) {
|
$trysquares = array_intersect_key($squareworkload, $allsquares[$targetgroup]);
|
||||||
$keeptrying = false;
|
// $o[] = 'debug::indent::individual workloads in this group are ' . json_encode($trysquares);
|
||||||
$o[] = 'error::indent::No more peers available in this separate group'; // todo translate
|
unset($trysquares[$circleid]); // can't allocate to self
|
||||||
break;
|
$trysquares = array_diff_key($trysquares, array_flip($circlelinks[$circleid])); // can't re-allocate the same
|
||||||
|
$targetsquare = $this->get_element_with_lowest_workload($trysquares);
|
||||||
|
if (false === $targetsquare) {
|
||||||
|
$o[] = 'debug::indent::unable to find an available square. trying another group';
|
||||||
|
$failedgroups[] = $targetgroup;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
$targetgroup = $circlegroupid;
|
$o[] = 'debug::indent::target square = ' . $targetsquare;
|
||||||
} elseif (VISIBLEGROUPS == $gmode) {
|
// ok - we have found the square
|
||||||
$trygroups = array_diff_key($squaregroupsworkload, array(0 => null)); // all but [0]
|
$circlelinks[$circleid][] = $targetsquare;
|
||||||
$trygroups = array_diff_key($trygroups, array_flip($failedgroups)); // without previous failures
|
$squarelinks[$targetsquare][] = $circleid;
|
||||||
$targetgroup = $this->get_element_with_lowest_workload($trygroups);
|
$squareworkload[$targetsquare]++;
|
||||||
}
|
$o[] = 'debug::indent::increasing square workload to ' . $squareworkload[$targetsquare];
|
||||||
if ($targetgroup === false) {
|
if ($targetgroup) {
|
||||||
$keeptrying = false;
|
// recalculate the group workload
|
||||||
$o[] = 'error::indent::Not enough peers available'; // todo translate
|
$squaregroupsworkload[$targetgroup] = 0;
|
||||||
break;
|
foreach ($allsquares[$targetgroup] as $squareid => $square) {
|
||||||
}
|
$squaregroupsworkload[$targetgroup] += $squareworkload[$squareid];
|
||||||
$o[] = 'debug::indent::next square should be from group id ' . $targetgroup;
|
}
|
||||||
// now, choose a square from the target group
|
$squaregroupsworkload[$targetgroup] /= count($allsquares[$targetgroup]);
|
||||||
$trysquares = array_intersect_key($squareworkload, $allsquares[$targetgroup]);
|
$o[] = 'debug::indent::increasing group workload to ' . $squaregroupsworkload[$targetgroup];
|
||||||
// $o[] = 'debug::indent::individual workloads in this group are ' . json_encode($trysquares);
|
|
||||||
unset($trysquares[$circleid]); // can't allocate to self
|
|
||||||
$trysquares = array_diff_key($trysquares, array_flip($circlelinks[$circleid])); // can't re-allocate the same
|
|
||||||
$targetsquare = $this->get_element_with_lowest_workload($trysquares);
|
|
||||||
if (false === $targetsquare) {
|
|
||||||
$o[] = 'debug::indent::unable to find an available square. trying another group';
|
|
||||||
$failedgroups[] = $targetgroup;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$o[] = 'debug::indent::target square = ' . $targetsquare;
|
|
||||||
// ok - we have found the square
|
|
||||||
$circlelinks[$circleid][] = $targetsquare;
|
|
||||||
$squarelinks[$targetsquare][] = $circleid;
|
|
||||||
$squareworkload[$targetsquare]++;
|
|
||||||
$o[] = 'debug::indent::increasing square workload to ' . $squareworkload[$targetsquare];
|
|
||||||
if ($targetgroup) {
|
|
||||||
// recalculate the group workload
|
|
||||||
$squaregroupsworkload[$targetgroup] = 0;
|
|
||||||
foreach ($allsquares[$targetgroup] as $squareid => $square) {
|
|
||||||
$squaregroupsworkload[$targetgroup] += $squareworkload[$squareid];
|
|
||||||
}
|
}
|
||||||
$squaregroupsworkload[$targetgroup] /= count($allsquares[$targetgroup]);
|
} // end of processing this circle
|
||||||
$o[] = 'debug::indent::increasing group workload to ' . $squaregroupsworkload[$targetgroup];
|
} // end of one iteration of processing circles in the group
|
||||||
}
|
} // end of all iterations over circles in the group
|
||||||
} // end of processing this circle
|
|
||||||
} // end of processing circles in the group
|
|
||||||
} // end of processing circle groups
|
} // end of processing circle groups
|
||||||
$returned = array();
|
$returned = array();
|
||||||
if (self::USERTYPE_AUTHOR == $numper) {
|
if (self::USERTYPE_AUTHOR == $numper) {
|
||||||
@ -569,15 +575,14 @@ class workshop_random_allocator implements workshop_allocator {
|
|||||||
/**
|
/**
|
||||||
* Shuffle the order of array elements preserving the key=>values
|
* Shuffle the order of array elements preserving the key=>values
|
||||||
*
|
*
|
||||||
* @author rich at home dot nl
|
|
||||||
* @link http://php.net/manual/en/function.shuffle.php#80586
|
|
||||||
* @param array $array to be shuffled
|
* @param array $array to be shuffled
|
||||||
* @return true
|
* @return true
|
||||||
*/
|
*/
|
||||||
protected function shuffle_assoc(&$array) {
|
protected function shuffle_assoc(&$array) {
|
||||||
if (count($array) > 1) {
|
if (count($array) > 1) {
|
||||||
// $keys needs to be an array, no need to shuffle 1 item or empty arrays, anyway
|
// $keys needs to be an array, no need to shuffle 1 item or empty arrays, anyway
|
||||||
$keys = array_rand($array, count($array));
|
$keys = array_keys($array);
|
||||||
|
shuffle($keys);
|
||||||
foreach($keys as $key) {
|
foreach($keys as $key) {
|
||||||
$new[$key] = $array[$key];
|
$new[$key] = $array[$key];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user