<?php 

/*
Loads all the functions necessary for rendering each test type for this class.
Class names should be the same as test_type entries, and a 'class_file' property
should point to the relevant include file.
*/
function load_test_classes() {
	$test_types = get_task_property('test_types');
	foreach ($test_types as $test_type=>$value) {
		$include_file = get_task_property('class_file',$test_type);
		include_once($include_file);	
	}
}

function get_test_type($test_type_id) {
	$test_type_ids = get_task_property('test_type_ids');
	$test_type = $test_type_ids[$test_type_id];
	return $test_type;
}

function get_test_type_id($test_type) {
	return get_task_property('short_id',$test_type);
}

function get_max_per_page($test_type) {
	//first, check if this test type has an override
	$max_per_page = get_task_property('max_per_page',$test_type);
	
	//if not, get the global one
	if (!$max_per_page) {
		$max_per_page = get_task_property('max_per_page');
	}
	
	return $max_per_page;
	
}

function count_lines($filename) {
	$handle = fopen($filename,'r');
	$count = 0;
	while(fgets($handle)) {
		$count++;
	}
	fclose($handle);
	return $count;
}

function count_system_lines($systems) {
	$result = array();
	$translation_files = get_task_property('translation_file');
	foreach ($systems as $index=>$system) {
		$file = $translation_files[$index];
		$result[$system] = count_lines($file);
	}
	#print("counted systems: ");
	#print_r($result);
	#print('\n');
	return $result;

}

function display_progress() {
	$task_completed = 0;
	$total_completed = 0;
	$total_time = 0;
	$current_user = current_user();
	
	$line = load_judgements();
	for($i=0;$i<count($line);$i++) {
		list($t,$j,$assignmentid,$type,$judgment,$time) = split(" \|\|\| ",chop($line[$i]));
		if ($j == $current_user) {
			$total_completed++;
			if ($t == $_POST["TASK"]) {
				$task_completed++;	
			}
			$total_time+=$time;
		}

	}
	
	if ($total_completed > 0) {
		print("<FONT COLOR=#800000>You have judged ".$task_completed." sentences for <B>".$_POST["TASK"]."</B>, ".$total_completed." sentences total");
		if ($total_time> 0) {
			print (" taking ".number_format($total_time/$total_completed,1)." seconds per sentence");
		}
		print(".</FONT><BR><HR><BR>");
	}

	
}

function display_sentence() {
	global $assignments;

	$assignment_id = get_next_assignment();
	
	list($test_type_id,$assignment_number,$assignment_info_string) = split("-",$assignment_id);
	
	$test_type = get_test_type($test_type_id);

	
	display_head($test_type);
	
	//TODO: disable this for MT Workshop to stop server overloading?
	display_progress();
	
	//common header form info
	
	?>
	<FORM ACTION="" METHOD=POST>
	<INPUT TYPE=HIDDEN NAME=ASSIGNMENTID VALUE="<?php print($assignment_id);?>">
	<INPUT TYPE=HIDDEN NAME=ASSIGNMENTS VALUE="<?php print(join(";",$assignments));?>">
	<INPUT TYPE=HIDDEN NAME=TIME VALUE="<?php print(time());?>">
	<?php
	
		
	display_test_info($assignment_id);

	//common end task info
	?>
	<TR><TD><P><FONT COLOR=#800000><B>Annotator:</B> <?php print(current_user());?></B>
	<B>Task:</B> <?php print($_POST[TASK]);?></B>
	<INPUT TYPE=HIDDEN NAME=TASK VALUE="<?php print($_POST[TASK]);?>"></FONT>
	</TD><TD COLSPAN=2 ALIGN=RIGHT><INPUT TYPE=SUBMIT VALUE="Annotate"></TD></TR>
	
	<?
	
	display_instructions($test_type);
	
	?>

	</TABLE>
	</FORM>
	<?php
}

function get_max_item_number($test_type) {
	return call_user_func(array($test_type,'max_item_number'));
}


function get_min_item_number($test_type) {
	return call_user_func(array($test_type,'min_item_number'));
}

function display_instructions($test_type) {
	call_user_func(array($test_type,'instructions'));
}


function display_head($test_type) {
	head(call_user_func(array($test_type,'head_text')));
}

function display_test_info($assignment_id) {
	list($test_type_id) = split("-",$assignment_id);
	$test_type = get_test_type($test_type_id);

	call_user_func(array($test_type,'test_info'),$assignment_id);
}

