forked from science-ation/science-ation
The new judge scheduler.
- Missing: Having a project judged more than once by different judging teams is untested, I don't htink it'll work properly, still working on that part. - Missing: Auto updating the configuration if any of the variables are missing. - Missing: A way to preserve judging questions (like willing_chair), so the user doesn't delete them and break the scheduler, OR, notice saying that the question has been deleted and the scheduler won't use the chair calculations, then we need a way to add them back in with the click of a button.
This commit is contained in:
parent
6fc83836af
commit
e7d726355d
225
admin/anneal.inc.php
Normal file
225
admin/anneal.inc.php
Normal file
@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
class annealer {
|
||||
|
||||
var $num_buckets;
|
||||
var $bucket;
|
||||
var $bucket_cost;
|
||||
var $cost;
|
||||
var $start_temp, $start_moves;
|
||||
var $cost_function_callback;
|
||||
var $iterations;
|
||||
var $items_per_bucket;
|
||||
var $rate;
|
||||
|
||||
function annealer($num_buckets, $start_temp, $start_moves, $rate,
|
||||
$cost_function_cb, $items)
|
||||
{
|
||||
$this->num_buckets = $num_buckets;
|
||||
$this->start_temp = $start_temp;
|
||||
$this->start_moves = $start_moves;
|
||||
$this->cost_function_callback = $cost_function_cb;
|
||||
|
||||
$this->bucket_cost = array();
|
||||
$this->bucket = array();
|
||||
$this->iterations = 0;
|
||||
$this->items_per_bucket = count($items) / $num_buckets;
|
||||
$this->rate = $rate;
|
||||
$ipb = ceil($this->items_per_bucket);
|
||||
$i=0;
|
||||
$this->cost = 0;
|
||||
for($x=0; $x<$num_buckets; $x++) {
|
||||
unset($b);
|
||||
$b = array();
|
||||
for($y=0;$y<$ipb; $y++) {
|
||||
if($i == count($items)) break;
|
||||
$b[] = $items[$i];
|
||||
$i++;
|
||||
}
|
||||
$this->bucket[] = $b;
|
||||
$c = $this->cost_function($x);
|
||||
$this->bucket_cost[] = $c;
|
||||
$this->cost += $c;
|
||||
}
|
||||
TRACE("Annealer setup: T={$this->start_temp}, ".
|
||||
"M={$this->start_moves}, Bkts={$this->num_buckets}, ".
|
||||
"Cost={$this->cost}\n");
|
||||
}
|
||||
|
||||
|
||||
function pick_move()
|
||||
{
|
||||
/* Pick a bucket and item */
|
||||
while(1) {
|
||||
$b1 = rand(0, $this->num_buckets - 1);
|
||||
if(count($this->bucket[$b1]) > 0) break;
|
||||
}
|
||||
$i1 = rand(0, count($this->bucket[$b1]) -1);
|
||||
|
||||
/* Pick a csecond bucket that is different thatn the first */
|
||||
$b2 = rand(0, $this->num_buckets - 2);
|
||||
if($b2 >= $b1) $b2++;
|
||||
|
||||
/* Picket an item, or a blank, in the second bucket */
|
||||
$i2 = rand(0, count($this->bucket[$b2]));
|
||||
if($i2 == count($this->bucket[$b2])) $i2 = -1;
|
||||
// TRACE("Move ($b1,$i1)<->($b2,$i2)\n");
|
||||
return array($b1, $i1, $b2, $i2);
|
||||
}
|
||||
|
||||
function cost_function($b)
|
||||
{
|
||||
$bkt = $this->bucket[$b];
|
||||
$cb = $this->cost_function_callback;
|
||||
$c = $cb($this, $b, $bkt);
|
||||
// $this->print_bucket($b);
|
||||
// print("Computed cost to be: $c\n");
|
||||
return $c;
|
||||
}
|
||||
|
||||
function compute_delta_cost($move)
|
||||
{
|
||||
list($b1, $i1, $b2, $i2) = $move;
|
||||
|
||||
$cost = 0;
|
||||
|
||||
$b1_old = $this->bucket[$b1];
|
||||
$b2_old = $this->bucket[$b2];
|
||||
|
||||
$b1_new = array();
|
||||
$b2_new = array();
|
||||
/* Make 2 new bucket lists */
|
||||
for($x=0; $x<count($b1_old); $x++) {
|
||||
$id = $b1_old[$x];
|
||||
if($x == $i1) {
|
||||
/* Swap or remove this index */
|
||||
if($i2 != -1) $b1_new[] = $b2_old[$i2];
|
||||
} else {
|
||||
$b1_new[] = $id;
|
||||
}
|
||||
}
|
||||
for($x=0; $x<count($b2_old); $x++) {
|
||||
$id = $b2_old[$x];
|
||||
if($x == $i2) {
|
||||
/* Swap or remove this index */
|
||||
$b2_new[] = $b1_old[$i1];
|
||||
} else {
|
||||
$b2_new[] = $id;
|
||||
}
|
||||
}
|
||||
if($i2 == -1) $b2_new[] = $b1_old[$i1];
|
||||
|
||||
|
||||
/* Assign the new item lists to the buckets */
|
||||
$this->bucket[$b1] = $b1_new;
|
||||
$this->bucket[$b2] = $b2_new;
|
||||
|
||||
/* Compute costs */
|
||||
$cost -= $this->bucket_cost[$b1];
|
||||
$cost -= $this->bucket_cost[$b2];
|
||||
|
||||
$c1 = $this->cost_function($b1);
|
||||
$c2 = $this->cost_function($b2);
|
||||
|
||||
$cost += $c1 + $c2;
|
||||
|
||||
/* Return to the original bucket lists */
|
||||
$this->bucket[$b1] = $b1_old;
|
||||
$this->bucket[$b2] = $b2_old;
|
||||
|
||||
return array($cost, array($c1, $b1_new, $c2, $b2_new));
|
||||
}
|
||||
|
||||
function accept_move($move, $movedata)
|
||||
{
|
||||
list($b1, $i1, $b2, $i2) = $move;
|
||||
list($c1, $b1_new, $c2, $b2_new) = $movedata;
|
||||
// TRACE("Old buckets:\n");
|
||||
// $this->print_bucket($b1);
|
||||
// $this->print_bucket($b2);
|
||||
$this->bucket[$b1] = $b1_new;
|
||||
$this->bucket[$b2] = $b2_new;
|
||||
// TRACE("New buckets:\n");
|
||||
// $this->print_bucket($b1);
|
||||
// $this->print_bucket($b2);
|
||||
$this->bucket_cost[$b1] = $c1;
|
||||
$this->bucket_cost[$b2] = $c2;
|
||||
}
|
||||
|
||||
function anneal()
|
||||
{
|
||||
$temperature = $this->start_temp;
|
||||
$current_cost = $this->cost;
|
||||
$last_cost = 0;
|
||||
$last_cost_count = 0;
|
||||
|
||||
if($this->num_buckets <= 1) {
|
||||
TRACE("Only one Bucket, nothing to anneal.\n");
|
||||
return;
|
||||
}
|
||||
// $this->print_buckets();
|
||||
while(1) {
|
||||
$moves = $this->start_moves;
|
||||
for($m = 0; $m<$moves; $m++) {
|
||||
// $this->print_buckets();
|
||||
/* Pick 2 moves at random */
|
||||
$move = $this->pick_move();
|
||||
/* See what the new cost is compared to the old */
|
||||
list($delta_c, $movedata) =
|
||||
$this->compute_delta_cost($move);
|
||||
|
||||
|
||||
$r = floatval(rand()) / floatval(getrandmax());
|
||||
/* Decide if we want to keep it */
|
||||
$e = exp(-$delta_c / $temperature);
|
||||
// TRACE("r=$r, exp=$e, delta=$delta_c\n");
|
||||
if($r < exp(-$delta_c / $temperature)) {
|
||||
/* Yes, we do, record the move */
|
||||
$this->accept_move($move, $movedata);
|
||||
$current_cost += $delta_c;
|
||||
$n_accepted++;
|
||||
if($current_cost < $this->cost)
|
||||
$this->cost = $current_cost;
|
||||
// TRACE("Move accepted, cost=$current_cost\n");
|
||||
} else {
|
||||
// TRACE("Move rejected\n");
|
||||
}
|
||||
$this->iterations++;
|
||||
if($this->iterations % 50000 == 0) {
|
||||
TRACE(" {$this->iterations} iterations, cost={$this->cost}, temperature=$temperature\n");
|
||||
// $this->print_buckets();
|
||||
}
|
||||
}
|
||||
if($this->cost == $last_cost) {
|
||||
$last_cost_count ++;
|
||||
} else {
|
||||
$last_cost = $this->cost;
|
||||
$last_cost_count=0;
|
||||
}
|
||||
|
||||
if($temperature < 0.1 && $last_cost_count > 10)
|
||||
break;
|
||||
// TRACE("Cost is {$this->cost}\n");
|
||||
$temperature *= $this->rate;
|
||||
}
|
||||
TRACE("Annealing complete. {$this->iterations} iterations. Final cost is {$this->cost}\n");
|
||||
}
|
||||
|
||||
function print_bucket($x)
|
||||
{
|
||||
$b = $this->bucket[$x];
|
||||
print("Bucket $x: (cost: {$this->bucket_cost[$x]})\n");
|
||||
print(" ");
|
||||
for($y=0;$y<count($b); $y++) {
|
||||
print("{$b[$y]} ");
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
function print_buckets()
|
||||
{
|
||||
for($x=0; $x<$this->num_buckets; $x++) {
|
||||
$this->print_bucket($x);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@ -178,4 +178,16 @@ function getJudgingTeam($teamid)
|
||||
|
||||
}
|
||||
|
||||
function judges_scheduler_load_config()
|
||||
{
|
||||
global $config;
|
||||
$configq=mysql_query("SELECT * FROM config WHERE year='".$config['FAIRYEAR']."' AND var LIKE 'JSCHEDULER_%'");
|
||||
$data=array();
|
||||
while($configr=mysql_fetch_object($configq)) {
|
||||
$v = substr($configr->var, 11);
|
||||
$data[$v]=$configr->val;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
?>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,13 +16,15 @@
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
along with this pr<input type=\"submit\" value=\"".i18n("Save Configuration")."\" />\n";
|
||||
ogram; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
require("../common.inc.php");
|
||||
require("../config_editor.inc.php");
|
||||
auth_required('admin');
|
||||
require("judges.inc.php");
|
||||
require("judges_schedulerconfig_check.inc.php");
|
||||
@ -32,61 +34,66 @@
|
||||
echo "<a href=\"index.php\"><< ".i18n("Back to Administration")."</a>\n";
|
||||
echo "<a href=\"judges.php\"><< ".i18n("Back to Judges")."</a>\n";
|
||||
|
||||
if($_GET['edit']) $edit=$_GET['edit'];
|
||||
if($_POST['edit']) $edit=$_POST['edit'];
|
||||
if($_GET['action']) $action=$_GET['action'];
|
||||
if($_POST['action']) $action=$_POST['action'];
|
||||
|
||||
$q=mysql_query("SELECT * FROM judges_schedulerconfig WHERE year='-1'");
|
||||
while($r=mysql_fetch_object($q))
|
||||
{
|
||||
mysql_query("INSERT INTO judges_schedulerconfig (var,val,description,year) VALUES (
|
||||
'".mysql_escape_string($r->var)."',
|
||||
'".mysql_escape_string($r->val)."',
|
||||
'".mysql_escape_string($r->description)."',
|
||||
'".$config['FAIRYEAR']."')");
|
||||
}
|
||||
|
||||
if($_POST['action']=="save")
|
||||
{
|
||||
if($_POST['saveconfig'])
|
||||
{
|
||||
foreach($_POST['saveconfig'] as $key=>$val)
|
||||
{
|
||||
mysql_query("UPDATE judges_schedulerconfig SET val='".mysql_escape_string(stripslashes($val))."' WHERE year='".$config['FAIRYEAR']."' AND var='$key'");
|
||||
}
|
||||
}
|
||||
echo happy(i18n("Judges Scheduler Configuration successfully saved"));
|
||||
|
||||
|
||||
}
|
||||
$q=mysql_query("SELECT * FROM config WHERE year=0 ORDER BY var");
|
||||
echo "<form method=\"post\" action=\"judges_schedulerconfig.php\">";
|
||||
echo "<input type=\"hidden\" name=\"action\" value=\"save\">\n";
|
||||
echo "<table>";
|
||||
|
||||
echo "<tr><td colspan=\"3\"><hr /><br /><h3>".i18n("Scheduler configuration settings for fair year %1",array($config['FAIRYEAR']))."</h3></td></tr>";
|
||||
|
||||
$q=mysql_query("SELECT * FROM judges_schedulerconfig WHERE year='".$config['FAIRYEAR']."' ORDER BY var");
|
||||
$schedulerconfig=array();
|
||||
while($r=mysql_fetch_object($q))
|
||||
{
|
||||
$schedulerconfig[$r->var]=$r->val;
|
||||
echo "<tr><td>$r->var</td><td>".i18n($r->description)."</td><td><input type=\"text\" name=\"saveconfig[$r->var]\" value=\"$r->val\" /></td></tr>";
|
||||
|
||||
|
||||
}
|
||||
echo "</table>";
|
||||
echo "<input type=\"submit\" value=\"".i18n("Save Configuration")."\" />\n";
|
||||
echo "</form>";
|
||||
config_editor("JSCHEDULER_", $config['FAIRYEAR'], "var", $_SERVER['PHP_SELF']);
|
||||
|
||||
echo "<hr />";
|
||||
$ok = 1;
|
||||
|
||||
$ok=checkPrerequisites();
|
||||
echo "<table class='headertable'><tr><td><h3>Timeslots</h3></td>";
|
||||
echo "<td> - <a href=\"judges_timeslots.php\">".i18n("Timeslot Manager")."</a>";
|
||||
echo "</td></tr></table>";
|
||||
|
||||
$timeslots = judges_scheduler_check_timeslots();
|
||||
if($timeslots > 0) {
|
||||
echo happy(i18n("There are %1 timeslot(s) defined for divisional judging, good", array($timeslots)));
|
||||
} else {
|
||||
echo error(i18n("There are no timeslots defined for divisional judging"));
|
||||
$ok = 0;
|
||||
}
|
||||
|
||||
echo "<table class='headertable'><tr><td><h3>Awards</h3></td>";
|
||||
echo "<td> - <a href=\"awards.php\">".i18n("Awards Manager")."</a>";
|
||||
echo "</td></tr></table>";
|
||||
|
||||
$missing_awards = judges_scheduler_check_awards();
|
||||
if(count($missing_awards) == 0) {
|
||||
echo happy(i18n("There is a divisional award for each division, good"));
|
||||
} else {
|
||||
echo "<br />The following awards are missing:<br /><ul>";
|
||||
for($x=0; $x<count($missing_awards); $x++) {
|
||||
print($missing_awards[$x]."<br />");
|
||||
}
|
||||
echo "</ul>";
|
||||
echo error(i18n("There are missing divisional awards"));
|
||||
$ok = 0;
|
||||
}
|
||||
|
||||
echo "<table class='headertable'><tr><td><h3>Divisional Judging Groupings</h3></td>";
|
||||
echo "<td> - <a href=\"judges_jdiv.php\">".i18n("Divisional Judging Groupings Manager")."</a>";
|
||||
echo "</td></tr></table>";
|
||||
|
||||
$jdivs = judges_scheduler_check_jdivs();
|
||||
if($jdivs > 0) {
|
||||
echo happy(i18n("There are %1 divisional groups defined for divisional judging, good", array($jdivs)));
|
||||
} else {
|
||||
echo error(i18n("There are no divisional groups defined for divisional judging"));
|
||||
$ok = 0;
|
||||
}
|
||||
|
||||
echo "<h3>Projects and Judges</h3><br />";
|
||||
|
||||
$k=judges_scheduler_check_judges();
|
||||
|
||||
if(!$k) $ok=0;
|
||||
|
||||
if($ok)
|
||||
{
|
||||
echo i18n("Everything looks in order, we're ready to create the divisional awards judging teams. Click 'Create Divisional Awards Judging Teams' below to start the scheduler. Please be patient as it may take 20-30 seconds to find an optimal solution to the judging team assignments");
|
||||
echo i18n("Everything looks in order, we're ready to create the
|
||||
divisional awards judging teams. Click 'Create Divisional Awards
|
||||
Judging Teams' below to start the scheduler. Please be patient as it
|
||||
may take several minutes find an good solution to the judging team
|
||||
assignments.");
|
||||
|
||||
echo "<br />";
|
||||
echo "<br />";
|
||||
|
||||
|
@ -1,59 +1,119 @@
|
||||
<?
|
||||
|
||||
function checkPrerequisites()
|
||||
function judges_scheduler_check_timeslots()
|
||||
{
|
||||
global $config;
|
||||
global $config;
|
||||
|
||||
$q=mysql_query("SELECT * FROM judges_schedulerconfig WHERE year='".$config['FAIRYEAR']."' ORDER BY var");
|
||||
$q=mysql_query("SELECT * FROM judges_timeslots WHERE ".
|
||||
" year='".$config['FAIRYEAR']."'".
|
||||
" AND allowdivisional='yes'" );
|
||||
$rows = mysql_num_rows($q);
|
||||
|
||||
$schedulerconfig=array();
|
||||
while($r=mysql_fetch_object($q))
|
||||
{
|
||||
$schedulerconfig[$r->var]=$r->val;
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
echo i18n("Based on your configuration data above, here are some calculations");
|
||||
echo "<br />";
|
||||
function judges_scheduler_check_awards()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$totalteams=0;
|
||||
$catq=mysql_query("SELECT * FROM projectcategories WHERE year='{$config['FAIRYEAR']}' ORDER BY mingrade");
|
||||
while($catr=mysql_fetch_object($catq))
|
||||
{
|
||||
echo "<h3>$catr->category</h3>";
|
||||
echo "<table>";
|
||||
echo "<tr><th>Division</th><th>Projects</th><th>Teams</th></tr>";
|
||||
if($config['filterdivisionbycategory']=="yes")
|
||||
$divq=mysql_query("SELECT projectdivisions.* FROM projectdivisions,projectcategoriesdivisions_link WHERE projectdivisions.year='{$config['FAIRYEAR']}' AND projectcategoriesdivisions_link.projectcategories_id='$catr->id' AND projectcategoriesdivisions_link.projectdivisions_id=projectdivisions.id AND projectcategoriesdivisions_link.year='".$config['FAIRYEAR']."' ORDER BY id");
|
||||
else
|
||||
$divq=mysql_query("SELECT * FROM projectdivisions WHERE year='{$config['FAIRYEAR']}' ORDER BY id");
|
||||
echo mysql_error();
|
||||
while($divr=mysql_fetch_object($divq))
|
||||
{
|
||||
$langq=mysql_query("SELECT * FROM languages WHERE active='Y'");
|
||||
while($langr=mysql_fetch_object($langq))
|
||||
{
|
||||
$numq=mysql_query("SELECT COUNT(id) AS num FROM projects WHERE projectcategories_id='$catr->id' AND projectdivisions_id='$divr->id' AND year='{$config['FAIRYEAR']}' AND language='$langr->lang'");
|
||||
$numr=mysql_fetch_object($numq);
|
||||
echo "<tr><td>".i18n($divr->division)." ($langr->lang)</td>";
|
||||
echo "<td align=\"center\">$numr->num</td>";
|
||||
$numteams=ceil($numr->num/$schedulerconfig['max_projects_per_team']*$schedulerconfig['num_times_judged']);
|
||||
if($numteams<$schedulerconfig['num_times_judged']) $numteams=$schedulerconfig['num_times_judged'];
|
||||
if($numr->num==0) $numteams=0;
|
||||
$q=mysql_query("SELECT * FROM projectdivisions WHERE year='".$config['FAIRYEAR']."' ORDER BY id");
|
||||
while($r=mysql_fetch_object($q))
|
||||
$div[$r->id]=$r->division;
|
||||
|
||||
echo "<td align=\"center\">$numteams</td>";
|
||||
$totalteams+=$numteams;
|
||||
echo "</tr>";
|
||||
$q=mysql_query("SELECT * FROM projectcategories WHERE year='".$config['FAIRYEAR']."' ORDER BY id");
|
||||
while($r=mysql_fetch_object($q))
|
||||
$cat[$r->id]=$r->category;
|
||||
|
||||
$dkeys = array_keys($div);
|
||||
$ckeys = array_keys($cat);
|
||||
|
||||
$missing_awards = array();
|
||||
foreach($dkeys as $d) {
|
||||
reset($ckeys);
|
||||
foreach ($ckeys as $c) {
|
||||
$q=mysql_query("SELECT award_awards.id FROM
|
||||
award_awards,
|
||||
award_awards_projectcategories,
|
||||
award_awards_projectdivisions
|
||||
WHERE
|
||||
award_awards.year='{$config['FAIRYEAR']}'
|
||||
AND award_awards_projectcategories.year='{$config['FAIRYEAR']}'
|
||||
AND award_awards_projectdivisions.year='{$config['FAIRYEAR']}'
|
||||
AND award_awards.id=award_awards_projectcategories.award_awards_id
|
||||
AND award_awards.id=award_awards_projectdivisions.award_awards_id
|
||||
AND award_awards_projectcategories.projectcategories_id='$c'
|
||||
AND award_awards_projectdivisions.projectdivisions_id='$d'
|
||||
AND award_awards.award_types_id='1'
|
||||
");
|
||||
echo mysql_error();
|
||||
if(mysql_num_rows($q)!=1) {
|
||||
$missing_awards[] = "{$cat[$c]} - {$div[$d]}";
|
||||
}
|
||||
}
|
||||
echo "</table>";
|
||||
echo "<br />";
|
||||
echo "<br />";
|
||||
}
|
||||
return $missing_awards;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function judges_scheduler_check_jdivs()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$q=mysql_query("SELECT DISTINCT jdiv_id FROM judges_jdiv ");
|
||||
$rows = mysql_num_rows($q);
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
|
||||
function judges_scheduler_check_judges()
|
||||
{
|
||||
global $config;
|
||||
$ok = 1;
|
||||
|
||||
$data = judges_scheduler_load_config();
|
||||
|
||||
$jdiv = array();
|
||||
$q=mysql_query("SELECT * FROM judges_jdiv");
|
||||
while($r=mysql_fetch_object($q)) {
|
||||
$d = $r->projectdivisions_id;
|
||||
$c = $r->projectcategories_id;
|
||||
$l = $r->lang;
|
||||
|
||||
$qp = mysql_query("SELECT COUNT(id) as cnt FROM projects WHERE ".
|
||||
" year='".$config['FAIRYEAR']."' AND ".
|
||||
" projectdivisions_id='$d' AND ".
|
||||
" projectcategories_id='$c' AND ".
|
||||
" language='$l' "
|
||||
);
|
||||
$qr = mysql_fetch_object($qp);
|
||||
|
||||
$jdiv[$r->jdiv_id]['num_projects'] += $qr->cnt;
|
||||
|
||||
}
|
||||
|
||||
$totalteams = 0;
|
||||
print("<table width=75%><tr><th></th>".
|
||||
"<th>".i18n("Projects")."</th>".
|
||||
"<th>".i18n("Required Teams")."</th></tr>");
|
||||
$keys = array_keys($jdiv);
|
||||
for($k=0; $k<count($keys); $k++) {
|
||||
$jdiv_id = $keys[$k];
|
||||
$c = $jdiv[$jdiv_id]['num_projects'];
|
||||
$t=ceil($c/$data['max_projects_per_team']*$data['times_judged']);
|
||||
$jdiv[$jdiv_id]['num_jteams'] = $t;
|
||||
$totalteams+=$t;
|
||||
|
||||
print("<tr><td>Judging Division Group $jdiv_id</td><td align=center>$c</td><td align=center>$t</td></tr>");
|
||||
}
|
||||
print("</table>");
|
||||
|
||||
echo "<b>";
|
||||
echo "Total judging teams required: $totalteams";
|
||||
echo "<br />";
|
||||
$minjudges=($totalteams*$schedulerconfig['min_judges_per_team']);
|
||||
$maxjudges=($totalteams*$schedulerconfig['max_judges_per_team']);
|
||||
$minjudges=($totalteams*$data['min_judges_per_team']);
|
||||
$maxjudges=($totalteams*$data['max_judges_per_team']);
|
||||
echo "Minimum number of judges required: $minjudges";
|
||||
echo "<br />";
|
||||
echo "Maximum number of judges acceptable: $maxjudges";
|
||||
@ -65,131 +125,17 @@ function checkPrerequisites()
|
||||
echo "Current number of registered judges: $currentjudges";
|
||||
echo "<br />";
|
||||
echo "<br />";
|
||||
$ok=true;
|
||||
if($currentjudges<$minjudges)
|
||||
{
|
||||
echo error(i18n("You do not have sufficient number of judges based on your parameters"));
|
||||
echo " ";
|
||||
echo "<a href=\"judges_schedulerconfig.php\">".i18n("Update Scheduler Configuration")."</a> (".i18n("or get more judges!").")";
|
||||
$ok=false;
|
||||
echo "<a href=\"judges_data.php\">".i18n("Update Scheduler Configuration")."</a> (".i18n("or get more judges!").")";
|
||||
$ok=0;
|
||||
}
|
||||
else
|
||||
echo happy(i18n("You have a sufficient number of judges based on your parameters"));
|
||||
|
||||
//now check if we can find a divisional award for each division and category
|
||||
|
||||
|
||||
$q=mysql_query("SELECT * FROM projectdivisions WHERE year='".$config['FAIRYEAR']."' ORDER BY id");
|
||||
while($r=mysql_fetch_object($q))
|
||||
$div[$r->id]=$r->division;
|
||||
|
||||
$q=mysql_query("SELECT * FROM projectcategories WHERE year='".$config['FAIRYEAR']."' ORDER BY id");
|
||||
while($r=mysql_fetch_object($q))
|
||||
$cat[$r->id]=$r->category;
|
||||
|
||||
if($config['filterdivisionbycategory']=="yes")
|
||||
{
|
||||
$q=mysql_query("SELECT * FROM projectcategoriesdivisions_link WHERE year='".$config['FAIRYEAR']."' ORDER BY id");
|
||||
while($r=mysql_fetch_object($q))
|
||||
$catdiv[$r->projectcategories_id][]=$r->projectdivisions_id;
|
||||
}
|
||||
$foundawards="";
|
||||
$notfoundawards="";
|
||||
$foundteams="";
|
||||
foreach($div AS $d_id=>$d_division)
|
||||
{
|
||||
foreach($cat AS $c_id=>$c_category)
|
||||
{
|
||||
if($config['filterdivisionbycategory']=="yes")
|
||||
{
|
||||
if(!in_array($d_id,$catdiv[$c_id]))
|
||||
continue;
|
||||
}
|
||||
$q=mysql_query("SELECT award_awards.id FROM
|
||||
award_awards,
|
||||
award_awards_projectcategories,
|
||||
award_awards_projectdivisions
|
||||
WHERE
|
||||
award_awards.year='{$config['FAIRYEAR']}'
|
||||
AND award_awards_projectcategories.year='{$config['FAIRYEAR']}'
|
||||
AND award_awards_projectdivisions.year='{$config['FAIRYEAR']}'
|
||||
AND award_awards.id=award_awards_projectcategories.award_awards_id
|
||||
AND award_awards.id=award_awards_projectdivisions.award_awards_id
|
||||
AND award_awards_projectcategories.projectcategories_id='$c_id'
|
||||
AND award_awards_projectdivisions.projectdivisions_id='$d_id'
|
||||
AND award_awards.award_types_id='1'
|
||||
");
|
||||
echo mysql_error();
|
||||
if(mysql_num_rows($q)!=1)
|
||||
{
|
||||
while($r=mysql_fetch_object($q))
|
||||
print_r($r);
|
||||
$notfoundawards.="$c_category - $d_division, ";
|
||||
$ok=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$r=mysql_fetch_object($q);
|
||||
$foundawards.="$c_category - $d_division, ";
|
||||
//if we found an award thats good, but it would be bad if there's already a judges team
|
||||
//that is assigned to the award, so now lets check the judges teams to see if ones assigned
|
||||
//to this award.
|
||||
|
||||
$q=mysql_query("SELECT judges_teams.num,judges_teams.name
|
||||
FROM judges_teams,
|
||||
judges_teams_awards_link
|
||||
WHERE
|
||||
judges_teams_awards_link.award_awards_id='$r->id'
|
||||
AND judges_teams.year='".$config['FAIRYEAR']."'
|
||||
AND judges_teams_awards_link.judges_teams_id=judges_teams.id");
|
||||
if(mysql_num_rows($q))
|
||||
{
|
||||
$r=mysql_fetch_object($q);
|
||||
$ok=false;
|
||||
$foundteams.=i18n("(%1) %2, ",array($r->num,$r->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$notfoundawards=substr($notfoundawards,0,-2);
|
||||
$foundawards=substr($foundawards,0,-2);
|
||||
$foundteams=substr($foundteams,0,-2);
|
||||
|
||||
if($notfoundawards)
|
||||
{
|
||||
echo error(i18n("Cannot find awards for: %1. These awards must be created first",array($notfoundawards)));
|
||||
echo " ";
|
||||
echo "<a href=\"awards.php\">".i18n("Awards Manager")."</a>";
|
||||
}
|
||||
if($foundawards)
|
||||
echo happy(i18n("Found awards for: %1",array($foundawards)));
|
||||
if($foundteams)
|
||||
{
|
||||
echo error(i18n("Found judging teams that are currently assigned to divisional awards: %1. These teams must be removed first",array($foundteams)));
|
||||
echo " <a href=\"judges_teams.php\">".i18n("Judging Teams Manager")."</a>";
|
||||
}
|
||||
else
|
||||
echo happy(i18n("No judging teams are assigned to divisional awards (good!)"));
|
||||
|
||||
//now check if we have enough timeslots available...
|
||||
|
||||
$q=mysql_query("SELECT COUNT(id) AS num FROM judges_timeslots WHERE year='".$config['FAIRYEAR']."' AND allowdivisional='yes'");
|
||||
$r=mysql_fetch_object($q);
|
||||
$numslots=$r->num;
|
||||
|
||||
if($numslots<$schedulerconfig['max_projects_per_team'])
|
||||
{
|
||||
echo error(i18n("You do not have enough judging timeslots available for divisional judging. Please create more timeslots first. Available: %1, Required: %2",array($numslots,$schedulerconfig['max_projects_per_team'])));
|
||||
echo " <a href=\"judges_timeslots.php\">".i18n("Timeslot Manager")."</a>";
|
||||
$ok=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
echo happy(i18n("You have sufficient timeslots available. Available: %1, Required: %2",array($numslots,$schedulerconfig['max_projects_per_team'])));
|
||||
}
|
||||
//asdf
|
||||
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
|
104
config_editor.inc.php
Normal file
104
config_editor.inc.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?
|
||||
/*
|
||||
This file is part of the 'Science Fair In A Box' project
|
||||
SFIAB Website: http://www.sfiab.ca
|
||||
|
||||
Copyright (C) 2005 Sci-Tech Ontario Inc <info@scitechontario.org>
|
||||
Copyright (C) 2005 James Grant <james@lightbox.org>
|
||||
|
||||
This program 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, version 2.
|
||||
|
||||
This program 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 this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
|
||||
function config_editor_load($append, $year)
|
||||
{
|
||||
$query = "SELECT * FROM config WHERE year='$year' ";
|
||||
if($append != '') {
|
||||
$query .= " AND var LIKE '{$append}%'";
|
||||
}
|
||||
$q = mysql_query($query);
|
||||
print(mysql_error());
|
||||
|
||||
$var = array();
|
||||
while($r=mysql_fetch_object($q)) {
|
||||
$var[$r->var]['val'] = $r->val;
|
||||
$var[$r->var]['desc'] = $r->description;
|
||||
}
|
||||
return $var;
|
||||
}
|
||||
|
||||
function config_editor_parse_from_http_headers($array_name)
|
||||
{
|
||||
$ans = array();
|
||||
if(!is_array($_POST[$array_name])) return $ans;
|
||||
|
||||
$keys = array_keys($_POST[$array_name]);
|
||||
foreach($keys as $id) {
|
||||
$ans[$id] = stripslashes($_POST[$array_name][$id]);
|
||||
}
|
||||
return $ans;
|
||||
}
|
||||
|
||||
/* A complete question editor. Just call it with the
|
||||
* section you want to edit, a year, the array_name to use for
|
||||
* POSTing and GETting the questions (so you can put more than one
|
||||
* edtior on a single page), and give it $_SERVER['PHP_SELF'], because
|
||||
* php_self inside this function is this file.
|
||||
* FUTURE WORK: it would be nice to hide the order, and just implement
|
||||
* a bunch of up/down arrows, and dynamically compute the order for
|
||||
* all elements */
|
||||
function config_editor($append, $year, $array_name, $self)
|
||||
{
|
||||
global $config;
|
||||
|
||||
if($_POST['action']=="update") {
|
||||
|
||||
$var = config_editor_parse_from_http_headers($array_name);
|
||||
$varkeys = array_keys($var);
|
||||
foreach($varkeys as $k) {
|
||||
$val = mysql_escape_string(stripslashes($var[$k]));
|
||||
$v = mysql_escape_string(stripslashes($k));
|
||||
mysql_query("UPDATE config SET val=\"$val\" WHERE var=\"$v\"");
|
||||
print mysql_error();
|
||||
// echo "Saving {$v} = $val<br>";
|
||||
}
|
||||
echo happy(i18n("Configuration Updated"));
|
||||
}
|
||||
|
||||
/* Load questions, then handle up and down, because with up and down we
|
||||
* have to modify 2 questions to maintain the order */
|
||||
$var = config_editor_load($append, $year);
|
||||
|
||||
echo "<form method=\"post\" action=\"$self\">";
|
||||
|
||||
echo "<table>";
|
||||
|
||||
$varkeys = array_keys($var);
|
||||
foreach($varkeys as $k) {
|
||||
print("<tr>");
|
||||
print("<td>{$var[$k]['desc']}</td>");
|
||||
print("<td>");
|
||||
print("<input size=\"5\" type=\"text\" name=\"${array_name}[$k]\" value=\"".htmlspecialchars($var[$k]['val'])."\">\n");
|
||||
echo "</td></tr>";
|
||||
}
|
||||
print("</table>");
|
||||
print("<input type=hidden name=\"action\" value=\"update\" >\n");
|
||||
print("<input type=\"submit\" value=\"".i18n("Save Configuration")."\" />\n");
|
||||
|
||||
echo "</form>";
|
||||
}
|
||||
|
||||
?>
|
@ -13,3 +13,15 @@ CREATE TABLE `judges_jdiv` (
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
|
||||
--
|
||||
-- Dumping data for table `config`
|
||||
--
|
||||
|
||||
INSERT INTO `config` (`var`, `val`, `description`, `year`) VALUES
|
||||
('JSCHEDULER_max_projects_per_team', '7', 'The maximum number of projects that a judging team can judge.', -1),
|
||||
('JSCHEDULER_times_judged', '1', 'The number of times each project must be judged by different judging teams.', -1),
|
||||
('JSCHEDULER_min_judges_per_team', '3', 'The minimum number of judges that can be on a judging team.', -1),
|
||||
('JSCHEDULER_max_judges_per_team', '3', 'The maximum number of judges that can be on a judging team.', -1),
|
||||
('JSCHEDULER_effort', '10000', 'This number controls how long and hard the judge scheduler will look for a scheduling solution. Smaller numbers are lower effort. 100 is practically no effort, 1000 is moderate effort, 10000 is high effort. It can take several tens of minutes to run the scheduler with high effort, but it gives a very good solution.', -1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user