Logo Search packages:      
Sourcecode: tablix version File versions  Download package

double_period.c

/* 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: double_period.c,v 1.3 2004/10/17 09:37:04 avian Exp $ */

/* 
 * AUTHOR:
 *
 *  Patrick Cronin <pcronin@loyola.edu>
 *
 *  Minor modifications by Tomaz Solc <tomaz.solc@siol.net>
 *
 * DESCRIPTION:
 *
 *  Use this module to schedule double periods of classes.
 *  
 *  Example scenario: you want to have math class five times a week, but
 *  two of those five days, you want to make it a double period (for a
 *  total of 7 periods of math in a week).
 *  
 *  You need to make two subjects for Tablix to place, and the module will
 *  add weights if the restricted subject is not placed immediately before
 *  or after its dual.
 *
 * DEFINED TUPLE RESTRICTIONS:
 *
 *  Syntax of your config.xml file:
 *
 *  <timetable>
 *    <subject title="MATH_FIRST" teacher="Cronin" perweek="5"/>
 *    <subject title="MATH_SECOND" teacher="Cronin" perweek="2">
 *      <restriction type="double-period">MATH_FIRST</restriction>
 *    </subject>
 *  </timetable>
 *
 *  Description of the above config file:
 *
 *  There will be five MATH_FIRST classes per week (on different days IF you
 *  have the subject_sameday.so module in action).  Then, there will be two
 *  MATH_SECOND classes per week that come just before or after a MATH_FIRST
 *  class (as specified in the restriction content.  Weights will be added to
 *  the timetable if MATH_SECOND does not come directly before or after
 *  MATH_FIRST.
 *
 */

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

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

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

struct _second_period {
    int tupleid;
    char * dual_subject_name;
    int * dual_tupleid;
    int number_of_dual_tupleids;
};
typedef struct _second_period second_period;
second_period * second_periods;
int number_of_second_periods;

int init_mod()
{
    number_of_second_periods = 0;
    
    return 0;
}

/* Remember the tuple_ids for this second period */
int remember_tupleid(char *type, char *cont, int tupleid)
{
    /* make room for another second_period record */
    if (second_periods == NULL) {
      second_periods = (second_period *) malloc (sizeof(second_period) * (number_of_second_periods + 1));
      if (second_periods == NULL) {
          strcpy(moderror, _("out of memory"));
          return(1);
      }
    } else {
      second_periods = (second_period *) realloc (second_periods, sizeof(second_period) * (number_of_second_periods + 1));
      if (second_periods == NULL) {
          strcpy(moderror, _("out of memory"));
          return(1);
      }
    }
    
    /* remember that first morning_class is in position 0 */
    second_periods[number_of_second_periods].tupleid = tupleid;
    second_periods[number_of_second_periods].dual_subject_name = malloc (sizeof(char) * (strlen(cont) + 1));
    if (second_periods[number_of_second_periods].dual_subject_name == NULL) {
      strcpy(moderror, _("out of memory"));
      return(1);
    }
    /* should do some error checking here to make sure that the dual_subject_name from the config file is valid */
    strcpy(second_periods[number_of_second_periods].dual_subject_name, cont);
    second_periods[number_of_second_periods].dual_tupleid = NULL;
    second_periods[number_of_second_periods].number_of_dual_tupleids = 0;
    number_of_second_periods++;

    return 0;
}

parop tuple_restrictions[] = { 
      { type : "double-period", parfunc: remember_tupleid },
      { type : 0, parfunc: 0 }
};

/* Find the dual tupleids of each restricted tuple */
int precalc_mod()
{
    int i,t;

    for (i=0; i<number_of_second_periods; i++) {
      
      for (t=0; t < tuplenum; t++) {

          /* if the class ids match and,
             the specified subject name matches the name of the current subject,
             then add this tupleid to the list */

          if ((tuplemap[t].cid == tuplemap[second_periods[i].tupleid].cid) &&
            (!strcmp(smap[tuplemap[t].sid].title, second_periods[i].dual_subject_name))) {
            /* add the new tupleid to the list of tupleids to be checked. */
            if (second_periods[i].number_of_dual_tupleids == 0) {
                second_periods[i].dual_tupleid = (int *) malloc (sizeof(int));
                if (second_periods[i].dual_tupleid == NULL) {
                  strcpy(moderror, _("out of memory"));
                  return(1);
                }
            } else {
                second_periods[i].dual_tupleid = (int *) realloc (second_periods[i].dual_tupleid, sizeof(int) * ((second_periods[i].number_of_dual_tupleids) + 1));
                if (second_periods[i].dual_tupleid == NULL) {
                  strcpy(moderror, _("out of memory"));
                  return(1);
                }
            }
            second_periods[i].dual_tupleid[second_periods[i].number_of_dual_tupleids] = t;
            second_periods[i].number_of_dual_tupleids = second_periods[i].number_of_dual_tupleids + 1;
          }
      }
    }
    return(0);
}

int sametime (chromo *t, int s_time, int * tidlist, int num_of_tids)
{
    int i = 0;
    while (i < num_of_tids) {
      if (t->inf[tidlist[i]].time == s_time) return(1);
      i++;
    }
    return(0);
}

int grade_function(chromo *t, int *cpnt, int *tpnt, int **start, int **lead)
{
    int sum;
    int i;
    int tupletime;
    int period;

    sum=0;
    for (i=0;i<number_of_second_periods;i++) {
      tupletime = t->inf[second_periods[i].tupleid].time;
      period = (tupletime % PERIODS);

      /* If you want to make sure that the SECOND period is before
         the first, use block 1.  Otherwise, use block 2.
         Obviously, since block 2 allows more options, it will probably
           allow for a faster solution.  (Hmm, after testing, I'm not so
         sure.)
      */
      
        /* block 1 start - use if SECOND should be strictly after FIRST */

      if (period == 0) {
          sum++;
      } else if (!sametime(t, tupletime - 1, second_periods[i].dual_tupleid, second_periods[i].number_of_dual_tupleids)) {
          sum++;
      }

        /* block 1 end */

        /* block 2 start - use if you don't care in what order the FIRST
         and SECOND periods are in */
/*
      if ( ((period > 0) &&
            (!sametime(t, tupletime - 1, second_periods[i].dual_tupleid, second_periods[i].number_of_dual_tupleids))
           )
           ||
           ( (period + 1 < PERIODS) &&
             (!sametime(t, tupletime + 1, second_periods[i].dual_tupleid, second_periods[i].number_of_dual_tupleids)))
          ) {
          sum++;
      }
*/
        /* block 2 end */

    }
    return(sum);
}


Generated by  Doxygen 1.6.0   Back to index