function display_one_line($file,$n) {
	$line = file($file);
	return $line[$n];
}

//try for tokenized version of the file, fail silently if not found
function display_one_line_tokenized($file,$n) {
	if (file_exists($file.".tok")) {
		$line = file($file.".tok");
	} else {
		$line = file($file);
	}
	return remove_tok_markup($line[$n]);	
}

function remove_tok_markup($line) {
  $line = str_replace('-LRB-','(',$line);
  $line = str_replace('-RRB-',')',$line);
  $line = str_replace('-LSB-','[',$line);
  $line = str_replace('-RSB-',']',$line);
  $line = str_replace('-LCB-','{',$line);
  $line = str_replace('-RCB-','}',$line);

  return $line;
}


function display_one_phrase($file, $n, $start_word, $end_word) {
	$sentence = display_one_line_tokenized($file,$n);
	$word_list = split(" ",chop($sentence));
	$word_list[$start_word] = "<FONT style='BACKGROUND-COLOR: yellow'><B>".$word_list[$start_word];
	$word_list[$end_word-1] = $word_list[$end_word-1]."</B></FONT>";
	return(join(" ",$word_list));
	
}

function load_constituent_locations($system_id_list,$constituent_info_string) {
	$constituent_info_list = split(" \|\|\| ",chop($constituent_info_string));
	$constituent_map = array();
	for($i=2;$i<sizeof($constituent_info_list);$i++) {
		list($system_name,$coverage_string) = split(":",$constituent_info_list[$i]);
		list($start_word,$end_word) = split("-",$coverage_string);
		$constituent_map[$system_name] = array();
		$constituent_map[$system_name]['start_word'] = $start_word;
		$constituent_map[$system_name]['end_word'] = $end_word;
	}
	
	return $constituent_map;
}

function process_judgements() {
	
	global $assignments;
	
	
	if ($_POST["ASSIGNMENTID"]) {
		$success = false;
		
		
		list($test_type_id,$sentence_number,$assignment_info_string) = split("-",$_POST["ASSIGNMENTID"]);
		
		
		$test_type = get_test_type($test_type_id);
		$judgement_string = call_user_func(array($test_type,'process_judgement'));
		
		if ($judgement_string) {
			$success = true;
			$f = fopen(get_judgements_file(),"a");
			fputs($f,"$_POST[TASK] ||| ".current_user()." ||| $_POST[ASSIGNMENTID] ||| $test_type ||| $judgement_string ||| ".(time()-$_POST[TIME])."\n");
			fclose($f);
		}

		if($_POST["ASSIGNMENTID"] == $assignments[0] && $success) {
			//remove element 0, they finished it
			array_shift($assignments);	
		} else {
			//LAZY BASTARD!
			print("<FONT color=red><B>No judgements scored. Please try again.</B></FONT><BR>");
		}
	}                           
}


function get_next_assignment() {
	global $assignments;
	return $assignments[0];	
}


/*function load_task_info_OLD() {
	
	$line = file(get_tasks_file());
	$index = 0;
	for($i=0;$i<count($line);$i++) {
		if(preg_match("/^[\s]*#/",$line[$i])) continue;
		list($t,$key,$value,$value2) = split(" \|\|\| ",chop($line[$i]));
		if ($t == $_POST["TASK"]) {
			if ($key == "reference") {
				$GLOBALS[$key][] = $value;
			}
			else if ($key == "translation") {
				$GLOBALS["translation_file"][] = $value;
				$GLOBALS["translation_id"][] = $value2;
			} else if ($key == "test_types") {
				$GLOBALS["test_types"] = array();
				$ttypes = split(" ",$value);
				foreach($ttypes as $test_type) {
					$GLOBALS["test_types"][$test_type] = 1;		
				}
			#} else if ($value == "repeat_list") {
			#	$GLOBALS["repeat_list"][$key] = split(" ",$value2);
			} else if ($GLOBALS["test_types"][$key]) {
				#this is a test-specific parameter
				if (preg_match('/[^\ ]+ [^\ ]+/',$value2)) {
					#an array, so split it
					$GLOBALS[$value][$key] = split(" ",$value2);
				}
				else {
					$GLOBALS[$value][$key] = $value2;
				}
			} else {
				$GLOBALS[$key] = $value;
			}
		}
	}

}*/

function load_task_info() {
	load_global_task_info($_POST["TASK"]);
}

function get_task_property($key,$test_type=null,$default_fallback=true) {
	return get_global_task_property($key,$test_type,$default_fallback,$_POST["TASK"]);
}

