/*
 * Tabu.java
 *
 * Created on 12. říjen 2000, 16:33
 * Documented 18. 7. 2001
 */

package timetable.solver.strategy;

import timetable.data.*;
import timetable.util.*;
/** Třída implementující tabu-list. Jde o množinu posledních N přiřazení (aktivita, umístění).
 *
 * @author Tomáš Müller
 * @version 1.0
 */
public class Tabu extends java.lang.Object {
    /** posledních N aktivit */
    protected Activity[] activities;
    /** posledních N umístění - vybraných zdrojů*/
    protected ActivityResources[] resources;
    /** posledních N umístění - počátečních slotů*/
    protected int[] slots;
    /** pozice posledního přiřazení v cyklickém poli */
    protected int pos = 0;
    /** měření doby strávené na tabu-listu (v ms)*/
    public long tabuTime =0;
    
    /** Konstruktor.
     * @param config globální konfigurace - obsahuje délku tabu
     */
    public Tabu(Config config) throws TimetableException {
        int tabuLength = config.getInt("DELKA_TABU");
        activities = new Activity [ tabuLength];
        slots = new int [tabuLength];
        resources = new ActivityResources [ tabuLength];
        for (int i=0;i<tabuLength;i++) {
            activities[i]=null;
            resources[i]=null;
        }
        tabuTime =0;
        pos =0;
    }
    
    /** Přidání nového ohodnocenní do tabu-listu
     * @param a zvolená aktivita
     * @param slot umístění - počáteční časový slot
     * @param g umístění - vybrané zdroje
     */
    public void add(Activity a, int slot, ActivityResources g) {
        long start=System.currentTimeMillis();
        pos = (pos +1) % slots.length;
        activities[pos]=a;
        slots[pos]=slot;
        resources[pos]=(ActivityResources)g.clone();
        tabuTime+=(System.currentTimeMillis()-start);
    }

    /** Je dané umístění tabu?
     * @param a zvolená aktivita
     * @param slot umístění - počáteční časový slot
     * @param g umístění - vybrané zdroje
     * @return true, pokud je dané umístění pro danou aktivitu tabu (již je v tabu-listu)
     */
    public boolean isTabuMove(Activity a, int slot, ActivityResources g) {
        long start=System.currentTimeMillis();
        for (int i=0;i<slots.length;i++) 
            if (activities[i]==a && slots[i]==slot && resources[i].equals(g)) {
                tabuTime+=(System.currentTimeMillis()-start);
                return true;
            };
        tabuTime+=(System.currentTimeMillis()-start);
        return false;
    }

    /** Je dané umístění v tabu-listu dvakrát (či vícekrát)?
     * @param a zvolená aktivita
     * @param slot umístění - počáteční časový slot
     * @param g umístění - vybrané zdroje
     * @return true, pokud je dané umístění pro danou aktivitu tabu-listu více než jednou
     */
    public boolean isTabuMoveTwiceMore(Activity a, int slot, ActivityResources g) {
        boolean onesTabuMove = false;
        long start=System.currentTimeMillis();
        for (int i=0;i<slots.length;i++) 
            if (activities[i]==a && slots[i]==slot && resources[i].equals(g)) 
                if (onesTabuMove) {
                    tabuTime+=(System.currentTimeMillis()-start);
                    return true;
                } else onesTabuMove=true;
        tabuTime+=(System.currentTimeMillis()-start);
        return false;
    }

}
