/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package InitialSchedules;

import org.chocosolver.solver.Model;
import org.chocosolver.solver.variables.BoolVar;
import org.chocosolver.solver.variables.IntVar;

/**
 *
 * @author frabe
 */
public class ModelFullTimeEmployeesInitialSchedules {
    public final ParametersInitialSchedules myScheduleParameters;

    public final int numberOfFullTimeEmployees;

    public BoolVar workPeriodsSchedulesOfFullTimeEmployees[][];
    private BoolVar transposeWorkPeriodsSchedulesOfFullTimeEmployees[][];

    private IntVar fullTimeEmployeesPerWorkPeriods[];

    public final Model chocoModelInitialSchedules;

    public ModelFullTimeEmployeesInitialSchedules(ParametersInitialSchedules myScheduleParameters, int numberOfFullTimeEmployees) {

        this.myScheduleParameters = myScheduleParameters;
        this.chocoModelInitialSchedules = new Model("Model Full Time Employees Initial Schedules");
        this.numberOfFullTimeEmployees = numberOfFullTimeEmployees;
        
        this.createScheduleVariables();
        this.createModelConstraints();

    }

    private void createScheduleVariables() {

        // Variable pour l'horaire des employes
        this.workPeriodsSchedulesOfFullTimeEmployees = chocoModelInitialSchedules.boolVarMatrix(this.numberOfFullTimeEmployees, this.myScheduleParameters.getWorkPeriodsPerSchedule());
        
        // Creer la transpose des horaires pour compter les elements des colonnes
        this.transposeWorkPeriodsSchedulesOfFullTimeEmployees = chocoModelInitialSchedules.boolVarMatrix(this.myScheduleParameters.getWorkPeriodsPerSchedule(), this.numberOfFullTimeEmployees);
        for (int workPeriod = 0; workPeriod < this.myScheduleParameters.getWorkPeriodsPerSchedule(); workPeriod++) {
            for (int employee = 0; employee < this.numberOfFullTimeEmployees; employee++) {
                this.transposeWorkPeriodsSchedulesOfFullTimeEmployees[workPeriod][employee]
                        = this.workPeriodsSchedulesOfFullTimeEmployees[employee][workPeriod];
            }
        }

        // Variable pour faire le compte du nombre d'employes par periode de travail
        this.fullTimeEmployeesPerWorkPeriods = chocoModelInitialSchedules.intVarArray(this.myScheduleParameters.getWorkPeriodsPerSchedule(), 0, this.numberOfFullTimeEmployees, true);

    }

    private void createModelConstraints() {

        // Constraintes tableau pour choisir un type d'horaire dans les horaires possibles
        for (int employee = 0; employee < this.numberOfFullTimeEmployees; employee++) {
            chocoModelInitialSchedules.table(this.workPeriodsSchedulesOfFullTimeEmployees[employee],
                    this.myScheduleParameters.enumerationWorkPeriodsSchedulesOfFullTimeEmployees).post();
        }
     
        // Constraintes pour compter le nombre d'employes par periode de travail et s'assurer qu'il
        // satisfait la demande en employes
        for (int workPeriod = 0; workPeriod < this.myScheduleParameters.getWorkPeriodsPerSchedule(); workPeriod++) {
            chocoModelInitialSchedules.count(chocoModelInitialSchedules.intVar(1),
                    transposeWorkPeriodsSchedulesOfFullTimeEmployees[workPeriod],
                    this.fullTimeEmployeesPerWorkPeriods[workPeriod]).post();
            chocoModelInitialSchedules.arithm(this.fullTimeEmployeesPerWorkPeriods[workPeriod], "<=",
                    this.myScheduleParameters.getRequiredWorkForce(workPeriod)).post();

        }

        // Contrainte de bris de symétrie:
        // chaque horaire d'employé est léxicographiquement inférieure à la suivante, par type d'employé
        // Ne fonctionne pas avec l'heuristique par défaut
        for (int employee = 0; employee < (this.numberOfFullTimeEmployees-1); employee++){
            chocoModelInitialSchedules.lexLessEq(this.workPeriodsSchedulesOfFullTimeEmployees[employee],
                    this.workPeriodsSchedulesOfFullTimeEmployees[employee+1]).post();
        }
        
        IntVar[] workingPeriodsPerFullTimeEmployees =
                chocoModelInitialSchedules.intVarArray(this.numberOfFullTimeEmployees,0,this.myScheduleParameters.getWorkPeriodsPerSchedule(), true);
        for (int employee = 0; employee < this.numberOfFullTimeEmployees; employee++) {
            chocoModelInitialSchedules.sum(workPeriodsSchedulesOfFullTimeEmployees[employee],
                    "=", workingPeriodsPerFullTimeEmployees[employee]).post();
            chocoModelInitialSchedules.arithm(workingPeriodsPerFullTimeEmployees[employee], ">", 0).post();
        }
        
    }

}

