/* TABLIX, PGA highschool timetable generator				   */
/* Copyright (C) 2002 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: preferred.c,v 1.6 2004/10/17 09:37:05 avian Exp $		   */

/* 
 * AUTHOR:
 *
 *  Tomaz Solc <tomaz.solc@siol.net>
 *
 *  Ideas taken from a patch for Tablix 0.0.3 by 
 *  Jaume Obrador <obrador@espaiweb.net>
 *
 *  Ported to version 0.2.0 by Nick Robinson <npr@bottlehall.co.uk>
 *
 * DESCRIPTION:
 *
 *  Adds a weight whenever a tuple (or a group of tuples if perweek is greater
 *  than 1) is not scheduled at the specified preferred day and/or period.
 *
 * DEFINED TUPLE RESTRICTIONS:
 *
 *  <restriction type="preferred-period">period</restriction>
 *
 *  <restriction type="preferred-day">day</restriction>
 *
 *  These two restrictions specify the preferred period and day for a tuple.
 *
 */

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

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

#include "modsup.h"
#include "data.h"
#include "gettext.h"
#include "error.h"

int *pperiod;
int *pday;
int days;
int periods;

int getday(char *restriction, char *cont, tupleinfo *tuple)
{
	int p,c;
	
	c=sscanf(cont, "%d", &p);
	if(c<1||p<0||p>=days) {
		error(_("invalid preferred day"));
		return(1);
	}
	
	pday[tuple->tupleid]=p;

	return 0;
}

int getperiod(char *restriction, char *cont, tupleinfo *tuple)
{
	int p,c;
	
	c=sscanf(cont, "%d", &p);
	if(c<1||p<0||p>=periods) {
		error(_("invalid preferred period"));
		return(1);
	}

	pperiod[tuple->tupleid]=p;

	return 0;
}

int module_fitness(chromo **c, ext **e, slist **s)
{
	int a,m,n,u,sum;
	slist *list;
	chromo *time;
	
	list=s[0];
	time=c[1];
	
	sum=0;
	for(m=0;m<time->gennum;m++)
	{
		a=time->gen[m];
		for(n=0;n<list->tuplenum[a];n++)
		{
			int b;
			b=list->tupleid[a][n];

			u=time->gen[b];
			
			int d,t;
			sscanf(time->restype->res[u].name, "%d %d", &d, &t);
			if(pday[b]>-1 && d!=pday[b]) sum++;
			if(pperiod[b]>-1 && t!=pperiod[b]) sum++;
		}
	}

	return(sum);
}

int module_init(moduleoption *opt)
{
	int c;
	pperiod=malloc(sizeof(*pperiod)*dat_tuplenum);
	pday=malloc(sizeof(*pday)*dat_tuplenum);

	res_get_matrix( restype_find("time"), &days, &periods );
	
	for(c=0;c<dat_tuplenum;c++) {
		pperiod[c]=-1;
		pday[c]=-1;
	}
	
	fitnessfunc *fitness;

	handler_tup_new("preferred-day", getday);
	handler_tup_new("preferred-period", getperiod);

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

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

	fitness_request_slist(fitness, "time");

	return 0;
}