function load_assignment_list() {
	global $assignments;
	
	$current_user = current_user();
	
	$assignment_string = $_POST["ASSIGNMENTS"];
	if (strlen($assignment_string) > 0) {
		$assignments = split(";",$assignment_string);
		if (count($assignments) > 0) {
			return true;
		}
	}
	else {
		//look through finished tasks, remember tasks as we find them
		
		$line = load_judgements();
		for($i=0;$i<count($line);$i++) {
			list($t,$j,$assignment_id,$system,$type,$judgment,$time) = split(" \|\|{2,3} ",$line[$i]);
			if ($t == $_POST["TASK"] && $j == $current_user) {
				$already[$assignment_id] = $already[$assignment_id] + 1;
				if ($time>0) { 
					$total_time += $time; $count_time++;
				}
			}
		}
		
		$line = file(get_assignments_file());
		$index = 0;
		for($i=0;$i<count($line);$i++) {
			list($task,$annotator,$assignment_list_string) = split(" \|\|\| ",chop($line[$i]));
			if ($task == $_POST["TASK"] && $annotator == $current_user) {
				$assignment_list_temp = split(";",$assignment_list_string);				
				foreach ($assignment_list_temp as $assignment_id) {
					if (!$already[$assignment_id]) {
						$assignments[] = $assignment_id;
					} else {
						$already[$assignment_id]--;
					}
				}
			}			
		}
		if (count($assignments) == 0) {
			return false;
		} else {
			return true;
		}

	}
	
}

