science-ation/plugins/evaluations/eval_common.inc.php

459 lines
17 KiB
PHP

<?php
/*
This file is a plug-in to the 'Science Fair In A Box' project
SFIAB Website: http://www.sfiab.ca
Copyright (C) 2011 At Work Software (dennis@spanogle.net>
Copyright (C) 2011 Dennis Spanogle <dennis@spanogle.net>
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.
*/
?>
<?php
// ********* Check Evaluations installation or Add the appropriate eval_config parameters *********
$q=@mysql_query("SELECT * FROM eval_config");
if(mysql_error())
{
echo "<h1>Evaluations Plug-in</h1><br />";
echo "Evaluations database tables are not installed. You need to install those now!<br />";
echo "<a href=\"eval_install.php\">Proceed to Evaluations Database Installation</a><br />";
echo "<br>";
exit;
}
//if we have 0 (<1) then install is not done, which would get caught above,
if(mysql_num_rows($q)<1)
{
echo "<h1>Evaluations Plug-in</h1><br />";
echo "Evaluations 'eval_config' file has no data! You need to install the data base Files.<br />";
echo "<a href=\"eval_install.php\">Proceed to Evaluations Database Installation</a><br />";
echo "<br>";
exit;
}
// Get the appropriate values needed
$q=mysql_query("SELECT * FROM eval_config");
while($r=mysql_fetch_object($q)) // should only be one row
{
$eval_config['help_link']=$r->help_link;
$eval_config['plugin_name']=$r->plugin_name;
$eval_config['folder_name']=$r->folder_name;
$eval_config['code_version']=$r->code_version;
$eval_config['author']=$r->author;
$eval_config['db_version']=$r->db_version;
$eval_config['description']=$r->description;
}
// debug
// echo "plugin_common done. author = ".$eval_config['author']."<br />";
// see if up to date in revisions
if(file_exists("db/eval.code.version.txt"))
{
$evaldbcodeversion_file=file("db/eval.code.version.txt");
$evaldbcodeversion=trim($evaldbcodeversion_file[0]);
}
else
{
echo "<b>ERROR: Could not load plugins/evaluations/db/eval.code.version.txt</b><br />";
exit;
}
$q=@mysql_query("SELECT db_version FROM eval_config");
$r=@mysql_fetch_object($q);
$evaldbdbversion=$r->db_version;
if($evaldbdbversion)
{
if($evaldbcodeversion<$evaldbdbversion){
echo "ERROR: evaldbcodeversion<evaldbdbversion ($evaldbcodeversion<$evaldbdbversion). This should not happen!";
exit;
}
if($evaldbcodeversion>$evaldbdbversion){
echo "<h1>Evaluations Plug-in</h1><br />";
echo "Your 'Evaluations' plug-in database needs to be updated. You should run the update script to update the database!<br /><br />";
echo "<a href=\"db/db_eval_update.php\">Proceed to Evaluations Database Update!</a><br />";
exit;
}
}
else
{
// query returned nothing. This should not happen as we check it above.
echo "<b>It appears that you have not fully installed Evaluations plug-in</b><br />";
echo "Please click this link and do the installation now.<br /><br />";
echo "<a href=\"eval_install.php\">Proceed to installation</a><br />";
exit;
}
// check if there are any evaluations entered
$q = @mysql_query("SELECT * FROM eval_schemes");
if(mysql_error())
{
echo "ERROR Evaluations table eval_schemes is missing. Something failed in the database table installations for Evaluations!";
echo "<br>";
exit;
}
if(mysql_num_rows($q)<1) // no rows so no schemas
{
echo "<h1>Evaluations Plug-in</h1><br />";
echo "There are no schemes set up for Evaluations! You need to add at least one scheme! <br />";
echo "<a href=\"eval_setup.php\">Proceed to Evaluations Schemes Setup </a><br />";
echo "<br>";
exit;
}
// *********************** Eval Functions ********************
function calc_scores($project_id)
/*
This caluclates various score values from the evaluations entry in eval_projects_entry table (using the level_id entry, scheme_id etc and the
algorithm in the eval_help.htm file. The score that is placed in the SFIAB judges_teams_timeslots_projects_link table (one score for each team/project assignment
is the score resulting from a 'complete' evaluation (all criteria have an entry and there are no errors)
The score placed in the eval_projects table is created by first averaging each criteria for all team evaluations that have made an entry for the criteria.
note that some criteria for some teams may have errors (missing the mark on score form or multiple marks) so those are not included in the criteria average.
After all criteria are averaged - if there is a good average for every criteria, then the score is calculated. This allows the process to use every entry by the judges
even if one judge team has missed a criteria's mark or the scanner read multiple markes etc. The process assumes that score forms can be entered again after
corrections and thus after doing the calc_scores process again the newer entries will be used for a better average.
project_id must exist in table: 'judges_teams_timeslots_projects_link'
if error returns a string
for each team assigned to the project (eval_teams_entries records) calculates team score and status
- if error in entries or no entries score = 'null' status = list of errors
- if good entries score = result of entries (0 to 100) status = blank
- returns an array (see below)
for the project, calculates a score using Dennis Spanogle method (see help/documentation for detail - or read code)
(average each criteria entries first, then use criteria averages to calculate scores)
-This results in a project score even if some level values are missing or bad for one or more team-project entries
returns:
an array: array(project_num=>$project_num,eval_score=>$score, eval_score_status=>$ttlcode,num_teams=>$num_judges_teams,
team_scores=>$list_array);
where $list_array is array(team_id=>$arr[$team][0][0],team_num=>$arr[$team][0][5],proj_num=>$arr[$team][0][6],team_score=>$team_score,team_status=>$err.codes);
indexed from 0 to number of teams assigned to project - 1
An example of using calc_score
$ret_array = calc_scores($project_id);
for ($i=0;$i < $ret_array[num_teams]; $i++){
echo "team_id=".$ret_array[team_scores][$i][team_id]." team_num= ".$ret_array[team_scores][$i][team_num] ."project_num = ".
$ret_array[team_scores][$i][proj_num] ." score =".$ret_array[team_scores][$i][team_score] .
" status = ".$ret_array[team_scores][$i][team_status] ."<br />";
}
echo "Project number ".$ret_array[project_num].": score= ".$ret_array[eval_score]." status = ".$ret_array[eval_score_status]."<br />";
For actual use see eval_calc_scores.php
*/
{
if(!$project_id){
return "error";
}
// Get scheme to use
$q = mysql_query("SELECT * from eval_projects WHERE project_id = '".$project_id."' ");
if (!$q OR mysql_num_rows($q) == 0){
echo "No eval_ projects record for project_id ".$project_id."<br />";
return "error";
}
else {
$r=mysql_fetch_object($q);
$scheme_id = $r->scheme_id;
}
// Get the maximum level value for this scheme (used to calculate average score - see eval_help.htm)
$q = mysql_query("SELECT * from eval_levels WHERE scheme_id = '".$scheme_id."'");
if (!$q OR mysql_num_rows($q) == 0){
echo "No eval_ levels record for scheme_id ".$scheme_id."<br />";
return "error";
}
else {
$max_level_val = 0;
while($r=mysql_fetch_object($q)) {
if($r->spec_use == "no") {
if($r->level_value > $max_level_val){
$max_level_val = $r->level_value;
}
}
}
}
// need to build up and array of
// array(team_id,array(criteria_weight, level_value)
// and count number of teams
// and count number of critera
// then I can work on the array without having to mess with the databases
// IMPORTANT - it is important the way this is sorted for the code to work
$q = mysql_query("SELECT eval_projects_entries.*, projects.projectnumber, judges_teams.num
FROM eval_projects_entries, projects, judges_teams
WHERE eval_projects_entries.project_id = projects.id AND eval_projects_entries.judges_teams_id = judges_teams.id
AND project_id = '".$project_id."' ORDER BY judges_teams_id, criteria_id ");
if (!$q OR mysql_num_rows($q) == 0){
echo "No records for project_id ".$project_id."<br />";
return "error";
}
else {
$judges_teams_id = -1;
$num_judges_teams = 0;
while($r=mysql_fetch_object($q)) {
// setup for new judges team
if ($r->judges_teams_id != $judges_teams_id ){ // set for first or next judge team initial values
$judges_teams_id = $r->judges_teams_id;
$num_criterias = 0;
$judges_teams_num = $r->num;
$project_num = $r->projectnumber;
$num_judges_teams++;
}
// get the criteria weight and the level value from the tables
$crt = mysql_query("SELECT * from eval_criteria WHERE scheme_id = '".$scheme_id."' AND criteria_id = '".$r->criteria_id."' ");
if (!$crt OR mysql_num_rows($crt) == 0){
echo "No eval_ criteria record for scheme_id ".$scheme_id."<br />";
return "error";
}
else {
$crtr=mysql_fetch_object($crt);
$criteria_weight = $crtr->criteria_weight;
}
if (is_null($r->level_id)) { // null no entry has been made
// SET THE ARRAY level_Value = -1
$level_value = -1;
}
else {
$lv = mysql_query("SELECT * from eval_levels WHERE scheme_id = '".$scheme_id."' AND level_id = '".$r->level_id."' ");
if (!$lv OR mysql_num_rows($lv) == 0){
// a non-allowed level_id entry has been made for this so SET the array level_value = -1
$level_value = -1;
}
else {
$lvr=mysql_fetch_object($lv);
$level_value = $lvr->level_value;
$spec_use = $lvr->spec_use;
$spec_use_code = $lvr->spec_use_code;
}
} // level_id entry was null (no entry made yet) or not a valid entry
if ($level_value == -1){
$spec_use_code = "NoEnt"; // this indicate NO entry or Invalid entry (not in eval_levels table)
$spec_use = 'yes'; // force calculations to skip and add the code to the status code;
}
// FILL IN THE ARRAY HERE FOR THIS RECORD...
$arr[$num_judges_teams-1][$num_criterias] = array($judges_teams_id,$criteria_weight,$level_value,$spec_use,$spec_use_code, $judges_teams_num,$project_num);
$num_criterias++;
} // while all in eval_projects_entries
} // else have all eval_projects entries
// Note: for a given project EVERY team will always have the same number of criteria so use the count from last team
// Get a score for each team for judges_teams_timeslots_projects_link table (if possible) Must have all critieria with weight > 0 have entry with spec_use = 'no'
for ( $team = 0; $team < $num_judges_teams; $team++) { // ***** Loop thru Judge teams ****************************
//echo "Team number ".$arr[$team][0][5]." (id ".$arr[$team][0][0].")<br />";
$team_score =0;
$err_codes = "";
for ($crit = 0; $crit < $num_criterias; $crit++) {
$weight = $arr[$team][$crit][1];
$level_value =$arr[$team][$crit][2];
$spec_use = $arr[$team][$crit][3]; // note this may have been set to 'yes' for null or invalid entries or for special use levels (multiple, missing marks etc)
$spec_use_code = $arr[$team][$crit][4];
if($spec_use == "no"){ // OK to add into the score result
$team_score += $level_value * $weight;
}
else {
if ($weight > 0) { // spec_use = 'yes'. If criteria with weight == 0 then it is NOT an error, I.E. ISEF Teamwork for scheme_id 1 .
$err_codes .= $spec_use_code." ";
}
}
}
if ($err_codes == "") { // no error codes added so the score is GOOD!
$team_score = $team_score / $max_level_val;
//echo "Score= ".$team_score."<br />";
}
else {
$team_score = NULL;
//echo "Score= ".$team_score." codes: ".$err_codes."<br />";
}
$list_array[$team] = array(team_id=>$arr[$team][0][0],team_num=>$arr[$team][0][5],proj_num=>$arr[$team][0][6],team_score=>$team_score,team_status=>$err_codes);
} // ****** Loop thr Judge Teams ******************************
// This gets the project score based on the average of the sum of the criteria averages (Dennis Spanogle method)
$num_bad_crits = 0;
$ttlcode = "";
for ($cc = 0;$cc<$num_criterias;$cc++) {
$judcritttl = 0;
$avg_cnt = 0;
$err_codes = "";
for($jj = 0;$jj<$num_judges_teams;$jj++){ // get average for this criteria all judge teams
$weight = $arr[$jj][$cc][1];
$level_value =$arr[$jj][$cc][2];
$spec_use = $arr[$jj][$cc][3];
$spec_use_code = $arr[$jj][$cc][4];
// add in the good judge entries for this criteria
if($spec_use == "no" && $level_value != -1){ // have a good entry for this criteria
$judcritttl += $level_value * $weight;
$avg_cnt++;
}
else {
if ($weight > 0) { // if bad entry in criteria with weight == 0 then it is NOT and error.
if ($err_codes == "") {
$err_codes = "JT".$arr[$jj][$cc][0]." ".$spec_use_code;
}
else {
$err_codes .= ", "."JT".$arr[$jj][$cc][0]." ".$spec_use_code;
}
}
}
}
// Get the average for this criteria i.e. divide by the number of good criteria entries
if ($avg_cnt >0){
$crit_avg_wtd = $judcritttl/$avg_cnt;
}
else{ // This criteria had no entries so the total score can not be calculated unless weight = 0 then don't care
$crit_avg_wtd = 0;
if ($weight > 0){
$num_bad_crits ++;
}
}
$rst[$cc] = array($crit_avg_wtd,$err_codes);
}
// have array with the average weighted criteria levels - add them all up for the project
$ttl= 0;
for ($cc = 0;$cc<$num_criterias;$cc++) {
$ttl += $rst[$cc][0];
if($rst[$cc][1] != ""){
if($ttlcode == "") {
$ttlcode = $rst[$cc][1];
}
else {
$ttlcode .= ", ".$rst[$cc][1];
}
}
}
if ($num_bad_crits == 0){ // if any criteria had no entries then cannot use the score
$score = $ttl/$max_level_val;
}
else {
$score = 0;
}
$ret_array = array(project_num=>$project_num,eval_score=>$score, eval_score_status=>$ttlcode,num_teams=>$num_judges_teams, team_scores=>$list_array);
return $ret_array;
} // end of function calc_scores
// ******************** functions from SFIAB ****
function i18n($str,$args=array(),$argsdesc=array(),$forcelang="")
{
if(!$str)
return "";
if($forcelang)
{
$savelang=$_SESSION['lang'];
$_SESSION['lang']=$forcelang;
}
if($_SESSION['lang'])
{
if($_SESSION['lang']=="en")
{
for($x=1;$x<=count($args);$x++)
{
$str=str_replace("%$x",$args[$x-1],$str);
}
if($forcelang) $_SESSION['lang']=$savelang;
return $str;
}
else
{
$q=mysql_query("SELECT * FROM translations WHERE lang='".$_SESSION['lang']."' AND strmd5='".md5($str)."'");
if($r=@mysql_fetch_object($q))
{
if($r->val)
{
$ret=$r->val;
for($x=1;$x<=count($args);$x++)
{
$ret=str_replace("%$x",$args[$x-1],$ret);
}
if($forcelang) $_SESSION['lang']=$savelang;
return $ret;
}
else
{
for($x=1;$x<=count($args);$x++)
{
$str=str_replace("%$x",$args[$x-1],$str);
}
if($forcelang) $_SESSION['lang']=$savelang;
return "{{".$str."}}";
}
}
else
{
if(count($argsdesc))
{
$argsdescstring="";
$n=1;
foreach($argsdesc AS $ad)
{
$argsdescstring.="%$n=$ad, ";
$n++;
}
$argsdescstring=substr($argsdescstring,0,-2);
$argsdescstring="'".mysql_escape_string($argsdescstring)."'";
}
else
$argsdescstring="null";
mysql_query("INSERT INTO translations (lang,strmd5,str,argsdesc) VALUES ('".$_SESSION['lang']."','".md5($str)."','".mysql_escape_string($str)."',$argsdescstring)");
for($x=1;$x<=count($args);$x++)
{
$str=str_replace("%$x",$args[$x-1],$str);
}
if($forcelang) $_SESSION['lang']=$savelang;
return "{{".$str."}}";
}
}
}
else
{
//no language set, assume english
if($forcelang) $_SESSION['lang']=$savelang;
return $str;
}
}
function error($str,$type="normal")
{
if($type=="normal")
return "<div class=\"error\">$str</div><br />";
else if($type=="inline")
return "<span class=\"error\">$str</span><br />";
}
function notice($str,$type="normal")
{
if($type=="normal")
return "<div class=\"notice\">$str</div><br />";
else if($type=="inline")
return "<span class=\"notice\">$str</span><br />";
}
function happy($str,$type="normal")
{
if($type=="normal")
return "<div class=\"happy\">$str</div><br />";
else if($type=="inline")
return "<span class=\"happy\">$str</span><br />";
}
function display_messages()
{
/* Dump any messages in the queue */
if(is_array($_SESSION['messages'])) {
foreach($_SESSION['messages'] as $m) echo $m;
}
$_SESSION['messages'] = array();
}
function message_push($m)
{
if(!is_array($_SESSION['messages'])) $_SESSION['messages'] = array();
$_SESSION['messages'][] = $m;
}
?>