2006-01-03 02:08:23 +00:00
< ?
/*
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 .
*/
?>
< ?
require ( " ../common.inc.php " );
2006-08-01 19:43:15 +00:00
require ( " ../questions.inc.php " );
require ( " judges.inc.php " );
require ( " anneal.inc.php " );
2006-01-03 02:08:23 +00:00
auth_required ( 'admin' );
2006-01-31 22:34:04 +00:00
send_header ( " Judging teams automatic scheduler " );
2006-08-01 19:43:15 +00:00
echo i18n ( " The scheduler is running. Depending on the effort it may take
several minutes to complete . It will generate a lot of output on this page ,
most of it is just information about what the scheduler is doing . You can copy
this page and save it as a text file to have a record of what the scheduler
did . ( And this output helps us to debug problems with it if you encounter
something that clearly isn ' t correct , just send us this output ) " );
echo " <br /> " ;
echo " <br /> " ;
echo i18n ( " When complete, a green bar will appear at the BOTTOM of this page
saying that everything has completed successfully . When complete , you can use
the following links to manage the Judging Teams and the Judges assigned to them
( clicking on these links now will stop the scheduler ) . " );
echo " <br /> " ;
echo " <br /> " ;
echo " <a href= \" judges_teams.php \" > " . i18n ( " Manage Judge Teams " ) . " </a> " ;
echo " <br /> " ;
echo " <a href= \" judges_teams_members.php \" > " . i18n ( " Manage Judge Members " ) . " </a> " ;
echo " <br /> " ;
echo " <br /> " ;
echo i18n ( " If you get an error like: \" Fatal error: Maximum execution time of
30 seconds exceeded ... \ " you will need to talk to your system admin and have
them adjust the \ " max_execution_time \" variable in the \" php.ini \" file from
30 ( seconds ) to something larger , like 600 ( 10 minutes ) . And then have them
restart the webserver for the change to take effect " );
echo " <br /> " ;
echo " <br /> " ;
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
TRACE ( " <pre> " );
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
//function TRACE() { }
//function TRACE_R() { }
function TRACE ( $str ) { print ( $str ); }
function TRACE_R ( $array ) { print_r ( $array ); }
2006-01-03 02:08:23 +00:00
/* The cost function is :
2006-01-26 23:06:47 +00:00
+ 50 * each judge below the min for each team
2006-01-26 15:04:25 +00:00
+ 10 * each judge above the max for each team
+ 2 * each level of preference away from the
2006-01-03 02:08:23 +00:00
max level for each judge
2006-01-26 23:06:47 +00:00
+ 40 if the team doesn ' t have a chair .
2006-01-26 15:04:25 +00:00
+ 25 for each memember on the team that can ' t speak the language
of the judging team
2006-01-03 02:08:23 +00:00
( ex : if a judge has selected LS -> 2 , PS -> 0 , CS ->- 1
then matching that judge with a :
2006-01-26 15:04:25 +00:00
LS = - 4 ,
2006-01-03 02:08:23 +00:00
PS = 0 ,
2006-01-26 15:04:25 +00:00
CS = - 2 ,
2006-01-03 02:08:23 +00:00
else = 0
)
*/
/* Compute the cost of adding a judge to a team */
2006-01-26 15:04:25 +00:00
2006-08-01 19:43:15 +00:00
function judges_cost_function ( $annealer , $bucket_id , $ids )
2006-01-03 02:08:23 +00:00
{
2006-08-01 19:43:15 +00:00
global $jteam ;
global $judges ;
/* Bucket ID is the team number */
/* ids are the judge ids currently in the bucket */
// TRACE("Bucket id=$bucket_id, ids=");
// TRACE_R($ids);
2006-01-03 02:08:23 +00:00
$cost = 0 ;
2006-01-26 15:04:25 +00:00
$have_chair = 0 ;
2006-08-01 19:43:15 +00:00
if ( $bucket_id == 0 ) {
/* This is the placeholder */
$cost = count ( $ids ) * 5 ;
// TRACE("Extra judge team cost=$cost\n");
return $cost ;
}
2006-01-26 15:04:25 +00:00
2006-08-01 19:43:15 +00:00
$t =& $jteam [ $bucket_id ];
2006-01-03 02:08:23 +00:00
/* Compute the over max / under min costs */
2006-08-01 19:43:15 +00:00
$c = count ( $ids );
$min = ( $c < $t [ 'min_judges' ]) ? $t [ 'min_judges' ] - $c : 0 ;
$max = ( $c > $t [ 'max_judges' ]) ? $c - $t [ 'max_judges' ] : 0 ;
2006-01-26 23:06:47 +00:00
$cost += $min * 50 ;
2006-01-03 02:08:23 +00:00
$cost += $max * 10 ;
2006-01-16 04:58:43 +00:00
// TRACE("Under min=$min, over max=$max\n");
2006-01-03 02:08:23 +00:00
/* For each judge on the team, score their preferences */
2006-08-01 19:43:15 +00:00
for ( $x = 0 ; $x < count ( $ids ); $x ++ ) {
$j =& $judges [ $ids [ $x ]];
2006-01-03 02:08:23 +00:00
/* Get the division , and see where it fits with this
* judges preferences */
2006-08-01 19:43:15 +00:00
$cpref = 0 ;
for ( $y = 0 ; $y < count ( $t [ 'cats' ]); $y ++ ) {
$l = $t [ 'cats' ][ $y ];
/* Lookup the judge cat pref for this category */
$pref = - $j [ 'catprefs' ][ $l ] + 2 ;
/* $pref = 0 (best match) --- 4 (worst match) */
$cpref += $pref ;
}
$dpref = 0 ;
for ( $y = 0 ; $y < count ( $t [ 'divs' ]); $y ++ ) {
$l = $t [ 'divs' ][ $y ];
/* Lookup the judge cat pref for this category */
$pref = - $j [ 'divprefs' ][ $l ] + 2 ;
/* $pref = 0 (best match) --- 4 (worst match) */
$dpref += $pref ;
}
// TRACE("Judge {$ids[$x]}({$j['name']}) cp=$cpref, dp=$dpref\n");
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
$cost += 2 * $cpref ;
$cost += 2 * $dpref ;
2006-01-26 15:04:25 +00:00
/* See if the judge is willing to chair a team */
2006-08-01 19:43:15 +00:00
if ( $j [ 'willing_chair' ] == 'yes' ) $have_chair = 1 ;
2006-01-26 15:04:25 +00:00
2006-08-01 19:43:15 +00:00
/* For each lang the team needs that the judge doesn ' t have ,
* increase the cost */
for ( $y = 0 ; $y < count ( $t [ 'langs' ]); $y ++ ) {
$l = $t [ 'langs' ][ $y ];
if ( ! in_array ( $l , $j [ 'languages' ])) $cost += 25 ;
2006-01-26 15:04:25 +00:00
}
}
/* Huge penalty for a team without a willing chair */
2006-08-01 19:43:15 +00:00
if ( ! $have_chair ) $cost += 40 ;
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
// TRACE("Team $bucket_id, cost is $cost\n");
2006-01-03 02:08:23 +00:00
return $cost ;
}
2006-08-01 19:43:15 +00:00
$current_jdiv = array ();
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
function jdiv_compute_cost ( $annealer , $bucket_id , $ids )
2006-01-03 02:08:23 +00:00
{
2006-08-01 19:43:15 +00:00
/* IDS is a list of project ids for a judging team */
global $current_jdiv ;
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
$cost = 0 ;
$t_div = array ();
$t_cat = array ();
$t_lang = array ();
/* Foreach project this jteam is judging , record the
* div / cat / lang */
for ( $x = 0 ; $x < count ( $ids ); $x ++ ) {
$proj =& $current_jdiv [ 'projects' ][ $ids [ $x ]];
if ( ! in_array ( $proj [ 'div' ], $t_div )) $t_div [] = $proj [ 'div' ];
if ( ! in_array ( $proj [ 'cat' ], $t_cat )) $t_cat [] = $proj [ 'cat' ];
if ( ! in_array ( $proj [ 'lang' ], $t_lang )) $t_lang [] = $proj [ 'lang' ];
2006-01-03 02:08:23 +00:00
}
2006-08-01 19:43:15 +00:00
/* Square the project count for highter penalties for more projects */
$cost += floor ( abs ( count ( $ids ) - $annealer -> items_per_bucket )) * 100 ;
/* Score 100 pts for multiple languages */
$cost += ( count ( $t_lang ) - 1 ) * 75 ;
/* Score 25pts for multiple divs/cats */
$cost += ( count ( $t_div ) - 1 ) * 25 ;
$cost += ( count ( $t_cat ) - 1 ) * 25 ;
2006-08-02 08:07:51 +00:00
/* Score + 200 pts for each duplicate project this team is judging , we
* really don ' t want a jteam judging the same project twice */
for ( $x = 0 ; $x < count ( $ids ) - 1 ; $x ++ ) {
for ( $y = $x + 1 ; $y < count ( $ids ); $y ++ ) {
if ( $ids [ $x ] == $ids [ $y ]) $cost += 200 ;
}
}
2006-08-01 19:43:15 +00:00
return $cost ;
2006-01-03 02:08:23 +00:00
}
2006-08-01 19:43:15 +00:00
TRACE ( " \n \n " );
$div = array ();
TRACE ( " Loading Project Divisions... \n " );
2006-01-03 02:08:23 +00:00
$q = mysql_query ( " SELECT * FROM projectdivisions WHERE year=' " . $config [ 'FAIRYEAR' ] . " ' ORDER BY id " );
while ( $r = mysql_fetch_object ( $q ))
2006-01-31 22:34:04 +00:00
{
$divshort [ $r -> id ] = $r -> division_shortform ;
2006-01-03 02:08:23 +00:00
$div [ $r -> id ] = $r -> division ;
2006-08-01 19:43:15 +00:00
TRACE ( " { $r -> id } - { $div [ $r -> id ] } \n " );
2006-01-31 22:34:04 +00:00
}
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
TRACE ( " Loading Project Age Categories... \n " );
$cat = array ();
2006-01-03 02:08:23 +00:00
$q = mysql_query ( " SELECT * FROM projectcategories WHERE year=' " . $config [ 'FAIRYEAR' ] . " ' ORDER BY id " );
2006-08-01 19:43:15 +00:00
while ( $r = mysql_fetch_object ( $q )) {
2006-01-03 02:08:23 +00:00
$cat [ $r -> id ] = $r -> category ;
2006-08-01 19:43:15 +00:00
TRACE ( " { $r -> id } - { $r -> category } \n " );
2006-02-06 16:45:39 +00:00
}
2006-08-01 19:43:15 +00:00
TRACE ( " Loading Languages... \n " );
2006-01-16 04:58:43 +00:00
$langr = array ();
$q = mysql_query ( " SELECT * FROM languages WHERE active='Y' " );
while ( $r = mysql_fetch_object ( $q )) {
2006-08-01 19:43:15 +00:00
$langr [ $r -> lang ] = $r -> langname ;
TRACE ( " { $r -> lang } - { $r -> langname } \n " );
}
2006-01-16 04:58:43 +00:00
2006-08-01 19:43:15 +00:00
$jdiv = array ();
TRACE ( " Loading Judging Division Configuration and Projects... \n " );
$q = mysql_query ( " SELECT * FROM judges_jdiv " );
while ( $r = mysql_fetch_object ( $q )) {
$jdiv [ $r -> jdiv_id ][ 'config' ][] = array ( 'div' => $r -> projectdivisions_id ,
'cat' => $r -> projectcategories_id ,
'lang' => $r -> lang );
}
2006-01-16 04:58:43 +00:00
2006-08-01 19:43:15 +00:00
$keys = array_keys ( $jdiv );
for ( $k = 0 ; $k < count ( $keys ); $k ++ ) {
$jdiv_id = $keys [ $k ];
TRACE ( " $jdiv_id\t - " );
for ( $x = 0 ; $x < count ( $jdiv [ $jdiv_id ][ 'config' ]); $x ++ ) {
$d = $jdiv [ $jdiv_id ][ 'config' ][ $x ];
if ( $x > 0 ) TRACE ( " \t - " );
TRACE ( $cat [ $d [ 'cat' ]] . " " . $div [ $d [ 'div' ]] . " - " . $langr [ $d [ 'lang' ]]);
$qp = mysql_query ( " SELECT * FROM projects WHERE " .
" year=' " . $config [ 'FAIRYEAR' ] . " ' AND " .
" projectdivisions_id=' { $d [ 'div' ] } ' AND " .
" projectcategories_id=' { $d [ 'cat' ] } ' AND " .
" language=' { $d [ 'lang' ] } ' "
);
$count = 0 ;
while ( $rp = mysql_fetch_object ( $qp )) {
$jdiv [ $jdiv_id ][ 'projects' ][ $rp -> id ] = array (
'div' => $d [ 'div' ],
'cat' => $d [ 'cat' ],
'lang' => $d [ 'lang' ]);
$count ++ ;
}
TRACE ( " ( $count projects) \n " );
}
}
2006-01-16 04:58:43 +00:00
2006-08-01 19:43:15 +00:00
TRACE ( " Loading Scheduler Configuration Data... \n " );
$data = judges_scheduler_load_config ();
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
TRACE ( " Computing required judging teams... \n " );
TRACE ( " Each judging team may judge { $data [ 'max_projects_per_team' ] } projects \n " );
TRACE ( " Each project must be judged { $data [ 'times_judged' ] } times \n " );
$keys = array_keys ( $jdiv );
for ( $k = 0 ; $k < count ( $keys ); $k ++ ) {
$jdiv_id = $keys [ $k ];
$c = count ( $jdiv [ $jdiv_id ][ 'projects' ]);
$t = ceil ( $c / $data [ 'max_projects_per_team' ] * $data [ 'times_judged' ]);
TRACE ( " $jdiv_id has $c projects, requires $t judging teams \n " );
$jdiv [ $jdiv_id ][ 'num_jteams' ] = $t ;
2006-01-16 04:58:43 +00:00
}
2006-08-01 19:43:15 +00:00
$jteam = array ();
$jteam_id = 0 ;
/* Create one more jteam, for anyone the annealer doesn't want to place */
$jteam [ $jteam_id ][ 'id' ] = $jteam_id ;
$jteam [ $jteam_id ][ 'projects' ] = array ();
$jteam [ $jteam_id ][ 'divs' ] = array ();
$jteam [ $jteam_id ][ 'cats' ] = array ();
$jteam [ $jteam_id ][ 'langs' ] = array ();
$jteam [ $jteam_id ][ 'min_judges' ] = 0 ;
$jteam [ $jteam_id ][ 'max_judges' ] = 0 ;
$jteam_id ++ ;
2006-08-02 08:07:51 +00:00
2006-08-01 19:43:15 +00:00
TRACE ( " Assigning projects to judging teams... \n " );
$keys = array_keys ( $jdiv );
for ( $k = 0 ; $k < count ( $keys ); $k ++ ) {
2006-08-02 08:07:51 +00:00
$jdiv_id = $keys [ $k ];
TRACE ( " Judging Division $jdiv_id ( { $jdiv [ $jdiv_id ][ 'num_jteams' ] } teams): \n " );
$project_ids = array ();
for ( $x = 0 ; $x < $data [ 'times_judged' ]; $x ++ ) {
$project_ids = array_merge ( $project_ids , array_keys ( $jdiv [ $jdiv_id ][ 'projects' ]) );
}
2006-08-01 19:43:15 +00:00
$current_jdiv = $jdiv [ $jdiv_id ];
$e = 100 + 10 * ( $data [ 'effort' ] / 1000 );
$a = new annealer ( $jdiv [ $jdiv_id ][ 'num_jteams' ], 125 , $e , 0.9 ,
jdiv_compute_cost , $project_ids );
$a -> anneal ();
2006-08-08 03:21:08 +00:00
$jdiv [ $jdiv_id ][ 'jteams' ] = array ();
2006-08-01 19:43:15 +00:00
for ( $x = 0 ; $x < $a -> num_buckets ; $x ++ ) {
$bkt = $a -> bucket [ $x ];
TRACE ( " SubTeam $x : \n " );
2006-08-08 03:21:08 +00:00
$jdiv [ $jdiv_id ][ 'jteams' ][] = $jteam_id ;
2006-08-01 19:43:15 +00:00
$jteam [ $jteam_id ][ 'id' ] = $jteam_id ;
$jteam [ $jteam_id ][ 'projects' ] = $a -> bucket [ $x ];
$jteam [ $jteam_id ][ 'sub' ] = $x ;
$jteam [ $jteam_id ][ 'jdiv_id' ] = $jdiv_id ;
$jteam [ $jteam_id ][ 'divs' ] = array ();
$jteam [ $jteam_id ][ 'cats' ] = array ();
$jteam [ $jteam_id ][ 'langs' ] = array ();
$jteam [ $jteam_id ][ 'min_judges' ] = $data [ 'min_judges_per_team' ];
$jteam [ $jteam_id ][ 'max_judges' ] = $data [ 'max_judges_per_team' ];
for ( $y = 0 ; $y < count ( $bkt ); $y ++ ) {
$projid = $bkt [ $y ];
$p = $jdiv [ $jdiv_id ][ 'projects' ][ $projid ];
TRACE ( " $projid - " . $cat [ $p [ 'cat' ]] . " " . $div [ $p [ 'div' ]] . " - " . $langr [ $p [ 'lang' ]] . " \n " );
if ( ! in_array ( $p [ 'cat' ], $jteam [ $jteam_id ][ 'cats' ])) {
$jteam [ $jteam_id ][ 'cats' ][] = $p [ 'cat' ];
2006-01-16 04:58:43 +00:00
}
2006-08-01 19:43:15 +00:00
if ( ! in_array ( $p [ 'div' ], $jteam [ $jteam_id ][ 'divs' ])) {
$jteam [ $jteam_id ][ 'divs' ][] = $p [ 'div' ];
}
if ( ! in_array ( $p [ 'lang' ], $jteam [ $jteam_id ][ 'langs' ])) {
$jteam [ $jteam_id ][ 'langs' ][] = $p [ 'lang' ];
2006-01-16 04:58:43 +00:00
}
}
2006-08-01 19:43:15 +00:00
$jteam_id ++ ;
2006-01-03 02:08:23 +00:00
}
}
2006-08-01 19:43:15 +00:00
TRACE ( " There are " . ( count ( $jteam ) - 1 ) . " judging teams \n " );
2006-01-16 04:58:43 +00:00
2006-08-01 19:43:15 +00:00
$willing_chair_question_id = questions_find_question_id ( " judgereg " , $config [ 'FAIRYEAR' ], " Willing Chair " );
printf ( " Judge Willing Chair = Question ID $willing_chair_question_id\n " );
2006-08-02 07:36:21 +00:00
/* Clean out the judging teams that were autocreated */
2006-08-08 03:21:08 +00:00
TRACE ( " Deleting existing divisional judging teams: " );
2006-08-02 07:36:21 +00:00
$q = mysql_query ( " SELECT * FROM judges_teams WHERE autocreate_type_id=1 AND year= { $config [ 'FAIRYEAR' ] } " );
while ( $r = mysql_fetch_object ( $q )) {
$jteam_id = $r -> id ;
print ( " $jteam_id " );
/* Clean out the judges_teams_link */
mysql_query ( " DELETE FROM judges_teams_link WHERE judges_teams_id=' $jteam_id ' AND year= { $config [ 'FAIRYEAR' ] } " );
print mysql_error ();
/* Awards */
mysql_query ( " DELETE FROM judges_teams_awards_link WHERE judges_teams_id=' $jteam_id ' AND year= { $config [ 'FAIRYEAR' ] } " );
print mysql_error ();
/* Timeslots */
mysql_query ( " DELETE FROM judges_teams_timeslots_link WHERE judges_teams_id=' $jteam_id ' AND year= { $config [ 'FAIRYEAR' ] } " );
print mysql_error ();
/* Timeslots projects */
mysql_query ( " DELETE FROM judges_teams_timeslots_projects_link WHERE judges_teams_id=' $jteam_id ' AND year= { $config [ 'FAIRYEAR' ] } " );
print mysql_error ();
}
/* Findally, delete all the autocreated judges teams */
mysql_query ( " DELETE FROM judges_teams WHERE autocreate_type_id=1 AND year= { $config [ 'FAIRYEAR' ] } " );
print mysql_error ();
TRACE ( " Done. \n " );
2006-08-01 19:43:15 +00:00
TRACE ( " Loading Judges... \n " );
2006-01-03 02:08:23 +00:00
2006-08-02 07:36:21 +00:00
$q = mysql_query ( " SELECT judges.* FROM judges,judges_years WHERE " .
" complete='yes' " .
" AND judges_years.year=' { $config [ 'FAIRYEAR' ] } ' " .
" AND judges_years.judges_id=judges.id "
);
2006-01-03 02:08:23 +00:00
$judges = array ();
2006-01-16 04:58:43 +00:00
2006-08-01 19:43:15 +00:00
2006-01-03 02:08:23 +00:00
while ( $r = mysql_fetch_object ( $q ))
{
unset ( $divprefs );
unset ( $catprefs );
2006-01-26 15:04:25 +00:00
unset ( $langprefs );
2006-01-03 02:08:23 +00:00
2006-08-02 07:43:02 +00:00
/* Try to fetch a team link ID for this judge , if we can , we don ' t want to use this judge
* in the divisional awards , they are already assigned to soemthing */
$q2 = mysql_query ( " SELECT judges_id FROM judges_teams_link WHERE " .
" judges_id=' $r->id ' " .
" AND year=' " . $config [ 'FAIRYEAR' ] . " ' " );
if ( mysql_num_rows ( $q2 ) != 0 ) {
2006-08-02 07:44:31 +00:00
TRACE ( " { $r -> firstname } { $r -> lastname } is already on a judging team, skipping. \n " );
2006-08-02 07:43:02 +00:00
continue ;
}
2006-01-03 02:08:23 +00:00
//get category preferences
$q2 = mysql_query ( " SELECT * FROM judges_catpref WHERE judges_id=' $r->id ' AND year=' " . $config [ 'FAIRYEAR' ] . " ' ORDER BY projectcategories_id " );
$catprefs = array ();
while ( $r2 = mysql_fetch_object ( $q2 ))
$catprefs [ $r2 -> projectcategories_id ] = $r2 -> rank ;
//get division preferences
$q2 = mysql_query ( " SELECT * FROM judges_expertise WHERE judges_id=' $r->id ' AND year=' " . $config [ 'FAIRYEAR' ] . " ' AND projectsubdivisions_id IS NULL ORDER BY projectdivisions_id " );
//the areas of expertise are ranked from 1 to 5, and we need them as -2,-1,0,1,2 so we simply subtract 3
$divprefs = array ();
while ( $r2 = mysql_fetch_object ( $q2 ))
$divprefs [ $r2 -> projectdivisions_id ] = $r2 -> val - 3 ;
2006-01-26 15:04:25 +00:00
$langperfs = array ();
$q3 = mysql_query ( " SELECT * from judges_languages WHERE judges_id=' $r->id ' " );
while ( $r3 = mysql_fetch_object ( $q3 ))
$langprefs [] = $r3 -> languages_lang ;
2006-08-01 19:43:15 +00:00
$q2 = mysql_query ( " SELECT answer FROM question_answers WHERE " .
" registrations_id=' { $r -> id } ' AND " .
" questions_id=' $willing_chair_question_id ' AND " .
" year=' { $config [ 'FAIRYEAR' ] } ' " );
mysql_error ();
$willing_chair = 'no' ;
if ( mysql_num_rows ( $q2 ) == 1 ) {
$r2 = mysql_fetch_object ( $q2 );
if ( $r2 -> answer == 'yes' ) $willing_chair = 'yes' ;
}
2006-01-26 15:04:25 +00:00
2006-08-01 19:43:15 +00:00
$judges [ $r -> id ] = array (
2006-01-03 02:08:23 +00:00
" judges_id " => " $r->id " ,
" name " => " $r->firstname $r->lastname " ,
" years_school " => $r -> years_school ,
" years_regional " => $r -> years_regional ,
" years_national " => $r -> years_national ,
2006-08-01 19:43:15 +00:00
" willing_chair " => $willing_chair ,
2006-01-03 02:08:23 +00:00
" divprefs " => $divprefs ,
2006-01-26 15:04:25 +00:00
" catprefs " => $catprefs ,
" languages " => $langprefs
2006-01-03 02:08:23 +00:00
);
}
2006-08-01 19:43:15 +00:00
TRACE ( " Loaded " . count ( $judges ) . " judges. \n " );
$jteam [ 0 ][ 'max_judges' ] = count ( $judges );
$judge_ids = array_keys ( $judges );
$e = $data [ 'effort' ];
$a = new annealer ( count ( $jteam ), 25 , $e , 0.98 , judges_cost_function , $judge_ids );
$a -> anneal ();
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
function pr_judge ( & $jt , $jid )
{
global $judges ;
$j =& $judges [ $jid ];
print ( " - { $j [ 'name' ] } ( " );
for ( $x = 0 ; $x < count ( $j [ 'languages' ]); $x ++ ) {
print ( $j [ 'languages' ][ $x ] . " " );
}
print ( " ) " );
print ( " ( " );
for ( $x = 0 ; $x < count ( $jt [ 'cats' ]); $x ++ ) {
$pref = $j [ 'catprefs' ][ $jt [ 'cats' ][ $x ]];
print ( " c { $jt [ 'cats' ][ $x ] } = $pref " );
}
for ( $x = 0 ; $x < count ( $jt [ 'divs' ]); $x ++ ) {
$pref = $j [ 'divprefs' ][ $jt [ 'divs' ][ $x ]];
print ( " d { $jt [ 'divs' ][ $x ] } = $pref " );
}
print ( " ) " );
if ( $j [ 'willing_chair' ] == 'yes' ) {
print ( " (chair) " );
}
2006-01-03 02:08:23 +00:00
2006-08-01 19:43:15 +00:00
print ( " \n " );
}
2006-08-02 07:36:21 +00:00
/* Find the maximum judging team number */
$q = mysql_query ( " SELECT MAX(num) as max FROM judges_teams " );
$r = mysql_fetch_object ( $q );
$max_jteam_num = $r -> max ;
TRACE ( " Max Judging Team Number is currently $max_jteam_num\n " );
2006-08-01 19:43:15 +00:00
for ( $x = 1 ; $x < count ( $jteam ); $x ++ ) {
$t =& $jteam [ $x ];
2006-08-02 07:36:21 +00:00
$num = $x + $max_jteam_num ;
print ( " Judging Team $num : cost= { $a -> bucket_cost [ $x ] } " );
2006-08-01 19:43:15 +00:00
print ( " langs=( " );
$langstr = " " ;
for ( $y = 0 ; $y < count ( $t [ 'langs' ]); $y ++ ) {
if ( $y != 0 ) $langstr .= " " ;
$langstr .= $t [ 'langs' ][ $y ];
}
print ( " $langstr ) " );
print ( " cats=( " );
$catstr = " " ;
for ( $y = 0 ; $y < count ( $t [ 'cats' ]); $y ++ ) {
print ( " c " . $t [ 'cats' ][ $y ] . " " );
if ( $y != 0 ) $catstr .= " + " ;
$catstr .= $cat [ $t [ 'cats' ][ $y ]];
}
print ( " ) " );
print ( " divs=( " );
$divstr = " " ;
for ( $y = 0 ; $y < count ( $t [ 'divs' ]); $y ++ ) {
print ( " d " . $t [ 'divs' ][ $y ] . " " );
if ( $y != 0 ) $divstr .= " / " ;
$divstr .= $div [ $t [ 'divs' ][ $y ]];
}
print ( " ) \n " );
/* Add this judging team to the database */
$tn = $catstr . " " . $divstr . " ( " . $langstr . " ) " . ( $t [ 'sub' ] + 1 );
mysql_query ( " INSERT INTO judges_teams (num,name,autocreate_type_id,year) " .
2006-08-02 07:36:21 +00:00
" VALUES (' $num ',' $tn ','1',' { $config [ 'FAIRYEAR' ] } ') " );
2006-08-01 19:43:15 +00:00
$team_id = mysql_insert_id ();
$t [ 'team_id' ] = $team_id ;
$ids = $a -> bucket [ $x ];
for ( $y = 0 ; $y < count ( $ids ); $y ++ ) {
pr_judge ( $t , $ids [ $y ]);
$j =& $judges [ $ids [ $y ]];
/* Link Judges to the judging team we just inserted */
mysql_query ( " INSERT INTO judges_teams_link " .
" (judges_id,judges_teams_id,captain,year) " .
" VALUES (' { $ids [ $y ] } ',' $team_id ',' { $j [ 'willing_chair' ] } ', " .
" ' { $config [ 'FAIRYEAR' ] } ') " );
2006-01-03 02:08:23 +00:00
}
2006-08-01 19:43:15 +00:00
/* Get the original jdiv that this team was created from . The exact
* breakdown of each and every div / cat / lang that this team is judging
* is in the jdiv [ 'config' ] array */
$jd = $jdiv [ $t [ 'jdiv_id' ]];
for ( $y = 0 ; $y < count ( $jd [ 'config' ]); $y ++ ) {
$cfg = $jd [ 'config' ][ $y ];
2006-01-03 02:08:23 +00:00
$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 . id = award_awards_projectcategories . award_awards_id
AND award_awards . id = award_awards_projectdivisions . award_awards_id
2006-08-01 19:43:15 +00:00
AND award_awards_projectcategories . projectcategories_id = '{$cfg[' cat ']}'
AND award_awards_projectdivisions . projectdivisions_id = '{$cfg[' div ']}'
2006-01-03 02:08:23 +00:00
AND award_awards . award_types_id = '1'
" );
2006-08-01 19:43:15 +00:00
if ( mysql_num_rows ( $q ) != 1 ) {
echo error ( i18n ( " Cannot find award for %1 - %2 " , array ( $cat [ $cfg [ 'cat' ]], $div [ $cfg [ 'div' ]])));
} else {
2006-01-03 02:08:23 +00:00
$r = mysql_fetch_object ( $q );
mysql_query ( " INSERT INTO judges_teams_awards_link (award_awards_id,judges_teams_id,year) VALUES (' $r->id ',' $team_id ',' { $config [ 'FAIRYEAR' ] } ') " );
}
2006-08-01 19:43:15 +00:00
}
2006-01-26 23:06:47 +00:00
}
2006-08-01 19:43:15 +00:00
print ( " Unused Judges: \n " );
$ids = $a -> bucket [ 0 ];
for ( $y = 0 ; $y < count ( $ids ); $y ++ ) pr_judge ( $jteam [ 0 ], $ids [ $y ]);
TRACE ( " Loading Timeslot Data \n " );
$available_timeslots = array ();
$q = mysql_query ( " SELECT * FROM judges_timeslots WHERE " .
" year=' { $config [ 'FAIRYEAR' ] } ' AND " .
" allowdivisional='yes' ORDER BY date,starttime " );
$x = 0 ;
while ( $r = mysql_fetch_object ( $q )) {
$available_timeslots [] = array ( " id " => $r -> id ,
" date " => $r -> date ,
" starttime " => substr ( $r -> starttime , 0 , - 3 ),
" endtime " => substr ( $r -> endtime , 0 , - 3 ));
print ( " - " . $available_timeslots [ $x ][ 'starttime' ] . " -> " .
$available_timeslots [ $x ][ 'endtime' ] . " \n " );
$x ++ ;
2006-01-26 23:06:47 +00:00
}
2006-08-02 08:07:51 +00:00
2006-08-08 03:21:08 +00:00
$n_timeslots = count ( $available_timeslots );
2006-08-02 08:07:51 +00:00
2006-08-01 19:43:15 +00:00
2006-08-08 03:21:08 +00:00
$project_index = array ();
function timeslot_pick_move ( $a )
{
global $n_timeslots ;
/* Bucket id always 0 */
$b1 = 0 ;
$i1 = rand ( 0 , count ( $a -> bucket [ 0 ]) - 1 );
/* Find the start and end of this project timeslots */
$i_s = floor ( $i1 / $n_timeslots ) * $n_timeslots ;
$i_e = $i_s + $n_timeslots - 1 ;
/* THe second number must be between $i_s and $i_e */
$b2 = 0 ;
while ( 1 ) {
$i2 = rand ( $i_s , $i_e );
if ( $i2 != $i1 ) break ;
}
// TRACE("Move=($b1, $i1, $b2, $i2)\n");
return array ( $b1 , $i1 , $b2 , $i2 );
}
/* Computes the cost of everything , since we slice the data two
* ways we can ' t really use delta costs
* In this , the bucket_id will always be 1 , because we don ' t
* actually use buckets */
function timeslot_cost_function ( $annealer , $bucket_id , $ids )
{
global $project_index ;
global $jteam ;
global $n_timeslots ;
$cost = 0 ;
// print("Count $ids=".count($ids));
/* The pick_move function ensures that projects can ' t
* move out of a jteam so we dont ' need to check that */
/* First , check to see if the project is being judged 3 or
* more times in a row , OR , if it has large gaps that aren ' t
at the end of the judging */
for ( $x = 0 ; $x < count ( $project_index ); $x ++ ) {
$i_start = $x * $n_timeslots ;
$i_end = ( $x + 1 ) * $n_timeslots ;
$z_count = 0 ;
$r_count = 0 ;
for ( $y = $i_start ; $y < $i_end ; $y ++ ) {
$jteam_id = $ids [ $y ];
if ( $jteam_id == 0 ) {
$z_count ++ ;
$r_count = 0 ;
} else {
/* Do the z_count cost here so we don ; t
* count any zcount cost for the end
* of the timetable */
if ( $z_count > 2 ) $cost += $z_count ;
$r_count ++ ;
$z_count = 0 ;
if ( $r_count > 2 ) $cost += $r_count ;
}
}
}
/* Check to make sure a judge isn ' t judging two projects
* at the same time */
$n_pids = count ( $project_index );
for ( $offset = 0 ; $offset < $n_timeslots ; $offset ++ ) {
for ( $x = 0 ; $x < $n_pids - 1 ; $x ++ ) {
$o1 = $x * ( $n_timeslots ) + $offset ;
$jteam_id1 = $ids [ $o1 ];
if ( $jteam_id1 == 0 ) continue ;
for ( $y = $x + 1 ; $y < $n_pids ; $y ++ ) {
$o2 = $y * ( $n_timeslots ) + $offset ;
$jteam_id2 = $ids [ $o2 ];
if ( $jteam_id1 == $jteam_id2 )
$cost += 50 ;
}
}
}
return $cost ;
}
$keys = array_keys ( $jdiv );
for ( $k = 0 ; $k < count ( $keys ); $k ++ ) {
$jdiv_id = $keys [ $k ];
$pids = array_keys ( $jdiv [ $jdiv_id ][ 'projects' ]);
unset ( $project_rlookup );
$project_rlookup = array ();
for ( $x = 0 ; $x < count ( $pids ); $x ++ ) {
$project_rlookup [ $pids [ $x ]] = $x ;
}
$project_index = $pids ;
$current_jdiv = $jdiv_id ;
printf ( count ( $pids ) . " projects in this jdiv \n " );
unset ( $jteams_ids );
$jteams_ids = array ();
for ( $x = 0 ; $x < ( $n_timeslots * count ( $pids )); $x ++ )
$jteams_ids [] = 0 ;
/* Fill out the jteam array with a jteam_id for each time the
* jteam_id is supposed to judge a project , then pad with 0 up
* to a length of num_project * n_timeslots */
$jteams = $jdiv [ $jdiv_id ][ 'jteams' ];
foreach ( $jteams as $jteam_id ) {
$p = $jteam [ $jteam_id ][ 'projects' ];
for ( $y = 0 ; $y < count ( $jteam [ $jteam_id ][ 'projects' ]); $y ++ ) {
$pid = $jteam [ $jteam_id ][ 'projects' ][ $y ];
$idx = $project_rlookup [ $pid ];
$o = $n_timeslots * $idx ;
for ( $o = $n_timeslots * $idx ; ; $o ++ ) {
if ( $jteams_ids [ $o ] != 0 ) continue ;
$jteams_ids [ $o ] = $jteam_id ;
break ;
}
}
}
print ( " Jteams ids len= " . count ( $jteams_ids ));
print ( " \n " );
$e = 500 + 50 * ( $data [ 'effort' ] / 1000 );
$a = new annealer ( 1 , 100 , $e , 0.98 , timeslot_cost_function , $jteams_ids );
$a -> set_pick_move ( timeslot_pick_move );
$a -> anneal ();
for ( $x = 0 ; $x < count ( $pids ); $x ++ ) {
$pid = $pids [ $x ];
TRACE ( " Project $pid : " );
for ( $y = 0 ; $y < $n_timeslots ; $y ++ ) {
$idx = ( $x * $n_timeslots ) + $y ;
$jteam_id = $a -> bucket [ 0 ][ $idx ];
TRACE (( $y + 1 ) . " : $jteam_id " );
if ( $jteam_id == 0 ) continue ;
/* if jteam_id isn't 0, instert it into the db */
mysql_query ( " INSERT INTO judges_teams_timeslots_link " .
2006-08-01 19:43:15 +00:00
" (judges_teams_id,judges_timeslots_id,year) " .
2006-08-08 03:21:08 +00:00
" VALUES (' { $jteam [ $jteam_id ][ 'team_id' ] } ', " .
2006-08-01 19:43:15 +00:00
" ' { $available_timeslots [ $y ][ 'id' ] } ', " .
" ' { $config [ 'FAIRYEAR' ] } ') " );
2006-08-08 03:21:08 +00:00
mysql_query ( " INSERT INTO judges_teams_timeslots_projects_link " .
2006-08-01 19:43:15 +00:00
" (judges_teams_id,judges_timeslots_id,projects_id,year) " .
2006-08-08 03:21:08 +00:00
" VALUES (' { $jteam [ $jteam_id ][ 'team_id' ] } ', " .
2006-08-01 19:43:15 +00:00
" ' { $available_timeslots [ $y ][ 'id' ] } ', " .
" ' $pid ', ' { $config [ 'FAIRYEAR' ] } ') " );
2006-08-08 03:21:08 +00:00
}
TRACE ( " \n " );
2006-01-26 23:06:47 +00:00
}
2006-08-08 03:21:08 +00:00
2006-01-26 23:06:47 +00:00
}
2006-08-01 19:43:15 +00:00
TRACE ( " All Done. \n " );
echo " </pre> " ;
2006-01-26 23:06:47 +00:00
2006-08-01 19:43:15 +00:00
echo happy ( " Scheduler complete successfully " );
2006-01-03 02:08:23 +00:00
send_footer ();
?>