/* TABLIX, PGA highschool timetable generator                              */
/* Copyright (C) 2002-2004 Tomaz Solc                                      */

/* 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; either version 2 of the License, or       */
/* (at your option) any later version.                                     */

/* 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; if not, write to the Free Software             */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

/* $Id: teacher_preferred.c,v 1.7.2.6 2005/04/30 10:44:25 avian Exp $ */

/** @module
 *
 * @author Nick Robinson 
 * @author-email npr@bottlehall.co.uk
 *
 * @brief Adds a weight whenever a teacher is not in a preferred room.
 *
 * @ingroup School scheduling
 */

/** @resource-restriction preferred-room
 *
 * <restriction type="preferred-room">room name</restriction>
 *
 * This restriction specifies that current class or teacher should teach 
 * lessons in the room specified in the restriction.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "module.h"

int*ptroom;
int*pcroom;
int*peroom;

int gettroom(char *restriction, char *cont, resource *res1)
{
	resource *res2;
	res2=res_find(restype_find("room"), cont);
	if(res2==NULL) {
		error(_("invalid room in preferred-room restriction"));
		error(_("resource: %s resource type: %s"), cont, "room");
		return(-1);
	}

	ptroom[res1->resid]=res2->resid;

	return 0;
}

int getcroom(char *restriction, char *cont, resource *res1)
{
	resource *res2;
	res2=res_find(restype_find("room"), cont);
	if(res2==NULL) {
		error(_("invalid room in preferred-room restriction"));
		error(_("resource: %s resource type: %s"), cont, "room");
		return(-1);
	}

	pcroom[res1->resid]=res2->resid;

	return 0;
}

int geteroom(char *restriction, char *cont, tupleinfo *tuple)
{
	resource *res2;
	res2=res_find(restype_find("room"), cont);
	if(res2==NULL) {
		error(_("invalid room in preferred-room restriction"));
		error(_("resource: %s resource type: %s"), cont, "room");
		return(-1);
	}

	peroom[tuple->tupleid]=res2->resid;

	return 0;
}

int module_fitness(chromo **c, ext **e, slist **s)
{
	int m, sum;
	chromo *time, *room, *teacher, *class;
	time = c[0];
	teacher = c[1];
	room = c[2];
	class = c[3];
	
	sum=0;
	for(m=0;m<time->gennum;m++)
	{
		// ERROR between here
		if ( peroom[time->gen[m]] != -1 )
		{
			if ( room->gen[m] != peroom[time->gen[m]]) sum++;
		}
		else
		// AND HERE
		if (pcroom[class->gen[m]] != -1 )
		{
			if ( room->gen[m] != pcroom[class->gen[m]]) sum++;
		}
		else if (ptroom[teacher->gen[m]] != -1 && room->gen[m] != ptroom[teacher->gen[m]]) sum++;
	}
	return(sum);
}

int module_precalc(moduleoption *opt) 
{
	int c;
	int unused = 1;
	for ( c=0; c<restype_find("teacher")->resnum; c++ ) debug("troom[%d]=%d", c, ptroom[c] );
	for ( c=0; c<restype_find("class")->resnum; c++ ) debug("croom[%d]=%d", c, pcroom[c] );
	for ( c=0; c<dat_tuplenum; c++ ) debug("eroom[%d]=%d", c, peroom[c] );
	
	for ( c=0; c<restype_find("teacher")->resnum && ptroom[c] == -1; c++ ) /* null statement */;
	if ( ( unused = ( c == restype_find("teacher")->resnum ) ) )
	{
		for ( c=0; c<restype_find("class")->resnum && pcroom[c] == -1; c++ ) /* null statement */;
		if ( ( unused = ( c == restype_find("class")->resnum ) ) )
			for ( c=0; c<dat_tuplenum && peroom[c] == -1; c++ ) /* null statement */;
	}	
	if ( unused ) error( "module teacher_preferred has been loaded, but not used" );
	
	return( 0 );
}

int module_init(moduleoption *opt) 
{
	int c;
	ptroom=malloc(sizeof(*ptroom)*restype_find("teacher")->resnum);
	for(c=0;c<restype_find("teacher")->resnum;c++) ptroom[c]=-1;
	pcroom=malloc(sizeof(*pcroom)*restype_find("class")->resnum);
	for(c=0;c<restype_find("class")->resnum;c++) pcroom[c]=-1;
	peroom=malloc(sizeof(*peroom)*dat_tuplenum);
	for(c=0;c<dat_tuplenum;c++) peroom[c]=-1;
	
	fitnessfunc *fitness;

	precalc_new(module_precalc);

	handler_res_new("teacher", "preferred-room", gettroom);
	handler_res_new("class", "preferred-room", getcroom);
	handler_tup_new("preferred-room", geteroom);

	fitness=fitness_new("teacher preferred", 
			option_int(opt, "weight"), 
			option_int(opt, "mandatory"), 
			module_fitness);
	if(fitness==NULL) return -1;

	if(fitness_request_chromo(fitness, "time")) return -1;
	if(fitness_request_chromo(fitness, "teacher")) return -1;
	if(fitness_request_chromo(fitness, "room")) return -1;
	if(fitness_request_chromo(fitness, "class")) return -1;

	return(0);
}