function generate_new_assignments() {
	global $assignments,$annotator_conflict;
	
	$test_types = get_task_property('test_types');
	
	$test_switching = get_task_property('test_switching') == 'true';
	
	$translation_ids = get_task_property('translation_id');	
	
	$translation_excludes = get_task_property('translation_exclude');
	
	$test_order = array_keys($test_types);
	shuffle($test_order);
	
	$toAssign = array();
	$new_assignment_count = 0;
	
	foreach($test_order as $test_type) {
		
		//max per page is now test-type dependent

		//change max per page to the number of systems that are valid for us
		$max_per_page = get_max_per_page($test_type);

		//check for excluded systems
		$excluded_systems = get_task_property('excluded_systems',$test_type);
		if (!$excluded_systems) {
			$excluded_systems = array();
		} else if (is_scalar($excluded_systems)) {
			$value = $excluded_systems;
			$excluded_systems = array();
			$excluded_systems[] = $value;
		}
		$excluded_systems = array_flip($excluded_systems);
		$allowed_systems = 0;

		foreach($translation_ids as $possible_system) {
			$de_langed_system = ereg_replace("_[a-z]{2}\$","",$possible_system);
			if (!$annotator_conflict[current_user()][$de_langed_system] && !array_key_exists($possible_system,$excluded_systems)) $allowed_systems++;
		}
		
		//print("we are allowed $allowed_systems systems for $test_type\n");
		
		if ($allowed_systems < $max_per_page) $max_per_page = $allowed_systems;
		
		if ($max_per_page == 0) {
			//ERROR: no valid systems for this user to grade
			print_r($GLOBALS);
			print("ERROR: no valid systems for this user to grade");
			return;
		}

		$type_assignments = array();
		
		$num_non_local_repeat = get_task_property('random',$test_type) + get_task_property('global_repeat',$test_type);
		
		//load the repeat list and shuffle it
		$repeat_list = get_task_property('repeat_list',$test_type);
		shuffle($repeat_list);
		
		//First assign all the tasks that require randomly pulling from the whole list or just the repeats
		for ($i=0;$i<$num_non_local_repeat;$i++) {	
			
			$n = 0;
			//Random first
			if ($i<get_task_property('random',$test_type)) {
				$max_number = get_max_item_number($test_type);
				$min_number = get_min_item_number($test_type);
				$n = rand($min_number,$max_number);
			
			//Then repeat list
			// TODO: make this else-if, support in-order once-only translations
			} else {
				//get its sentence number
				if (count($repeat_list > 0)) {

					$n = array_pop($repeat_list);
				} else {
					//not enough repeats!
					continue;
				}
			}
			
			//generate the new task
			$assignmentid = get_test_type_id($test_type)."-".$n;
			
			$systems = array();
			foreach ($translation_ids as $index=>$system) {
				$de_langed_system = ereg_replace("_[a-z]{2}\$","",$system);
				if (!$annotator_conflict[current_user()][$de_langed_system] &&
					!array_key_exists($system,$excluded_systems) && 
					!array_key_exists($n,$translation_excludes[$index])) {
						$systems[] = $index;
				}
				
			}
			shuffle($systems);
			
			if (count($systems) > $max_per_page) {
				$systems = array_slice($systems,0,$max_per_page);
			} 
			
			if (count($systems) == 0) {
				//ERROR: no valid systems for this user to grade
				print("There is problem with the code. Please mail the contents of this web page to j.schroeder@ed.ac.uk\n"); 
				print_r($GLOBALS);
				print("ERROR: no valid systems for this user to grade");
				return;
			}
			
			/*$systems = array();
			$already = array();
			do {
				$sys = rand(0,sizeof($translation_ids)-1);
				if (!$already[$sys] && !$annotator_conflict[current_user()][$translation_ids[$sys]] && !array_key_exists($translation_ids[$sys],$excluded_systems)) {
					$already[$sys] = 1;
					$systems[] = $sys;	
				}
			} while (sizeof($systems) < $max_per_page);*/
			
			$sysList=join(",",$systems);
			$assignmentid = $assignmentid."-".$sysList;
			$type_assignments[] = $assignmentid;
		}
				
		//OK, shuffle up this list, then tack local repeats onto the end, pulling from the beginning.
		shuffle($type_assignments);
		
		$type_assignments_size = sizeof($type_assignments);
		
		//We want to randomly pull several items from the head of the list, but give ourselves enough buffer that
		//we're not always pulling just the first item in the list. 
		
		//Add 2 to the number of local repeats
		//set up a shuffled indexer, pull the first i entries from it and stick on the end of our array.
		
		$num_local_repeats = get_task_property('local_repeat',$test_type);
		
		if ($num_local_repeats > 0) {
			
			//build the array of index positions, 0 through 2+num_local_repeats
			$local_repeat_indexes = array();
			for($index=0;$index<$num_local_repeats+2 && $index<$type_assignments_size;$index++) {
				$local_repeat_indexes[] = $index;
			}
			
			//shuffle the order we'll sample
			shuffle($local_repeat_indexes);
			
			//now pull off the head of this index set to decide which items to recycle at the end
			//of our assignments.
			for ($i=0;$i<$num_local_repeats && $i<$type_assignments_size;$i++) {
				$local_repeat_index = array_pop($local_repeat_indexes);
				$type_assignments[] = $type_assignments[$local_repeat_index];
			}
		}
		
		//Instead of just appending to global array in this way, place each type alternating
		$toAssign[$test_type]= $type_assignments;
		$new_assignment_count += sizeof($type_assignments);
		
	}
	
	$new_assignments = array();
	
	
	//assign things in groups
	if (!$test_switching) {
		foreach($test_order as $test_type) {
			$new_assignments = array_merge($new_assignments,$toAssign[$test_type]);
		}	
	} else {
		while(sizeof($new_assignments) < $new_assignment_count) {
			foreach($test_order as $test_type) {
				for($i=0;$i<get_task_property('switch_size',$test_type) && sizeof($toAssign[$test_type]) > 0;$i++) {
					$new_assignments[] = array_shift($toAssign[$test_type]);
				}
			}
		}
	}
	
	$assignments = $new_assignments;
	$assignment_list = join(";",$assignments);
	
	$f = fopen(get_assignments_file(),"a");
	fputs($f,$_POST["TASK"]." ||| ".current_user()." ||| ".$assignment_list."\n");
	fclose($f);
}

if (check_password()) {

	load_task_info();

	load_test_classes();

	if ($_POST["GENERATEASSIGNMENT"]) {
		//user has requested a new work unit
		generate_new_assignments();

		if (sizeof($assignments) == 0) {
			//nothing to generate for this task
			print("You have completed all required judgements for task $_POST[TASK]. Please choose another task.");	
			include("select_task_contents.php");
			tail();
			exit;
		}
		
	} else {
		load_assignment_list();
		process_judgements();
	}
	
	if (sizeof($assignments) == 0) {		
		//Decide if this assignments = 0 is because they've never done anything for this task
		
		head("Choose Next Task");
		?>
		You have completed your current assignments for the task <b><?php print($_POST[TASK]);?></b>. Please choose your next task (or continue with your current task):
		<P>
		
		<?php
		include("select_task_contents.php");
	} else {
		//we have tasks remaining

		display_sentence(); 
	}

}
tail();
