/**
 * Copyright (C) 2019 Patrik Dufresne Service Logiciel <info@patrikdufresne.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package com.planimod.core;

import static com.planimod.core.TimeUtils.date;
import static com.planimod.core.TimeUtils.time;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.junit.Before;
import org.junit.Test;

import com.patrikdufresne.managers.ManagerException;
import com.planimod.core.planif.GeneratePlanifContext;
import com.planimod.core.planif.MockGeneratePlanifMonitor;
import com.planimod.core.planif.ProposedTasks;

/**
 * Test cases for generate planif function.
 * <ul>
 * <li>100 series include basic tests</li>
 * <li>200 series non-availabilities tests</li>
 * <li>300 series shifts tests</li>
 * <li>400 series preferred-position / classified-position tests</li>
 * </ul>
 * 
 * @author Patrik Dufresne
 * 
 */
public class PlanifEventManagerGeneratePlanifTest extends ManagerTestCase {

    public static final List<Employee> NULL = Arrays.asList((Employee) null);

    /**
     * Class holding all the shift event
     */
    protected ShiftUtils shifts;

    /**
     * Create the required shifts.
     */
    @Before
    public void createShifts() {
        shifts = new ShiftUtils();
        shifts.addShifts(managers);
        shifts.addExtendedShifts(managers);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Simple scenario with one employee one position to fill.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif_WithOnePositionOneEmployee_AllPositionAssign() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Simple scenario with one employee one position to fill.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif_WithTheSameContext_ExpectSameResult() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));
        context.searchSolution(new MockGeneratePlanifMonitor());
        context.searchSolution(new MockGeneratePlanifMonitor());
        List<Task> events;
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Make sure it's possible to have more then one null. This test make sure an employee is not assign to multiple
     * event at the same time.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required three (3) position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif100_WithMultiplePosition_OnePositionAssignOtherPositionsUnassign() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }

        assertEquals("Wrong number of events", 3, events.size());
        assertAssignment(events, event1, pos1, emp1);
        assertAssignment(2, events, event1, pos1, NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Make sure it's possible to have more then one null on multiple shift.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <p>
     * Employee#1 should work on one shift. Other entries are null.
     * </p>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif101_WithMultipleShiftAndOneEmployeeMultipleNullOnMultipleShift() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(events, Arrays.asList(event1, event2), pos1, emp1);
        assertAssignment(3, events, Arrays.asList(event1, event2), pos1, NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if two production event are handle properly be creating the associated position. Also check to assign the
     * employee to a qualify position.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1</li>
     * <li>product#2 required position#2</li>
     * <li>employee#1 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif102UnassignTwoProductionEvents() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);

        // Create the planif.

        ProductionEvent event11 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event21 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event12 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event22 = addProductionEvent(managers, pro2, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event11, event12), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event21, event22), pos2, NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if two production events with different positions are create properly and assign to qualify employees.
     * <p>
     * In this scenario both, position#1 and position#2, get assign to an employee.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>product#2 required one position#2</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#2</li>
     * <li>employee#3 qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif103AssignTwoProductionEvents() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos2);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);

        // Create the planif.

        ProductionEvent event11 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event21 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event12 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event13 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event14 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 5, events.size());
        assertAssignment(4, events, Arrays.asList(event11, event21, event12, event13, event14), pos1, emp1);
        assertAssignment(events, event21, pos2, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with one production events and multiple position to fill. In this scenario, the position should be filled by
     * the most senior employees. Employee#1 and employee#2 will work. Employee#3 should not work.
     * 
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 and one position#2</li>
     * <li>employee#1 qualify on position#1, position#2</li>
     * <li>employee#2 qualify on position#1, position#2</li>
     * <li>employee#3 qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * NOTICE: Multiple solution exists.
     * 
     */
    @Test
    public void generatePlanif104_1_WithTwoDifferentPositionsSameQualify_AssignToHigher() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(events, event1, Arrays.asList(pos1, pos2), emp1);
        assertAssignment(events, event2, Arrays.asList(pos1, pos2), emp1);
        assertAssignment(events, event1, Arrays.asList(pos1, pos2), emp2);
        assertAssignment(events, event2, Arrays.asList(pos1, pos2), emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with one production events and multiple position to fill. In this scenario, the position should be filled by
     * the most senior employees. So employee#1 and employee#2 will work. Employee#3 should not work.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#1</li>
     * <li>employee#3 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * NOTICE: Multiple solution exists.
     */
    @Test
    public void generatePlanif104_2_WithTwoIdenticalPositions_AssignToHigher() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(events, event1, pos1, emp1);
        assertAssignment(events, event2, pos1, emp1);
        assertAssignment(events, event1, pos1, emp2);
        assertAssignment(events, event2, pos1, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with two (2) employee having different qualification.
     * <p>
     * Check if the employees are properly assign according to there qualification.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 and one position#2</li>
     * <li>employee#1 qualify on position#1, position#2</li>
     * <li>employee#2 qualify on position#2</li>
     * <li>employee#3 qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif105_WithTwoDifferentPositionsDifferentQualify_AssigntoHigher() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos2);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event2), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event2), pos2, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with two (2) employee having different qualification.
     * <p>
     * Check if the employees are properly assign according to there qualification.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 and one position#2</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#2</li>
     * <li>employee#3 qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif106AssignProductionEventSingleChoice() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos2);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event2), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event2), pos2, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Basic check for seniority. In this scenario, employee#1 with more seniority should be schedule. Other employee
     * are not working.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#1</li>
     * <li>employee#3 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif107AssignSeniorEmployee() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2008-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-01"));
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-01"));
        addQualification(managers, emp3, pos1);

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 3, events.size());
        assertAssignment(3, events, Arrays.asList(event1, event2, event3), pos1, emp1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Basic check for employee seniority. In this scenario, employee#2 will not be schedule to work, since he is not
     * qualify on any position. employee#3 with the required qualification will work instead. (Related to hard task)
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1 and position#2</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#1</li>
     * <li>employee#3 qualify on position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif108AssignSeniorEmployeeWithRequiredQualification() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2008-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-01"));
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-01"));
        addQualification(managers, emp3, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1, pos2), emp1);
        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1, pos2), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Basic check for employee seniority. In this scenario, employee#2 will not be schedule to work, since he's not
     * qualify on any position. employee#3 with the required qualification will work instead. (Related to hard task)
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1 and position#2</li>
     * <li>employee#1 qualify on position#1, position#2</li>
     * <li>employee#2 qualify on position#1, position#2</li>
     * <li>employee#3 qualify on position#1</li>
     * <li>employee#4 qualify on position#2</li>
     * <li>employee#5 qualify on position#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#3</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif109_WithLimitedPosition_AssignHigherQualifyAndLowerNotWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2008-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-01"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-01"));
        addQualification(managers, emp3, pos1);

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-01"));
        addQualification(managers, emp4, pos2);

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-01"));
        addQualification(managers, emp5, pos3);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 6, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1, pos2), emp1);
        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1, pos2), emp2);
        assertAssignment(2, events, Arrays.asList(event1, event2), pos3, emp5);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign the higher employee qualify to work on the shift all the week. In this scenario, employee#1 is
     * qualify to work on position#1 but not on position#2, so he can't be assign.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif110_WithHigherEmployeeNotQualify_LowerEmployeeWorking() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        generatePlanif(managers, shifts.start);
        events = managers.getTaskManager().list(shifts.start, shifts.end);
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), Arrays.asList(pos2, pos1), emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign the higher employee qualify to work on the shift all the week. In this scenario, employee#1 and
     * employee#2 are qualify to work either on position#1 or position#2, so they can't be assign.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#2</li>
     * <li>employee#3 qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif111_WithTwoHigherEmployeesNotQualify_LowerEmployeeWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos2);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.thuDay);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), Arrays.asList(pos1, pos2), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Since there is no employee qualify on position#1 and position#2, employee#1 and employee#2 will work.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_1_WithNoEmployeeQualify_TwoLowerEmployeeWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1), emp1);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos2), emp2);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * This scenario is used to demonstrate the precedence of qualification over preferred-team.
     * <p>
     * In this scenario, all positions are covered using employee #1, #2, #3. Employee#4 is not required. Employee#2 is
     * then the only available and qualify employee to work on position#1, so he's assign to the shift shifts.weekDay.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>product#3 required two (2) position#2</li>
     * <li>employee#1 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, position#2, preferred-team shifts.weekEvening</li>
     * <li>employee#3 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#4 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th>shifts.weekDay</th>
     * <th>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th colspan=2>shifts.weekDay</th>
     * <th colspan=2>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif112_10_WithNoEmployeeQualifyMultipleShiftAndShiftPreferences_TwoHigherEmployeeWorking() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Product pro3 = addProduct(managers, "product3");
        addProductPosition(managers, pro3, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro3, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro3, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro3, shifts.thuEvening);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 12, events.size());

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp1);

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp3);

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1, pos2), emp2);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * This scenario integrate different case of the rule related to series 112.
     * <p>
     * All position are cover with the employees #1, #2, #3, #4 and #6. Employee#5 and #7 are not required.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1, one (1) position#2</li>
     * <li>product#2 required three (2) position#2</li>
     * <li>product#3 required two (2) position#2</li>
     * <li>employee#1 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#1, position#2, preferred-team shifts.weekEvening
     * <li>employee#4 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#5 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#6 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * <li>employee#7 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th>shifts.weekDay</th>
     * <th>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th colspan=2>shifts.weekDay</th>
     * <th colspan=2>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#3</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#6</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * <!-- Evening -->
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#3</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#6</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * <!-- Evening -->
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#6</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * <!-- Evening -->
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#6</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * <!-- Evening -->
     * <td></td>
     * <td></td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_11_WithNoEmployeeQualifyMultipleShiftAndShiftPreferences_TwoHigherEmployeeWorking() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        addProductPosition(managers, pro1, pos2, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Product pro3 = addProduct(managers, "product3");
        addProductPosition(managers, pro3, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2011-01-05"));
        addQualification(managers, emp5, pos2);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2011-01-06"));
        addQualification(managers, emp6, pos1);
        addQualification(managers, emp6, pos2);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2011-01-07"));
        addQualification(managers, emp7, pos1);
        addQualification(managers, emp7, pos2);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro3, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro3, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro3, shifts.thuEvening);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 20, events.size());

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos2), emp1);

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp2);

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1, pos2), emp3);

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp4);

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1, pos2), emp6);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * In this scenario, a position known by employee#1 and employee#2 as been added, making it possible for them to
     * work.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1, one (1) position#3</li>
     * <li>product#2 required one (1) position#2, one (1) position#3</li>
     * <li>employee#1 qualify on position#1, position#3</li>
     * <li>employee#2 qualify on position#2, position#3</li>
     * <li>employee#3 qualify on position#1, position#2, position#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#3</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#3</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_2_WithNoEmployeeQualify_TwoLowerEmployeeWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);
        addProductPosition(managers, pro2, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos3);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos2);
        addQualification(managers, emp2, pos3);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos3);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 8, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1), emp1);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos3), emp1);

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos3), emp2);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos2), emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * In this scenario, the higher employee#1 only know position#3 making it possible for him to work on
     * shifts.weekDay, but it's conflicting with the qualification of employee#2 and employee#3.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1, one (1) position#3</li>
     * <li>product#2 required one (1) position#2, one (1) position#3</li>
     * <li>employee#1 qualify on position#3</li>
     * <li>employee#2 qualify on position#1, position#3</li>
     * <li>employee#3 qualify on position#2, position#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_3_WithNoEmployeeQualify_TwoLowerEmployeeWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);
        addProductPosition(managers, pro2, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos3);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos3);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos3);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.thuDay);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 8, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1), emp2);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos3), emp2);

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos3), emp3);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos2), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * In this scenario, the lower employee#4 is not required because employee#2 and employee#3 is covering all the
     * positions. Then, it's possible to identify employee#1 as useless.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1, one (1) position#3</li>
     * <li>product#2 required one (1) position#2, one (1) position#3</li>
     * <li>employee#1 qualify on position#3</li>
     * <li>employee#2 qualify on position#1, position#3</li>
     * <li>employee#3 qualify on position#2, position#3</li>
     * <li>employee#4 qualify on position#1, position#2, position#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_4_WithNoEmployeeQualify_TwoLowerEmployeeWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);
        addProductPosition(managers, pro2, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos3);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos3);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos3);

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        addQualification(managers, emp4, pos3);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.thuDay);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 8, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1), emp2);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos3), emp2);

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos3), emp3);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos2), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * In this scenario, the higher employee#1 is not working because, all the position are cover by lower employees #2,
     * #3 and #4.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1, one (1) position#3</li>
     * <li>product#2 required two (2) position#2, one (1) position#3</li>
     * <li>employee#1 qualify on position#3</li>
     * <li>employee#2 qualify on position#1, position#3</li>
     * <li>employee#3 qualify on position#2, position#3</li>
     * <li>employee#4 qualify on position#1, position#2, position#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_5_WithNoEmployeeQualify_TwoLowerEmployeeWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        addProductPosition(managers, pro1, pos3, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);
        addProductPosition(managers, pro2, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos3);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos3);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos3);

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        addQualification(managers, emp4, pos3);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.thuDay);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 12, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1), emp2);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos3), emp2);

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos3), emp3);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos2), emp3);

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1), emp4);
        assertAssignment(2, events, Arrays.asList(event3, event4), Arrays.asList(pos2), emp4);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * This scenario is testing the precedence of qualification over preferred-team.
     * <p>
     * All positions may be cover by higher employee#1 and #2 at the condition that employee#2 is working on
     * shifts.weekDay making it impossible to employee#1 to work on it's preferred shift shifts.weekDay.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>employee#1 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th>shifts.weekDay</th>
     * <th>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#2</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#2</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th colspan=2>shifts.weekDay</th>
     * <th colspan=2>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_6_WithNoEmployeeQualifyMultipleShiftAndShiftPreferences_TwoHigherEmployeeWorking() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro2, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro2, shifts.thuEvening);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 8, events.size());

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp1);

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1, pos2), emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * This scenario is testing the precedence of qualification over preferred-team.
     * <p>
     * All positions are covered by employee#1, #2, #3, at the condition that employee#2 or employee#3 is working on
     * shifts.weekDay. Like 112_6, employee#1 will not work on it's preferred shift.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>product#3 required two (2) position#2</li>
     * <li>employee#1 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, position#2, preferred-team shifts.weekEvening</li>
     * <li>employee#3 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th>shifts.weekDay</th>
     * <th>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th colspan=2>shifts.weekDay</th>
     * <th colspan=2>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#3</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#3</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_8_WithNoEmployeeQualifyMultipleShiftAndShiftPreferences_TwoHigherEmployeeWorking() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Product pro3 = addProduct(managers, "product3");
        addProductPosition(managers, pro3, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro3, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro3, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro3, shifts.thuEvening);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 12, events.size());

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp1);

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp2);

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1, pos2), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * This scenario is used to demonstrate the precedence of qulification of preferred-team.
     * <p>
     * In this scenario, employee#2 is required to work on shifts.weekDay since it's the only employee qualify on
     * position#1.
     * <p>
     * Employee#2 is required to work on shifts.weekDay even if it's doesn't match it's preferred shift, since he's the
     * only one qualify on position#1.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>product#3 required two (2) position#2</li>
     * <li>employee#1 qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, position#2, preferred-team shifts.weekEvening</li>
     * <li>employee#3 qualify on position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th>shifts.weekDay</th>
     * <th>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day \ Shift</th>
     * <th colspan=2>shifts.weekDay</th>
     * <th colspan=2>shifts.weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <!-- Day -->
     * <td>position#1</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <!-- Day -->
     * <td>position#2</td>
     * <td>employee#2</td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <!-- Day -->
     * <td></td>
     * <td></td>
     * <!-- Evening -->
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif112_9_WithNoEmployeeQualifyMultipleShiftAndShiftPreferences_TwoHigherEmployeeWorking() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Product pro3 = addProduct(managers, "product3");
        addProductPosition(managers, pro3, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro3, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro3, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro3, shifts.thuEvening);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 12, events.size());

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp1);

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos2), emp3);

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1, pos2), emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the preferred seniority supersede the usual employee seniority. In this scenario, employee#3 with the
     * preferred seniority will will on it's preferred shift even if employee#2 is not working at all.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#1</li>
     * <li>employee#3 qualify on position#1, preferred-seniority, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>..</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif113_WithPreferredSeniority_EmployeeAssignToPreferredShift() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));
        setEmployeePreferredSeniority(managers, emp3, true);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), Arrays.asList(pos1), emp1);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), Arrays.asList(pos1), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check the employee with a preferred seniority when the preferred-team doesn't exists.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#1</li>
     * <li>employee#3 qualify on position#1, preferred-seniority, preferred-team shifts.weekEvening</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>..</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif114_WithPreferredSeniorityShiftNotExist_EmployeeNotAssign() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekEvening));
        setEmployeePreferredSeniority(managers, emp3, true);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), Arrays.asList(pos1), emp1);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), Arrays.asList(pos1), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if an employee with a preferred seniority who cannot work on his preferred team will be correctly assigned.
     * <p>
     * In this scenario, employee#3 with a preferred-seniority can't' be assign to it's preferred shift, because he's
     * not qualify on any position for shifts.weekDay. Then, employee#3 is assign as a usual employee without
     * consideration of it's preferred-seniority.
     * 
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>product#2 required two (2) position#2</li>
     * <li>employee#1 qualify on position#1, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#2, preferred-seniority, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>..</td>
     * <td>..</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>monEvening</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td>position#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>tueEvening</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td>position#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     */
    @Test
    public void generatePlanif115_1_WithEmployeePreferredSeniorityNotQualify() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDay));
        setEmployeePreferredSeniority(managers, emp3, true);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro2, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro2, shifts.thuEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));

        assertAssignment(8, events, Arrays.asList(event1, event3, event5, event7), pos1, Arrays.asList(emp1, emp2));
        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), pos2, emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4> *
     * <p>
     * Check if an employee with a preferred seniority who cannot work on his preferred team will be correctly assigned.
     * <p>
     * In this scenario, employee#5 with a preferred-seniority can't' be assign to it's preferred shift, because he's
     * not qualify on any position for shifts.weekDay. Then, employee#5 is assign as a usual employee without
     * consideration of it's preferred-seniority.
     * 
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>product#2 required two (2) position#2</li>
     * <li>employee#1 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#1, position#2, preferred-team shifts.weekEvening</li>
     * <li>employee#4 qualify on position#1, position#2, preferred-team shifts.weekEvening</li>
     * <li>employee#5 qualify on position#2, preferred-seniority, preferred-team shifts.weekDay, shifts.weekEvening</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td>product#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>..</td>
     * <td>..</td>
     * <td>..</td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td>product#2</td>
     * <td></td>
     * <tr>
     * <td>sat</td>
     * <td>product#2</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>sunDay</td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>monEvening</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>tueEvening</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * <tr>
     * <td>friDay</td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>satDay</td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * </table>
     */
    @Test
    public void generatePlanif115_2_WithEmployeePreferredSeniorityNotQualify() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2011-01-05"));
        addQualification(managers, emp5, pos2);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));
        setEmployeePreferredSeniority(managers, emp5, true);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro2, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro2, shifts.thuEvening);

        ProductionEvent event9 = addProductionEvent(managers, pro2, shifts.sunDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.friDay);
        ProductionEvent event11 = addProductionEvent(managers, pro2, shifts.satDay);

        /*
         * Not optimized
         */
        List<Task> events;
        generatePlanif(managers, shifts.start);
        events = managers.getTaskManager().list(shifts.start, shifts.end);

        assertAssignment(8, events, Arrays.asList(event1, event3, event5, event7), pos1, Arrays.asList(emp1, emp2));
        assertAssignment(8, events, Arrays.asList(event2, event4, event6, event8), pos2, Arrays.asList(emp3, emp4));
        assertAssignment(3, events, Arrays.asList(event9, event10, event11), pos2, emp5);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if an employee with a preferred seniority who cannot work on his preferred team will be correctly assigned.
     * <p>
     * In this scenario, employee#5 with a preferred-seniority can't' be assign to it's preferred shift, because he's
     * not qualify on any position for shifts.weekDay. Then, employee#5 is assign as a usual employee without
     * consideration of it's preferred-seniority, BUT is required to work.
     * 
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>product#2 required two (2) position#2</li>
     * <li>employee#1 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#1, position#2, preferred-team shifts.weekEvening</li>
     * <li>employee#4 qualify on position#1, position#2, preferred-team shifts.weekEvening</li>
     * <li>employee#5 qualify on position#2, preferred-seniority, preferred-team shifts.weekDay, shifts.weekEvening</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>..</td>
     * <td>..</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>monEvening</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>tueEvening</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     */
    @Test
    public void generatePlanif115_3_WithEmployeePreferredSeniorityNotQualify() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2011-01-05"));
        addQualification(managers, emp5, pos2);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));
        setEmployeePreferredSeniority(managers, emp5, true);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro2, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro2, shifts.thuEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));

        assertAssignment(8, events, Arrays.asList(event1, event3, event5, event7), pos1, Arrays.asList(emp1, emp2));
        assertAssignment(8, events, Arrays.asList(event2, event4, event6, event8), pos2, Arrays.asList(emp5, emp3));

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if an employee with a preferred seniority with a non-availabilities is not assign to the team.
     * <p>
     * In this scenario, employee#3 has a preferred-seniority but is not-available all the week. Then he will not be
     * assign to the team and no error is raised.
     * 
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>employee#1 qualify on position#1, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#1, preferred-seniority, preferred-team shifts.weekDay, not-available all the
     * week.</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Day</th>
     * <th>Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>..</td>
     * <td>..</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th colspan=2>Day</th>
     * <th colspan=2>Evening</th>
     * </tr>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif116_1_WithEmployeePreferredSeniorityNotAvailable() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));
        setEmployeePreferredSeniority(managers, emp3, true);
        addNonAvailability(managers, emp3, shifts.start, shifts.end);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.thuEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        generatePlanif(managers, shifts.start);
        events = managers.getTaskManager().list(shifts.start, shifts.end);
        assertEquals("Wrong number of events", 16, events.size());

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1), emp1);

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1), emp2);

        assertAssignment(8, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos1), NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with two employee with preferred-seniority. On of them is not available all the week.
     * <p>
     * In this scenario, employee#3 has a preferred seniority but is not-available during the week. Still, employee#4
     * also has a preferred seniority and then will be assign the shifts.weekDay.
     * 
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>employee#1 qualify on position#1, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#1, preferred-seniority, preferred-team shifts.weekDay, not-available all the
     * week.</li>
     * <li>employee#4 qualify on position#1, preferred-seniority, preferred-team shifts.weekDay.</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Day</th>
     * <th>Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>..</td>
     * <td>..</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th colspan=2>Day</th>
     * <th colspan=2>Evening</th>
     * </tr>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif116_2_WithEmployeePreferredSeniorityNotAvailable() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));
        setEmployeePreferredSeniority(managers, emp3, true);
        addNonAvailability(managers, emp3, shifts.start, shifts.end);

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));
        setEmployeePreferredSeniority(managers, emp4, true);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.thuEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 16, events.size());

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1), emp1);

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos1), emp2);

        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), Arrays.asList(pos1), emp4);

        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), Arrays.asList(pos1), NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign the higher employee qualify to work on the shift all the week. In this scenario, employee#1 is
     * only qualify to work on position#1. Event if he's not available Thursday, he won't be assign to the
     * shifts.weekDay shift.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>employee#1 qualify on position#1, not-available Thursday</li>
     * <li>employee#2 qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Day</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>Day</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     * @see #generatePlanif110_WithHigherEmployeeNotQualify_LowerEmployeeWorking()
     */
    @Test
    public void generatePlanif117_WithHigherEmployeeNotQualify_LowerEmployeeWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        addNonAvailability(managers, emp1, shifts.thuDay.getStartDate(), shifts.thuDay.getEndDate());

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), Arrays.asList(pos1, pos2), emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if an employee with a preferred seniority who cannot work on his preferred team and is not available half
     * the week will be correctly assigned.
     * <p>
     * In this scenario, employee#1 with a preferred-seniority can't be assign to it's preferred shift, because he's not
     * qualify on any position for shifts.weekDay and is not available monday and tuesday on his second preferred shift.
     * Then, employee#1 is assign as a usual employee without consideration of it's preferred-seniority.
     * 
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1</li>
     * <li>product#2 required one (1) position#2</li>
     * <li>employee#1 qualify on position#1, preferred-seniority, preferred-section position#1, preferred-team
     * shifts.weekEndDay(not available monDay, tueDay)</li>
     * <li>employee#2 qualify on position#1 and position#2</li>
     * <li>employee#3 qualify on position#1 and position#2</li>
     * <li>employee#4 qualify on position#1 and position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td>product#2</td>
     * <td>-</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td>product#2</td>
     * <td>-</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td>product#2</td>
     * <td>-</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>sunDay</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td>sunEvening</td>
     * <td>-</td>
     * <td>-</td>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>monEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>tueEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>wedDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>tueEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>thuDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>tueEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>friDay</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td>tueEvening</td>
     * <td>-</td>
     * <td>-</td>
     * </tr>
     * <tr>
     * <td>satDay</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td>tueEvening</td>
     * <td>-</td>
     * <td>-</td>
     * </tr>
     * </table>
     */
    @Test
    public void generatePlanif118_WithEmployeePreferredSeniorityNotQualifyAndNotAvailable() throws ManagerException {

        Section sect1 = addSection(managers, "section#1");
        Position pos1 = addPosition(managers, sect1, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, sect1, Arrays.asList(shifts.weekEndDay, shifts.weekDay));
        addNonAvailability(managers, emp1, shifts.monDay.getStartDate(), shifts.monDay.getEndDate());
        addNonAvailability(managers, emp1, shifts.tueDay.getStartDate(), shifts.tueDay.getEndDate());
        setEmployeePreferredSeniority(managers, emp1, true);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event0 = addProductionEvent(managers, pro2, shifts.sunDay);
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.thuEvening);
        ProductionEvent event9 = addProductionEvent(managers, pro2, shifts.friDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.satDay);

        /*
         * Not optimized
         */
        List<Task> events;
        generatePlanif(managers, shifts.start);
        events = managers.getTaskManager().list(shifts.start, shifts.end);

        assertAssignment(2, events, Arrays.asList(event5, event7), pos1, Arrays.asList(emp1));
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, Arrays.asList(emp2));
        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), pos1, Arrays.asList(emp3));
        assertAssignment(3, events, Arrays.asList(event0, event9, event10), pos2, Arrays.asList(emp4));
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Basic check with a non-availability.
     * <p>
     * In this scenario, employee#1 is not available on Tuesday and there isn't any other employee available to replace
     * him. So the position is not assign.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 qualify on position#1, not-available shifts.tueDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif201_WithUnavailableEmployee_Unassign() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        addNonAvailability(managers, emp1, shifts.tueDay.getStartDate(), shifts.tueDay.getEndDate());

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(3, events, Arrays.asList(event1, event3, event4), pos1, emp1);
        assertAssignment(events, event2, pos1, NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Basic check with a non-availability.
     * <p>
     * In this scenario, employee#1 is not available on Tuesday and there is someone to replace him. So the position get
     * assign.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>product#2 required one position#2</li>
     * <li>employee#1 qualify on position#1, position#2 not-available shifts.tueDay</li>
     * <li>employee#2 qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1, product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1, product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#1, product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif202_1_WithUnavailableEmployee_AssignToOtherEmployee() {

        Product pro1 = addProduct(managers, "product1");
        Product pro2 = addProduct(managers, "product2");
        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        addNonAvailability(managers, emp1, shifts.tueDay.getStartDate(), shifts.tueDay.getEndDate());

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event5 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event7 = addProductionEvent(managers, pro2, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 7, events.size());

        assertAssignment(3, events, Arrays.asList(event1, event2, event3, event4, event5, event6, event7), Arrays.asList(pos1, pos2), emp1);

        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4, event5, event6, event7), Arrays.asList(pos1, pos2), emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Basic check with a non-availability.
     * <p>
     * In this scenario, employee#1 is not available on Tuesday and there is someone to replace him. So the position get
     * assign.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 qualify on position#1 not-available shifts.tueDay</li>
     * <li>employee#2 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     */
    @Test
    public void generatePlanif202_WithUnavailableEmployee_PossitionAssignToOtherEmployee() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);
        addNonAvailability(managers, emp1, shifts.tueDay.getStartDate(), shifts.tueDay.getEndDate());

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(0, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with an employee not avaiable in a scenario where their isn't enough employee to assigned all task because
     * of the non-availabilities.
     * <p>
     * In this scenario employee#2 is not available on Tuesday. No employee is avaiable to replace him, then the one
     * position will not be assigned.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1, one position#2, one position#3</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#2 not-available shifts.tueDay</li>
     * <li>employee#3 qualify on position#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>wedDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>thuDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif203_WithUnavailableEmployee_PositionNotAssigned() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos2);
        addNonAvailability(managers, emp2, shifts.tueDay.getStartDate(), shifts.tueDay.getEndDate());

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos3);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 12, events.size());
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);
        assertAssignment(3, events, Arrays.asList(event1, event3, event4), pos2, emp2);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos3, emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if non-availabilities is apply correctly when an employee is assigned to his preferred position.
     * <p>
     * In this scenario, employee#1 is not available Tuesday but will be assigned to hispreferred position. Make sure to
     * assigned the classified position on Tuesday to someone else.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>employee#1 with preferred-position#1 (classified), position#2, not-available Tuesday, preferred-team
     * shifts.weekDay</li>
     * <li>employee#2 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#4 with position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * <li>employee#5 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#6 with position#2, preferred-team shifts.weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * 
     * <table border=1>
     * <tr>
     * <th></th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * <ul>
     * <li>position#1: employee#1</li>
     * <li>position#2: employee#2</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2: employee#3</li>
     * <li>position#2: employee#5</li>
     * <li>position#2: employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * <ul>
     * <li>position#1: employee#4</li>
     * <li>position#2: employee#2</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2: employee#3</li>
     * <li>position#2: employee#5</li>
     * <li>position#2: employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>tue-position#1 to employee#4</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif204_WithUnavailableEmployeeAssignedToPreferredPosition() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));
        addNonAvailability(managers, emp1, shifts.tueDay.getStartDate(), shifts.wedDay.getStartDate());

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos2);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos2);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate planif
         */
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 10, events.size());

        assertAssignment(1, events, event1, pos1, emp1);
        assertAssignment(1, 2, events, Arrays.asList(event1, event3), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);
        assertAssignment(0, 1, events, event1, pos2, emp4);
        assertAssignment(1, events, event3, pos1, emp4);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp6);

        /*
         * Check offer
         */
        ProposedTasks tasks = context.getProposedTasks();
        assertEquals(1, tasks.employees().size());

        assertEquals(1, tasks.tasks(emp4).size());

        assertAssignment(1, tasks.tasks(emp4), event3, pos1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the non-availabilities is apply at the right moment for employee with preferred seniority.
     * <p>
     * In this scenario, employee#1 is not available Tuesday but will be assigned to hispreferred position. Make sure to
     * assigned the classified position on Tuesday to someone else.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>product#2 required three (3) position#1</li>
     * <li>employee#1 with position#1, preferred-team weekEvening</li>
     * <li>employee#2 with position#1, preferred-team weekDay</li>
     * <li>employee#3 with position#2, preferred-team weekDay, preferred-seniority -- not-available Tuesday</li>
     * <li>employee#4 with position#2, preferred-team weekEvening</li>
     * <li>employee#5 with position#2, preferred-team weekDay</li>
     * <li>employee#6 with position#2, preferred-team weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * 
     * <table border=1>
     * <tr>
     * <th></th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * <ul>
     * <li>position#2: employee#2</li>
     * <li>position#2: employee#5</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2: employee#1</li>
     * <li>position#2: employee#4</li>
     * <li>position#2: employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * <ul>
     * <li>position#2: employee#2</li>
     * <li>position#2: employee#3</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2: employee#1</li>
     * <li>position#2: employee#4</li>
     * <li>position#2: employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif205_1_WithUnavailableEmployeePreferredSeniority() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos1, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));
        setEmployeePreferredSeniority(managers, emp3, true);
        addNonAvailability(managers, emp3, shifts.tueDay.getStartDate(), shifts.tueDay.getEndDate());

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos1);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos1);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate planif
         */
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 10, events.size());

        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp1);
        assertAssignment(1, 2, events, Arrays.asList(event1, event3), pos1, emp2);
        assertAssignment(1, events, event1, pos1, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp4);
        assertAssignment(1, events, Arrays.asList(event3), pos1, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp6);

        /*
         * Check offer
         */
        ProposedTasks tasks = context.getProposedTasks();
        assertEquals(0, tasks.employees().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the non-availabilities is apply at the right moment for employee with preferred seniority.
     * <p>
     * In this scenario, employee#1 is not available Tuesday but will be assigned to hispreferred position. Make sure to
     * assigned the classified position on Tuesday to someone else.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>product#2 required three (3) position#1</li>
     * <li>employee#1 with position#1, preferred-team weekEvening</li>
     * <li>employee#2 with position#1, preferred-team weekDay</li>
     * <li>employee#3 with position#2, preferred-team weekDay</li>
     * <li>employee#4 with position#2, preferred-team weekEvening</li>
     * <li>employee#5 with position#2, preferred-team weekDay, preferred-seniority -- not-available Tuesday</li>
     * <li>employee#6 with position#2, preferred-team weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * 
     * <table border=1>
     * <tr>
     * <th></th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * <ul>
     * <li>position#2: employee#2</li>
     * <li>position#2: employee#5</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2: employee#1</li>
     * <li>position#2: employee#4</li>
     * <li>position#2: employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * <ul>
     * <li>position#2: employee#2</li>
     * <li>position#2: employee#3</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2: employee#1</li>
     * <li>position#2: employee#4</li>
     * <li>position#2: employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif205_WithUnavailableEmployeePreferredSeniority() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos1, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos1);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay));
        setEmployeePreferredSeniority(managers, emp5, true);
        addNonAvailability(managers, emp5, shifts.tueDay.getStartDate(), shifts.tueDay.getEndDate());

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos1);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate planif
         */
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 10, events.size());

        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp1);
        assertAssignment(1, 2, events, Arrays.asList(event1, event3), pos1, emp2);
        assertAssignment(1, events, event3, pos1, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp4);
        assertAssignment(0, 1, events, Arrays.asList(event1, event3), pos1, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp6);

        /*
         * Check offer
         */
        ProposedTasks tasks = context.getProposedTasks();
        assertEquals(0, tasks.employees().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if it's possible for an employee to be non-available part of the week resulting in no assignment for this
     * employee. In this scenario, the employee #2 is not available from sun to thu (inclusive) and should be assign to
     * week day team.
     * <p>
     * See ticket #191.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>employee#1 with position#1, preferred-team weekDay</li>
     * <li>employee#2 with position#1, preferred-team weekDay -- not-available from sun to thu</li>
     * <li>employee#3 with position#1, preferred-team weekEndDay</li>
     * <li>employee#4 with position#1, preferred-team weekDay</li>
     * <li>employee#5 with position#1, preferred-team weekEndDay</li>
     * <li>employee#6 with position#1, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Day</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * 
     * <table border=1>
     * <tr>
     * <th></th>
     * <th>Day</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td>
     * <ul>
     * <li>position#1: employee#3</li>
     * <li>position#1: employee#5</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * <ul>
     * <li>position#1: employee#1</li>
     * <li>position#1: employee#4</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * <ul>
     * <li>position#1: employee#1</li>
     * <li>position#1: employee#4</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>
     * <ul>
     * <li>position#1: employee#1</li>
     * <li>position#1: employee#4</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>
     * <ul>
     * <li>position#1: employee#1</li>
     * <li>position#1: employee#4</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td>
     * <ul>
     * <li>position#1: employee#3</li>
     * <li>position#1: employee#5</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td>
     * <ul>
     * <li>position#1: employee#3</li>
     * <li>position#1: employee#5</li>
     * </ul>
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif206_WithUnavailableEmployee_NeverAssigned() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));
        addNonAvailability(managers, emp2, shifts.sunDay.getStartDate(), shifts.friDay.getStartDate());

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekEndDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos1);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekEndDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos1);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.sunDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.friDay);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.satDay);

        /*
         * Generate planif
         */
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(shifts.sunDay.getStartDate(), shifts.satDay.getEndDate());

        assertEquals("Wrong number of events", 14, events.size());

        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);
        assertAssignment(3, events, Arrays.asList(event5, event6, event7), pos1, emp3);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp4);
        assertAssignment(3, events, Arrays.asList(event5, event6, event7), pos1, emp5);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if a non-availability is take in consideration very early is the employee is locked. See ticket # 227.
     * <p>
     * See ticket # 227.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two (2) position#1 (classified), two (2) position#3</li>
     * <li>product#2 required two (2) position#1 (classified), one (1) position#2, one (1) position#3</li>
     * <li>product#3 required one (1) position#1 (classified), one (1) position#2, two (2) position#3</li>
     * <li>product#4 required two (2) position#3</li>
     * <li>employee#1 with preferred-position#1-weekDay, preferred-team weekDay, position#2, position#3</li>
     * <li>employee#2 with position#3, preferred-team weekDay</li>
     * <li>employee#3 with position#3, preferred-team weekDay</li>
     * <li>employee#4 with position#1, position#3, preferred-team weekDay -- not available monday -- locked tuesday on
     * position#1</li>
     * <li>employee#5 with position#3, preferred-team weekDay</li>
     * <li>employee#6 with position#2, position#3, preferred-team weekDay</li>
     * <li>employee#7 with position#3, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * 
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1: employee#1<br />
     * position#1: employee#6<br />
     * position#3: employee#2<br />
     * position#3: employee#3</td>
     * <td>position#3: employee#5 <br />
     * position#3: employee#7</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1: employee#1<br />
     * position#1: employee#4 (locked)<br />
     * position#2: employee#6<br />
     * position#3: employee#2</td>
     * <td>position#3: employee#5 <br />
     * position#3: employee#7</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1: employee#1<br />
     * position#2: employee#6<br />
     * position#3: employee#2<br />
     * position#3: employee#2</td>
     * <td>position#3: employee#5 <br />
     * position#3: employee#7</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#1: employee#1<br />
     * position#2: employee#6<br />
     * position#3: employee#2<br />
     * position#3: employee#2</td>
     * <td>position#3: employee#5 <br />
     * position#3: employee#7</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif207_WithUnavailableEmployeeLocked() throws ManagerException {

        Section section1 = addSection(managers, "section1");
        Position pos1 = addPosition(managers, section1, "position#1", true);
        Position pos2 = addPosition(managers, section1, "position#2", false);
        Position pos3 = addPosition(managers, section1, "position#3", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        addProductPosition(managers, pro1, pos3, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos1, 2);
        addProductPosition(managers, pro2, pos2, 1);
        addProductPosition(managers, pro2, pos3, 1);
        Product pro3 = addProduct(managers, "product3");
        addProductPosition(managers, pro3, pos1, 1);
        addProductPosition(managers, pro3, pos2, 1);
        addProductPosition(managers, pro3, pos3, 2);
        Product pro4 = addProduct(managers, "product4");
        addProductPosition(managers, pro4, pos3, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2, pos3);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, section1, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos3);
        setEmployeePreference(managers, emp2, null, null, section1, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos3);
        setEmployeePreference(managers, emp3, null, null, section1, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1, pos3);
        setEmployeePreference(managers, emp4, null, null, section1, Arrays.asList(shifts.weekDay));
        addNonAvailability(managers, emp4, shifts.monDay.getStartDate(), shifts.monDay.getEndDate());

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos3);
        setEmployeePreference(managers, emp5, null, null, section1, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos1, pos2, pos3);
        setEmployeePreference(managers, emp6, null, null, section1, Arrays.asList(shifts.weekDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2010-01-07"));
        addQualification(managers, emp7, pos3);
        setEmployeePreference(managers, emp7, null, null, section1, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro3, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.thuDay);
        ProductionEvent event5 = addProductionEvent(managers, pro4, shifts.monEvening);
        ProductionEvent event6 = addProductionEvent(managers, pro4, shifts.tueEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro4, shifts.wedEvening);
        ProductionEvent event8 = addProductionEvent(managers, pro4, shifts.thuEvening);

        /*
         * Generate planif
         */
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(shifts.sunDay.getStartDate(), shifts.satDay.getEndDate());

        assertEquals("Wrong number of events", 24, events.size());
        // FIXME The expected result.
        // assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);
        // assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos3, emp2);
        // assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos3, emp3);
        // assertAssignment(1, events, Arrays.asList(event2), pos1, emp4);
        // assertAssignment(2, events, Arrays.asList(event3, event4), pos3, emp4);
        // assertAssignment(4, events, Arrays.asList(event5, event6, event7, event8), pos3, emp5);
        // assertAssignment(1, events, Arrays.asList(event1), pos1, emp6);
        // assertAssignment(3, events, Arrays.asList(event2, event3, event4), pos2, emp6);
        // assertAssignment(4, events, Arrays.asList(event5, event6, event7, event8), pos3, emp7);

        // FIXME Broken
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos3, emp2);
        assertAssignment(4, events, Arrays.asList(event5, event6, event7, event8), pos3, emp3);
        assertAssignment(1, events, Arrays.asList(event2), pos1, emp4);
        assertAssignment(2, events, Arrays.asList(event3, event4), pos3, emp4);
        assertAssignment(1, events, Arrays.asList(event1), pos3, emp5);
        assertAssignment(1, events, Arrays.asList(event1), pos1, emp6);
        assertAssignment(3, events, Arrays.asList(event2, event3, event4), pos2, emp6);
        assertAssignment(4, events, Arrays.asList(event5, event6, event7, event8), pos3, emp7);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to ensure an employee is not schedule to work on two different shifts. In this scenario, each employee
     * should be assign to a single shift during the week. NOTICE: The employee doesn't have a preferred shift, so they
     * can be assign to any one.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#1</li>
     * <li>employee#3 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * Each employee should only work once.
     */
    @Test
    public void generatePlanif301AssignEmployeeToOneShift() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());

        // Each employee need to work once
        assertAssignment(1, events, Arrays.asList(event1, event2), pos1, emp1);
        assertAssignment(1, events, Arrays.asList(event1, event2), pos1, emp2);
        assertAssignment(1, events, Arrays.asList(event1, event2), pos1, emp3);
        assertAssignment(1, events, Arrays.asList(event1, event2), pos1, NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with multiple shifts and one non-availability.
     * <p>
     * In this scenario, employee#1 is not available Tuesday AM. Employee#3 should than be schedule to replace him
     * during this period. NOTICE : Multiple solution exists since there is not shift preferences.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 qualify on position#1, not available Tuesday 6h-12h</li>
     * <li>employee#2 qualify on position#1</li>
     * <li>employee#3 qualify on position#1</li>
     * <li>employee#4 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay 6h-12h</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay 12h-16h</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif302UnassignUnavailableEmployeeWithMultipleShift() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);
        addNonAvailability(managers, emp1, shifts.tueDay.getStartDate(), time("Tue 13:00"));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos1);

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2012-01-04"));
        addQualification(managers, emp4, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        List<Task> events;
        try {
            generatePlanif(managers, shifts.start);
            events = managers.getTaskManager().list(shifts.start, shifts.end);
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }

        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, Arrays.asList(emp1, emp2));

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with multiple shifts and one non-availability.
     * <p>
     * In this scenario, employee#1 is not available Tuesday from 6AM to 12AM.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 qualify on position#1, not available Tuesday 6h-12h</li>
     * <li>employee#2 qualify on position#1</li>
     * <li>employee#3 qualify on position#1</li>
     * <li>employee#4 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1 / employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif303UnassignUnavailableEmployee() {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2012-01-01"));
        addQualification(managers, emp1, pos1);
        addNonAvailability(managers, emp1, shifts.tueDay.getStartDate(), time("Tue 12:00"));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2012-01-02"));
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2012-01-03"));
        addQualification(managers, emp3, pos1);

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2012-01-04"));
        addQualification(managers, emp4, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }
        assertEquals("Wrong number of events", 5, events.size());

        // Multiple solution are allowed.
        // Make sure only 3 employee are used

        assertAssignment(5, events, Arrays.asList(event1, event2, event3, event4, event5), pos1, Arrays.asList(emp1, emp2, emp3));

    }

    /**
     * 
     * <h4>Test Objective</h4> Check to assign a classified position to the employee with the preffered-position.
     * <p>
     * This this scenario, two employees has the qualification to work on the classified position and the seniority to
     * work on the associated team. The classified position is then assigne to the employe owning the position.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1, position#2</li>
     * <li>employee#1 preferred-position#1 (classified), position#2</li>
     * <li>employee#2 qualify on position#1 (classified), position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif400AssignClassifiedPositionToOwner() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, null, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Generate planif
         */
        List<Task> events;
        GeneratePlanifContext context;
        context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos2, emp2);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4> Check to assign a classified position to the employee with the preffered-position.
     * <p>
     * This this scenario, two employees has the qualification to work on the classified position and the seniority to
     * work on the associated team. The classified position is then assigne to the employe owning the position.
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (Classified) and position#2</li>
     * <li>employee#1 qualify on position#1 (Classified), position#2</li>
     * <li>employee#2 with preferred-position#1 (classified), qualify on position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     * @see {@link #generatePlanif400AssignClassifiedPositionToOwner()}
     */
    @Test
    public void generatePlanif401AssignClassifiedPositionToOwner() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, pos1, shifts.weekDay, null, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 8, events.size());
        // Employee#1 is assign all the week to position#2
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos2, emp1);
        // Employee#2 is assign all the week to position#1
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp2);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign a classified posiiton without a owner according to the employee's preferred-team.
     * <p>
     * Since there is no employee with the required preferred-position, the classified position get assign to employee#1
     * according to his shift preference.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1 (classified)</li>
     * <li>product#2 required position#2</li>
     * <li>employee#1 qualify on position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day</th>
     * <th>weekEvening</th>
     * <th>weekDay</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1 : employee#1</td>
     * <td>position#2 : employee#2<br/>
     * position#2 : employee#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1 : employee#1</td>
     * <td>position#2 : employee#2<br/>
     * position#2 : employee#3</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * <h4>Offered position</h4>
     * <ul>
     * <li>position#1 is offered to employee#1 and employee#2</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif402AssignClassifiedPositionWithoutOwner() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        addProductPosition(managers, pro1, pos1, 1);

        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp3, date("2010-01-02"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 6, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(2, list.size());
        assertTrue(list.containsAll(Arrays.asList(emp1, emp2)));

        Collection<Task> tasks;
        tasks = context.getProposedTasks().tasks(emp1);
        assertEquals(2, tasks.size());

        tasks = context.getProposedTasks().tasks(emp2);
        assertEquals(2, tasks.size());

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Basic check for preferred position. In this scenario, the employee#1 with the preferred position should be assign
     * to it. The employee#2 may be assign to position#2 on any shift (since he doesn't have a preferred shift).
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (classified), one position#2</li>
     * <li>employee#1 with preferred-position#1-weekDay, qualify position#2</li>
     * <li>employee#2 qualify position#1 and position#2</li>
     * <li>employee#3 qualify position#2</li>
     * <li>employee#4 qualify position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1 : employee#1<br />
     * position#2 : employee#3 or #4</td>
     * <td>position#1 : employee#2<br />
     * position#2 : employee#3 or #4</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1 : employee#1<br />
     * position#2 : employee#3 or #4</td>
     * <td>position#1 : employee#2<br />
     * position#2 : employee#3 or #4</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>position#1-weekEvening is offered to employee#2</li>
     * <li>no warning because employee#2 doesn't have a preferred shift.</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif403AssignOwnedClassifiedPositionWithMultipleShifts() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, null, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, null);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp2, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, null);

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, null);

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.thuEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 16, events.size());
        // Employee#1 should work on position#1 all the shifts.weekDay
        assertAssignment(4, events, Arrays.asList(event1, event3, event5, event7), pos1, emp1);
        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), pos1, emp2);

        assertAssignment(8, events, Arrays.asList(event1, event2, event3, event4, event5, event6, event7, event8), pos2, Arrays.asList(emp3, emp4));

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(1, list.size());
        assertTrue(list.contains(emp2));

        assertEquals(4, context.getProposedTasks().tasks(emp2).size());
        assertAssignment(4, context.getProposedTasks().tasks(emp2), Arrays.asList(event2, event4, event6, event8), pos1);

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign the classified position according to it's owner.
     * <p>
     * In this scenario, employee #3 as the sceniority to work on the team, then he is assigne to the classified
     * position.
     * 
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (classified), two position#2</li>
     * <li>employee#1 qualify on position#2</li>
     * <li>employee#2 qualify on position#1 (classified), qualify on position#2</li>
     * <li>employee#3 with preferred-position#1, qualify on position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * 
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif404_AssignClassifiedPositionToOwner() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 12, events.size());
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos2, emp1);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos2, emp2);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp3);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the classified position owned by employee#3, is not assign to him since he doesn't have the seniority to
     * work on the shift. The classified position get assign to the higer employee#1. Employee#3 is then assigned to
     * it's second preferred shift.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (classified), position#2</li>
     * <li>product#1 required two position#2</li>
     * <li>employee#1 qualify on position#1 (classified), position#2, preferred-team shifts.weekDay, shifts.weekEvening</li>
     * <li>employee#2 qualify on position#2, preferred-team shifts.weekDay, shifts.weekEvening</li>
     * <li>employee#3 preferred-position#1 (classified), qualify on position#2, preferred-team shifts.weekDay,
     * shifts.weekEvening</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>monEvening</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>monEvening</td>
     * <td>position#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * <h4>Offered position</h4>
     * <ul>
     * <li>position#1 offered to employee#1 and employee#2</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif406_withLowerEmployeeOwnerNotSeniorToWorkOnShift_ClassifiedPositionAssignToHigherEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, NULL);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(2, list.size());

        assertAssignment(2, context.getProposedTasks().tasks(emp1), Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        assertAssignment(2, context.getProposedTasks().tasks(emp3), Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the classified position#1 owned by employee#3 is not assigned to him since he doesn't have the seniority
     * to work and there is an higher employee qualify for the position. Then the classified position is assigned to
     * employee#2.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (classified)</li>
     * <li>employee#1 qualify position#2, preferred-team weekDay, weekEvening</li>
     * <li>employee#2 qualify position#1, position#2, preferred-team weekDay, weekEvening</li>
     * <li>employee#3 preferred-position#1-weekDay, preferred-team weekDay, weekEvening</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * <h4>Offered position</h4>
     * <ul>
     * <li>position#1 offered to employee#1 and employee#2</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif407_withLowerEmployeeOwnerNotSeniorToWork_ClassifiedPositionAssignToHigherEmployee() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        // Create the planif

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(2, list.size());

        Collection<Task> tasks;
        tasks = context.getProposedTasks().tasks(emp2);
        assertAssignment(2, tasks, Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        tasks = context.getProposedTasks().tasks(emp3);
        assertAssignment(2, tasks, Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the classified position owned by the lower employee#3, is not assign to him since he doesn't have the
     * seniority to work on the shift. The classified position get assign to the higer employee#2. Employee#3 is then
     * assigned to it's second preferred shift.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (classified)</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>employee#1 qualify on, position#2, preferred-team weekDay, weekEvening</li>
     * <li>employee#2 qualify on position#1, position#2, preferred-team weekDay, weekEvening</li>
     * <li>employee#3 preferred-position#1-weekDay, position#2, preferred team weekDay, weekEvening</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>monEvening</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>monEvening</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>monEvening</td>
     * <td>position#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * <h4>Offered position</h4>
     * <ul>
     * <li>position#1 offered to employee#2 and employee#3</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     * @see #generatePlanif406_withLowerEmployeeOwnerNotSeniorToWorkOnShift_ClassifiedPositionAssignToHigherEmployee()
     */
    @Test
    public void generatePlanif408_withLowerEmployeeOwnerNotSeniorToWorkOnShift_ClassifiedPositionAssignToHigherEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);

        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-01"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-02"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        // Create the planif

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, NULL);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(2, list.size());

        Collection<Task> tasks;
        tasks = context.getProposedTasks().tasks(emp2);
        assertAssignment(2, tasks, Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        tasks = context.getProposedTasks().tasks(emp3);
        assertAssignment(2, tasks, Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with two classified positions owned by employee#3 and employee#4. Both employees doesn't have the
     * seniorities to work on the classified positions. The classified positions are then assigned to employee#1 and
     * employee#2 according the preferred-team.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two (2) position#1 (classified)</li>
     * <li>product#2 required two (3) position#2 (classified)</li>
     * <li>employee#1 qualify position#1, position#2, preferred-team weekDay</li>
     * <li>employee#2 qualify position#1 , position#2, preferred-team weekDay</li>
     * <li>employee#3 with preferred-position#1-weekDay, qualify position#2, preferred-team weekDay</li>
     * <li>employee#4 with preferred-position#1-weekDay, qualify position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * <h4>Offered position</h4>
     * <ul>
     * <li>position#1 offered to employee#1, employee#2, employee#3 and employee#4</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif409_WithHigherUnAssignPreferredShiftEmployee_PreferredPositionOwnerNotAssign() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 10, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp4);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, NULL);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(4, list.size());

        Collection<Task> tasks;
        tasks = context.getProposedTasks().tasks(emp1);
        assertAssignment(4, tasks, Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        tasks = context.getProposedTasks().tasks(emp2);
        assertAssignment(4, tasks, Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        tasks = context.getProposedTasks().tasks(emp3);
        assertAssignment(4, tasks, Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        tasks = context.getProposedTasks().tasks(emp4);
        assertAssignment(4, tasks, Arrays.asList(event1, event3), pos1, Arrays.asList(null, emp1, emp2, emp3));

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign classified position to most senior employee even if a more senior employee doesn't work on the
     * preferred-team.
     * <p>
     * In this scenario, employee#3 is assign to it's preferred-position even if employee#2 is not assign to it's
     * preferred-team because there is no higher employee qualify to work on position#1.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 and one (1) position#2</li>
     * <li>product#2 required one (1) position#2 and one (1) position#3</li>
     * <li>employee#1 with position#2, position#3, preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#2, position#3, preferred-team shifts.weekDay</li>
     * <li>employee#3 with preferred-position#1 (classified), qualify on position#2, position#3, preferred-team
     * shifts.weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4> *
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif415_WithUnAssignEmployeeButNoHigherEmployeeAvailable_LowerPreferredPositionOwnerAssign() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);
        addProductPosition(managers, pro2, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        addQualification(managers, emp1, pos3);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        addQualification(managers, emp2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos3);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 8, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);

        assertAssignment(2, events, Arrays.asList(event2, event4), Arrays.asList(pos2, pos3), emp2);

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp3);

        assertAssignment(2, events, Arrays.asList(event2, event4), Arrays.asList(pos2, pos3), NULL);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign classified position to most senior employee de when someone qualify is working on the team but
     * assign to a classified position.
     * <p>
     * In this scenario, employee#4 is assign to his preferred position even if employee#3 is not assign to it's
     * preferred-team, because all available senior employees are working on classified position.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), one (1) position#2 (classified) and one (1) position#3</li>
     * <li>product#2 required three (3) position#3</li>
     * <li>employee#1 with preferred-position#1 (classified), position#2 (classified), position#3, preferred-team
     * shifts.weekDay</li>
     * <li>employee#2 with position#3, preferred-team shifts.weekDay</li>
     * <li>employee#3 with position#3, preferred-team shifts.weekDay</li>
     * <li>employee#4 with preferred-position#2 (classified), position#3, preferred-team shifts.weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <td></td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <td></td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif416_WithUnAssignEmployeeButHigherEmployeeWorkingOnClassified_LowerPreferredPositionOwnerAssign() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", true);
        Position pos3 = addPosition(managers, null, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos3, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        addQualification(managers, emp1, pos3);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos2);
        addQualification(managers, emp4, pos3);
        setEmployeePreference(managers, emp4, pos2, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 12, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos3, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos3, emp3);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp4);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign classified position by default to the most senior employee owning the position.
     * <p>
     * In this scenario, employee#4 is assign to it's preferred position by default if employee#3 is not assign to it's
     * preferred shift, because the preferred-team of employee#1 is weekEvening and he is assign to it.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>prduct#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>prduct#2 required three (3) position#2</li>
     * <li>employee#1 with position#1 (classified), qualify on position#2, preferred-team shifts.weekEvening</li>
     * <li>employee#2 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#4 with preferred position#1 (classified), qualify on position#2 preferred-team shifts.weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * <h4>Offered position</h4>
     * <ul>
     * <li>position#1 offered to employee#1</li>
     * </ul>
     * 
     * @throws ManagerException
     * @see {@link #generatePlanif434_ClassifiedPositionOfferedToSeniorEmployee()}
     * 
     */
    @Test
    public void generatePlanif417_WithUnAssignButHigherAvailableEmployeeAssignToDifferentShift_LowerPreferredPositionOwnerAssign() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 10, events.size());
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp4);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());
        // assertTrue(list.contains(emp1));
        // assertAssignment(2, context.getProposedTasks().tasks(emp1), Arrays.asList(event1, event3), pos1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if a classified position is assign to an employee event if he doesn't have the seniority to work on it's
     * preferred shift.
     * <p>
     * In this scenario, employee#4 is assign to it's preferred position event if employee#3 is not assign to it's
     * preferred shift, because all higher employees are locked on other position.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>employee#1 with position#1 (classified), qualify on position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#4 with preferred position#1 (classified), qualify on position#2, preferred-team shifts.weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1 (locked)</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif418_WithUnAssignButHigherAvailableEmployeeLocked_LowerPreferredPositionOwnerAssign() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        // Lock event
        Task lockedEvent;
        lockedEvent = addTask(managers, event1, pos2, null, null);
        setTaskLocked(managers, lockedEvent, emp1);
        lockedEvent = addTask(managers, event3, pos2, null, null);
        setTaskLocked(managers, lockedEvent, emp1);

        /*
         * Generate planif
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 10, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp4);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign the preferred position to the higher employee with the required preferred position. The lower
     * employees are assign to another positions.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>employee#1 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 with preferred-position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * <li>employee#4 with preferred-position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>none</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif420_WithTwoPreferredPositionOwnerAndOnlyOneAvailable_HigherEmployeeAssign() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate planif
         */
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 10, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp4);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign the preferred position when there is two identical classified position to be assign.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * 
     * <li>product#1 required two (2) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>employee#1 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 with preferred position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * <li>employee#4 with preferred position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif421_WithTwoClassiedPosition_AssignToTwoDifferentEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate Planif
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 12, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp3);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp4);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if a classified position is assign to an employee event if he doesn't have the seniority to work on it's
     * preferred shift.
     * <p>
     * In this scenario, employee#4 is assign to it's preferred position even if employee#3 is not assign to it's
     * preferred shift, because employee#1 is not available all the week to be assign to position#1.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>employee#1 with position#1 (classified), position#2, not-available Tuesday, preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#4 with preferred-position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * <li>employee#5 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#6 with position#2, preferred-team shifts.weekDay</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * 
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Day</th>
     * <th>Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * <ul>
     * <li>position#1 : employee#4</li>
     * <li>position#2 : employee#1</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2 : employee#3</li>
     * <li>position#2 : employee#5</li>
     * <li>position#2 : employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * <ul>
     * <li>position#1 : employee#4</li>
     * <li>position#2 : employee#2</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2 : employee#3</li>
     * <li>position#2 : employee#5</li>
     * <li>position#2 : employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered position</h4>
     * <ul>
     * <li>mon-position#1 to employee#1 (ambiguous)</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif423_WithUnAssignPreferredShiftEmployeeButPreferredPositionOwnerRequiredOnTheShift_LowerPreferredPositionOwnerAssign()
            throws ManagerException {

        Section sec = addSection(managers, "section1");
        Position pos1 = addPosition(managers, sec, "position#1", true);
        Position pos2 = addPosition(managers, sec, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec, Arrays.asList(shifts.weekDay));
        addNonAvailability(managers, emp1, shifts.tueDay.getStartDate(), shifts.wedDay.getStartDate());

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, sec, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1, pos2);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, sec, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos2);
        setEmployeePreference(managers, emp5, null, null, sec, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos2);
        setEmployeePreference(managers, emp6, null, null, sec, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate planif
         */
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 10, events.size());

        assertAssignment(events, event1, pos2, emp1);
        assertAssignment(events, event3, pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp4);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp6);

        /*
         * Check offer
         */
        ProposedTasks tasks = context.getProposedTasks();
        assertEquals(0, tasks.employees().size());

        // assertEquals(1, tasks.tasks(emp1).size());

        // assertAssignment(1, tasks.tasks(emp1), event1, pos1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with two employee not available to be assigned to classified position.
     * <p>
     * In this scenario, employee#4 is not assign to it's preferred position#1, because employee#1 and employee#2 are
     * available to fill the classified position.
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two (2) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>employee#1 with position#1 (classified), position#2 - not available monDay, preferred-team weekDay</li>
     * <li>employee#2 with position#1 (classified), position#2 - not available Tuesday, preferred-team weekDay</li>
     * <li>employee#3 with position#2, preferred-team weekDay</li>
     * <li>employee#4 with preferred-position#1 (classified), position#2, preferred-team weekDay</li>
     * <li>employee#5 with position#2, preferred-team weekDay</li>
     * <li>employee#6 with position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * 
     * <table border=1>
     * <tr>
     * <th>Day</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * <ul>
     * <li>position#1: employee#2</li>
     * <li>position#2: employee#3</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2: employee#4</li>
     * <li>position#2: employee#5</li>
     * <li>position#2: employee#6</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * <ul>
     * <li>position#1: employee#1</li>
     * <li>position#2: employee#3</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#2: employee#4</li>
     * <li>position#2: employee#5</li>
     * <li>position#2: employee#6</li>
     * </ul>
     * </td>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif426UnAssignOwnedClassifiedPositionWhenMultipleHigherEmployeeArePartiallyAvailable() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));
        addNonAvailability(managers, emp1, shifts.monDay.getStartDate(), shifts.monDay.getEndDate());

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));
        addNonAvailability(managers, emp2, shifts.tueDay.getStartDate(), shifts.tueDay.getEndDate());

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos2);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos2);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 10, events.size());
        assertAssignment(events, event3, pos1, emp1);
        assertAssignment(events, event1, pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp4);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp6);

        /*
         * Check offer
         */
        ProposedTasks tasks = context.getProposedTasks();
        assertEquals(3, tasks.employees().size());

        assertAssignment(1, tasks.tasks(emp1), event3, pos1);

        assertAssignment(1, tasks.tasks(emp2), event1, pos1);

        assertAssignment(2, tasks.tasks(emp4), Arrays.asList(event1, event3), pos1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check the classified position assignment. In this scenario, employee#4 is not assign to it's preferred position
     * because employee#1 can replace him. On the other hand, employee#5 will be assign to it's preferred position
     * because nobody is capable of replacing him.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), one (1) position#2 (classified) and one (1) position#3</li>
     * <li>product#2 required three (3) position#3</li>
     * <li>employee#1 with position#1 (classified), position#3, preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#3, preferred-team shifts.weekDay</li>
     * <li>employee#3 with position#3, preferred-team shifts.weekDay</li>
     * <li>employee#4 with preferred-position#1 (classified), position#3, preferred-team shifts.weekDay</li>
     * <li>employee#5 with preferred-position#2 (classified), position#3, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * 
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif427MixedAssignAndUnassignOwnedClassifiedPosition() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", true);
        Position pos3 = addPosition(managers, null, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos3, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos3);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos3);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-04"));
        addQualification(managers, emp5, pos2);
        addQualification(managers, emp5, pos3);
        setEmployeePreference(managers, emp5, pos2, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 12, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos3, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos3, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos3, emp4);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos3, NULL);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(2, list.size());

        Collection<Task> tasks;
        tasks = context.getProposedTasks().tasks(emp1);
        assertAssignment(2, tasks, Arrays.asList(event1, event3), pos1, emp1);

        tasks = context.getProposedTasks().tasks(emp4);
        assertAssignment(2, tasks, Arrays.asList(event1, event3), pos1, emp1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if a two (2) classified position are not assign if employee is qualify/available for both.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), one (1) position#2 (classified), one (1) position#3
     * (classified) and one (1) position#4</li>
     * <li>product#2 required four (4) position#4</li>
     * <li>employee#1 with position#1 (classified), position#2 (classified), position#3 (classified), position#4,
     * preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#4, preferred-team shifts.weekDay</li>
     * <li>employee#3 with position#4, preferred-team shifts.weekDay</li>
     * <li>employee#4 with preferred position#1 (classified), position#4, preferred-team shifts.weekDay</li>
     * <li>employee#5 with preferred position#2 (classified), position#4, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#4</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td>position#4</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#3</td>
     * <td>employee#1</td>
     * <td>position#4</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#4</td>
     * <td>employee#2</td>
     * <td>position#4</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * <td>position#4</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td>position#4</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#3</td>
     * <td>employee#1</td>
     * <td>position#4</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#4</td>
     * <td>employee#2</td>
     * <td>position#4</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif428_WithUnAssignPreferredShiftEmployeeAndAvailableEmployeeForTwoClassified_LowerPreferredPositionOwnerNotAssign()
            throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", true);
        Position pos3 = addPosition(managers, null, "position#3", true);
        Position pos4 = addPosition(managers, null, "position#4", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);
        addProductPosition(managers, pro1, pos4, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos4, 4);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        addQualification(managers, emp1, pos3);
        addQualification(managers, emp1, pos4);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos4);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos4);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos4);
        setEmployeePreference(managers, emp4, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-04"));
        addQualification(managers, emp5, pos2);
        addQualification(managers, emp5, pos4);
        setEmployeePreference(managers, emp5, pos2, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 16, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos3, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos4, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos4, emp3);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp4);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp5);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(1, list.size());

        Collection<Task> tasks;
        tasks = context.getProposedTasks().tasks(emp1);
        assertAssignment(2, tasks, Arrays.asList(event1, event3), pos3, emp1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with a lower employee required to work on preferred position, is used all the week causing the higher
     * employee to work on it's second preferred shift.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required two (2) position#2</li>
     * <li>employee#1 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 with preferred position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#2</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif429_WithLowerEmployeeAssignToPreferredPosition_UseLessEmployeeHigherEmployeeAssignToSecondPreferredShift()
            throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 8, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), Arrays.asList(pos1, pos2), emp3);

        /*
         * Check offer
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check assign of employee with preferred seniority not being offered to work on the classified position.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required two (2) position#3</li>
     * <li>employee#1 qualify position#2, position#3, preferred-team shifts.weekDay</li>
     * <li>employee#2 with preferred position#1-shifts.weekDay</li>
     * <li>employee#3 qualify position#1, position#2, position#3 with <b>preferred-seniority</b> shifts.weekDay</li>
     * <li>employee#4 qualify position#2, position#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif430_WithLowerEmployeePreferredSeniority_HigherAssignToPreferredPosition() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos3, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        addQualification(managers, emp1, pos3);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));
        setEmployeePreferredSeniority(managers, emp3, true);

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-03"));
        addQualification(managers, emp4, pos2);
        addQualification(managers, emp4, pos3);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(2, events, Arrays.asList(event2, event4), Arrays.asList(pos2, pos3), emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), Arrays.asList(pos2, pos3), emp4);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if it's possible to lock a classified position to null. And make sure the position is not offered.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required two (2) position#2</li>
     * <li>employee#1 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#2 with position#1 (classified), position#2, preferred-team shifts.weekDay</li>
     * <li>employee#3 with position#2, preferred-team shifts.weekDay</li>
     * <li>employee#4 with position#2, preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#2</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#2</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>null (locked)</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>null (locked)</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif431_WithNullLockedOnClassifiedPosition() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Create tasks then lock tasks
        context.createTasks();
        setTaskLocked(managers, pro1, shifts.monEvening, pos1, null);
        setTaskLocked(managers, pro1, shifts.tueEvening, pos1, null);

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 8, events.size());

        /*
         * Check results.
         */
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);

        /*
         * Check offer.
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if a classified position is assigned by defualt to the least senior employee when it doesn't matches it's
     * preferred position.
     * <p>
     * In this scenario, two employes are qualify to work on the classified position, but it doesn't matches their
     * preferred shift, so the less senior employee is then assigned to the classifed posiiton by default.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required two (2) position#2</li>
     * <li>employee#1 with position#1, position#2, preferred-team weekDay</li>
     * <li>employee#2 with position#1, position#2, preferred-team weekDay</li>
     * <li>employee#3 with position#2, preferred-team weekDay</li>
     * <li>employee#4 with position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#2</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#2</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * </tr>
     * </table>
     * 
     * <h4>Offered Position</h4>
     * <ul>
     * <li>position#1 is offered to employee#1 and employee#2</li>
     * <li>default assigned to employee#2 is mark with a warning</li>
     * </ul>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif432_ClassifiedPositionAssignedConflictWithPreferredPosition() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 8, events.size());

        /*
         * Check results.
         */
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp4);

        /*
         * Check offer.
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(2, list.size());
        assertTrue(list.contains(emp1));
        assertAssignment(2, context.getProposedTasks().tasks(emp1), Arrays.asList(event2, event4), pos1);
        assertTrue(list.contains(emp2));
        assertAssignment(2, context.getProposedTasks().tasks(emp2), Arrays.asList(event2, event4), pos1, emp2);

        assertEquals(2, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with a classified position assigned by default to it's owner but offered to a more senior employee working
     * on a different preffered shift.
     * <p>
     * In this scenario, one employee own the classified position and is assigned to it by default, but the classified
     * position need to be offered to a more senior employee not working on the same shift.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and one (1) position#2</li>
     * <li>product#2 required four (4) position#2</li>
     * <li>employee#1 with position#2, preferred-team weekEvening</li>
     * <li>employee#2 with position#2, preferred-team weekDay</li>
     * <li>employee#3 with position#2, preferred-team weekDay</li>
     * <li>employee#4 with position#1, position#2, preferred-team weekEvening</li>
     * <li>employee#5 with preferred-position#1, position#2, preferred-team weekDay</li>
     * <li>employee#6 with position#2, preferred-team weekDay</li>
     * <li>employee#7 with position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * position#1 : employee#5<br />
     * position#2 : employee#2<br />
     * </td>
     * <td>
     * position#2 : employee#1<br />
     * position#2 : employee#3<br />
     * position#2 : employee#4<br />
     * position#2 : employee#6<br />
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * position#1 : employee#5<br />
     * position#2 : employee#2<br />
     * </td>
     * <td>
     * position#2 : employee#1<br />
     * position#2 : employee#3<br />
     * position#2 : employee#4<br />
     * position#2 : employee#6<br />
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered Position</h4>
     * <ul>
     * <li>position#1 is offered to employee#4</li>
     * </ul>
     * <h4>Warnings</h4>
     * <ul>
     * <li>No warning</li>
     * </ul>
     * 
     * @throws ManagerException
     * @see {@link #generatePlanif434_ClassifiedPositionOfferedToSeniorEmployee()}
     */
    @Test
    public void generatePlanif433_ClassifiedPositionOfferedToSeniorEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 4);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos1, pos2);
        setEmployeePreference(managers, emp5, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos2);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2010-01-07"));
        addQualification(managers, emp7, pos2);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 12, events.size());

        /*
         * Check results.
         */
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp4);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp6);

        /*
         * Check offer.
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

        // assertTrue(list.contains(emp4));
        // assertAssignment(2, context.getProposedTasks().tasks(emp4), Arrays.asList(event1, event3), pos1);
        // assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with classified position assigned by default to it's owner but offered to a more senior employee working on
     * a different preffered shift.
     * <p>
     * In this scenario, one employee own the classified position and is assigned to it by default, but the classified
     * position need to be offered to a more senior employee not working on the same shift.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and two (2) position#2</li>
     * <li>product#2 required three (3) position#2</li>
     * <li>employee#1 with position#2, preferred-team weekEvening</li>
     * <li>employee#2 with position#2, preferred-team weekDay</li>
     * <li>employee#3 with position#2, preferred-team weekDay</li>
     * <li>employee#4 with position#1, position#2, preferred-team weekEvening</li>
     * <li>employee#5 with preferred-position#1, position#2, preferred-team weekDay</li>
     * <li>employee#6 with position#2, preferred-team weekDay</li>
     * <li>employee#7 with position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * position#1 : employee#5<br />
     * position#2 : employee#2<br />
     * position#2 : employee#3<br />
     * </td>
     * <td>
     * position#2 : employee#1<br />
     * position#2 : employee#4<br />
     * position#2 : employee#6<br />
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * position#1 : employee#5<br />
     * position#2 : employee#2<br />
     * position#2 : employee#3<br />
     * </td>
     * <td>
     * position#2 : employee#1<br />
     * position#2 : employee#4<br />
     * position#2 : employee#6<br />
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered Position</h4>
     * <ul>
     * <li>position#1 is offered to employee#4</li>
     * </ul>
     * <h4>Warnings</h4>
     * <ul>
     * <li>No warning</li>
     * </ul>
     * 
     * @throws ManagerException
     * @see #generatePlanif433_ClassifiedPositionOfferedToSeniorEmployee()
     * @see #generatePlanif435_ClassifiedPositionNotOfferedToSeniorEmployee()
     */
    @Test
    public void generatePlanif434_ClassifiedPositionOfferedToSeniorEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 3);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos1, pos2);
        setEmployeePreference(managers, emp5, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos2);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2010-01-07"));
        addQualification(managers, emp7, pos2);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 12, events.size());

        /*
         * Check results.
         */
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp4);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp6);

        /*
         * Check offer.
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

        // assertTrue(list.contains(emp4));
        // assertAssignment(2, context.getProposedTasks().tasks(emp4), Arrays.asList(event1, event3), pos1);
        // assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with a classified position assigned by default to it's owner but offered to a more senior employee working
     * on a different preffered shift.
     * <p>
     * In this scenario, one employee own the classified position and is assigned to it by default, but the classified
     * position need to be offered to a more senior employee not working on the same shift.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified) and three (3) position#2</li>
     * <li>product#2 required two (2) position#2</li>
     * <li>employee#1 with position#2, preferred-team weekEvening</li>
     * <li>employee#2 with position#2, preferred-team weekDay</li>
     * <li>employee#3 with position#2, preferred-team weekDay</li>
     * <li>employee#4 with position#1, position#2, preferred-team weekEvening</li>
     * <li>employee#5 with preferred-position#1, position#2, preferred-team weekDay</li>
     * <li>employee#6 with position#2, preferred-team weekDay</li>
     * <li>employee#7 with position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * position#1 : employee#5<br />
     * position#2 : employee#2<br />
     * position#2 : employee#3<br />
     * position#2 : employee#6<br />
     * </td>
     * <td>
     * position#2 : employee#1<br />
     * position#2 : employee#4<br />
     * 
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * position#1 : employee#5<br />
     * position#2 : employee#2<br />
     * position#2 : employee#3<br />
     * position#2 : employee#6<br />
     * </td>
     * <td>
     * position#2 : employee#1<br />
     * position#2 : employee#4<br />
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered Position</h4>
     * <ul>
     * <li>position#1 is offered to employee#4</li>
     * </ul>
     * <h4>Warning</h4>
     * <ul>
     * <li>No warning</li>
     * </ul>
     * 
     * @throws ManagerException
     * @see {@link #generatePlanif433_ClassifiedPositionOfferedToSeniorEmployee()}
     * @see {@link #generatePlanif434_ClassifiedPositionOfferedToSeniorEmployee()}
     */
    @Test
    public void generatePlanif435_ClassifiedPositionNotOfferedToSeniorEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 3);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos1, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos1, pos2);
        setEmployeePreference(managers, emp5, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos2);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2010-01-07"));
        addQualification(managers, emp7, pos2);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 12, events.size());

        /*
         * Check results.
         */
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp4);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp5);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp6);

        /*
         * Check offer.
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(0, list.size());

        assertEquals(0, context.getProposedTasks().warnings().size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to offer classified position even if the employee is assigned to it's own classified position during the
     * week. In this scenario, employee#1 is assign to his preferred position on monday, but the other classified
     * position#2 on tuesday should be offered to him. Refs #59 comment:3
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), one (1) position#2 (classified) and two (2) position#2</li>
     * <li>product#2 required two (2) position#2 (classified) and two (2) position#2</li>
     * <li>product#3 required two (2) position#2</li>
     * <li>employee#1 with position#1, position#2, position#3, preferred-team weekDay, preferred-position#1-weekDay</li>
     * <li>employee#2 with position#2, preferred-team weekDay</li>
     * <li>employee#3 with position#1, position#2, position#3, preferred-team weekEvening</li>
     * <li>employee#4 with position#1, position#3, preferred-team weekDay</li>
     * <li>employee#5 with position#2, position#3, preferred-team weekDay</li>
     * <li>employee#6 with position#3, preferred-team weekDay</li>
     * <li>employee#7 with position#3, preferred-team weekEvening</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#2</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * position#1 : employee#1<br />
     * position#2 : employee#5<br />
     * position#3 : employee#2<br />
     * position#3 : employee#4<br />
     * </td>
     * <td>
     * position#3 : employee#3<br />
     * position#3 : employee#6<br />
     * 
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * position#2 : employee#1<br />
     * position#2 : employee#5<br />
     * position#3 : employee#2<br />
     * position#3 : employee#4<br />
     * </td>
     * <td>
     * position#3 : employee#3<br />
     * position#3 : employee#6<br />
     * </td>
     * </tr>
     * </table>
     * 
     * <h4>Offered Position</h4>
     * <ul>
     * <li>position#2-tue is offered to employee#1, employe#3, employee#4</li>
     * </ul>
     * <h4>Warnings</h4>
     * <ul>
     * <li>No warning</li>
     * </ul>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif436_ClassifiedPositionOffered() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", true);
        Position pos3 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);
        addProductPosition(managers, pro2, pos3, 2);
        Product pro3 = addProduct(managers, "product3");
        addProductPosition(managers, pro3, pos3, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2, pos3);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2010-01-03"));
        addQualification(managers, emp3, pos1, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2010-01-04"));
        addQualification(managers, emp4, pos2, pos3);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2010-01-05"));
        addQualification(managers, emp5, pos2, pos3);
        setEmployeePreference(managers, emp5, pos2, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2010-01-06"));
        addQualification(managers, emp6, pos3);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2010-01-07"));
        addQualification(managers, emp7, pos3);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekEvening));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro3, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.tueEvening);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        assertEquals("Wrong number of events", 12, events.size());

        /*
         * Check results.
         */
        assertAssignment(1, events, event1, pos1, emp1);
        assertAssignment(1, events, event3, Arrays.asList(pos2, pos3), emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos3, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos3, emp3);
        assertAssignment(2, events, Arrays.asList(event1, event3), Arrays.asList(pos2, pos3), emp4);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp5);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos3, emp6);

        /*
         * Check offer.
         */
        Collection<Employee> list = context.getProposedTasks().employees();
        assertEquals(3, list.size());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if assignment of classified position is more important then any other assignment.
     * <p>
     * In this scenario, the employee will be assigned to the classified position on the week-end team even if it
     * doesn't match his preferences and result in less number of assigned task.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified)</li>
     * <li>product#2 required two (1) position#2</li>
     * <li>employee#1 with position#1, position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td></td>
     * <td>
     * position#1 : employee#1</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#2 : null</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#2 : null</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#2 : null</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#2 : null</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td></td>
     * <td>
     * position#1 : employee#1</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td></td>
     * <td>
     * position#1 : employee#1</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif437_MaxImportantTask() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.sunDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event5 = addProductionEvent(managers, pro2, shifts.tueEvening);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.friDay);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.satDay);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 23:59"));
        assertEquals("Wrong number of events", 7, events.size());

        /*
         * Check results.
         */
        assertAssignment(3, events, Arrays.asList(event1, event6, event7), pos1, emp1);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * When a preferred position is assigned to an employee, if the employee as the seniority to work on the shift, the
     * employee should be assigned to his preferred position event if it cause the planification to have vacant
     * position.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), one (1) position#2</li>
     * <li>employee#1 with position#2, preferred-team weekDay</li>
     * <li>employee#2 with preferred-position#1-weekEndDay, position#2</li>
     * <li>employee#3 with position#2,</li>
     * <li>employee#4 with position#1, position#2, preferred-team weekDay, with preferred-seniority</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td></td>
     * <td>
     * position#1 : employee#4<br>
     * position#2 : employee#3</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1 : employee#2<br>
     * position#2 : employee#1</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1 : employee#2<br>
     * position#2 : employee#1</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1 : employee#2<br>
     * position#2 : employee#1</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#1 : employee#2<br>
     * position#2 : employee#1</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td></td>
     * <td>
     * position#1 : employee#4<br>
     * position#2 : employee#3</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td></td>
     * <td>
     * position#1 : employee#4<br>
     * position#2 : employee#3</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif438_ClassifiedPositionAssignToPrefferedSeniority() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos2);
        setEmployeePreference(managers, emp2, pos1, shifts.weekEndDay, null, Arrays.asList(shifts.weekEndDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEndDay));
        setEmployeePreferredSeniority(managers, emp4, true);

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.sunDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.friDay);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.satDay);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 23:59"));
        assertEquals("Wrong number of events", 14, events.size());

        /*
         * Check results.
         */
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos2, emp1);
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos1, emp2);
        assertAssignment(3, events, Arrays.asList(event1, event6, event7), pos2, emp3);
        assertAssignment(3, events, Arrays.asList(event1, event6, event7), pos1, emp4);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * When a preferred position is assigned to an employee, if the employee as the seniority to work on the shift, the
     * employee should be assigned to his preferred position event if it broke the max senior employee rule. See ticket
     * #218.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), one (1) position#2</li>
     * <li>employee#1 with position#2, preferred-team weekDay</li>
     * <li>employee#2 with preferred-position#1-weekEndDay, position#2</li>
     * <li>employee#3 with position#2,</li>
     * <li>employee#4 with position#1, position#2, preferred-team weekDay, with preferred-seniority</li>
     * <li>employee#5 with position#2, preferred-team weekDay</li>
     * <li>employee#6 with position#1, position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td></td>
     * <td>
     * position#1 : employee#2<br>
     * position#2 : employee#4</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1 : employee#6<br>
     * position#2 : employee#1</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1 : employee#6<br>
     * position#2 : employee#1</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1 : employee#6<br>
     * position#2 : employee#1</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#1 : employee#6<br>
     * position#2 : employee#1</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td></td>
     * <td>
     * position#1 : employee#2<br>
     * position#2 : employee#4</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td></td>
     * <td>
     * position#1 : employee#2<br>
     * position#2 : employee#4</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif439_AssignedPreferredPositionBrokeMaxSeniorEmployee_WithPreferredSeniority() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos2);
        setEmployeePreference(managers, emp2, pos1, shifts.weekEndDay, null, Arrays.asList(shifts.weekEndDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekEndDay));
        setEmployeePreferredSeniority(managers, emp4, true);

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos2);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos1, pos2);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.sunDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.friDay);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.satDay);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 23:59"));
        assertEquals("Wrong number of events", 14, events.size());

        /*
         * Check results.
         */
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos2, emp1);
        assertAssignment(3, events, Arrays.asList(event1, event6, event7), pos1, emp2);
        assertAssignment(3, events, Arrays.asList(event1, event6, event7), pos2, emp4);
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos1, emp6);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * An employee may be assigned to his preferred position, conditional to his seniority, even if it's brake the
     * max-senior-rule. Meaning, the assignment of a preffered position is not conditional to the respected of the
     * seniority of less senior employee. This might cause lower employee to be unassigned. In this scenario, employee
     * #3 will be aassigned to his preferred position, but this assignment will cause employee #6 to be unassigned while
     * employee #8 will work. See ticket #218.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), two (2) position#2</li>
     * <li>employee#1 with position#2, preferred-team weekDay</li>
     * <li>employee#2 with position#1, position#2, preferred-team weekDay</li>
     * <li>employee#3 with preferred-position#1-week-day</li>
     * <li>employee#4 with position#2, preferred-team weekDay</li>
     * <li>employee#5 with position#2, preferred-team weekEndDay</li>
     * <li>employee#6 with position#2, preferred-team weekEndDay</li>
     * <li>employee#7 with position#2, preferred-team weekEndDay</li>
     * <li>employee#8 with position#1, position#2, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td></td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td></td>
     * <td>
     * position#1 : employee#8<br>
     * position#2 : employee#5<br>
     * position#2 : employee#4</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1 : employee#3<br>
     * position#2 : employee#1<br>
     * position#2 : employee#2</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1 : employee#3<br>
     * position#2 : employee#1<br>
     * position#2 : employee#2</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1 : employee#3<br>
     * position#2 : employee#1<br>
     * position#2 : employee#2</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#1 : employee#3<br>
     * position#2 : employee#1<br>
     * position#2 : employee#2</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>fri</td>
     * <td></td>
     * <td>
     * position#1 : employee#8<br>
     * position#2 : employee#5<br>
     * position#2 : employee#4</td>
     * </tr>
     * <tr>
     * <td>sat</td>
     * <td></td>
     * <td>
     * position#1 : employee#8<br>
     * position#2 : employee#5<br>
     * position#2 : employee#4</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif440_AssignedPreferredPositionBrokeMaxSeniorEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos2);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekEndDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos2);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekEndDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2009-01-07"));
        addQualification(managers, emp7, pos2);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekEndDay));

        Employee emp8 = addEmployee(managers, "employee#8");
        setHireDate(managers, emp8, date("2009-01-08"));
        addQualification(managers, emp8, pos1, pos2);
        setEmployeePreference(managers, emp8, null, null, null, Arrays.asList(shifts.weekEndDay));

        // Create the planif.
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.sunDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.friDay);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.satDay);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 23:59"));
        assertEquals("Wrong number of events", 21, events.size());

        /*
         * Check results.
         */
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos2, emp1);
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos2, emp2);
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos1, emp3);
        assertAssignment(3, events, Arrays.asList(event1, event6, event7), pos2, emp4);
        assertAssignment(3, events, Arrays.asList(event1, event6, event7), pos2, emp5);
        assertAssignment(3, events, Arrays.asList(event1, event6, event7), pos1, emp8);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * In this scenario, the classified position is no assigned to his owner, because employee #5 doesn't have the
     * seniority. Still, employee#5 is working on his preferred team mostly because is qualify for position #2. See
     * ticket #218 with Mathieu Guy working on his preferred team but not working on his preferred position.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), one (1) position#2 and one (1) position#3</li>
     * <li>employee#1 with position#1, position#3 preferred-team weekDay</li>
     * <li>employee#2 with position#3, preferred-team weekDay</li>
     * <li>employee#3 with position#3, preferred-team weekDay</li>
     * <li>employee#4 with position#3, preferred-team weekDay</li>
     * <li>employee#5 with preferred-position#1-weekDay, position#2, position#3, preferred-team weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1 : employee#1<br>
     * position#2 : employee#5<br>
     * position#3 : employee#2</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1 : employee#1<br>
     * position#2 : employee#5<br>
     * position#3 : employee#2</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1 : employee#1<br>
     * position#2 : employee#5<br>
     * position#3 : employee#2</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#1 : employee#1<br>
     * position#2 : employee#5<br>
     * position#3 : employee#2</td>
     * <td>
     * </td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif441_AssignedPreferredPositionBrokeMaxSeniorEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos3);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos3);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos1, pos2, pos3);
        setEmployeePreference(managers, emp5, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 23:59"));
        assertEquals("Wrong number of events", 12, events.size());

        /*
         * Check results.
         */
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos1, emp1);
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos3, emp2);
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos2, emp5);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the assignment of classified position is forced event if it brake the seniority. Reference to ticket
     * #263.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one (1) position#1 (classified), one (1) position#3</li>
     * <li>product#2 required one (1) position#1 (classified), one (1) position#2</li>
     * <li>employee#1 with preferred-position#1-weekDay, position#2, position#3</li>
     * <li>employee#2 with position#1, position#3</li>
     * <li>employee#3 with position#2, position#3,</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>product#2</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEndDay</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1 : employee#1<br>
     * position#3 : employee#3</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1 : employee#1<br>
     * position#3 : employee#3</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1 : employee#1<br>
     * position#2 : employee#3</td>
     * <td>
     * </td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#1 : employee#1<br>
     * position#3 : employee#3</td>
     * <td>
     * </td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif442_AssignedPreferredPositionBrokeMaxSeniorEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Position pos3 = addPosition(managers, null, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos1, 1);
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2, pos3);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Generate planif with locked
         */
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        // Generate the planif
        List<Task> events;
        context.searchSolution(new MockGeneratePlanifMonitor());
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 23:59"));
        assertEquals("Wrong number of events", 8, events.size());

        /*
         * Check results.
         */
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), pos1, emp1);
        assertAssignment(4, events, Arrays.asList(event2, event3, event4, event5), Arrays.asList(pos2, pos3), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the employees are assigned to their preferred section.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1 position#2</li>
     * <li>position#1 in section #1</li>
     * <li>position#2 in section #2</li>
     * <li>employee#1 with preferred section#1, qualify on position#1, position #2</li>
     * <li>employee#2 with preferred section#2, qualify on position#1, position #2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.weekDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.weekDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif501_WithPreferredSection_EmployeesAssignToPreferredSection() throws ManagerException {

        Section sec1 = addSection(managers, "section#1");
        Section sec2 = addSection(managers, "section#2");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec1, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec2, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);

        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the higher employee is assign to it's preferred section and the lower employee is assign other position.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1 position#2</li>
     * <li>position#1 in section #1</li>
     * <li>position#2 in section #2</li>
     * <li>employee#1 with preferred section#2, qualify on position#1, position #2</li>
     * <li>employee#2 with preferred section#2, qualify on position#1, position #2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif502AssignPreferredSectionToHigherEmployee() throws ManagerException {

        Section sec1 = addSection(managers, "section#1");
        Section sec2 = addSection(managers, "section#2");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec2, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec2, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);
        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());

        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos2, emp1);

        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Basic check with a preferred-section that can't be assign since the employee is not qualify. In this scenario,
     * employee#1 won't be assign to it's preferred section because he is not qualify on position#2.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (section1), one position#2 (section2)</li>
     * <li>employee#1 with preferred-section2, qualify on position#1</li>
     * <li>employee#2 with preferred-section2, qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif503AssignPreferredSectionConflictWithQualification() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Section sec1 = addSection(managers, "Section1");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Section sec2 = addSection(managers, "Section2");
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, sec2, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec2, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.thuDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos1, emp1);
        assertAssignment(4, events, Arrays.asList(event1, event2, event3, event4), pos2, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with one employee with a preferred position not matching it's preferred section.
     * <p>
     * In this scenario, employee#1 should be assign to it's preferred position even if it doesn't match it's preferred
     * section.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (section1, classified), one</li>
     * <li>position#2 (section1), one position#3 (section2)</li>
     * <li>employee#1 with preferred position#1, preferred section#2, qualification on position#1, position#2,
     * position#3</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif505AssignPreferredSectionConflictWithPreferredPosition() throws ManagerException {

        Section sec1 = addSection(managers, "Section1");
        Section sec2 = addSection(managers, "Section2");
        Position pos1 = addPosition(managers, sec1, "position#1", true);
        Position pos2 = addPosition(managers, sec1, "position#2", false);
        Position pos3 = addPosition(managers, sec2, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        addQualification(managers, emp1, pos3);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, sec2, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 6, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event2), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event2), pos2, NULL);
        assertAssignment(2, events, Arrays.asList(event1, event2), pos3, NULL);

        /*
         * Optimized
         */
        try {
            managers.getTaskManager().remove(events);
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 6, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event2), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event2), pos2, NULL);
        assertAssignment(2, events, Arrays.asList(event1, event2), pos3, NULL);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with tree employees with different preferred section causing an employee to be moved to a non-preferred
     * section.
     * <p>
     * In this scenario, employee#1 is assign to it's preferred section. Employee#2 can't work on it's preferred section
     * because it's complete. Employee#3 is assign to it's preferred section.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (section1), one position#2 (section2), one position#3 (section3)</li>
     * <li>employee#1 with preferred section2, qualification on position#1, position#2, position#3</li>
     * <li>employee#2 with preferred section2, qualification on position#1, position#2, position#3</li>
     * <li>employee#3 with preferred section1, qualification on position#1, position#2, position#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif506AssignPreferredSectionEmployeeBumped() throws ManagerException {

        Section sec1 = addSection(managers, "Section1");
        Section sec2 = addSection(managers, "Section2");
        Section sec3 = addSection(managers, "Section3");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Position pos3 = addPosition(managers, sec3, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        addQualification(managers, emp1, pos3);
        setEmployeePreference(managers, emp1, null, null, sec2, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        addQualification(managers, emp2, pos3);
        setEmployeePreference(managers, emp2, null, null, sec2, null);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos3);
        setEmployeePreference(managers, emp3, null, null, sec1, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 6, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos3, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp3);

        /*
         * Optimized
         */
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 6, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos3, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the preferred shift take precedence on the preferred section.
     * <p>
     * In this scenario, employee#2 is not working on it's preferred section, but is working on it's preferred shift.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one position#1 (section1), one position#2 (section2)</li>
     * <li>employee#1 with preferred section2, qualify on position#1, position#2</li>
     * <li>employee#2 with preferred section2, qualify on position#1, position#2</li>
     * <li>employee#3 with preferred section1, qualify on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif507_WithPreferredSectionAndMultipleShift_ALowerEmployeeAssignToOtherShift() throws ManagerException {

        Section sec1 = addSection(managers, "Section1");
        Section sec2 = addSection(managers, "Section2");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec2, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec2, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, sec1, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with preferred-section and preferred-team. In this scenario, an employee will not work on it's preferred
     * section but will at least work on it's preferred shift. In this scenario, employee#2 need to be assign to
     * position#3 to allow employee#3 to be assign to it's preferred shift.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 (section1), one position#2 (section2), one position#3 (section2)</li>
     * <li>product#2 require one position#4</li>
     * <li>employee#1 preferred-section1, qualify on position#1, position#2, position#3, preferred shift shifts.weekDay,
     * shifts.weekEvening</li>
     * <li>employee#2 preferred-section2, qualify on position#2, position#3, preferred shift : shifts.weekDay,
     * shifts.weekEvening</li>
     * <li>employee#3 preferred-section1, qualify on position#1, position#2, position#4, preferred shift shifts.weekDay,
     * shifts.weekEvening</li>
     * <li>employee#4 preferred section2, qualification on position#3, position#4, preferred shift shifts.weekDay,
     * shifts.weekEvening</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#4</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#4</td>
     * <td>employee#4</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif509AssignPreferredSectionWithMultipleShifts() throws ManagerException {

        Section sec1 = addSection(managers, "Section1");
        Section sec2 = addSection(managers, "Section2");
        Product pro1 = addProduct(managers, "product1");
        Product pro2 = addProduct(managers, "product2");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Position pos3 = addPosition(managers, sec2, "position#3", false);
        Position pos4 = addPosition(managers, sec2, "position#4", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        addProductPosition(managers, pro1, pos3, 1);
        addProductPosition(managers, pro2, pos4, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        addQualification(managers, emp1, pos3);
        setEmployeePreference(managers, emp1, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos2);
        addQualification(managers, emp2, pos3);
        setEmployeePreference(managers, emp2, null, null, sec2, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos4);
        setEmployeePreference(managers, emp3, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos3);
        addQualification(managers, emp4, pos4);
        setEmployeePreference(managers, emp4, null, null, sec2, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos3, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos4, emp4);

        /*
         * Optimized
         */
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos3, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos4, emp4);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if an higher employee is assign to remaining section when there is no position matching it's preferred
     * section.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1 (section1), one position#2 (section2)</li>
     * <li>employee#1 with preferred section#3, qualification on position#1, position#2, position#3</li>
     * <li>employee#2 with preferred section#1, qualification on position#1, position#2</li>
     * <li>employee#3 with preferred section#2, qualification on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif510_WithNoPositionForPreferredSection_HigherEmployeeNotAssignToPreferredSection() throws ManagerException {

        Section sec1 = addSection(managers, "Section1");
        Section sec2 = addSection(managers, "Section2");
        Section sec3 = addSection(managers, "Section3");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec3, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec1, null);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, sec2, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 6, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * This scenario is testing a special case with the Hungarian algorithm.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (section1), one position#2 (section2)</li>
     * <li>product#2 required two position#1 (section1), one position#2 (section2)</li>
     * <li>employee#1 with preferred section#2, qualification on position#1, position#2, position#3</li>
     * <li>employee#2 with preferred section#2, qualification on position#1, position#2</li>
     * <li>employee#3 with preferred section#1, qualification on position#1, position#2</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif511AssignLowerEmployeeToPreferredSection() throws ManagerException {

        Section sec1 = addSection(managers, "Section1");
        Section sec2 = addSection(managers, "Section2");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos1, 2);
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec2, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec2, null);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, sec1, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.tueDay);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 5, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(events, event3, pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the employees are assign to their preferred shifts.
     * <p>
     * In this scenario, employee#1 ans employee#2 are assign to their preferred shift.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1</li>
     * <li>employee#1 with preferred shift shifts.weekEvening, qualify on position#1</li>
     * <li>employee#2 with preferred shift shifts.weekDay, qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif600AssignPreferredShift() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-01"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        /*
         * Not Optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);

        /*
         * Optimized
         */
        try {
            managers.getTaskManager().remove(events);
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the higher employee is assign to it's preferred shift. The lower employee is assign to the other shift.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1</li>
     * <li>employee#1 with preferred shift shifts.weekDay, qualify on position#1</li>
     * <li>employee#2 with preferred shift shifts.weekDay, qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif601AssignPreferredShiftToHigherEmployee() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2010-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        /*
         * Not Optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp2);

        /*
         * Optimized
         */
        try {
            managers.getTaskManager().remove(events);
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp2);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if the employee with a preferred position is assign to the classified position even if it doesn't match
     * it's preferred shift.
     * <p>
     * In this scenario, all the classified position may be assigned.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1 (classified), position#2</li>
     * <li>employee#1 preferred position#1-shifts.weekEvening, with preferred-team shifts.weekDay, shifts.weekEndDay,
     * shifts.weekEvening, qualify on position#1, position#2</li>
     * <li>employee#2 with preferred-team shifts.weekDay, shifts.weekEndDay, shifts.weekEvening, qualify on position#1,
     * position#2</li>
     * <li>employee#3 with preferred-team shifts.weekDay, shifts.weekEndDay, shifts.weekEvening, qualify on position#1,
     * position#2</li>
     * <li>employee#4 with preferred-team shifts.weekDay, shifts.weekEndDay, shifts.weekEvening, qualify on position#1,
     * position#2</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Day</th>
     * <th>Evening</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * <th colspan=2>weekEvening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>sun</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>null</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif602PreferredShiftConflictWithPreferredPosition() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, pos1, shifts.weekEvening, null, Arrays.asList(shifts.weekDay, shifts.weekEndDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEndDay, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEndDay, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEndDay, shifts.weekEvening));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.sunDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.sunEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.friDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.friEvening);

        /*
         * Not Optimized
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));

        assertEquals("Wrong number of events", 16, events.size());
        assertAssignment(2, events, Arrays.asList(event4, event6), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event3, event5), Arrays.asList(pos1, pos2), emp2);
        assertAssignment(2, events, Arrays.asList(event1, event7), Arrays.asList(pos1, pos2), emp3);
        assertAssignment(2, events, Arrays.asList(event2, event8), Arrays.asList(pos1, pos2), emp4);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check the priority of the objective. In this scenario, employee#1 will not be assign to it's preferred shift,
     * because he's required to work on position#1 on weekDay since he's the only one qualify for this position.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required position#1</li>
     * <li>product#2 required position#2</li>
     * <li>employee#1 with preferred-team shifts.weekEvening, shifts.weekDay qualify position#1, position#2</li>
     * <li>employee#2 qualify on position#2 with preferred-team shifts.weekEvening, shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif605_AssignPreferredShiftLowerEmployeeWithoutQualificationNotAssign() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);

        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign the senior employee to it's preferred shift. In this scenario, the lower employee#2 is not assign
     * to it's preferred shift because he doesn't have the required qualification.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>product#2 required two position#2</li>
     * <li>employee#1 with preferred-team shifts.weekDay, shifts.weekEvening qualify on position#1, position#2</li>
     * <li>employee#2 qualify on position#2 with preferred-team shifts.weekDay, shifts.weekEvening</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif607AssignPreferredShiftLowerEmployeeAssignToLowerShift() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, NULL);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, NULL);

        /*
         * Optimized
         */
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, NULL);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos2, NULL);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign the senior employee to optimize the preferred shift assignment. In this scenario, the senior
     * employee required to be assign in a specific way so that employee#3 is working on it’s preferred shift.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>employee#1 qualify on position#1, position#2, preferred-team shifts.weekDay, shifts.weekEvening</li>
     * <li>employee#2 qualify on position#1, position#2, preferred-team shifts.weekDay, shifts.weekEvening</li>
     * <li>employee#3 qualify on position#1, preferred-team shifts.weekDay, shifts.weekEvening</li>
     * <li>employee#4 qualify on position#1, position#2, preferred-team shifts.weekDay, shifts.weekEvening</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>TODO</td>
     * <td>TODO</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1 or #2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#2 or #1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#2</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif608AssignPreferredShiftRequiredHeuristic() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2011-01-04"));
        addQualification(managers, emp4, pos1);
        addQualification(managers, emp4, pos2);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 12, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), Arrays.asList(pos1, pos2), emp1);
        assertAssignment(2, events, Arrays.asList(event1, event3), Arrays.asList(pos1, pos2), emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp3);
        assertAssignment(2, events, Arrays.asList(event2, event4), Arrays.asList(pos1, pos2), emp4);
        assertAssignment(4, events, Arrays.asList(event2, event4), Arrays.asList(pos1, pos2), NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with mixed notion of preferred-section, preferred-position, and multiple shifts. In this scenario, the
     * schedule need to find the optimal solution to satisfy the employee’s preferences.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 (section1) (classified)</li>
     * <li>product#2 require one position#2 (section1)</li>
     * <li>product#3 require one position#3 (section2)</li>
     * <li>product#4 require one position#4 (section3)</li>
     * <li>employee#1 preferred section#1, qualification on position#1, position#2, position#4, preferred shift :
     * shifts.weekDay, shifts.weekEvening, weekend</li>
     * <li>employee#2 preferred-position#1 shifts.weekDay, preferred section#1, qualification on position#1, position#2,
     * preferred shift : shifts.weekDay, shifts.weekEvening, weekend</li>
     * <li>employee#3 preferred section#1, qualification on position#2, position#3, position#4, preferred shift :
     * shifts.weekDay, shifts.weekEvening, weekend</li>
     * <li>employee#4 preferred section#2, qualification on position#3, position#4, preferred shift : shifts.weekDay,
     * shifts.weekEvening, weekend</li>
     * <li>employee#5 preferred section#1, qualification on position#2, position#3, position#4, preferred shift :
     * shifts.weekDay, shifts.weekEvening,weekend</li>
     * <li>employee#6 preferred section#2, qualification on position#4, preferred shift : shifts.weekDay,
     * shifts.weekEvening, weekend</li>
     * <li>employee#7 preferred section#1, qualification on position#2, position#3, preferred shift : shifts.weekDay,
     * shifts.weekEvening, weekend</li>
     * <li>employee#8 preferred section#1, qualification on position#1, position#2, position#3, position#4 preferred
     * shift : shifts.weekDay, shifts.weekEvening, weekend</li>
     * 
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.sunDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.sunDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.sunDay</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#4</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#4</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>product#4</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>product#4</td>
     * </tr>
     * <tr>
     * <td>shifts.wedEvening</td>
     * <td>product#4</td>
     * </tr>
     * <tr>
     * <td>shifts.wedEvening</td>
     * <td>product#4</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.thuEvening</td>
     * <td>product#4</td>
     * </tr>
     * <tr>
     * <td>shifts.thuEvening</td>
     * <td>product#4</td>
     * </tr>
     * <tr>
     * <td>shifts.friDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.friDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.friDay</td>
     * <td>product#3</td>
     * </tr>
     * <tr>
     * <td>shifts.satDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.satDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>shifts.satDay</td>
     * <td>product#3</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.sunDay</td>
     * <td>position#1</td>
     * <td>employee#8</td>
     * </tr>
     * <tr>
     * <td>shifts.sunDay</td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td>shifts.sunDay</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#3</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#4</td>
     * <td>employee#6</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#4</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#3</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#4</td>
     * <td>employee#6</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.wedDay</td>
     * <td>position#4</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.wedEvening</td>
     * <td>position#4</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>shifts.wedEvening</td>
     * <td>position#4</td>
     * <td>employee#6</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>shifts.thuDay</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.thuEvening</td>
     * <td>position#4</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>shifts.thuEvening</td>
     * <td>position#4</td>
     * <td>employee#6</td>
     * </tr>
     * <tr>
     * <td>shifts.friDay</td>
     * <td>position#1</td>
     * <td>employee#8</td>
     * </tr>
     * <tr>
     * <td>shifts.friDay</td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td>shifts.friDay</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.satDay</td>
     * <td>position#1</td>
     * <td>employee#8</td>
     * </tr>
     * <tr>
     * <td>shifts.satDay</td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td>shifts.satDay</td>
     * <td>position#3</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     */
    // TODO Change the series
    // TODO Change the assertion
    @Test
    public void generatePlanif609AssignPreferredSectionPreferredShift() throws ManagerException {

        Section sec1 = addSection(managers, "Section1");
        Section sec2 = addSection(managers, "Section2");
        Section sec3 = addSection(managers, "Section3");

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, sec1, "position#1", true);
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, sec1, "position#2", false);
        addProductPosition(managers, pro2, pos2, 1);
        Product pro3 = addProduct(managers, "product3");
        Position pos3 = addPosition(managers, sec2, "position#3", false);
        addProductPosition(managers, pro3, pos3, 1);
        Product pro4 = addProduct(managers, "product4");
        Position pos4 = addPosition(managers, sec3, "position#4", false);
        addProductPosition(managers, pro4, pos4, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        addQualification(managers, emp1, pos4);
        setEmployeePreference(managers, emp1, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekEndDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, pos1, shifts.weekDay, sec1, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekEndDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos2);
        addQualification(managers, emp3, pos3);
        addQualification(managers, emp3, pos4);
        setEmployeePreference(managers, emp3, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekEndDay));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos3);
        addQualification(managers, emp4, pos4);
        setEmployeePreference(managers, emp4, null, null, sec2, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekEndDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos2);
        addQualification(managers, emp5, pos3);
        addQualification(managers, emp5, pos4);
        setEmployeePreference(managers, emp5, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekEndDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos4);
        setEmployeePreference(managers, emp6, null, null, sec2, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekEndDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2009-01-07"));
        addQualification(managers, emp7, pos2);
        addQualification(managers, emp7, pos3);
        setEmployeePreference(managers, emp7, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekEndDay));

        Employee emp8 = addEmployee(managers, "employee#8");
        setHireDate(managers, emp8, date("2009-01-08"));
        addQualification(managers, emp8, pos1);
        addQualification(managers, emp8, pos2);
        addQualification(managers, emp8, pos3);
        addQualification(managers, emp8, pos4);
        setEmployeePreference(managers, emp8, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekEndDay));

        // Create the planif.

        ProductionEvent event0 = addProductionEvent(managers, pro1, shifts.sunDay);
        ProductionEvent event1 = addProductionEvent(managers, pro2, shifts.sunDay);
        ProductionEvent event2 = addProductionEvent(managers, pro3, shifts.sunDay);

        // shifts.monDay
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event4 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event5 = addProductionEvent(managers, pro3, shifts.monDay);
        ProductionEvent event6 = addProductionEvent(managers, pro3, shifts.monDay);
        ProductionEvent event7 = addProductionEvent(managers, pro3, shifts.monEvening);
        ProductionEvent event8 = addProductionEvent(managers, pro4, shifts.monEvening);

        // Tuesday
        ProductionEvent event9 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event11 = addProductionEvent(managers, pro3, shifts.tueDay);
        ProductionEvent event12 = addProductionEvent(managers, pro4, shifts.tueDay);
        ProductionEvent event13 = addProductionEvent(managers, pro3, shifts.tueEvening);
        ProductionEvent event14 = addProductionEvent(managers, pro4, shifts.tueEvening);

        // Wednesday
        ProductionEvent event15 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event16 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event17 = addProductionEvent(managers, pro3, shifts.wedDay);
        ProductionEvent event18 = addProductionEvent(managers, pro4, shifts.wedDay);
        ProductionEvent event19 = addProductionEvent(managers, pro4, shifts.wedEvening);
        ProductionEvent event20 = addProductionEvent(managers, pro4, shifts.wedEvening);

        // Thuesday
        ProductionEvent event21 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event22 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event23 = addProductionEvent(managers, pro3, shifts.thuDay);
        ProductionEvent event24 = addProductionEvent(managers, pro3, shifts.thuDay);
        ProductionEvent event25 = addProductionEvent(managers, pro4, shifts.thuEvening);
        ProductionEvent event26 = addProductionEvent(managers, pro4, shifts.thuEvening);

        // shifts.friDay
        ProductionEvent event27 = addProductionEvent(managers, pro1, shifts.friDay);
        ProductionEvent event28 = addProductionEvent(managers, pro2, shifts.friDay);
        ProductionEvent event29 = addProductionEvent(managers, pro3, shifts.friDay);

        // Saterday
        ProductionEvent event30 = addProductionEvent(managers, pro1, shifts.satDay);
        ProductionEvent event31 = addProductionEvent(managers, pro2, shifts.satDay);
        ProductionEvent event32 = addProductionEvent(managers, pro3, shifts.satDay);

        /*
         * Not optimizied
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 18:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }

        assertEquals("Wrong number of events", 33, events.size());
        assertAssignment(4, events, Arrays.asList(event4, event10, event16, event22), pos2, emp1);
        assertAssignment(4, events, Arrays.asList(event3, event9, event15, event21), pos1, emp2);
        assertAssignment(4, events, Arrays.asList(event5, event6, event11, event12, event17, event18, event23, event24), Arrays.asList(pos3, pos4), emp3);
        assertAssignment(4, events, Arrays.asList(event5, event6, event11, event12, event17, event18, event23, event24), pos3, emp4);

        assertAssignment(4, events, Arrays.asList(event7, event8, event13, event14, event19, event20, event25, event26), Arrays.asList(pos3, pos4), emp5);
        assertAssignment(4, events, Arrays.asList(event7, event8, event13, event14, event19, event20, event25, event26), pos4, emp6);
        assertAssignment(3, events, Arrays.asList(event0, event1, event2, event27, event28, event29, event30, event31, event32), pos2, emp7);
        assertAssignment(
                3,
                events,
                Arrays.asList(event0, event1, event2, event27, event28, event29, event30, event31, event32),
                Arrays.asList(pos1, pos3),
                emp8);

    }

    /**
     * <h4>Test Objective</h4>
     * <p>
     * Check if a swappable task allow employees to work on two different team. When an employee is assigned to a team,
     * we try to reduce the number of assignmend to swapabble task of another team. Then, it always the least senior
     * employee working on the swappable task.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 not-swappable</li>
     * <li>product#2 require one position#2 swappable</li>
     * <li>product#3 require one position#3 not-swappable</li>
     * <li>employee#1 qualification on position#2, position#3 preferred shift : weekDay, weekDayRep</li>
     * <li>employee#2 qualification on position#2, position#3 preferred shift : weekDayRep, weekDay</li>
     * <li>employee#3 qualification on position#2, position#3 preferred shift : weekDay, weekDayRep</li>
     * <li>employee#4 qualification on position#2, position#3 preferred shift : weekDayRep, weekDay</li>
     * <li>employee#5 qualification on position#1, position#2, position#3 preferred shift : weekDay, weekDayRep</li>
     * <li>employee#6 qualification on position#2, position#3 preferred shift : weekDay, weekDayRep</li>
     * 
     * </ul>
     * 
     * 
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Week Day</th>
     * <th>Week Day Remp.</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>1x pos#1, 1x pos#2</td>
     * <td>4x pos#3</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>1x pos#1, 2x pos#2</td>
     * <td>3x pos#3</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>1x pos#1, 3x pos#2</td>
     * <td>2x pos#3</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>4x pos#2</td>
     * <td>1x pos#3</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>Week Day</th>
     * <th colspan=2>Week Day Remp.</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td>position#3</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#6</td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * <td></td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif610AssignSwappableTasks() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, null, "position#2", false, true);
        addProductPosition(managers, pro2, pos2, 1);
        Product pro3 = addProduct(managers, "product3");
        Position pos3 = addPosition(managers, null, "position#3", false);
        addProductPosition(managers, pro3, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2, pos3);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDayRep, shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos2, pos3);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDayRep, shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos1, pos2, pos3);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos2, pos3);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep));

        // Monday
        ProductionEvent event0 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event1 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event3 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event5 = addProductionEvent(managers, pro3, shifts.monRep);

        // Tuesday
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event7 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event8 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event9 = addProductionEvent(managers, pro3, shifts.tueRep);
        ProductionEvent event10 = addProductionEvent(managers, pro3, shifts.tueRep);
        ProductionEvent event11 = addProductionEvent(managers, pro3, shifts.tueRep);

        // Wednesday
        ProductionEvent event12 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event13 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event14 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event15 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event16 = addProductionEvent(managers, pro3, shifts.wedRep);
        ProductionEvent event17 = addProductionEvent(managers, pro3, shifts.wedRep);

        // Thrusday
        ProductionEvent event18 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event19 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event20 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event21 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event22 = addProductionEvent(managers, pro3, shifts.thuRep);

        /*
         * Not optimizied
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 18:00"));

        List<ProductionEvent> weekDay = Arrays.asList(
                event0,
                event1,
                event6,
                event7,
                event8,
                event12,
                event13,
                event14,
                event15,
                event18,
                event19,
                event20,
                event21);
        List<ProductionEvent> weekDayRep = Arrays.asList(event2, event3, event4, event5, event9, event10, event11, event16, event17, event22);
        assertEquals("Wrong number of events", 23, events.size());

        // Employee#1
        assertAssignment(4, events, weekDay, pos2, emp1);

        // Employee#2
        assertAssignment(1, 4, events, weekDayRep, pos3, emp2);

        // Employee#3
        assertAssignment(1, 4, events, weekDayRep, pos3, emp3);

        // Employee#4
        assertAssignment(1, 3, events, weekDayRep, pos3, emp4);
        assertAssignment(0, 2, events, weekDay, pos2, emp4);

        // Employee#5
        assertAssignment(4, events, weekDay, Arrays.asList(pos1, pos2), emp5);

        // Employee#6
        assertAssignment(1, 4, events, weekDayRep, pos3, emp6);
        assertAssignment(0, 3, events, weekDay, pos2, emp6);
    }

    /**
     * <h4>Test Objective</h4>
     * <p>
     * Test the functionnality of the swappable task by checking how the preferred teams are allocated to each employee.
     * To be assigned to the preferred team, the employee should work at least once on the real team. When assigned to
     * preferred team, the number of time the employee is assigned to swappable task of a different team should be
     * minimize.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 not-swappable</li>
     * <li>product#2 require one position#2 swappable</li>
     * <li>product#3 require one position#3 not-swappable</li>
     * <li>employee#1 preferred shift : weekDayRep, weekDay, weekEvening</li>
     * <li>employee#2 preferred shift : weekDayRep, weekEvening, weekDay</li>
     * <li>employee#3 preferred shift : weekDayRep, weekDay, weekEvening</li>
     * <li>employee#4 preferred shift : weekDayRep, weekEvening, weekDay</li>
     * <li>employee#5 preferred shift : weekEvening, weekDayRep, weekDay</li>
     * <li>employee#6 preferred shift : weekEvening, weekDay, weekDayRep</li>
     * <li>employee#7 preferred shift : weekDay, weekEvening, weekDayRep</li>
     * <li>employee#8 preferred shift : weekDay, weekDayRep, weekEvening</li>
     * </ul>
     * 
     * 
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Week Day</th>
     * <th>Week Day Remp.</th>
     * <th>Week Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>2x pos#1, 1x pos#2</td>
     * <td>2x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>2x pos#1, 2x pos#2</td>
     * <td>1x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>2x pos#1, 3x pos#2</td>
     * <td></td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>4x pos#2</td>
     * <td>2x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>Week Day</th>
     * <th colspan=2>Week Day Remp.</th>
     * <th colspan=2>Evening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td rowspan=2>employee#1, #2</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * <td>position#3</td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#8</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td>employee#1 or #2</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#8</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#8</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td>position#3</td>
     * <td>employee#1</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td>employee#2</td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#8</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif611AssignSwappableTasks() throws ManagerException {
        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, null, "position#2", false, true);
        addProductPosition(managers, pro2, pos2, 1);
        Product pro3 = addProduct(managers, "product3");
        Position pos3 = addPosition(managers, null, "position#3", false);
        addProductPosition(managers, pro3, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2, pos3);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDayRep, shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDayRep, shifts.weekEvening, shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDayRep, shifts.weekDay, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1, pos2, pos3);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDayRep, shifts.weekEvening, shifts.weekDay));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos1, pos2, pos3);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDayRep, shifts.weekDay));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos1, pos2, pos3);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2009-01-07"));
        addQualification(managers, emp7, pos1, pos2, pos3);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp8 = addEmployee(managers, "employee#8");
        setHireDate(managers, emp8, date("2009-01-08"));
        addQualification(managers, emp8, pos1, pos2, pos3);
        setEmployeePreference(managers, emp8, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        // Monday
        ProductionEvent event0 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.monEvening);

        // Tuesday
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event9 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event11 = addProductionEvent(managers, pro3, shifts.tueRep);
        ProductionEvent event12 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event13 = addProductionEvent(managers, pro1, shifts.tueEvening);

        // Wednesday
        ProductionEvent event14 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event15 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event16 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event17 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event18 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event19 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event20 = addProductionEvent(managers, pro1, shifts.wedEvening);

        // Thrusday
        ProductionEvent event21 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event22 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event23 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event24 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event25 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event26 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event27 = addProductionEvent(managers, pro1, shifts.thuEvening);
        ProductionEvent event28 = addProductionEvent(managers, pro1, shifts.thuEvening);

        /*
         * Not optimizied
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 18:00"));

        List<ProductionEvent> weekDay = Arrays.asList(
                event0,
                event1,
                event2,
                event7,
                event8,
                event9,
                event10,
                event14,
                event15,
                event16,
                event17,
                event18,
                event21,
                event22,
                event23,
                event24);
        List<ProductionEvent> weekDayRep = Arrays.asList(event3, event4, event11, event25, event26);
        List<ProductionEvent> weekEvening = Arrays.asList(event5, event6, event12, event13, event19, event20, event27, event28);

        assertEquals("Wrong number of events", 29, events.size());
        // Employee#1
        assertAssignment(1, 3, events, weekDayRep, pos3, emp1);
        assertAssignment(0, 1, events, weekDay, pos2, emp1);

        // Employee#2
        assertAssignment(1, 3, events, weekDayRep, pos3, emp2);
        assertAssignment(0, 1, events, Arrays.asList(event16, event17, event18), pos2, emp2);

        // Employee#3
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp3);

        // Employee#4
        assertAssignment(4, events, weekEvening, pos1, emp4);

        // Employee#5
        assertAssignment(4, events, weekEvening, pos1, emp5);

        // Employee#6
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp6);

        // Employee#7
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp7);

        // Employee#8
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp8);

    }

    /**
     * <h4>Test Objective</h4>
     * <p>
     * Test how the swappable tasks are assigned according to the employee preferred team.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 not-swappable</li>
     * <li>product#2 require one position#2 swappable</li>
     * <li>product#3 require one position#3 not-swappable</li>
     * <li>employee#1 preferred shift : weekDay, weekDayRep, weekEvening</li>
     * <li>employee#2 preferred shift : weekDay, weekEvening, weekDayRep</li>
     * <li>employee#3 preferred shift : weekDay, weekDayRep, weekEvening</li>
     * <li>employee#4 preferred shift : weekDay, weekEvening, weekDayRep</li>
     * <li>employee#5 preferred shift : weekDay, weekEvening, weekDayRep</li>
     * <li>employee#6 preferred shift : weekDay, weekDayRep, weekEvening</li>
     * <li>employee#7 preferred shift : weekEvening, weekDay, weekDayRep</li>
     * <li>employee#8 preferred shift : weekEvening, weekDay, weekDayRep</li>
     * </ul>
     * 
     * 
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Week Day</th>
     * <th>Week Day Remp.</th>
     * <th>Week Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>2x pos#1, 1x pos#2</td>
     * <td>2x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>2x pos#1, 2x pos#2</td>
     * <td>1x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>2x pos#1, 3x pos#2</td>
     * <td></td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>4x pos#2</td>
     * <td>2x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>Week Day</th>
     * <th colspan=2>Week Day Remp.</th>
     * <th colspan=2>Evening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#8</td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>employee#6</td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#6 or #8</td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#8</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#8</td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>employee#6</td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif612AssignSwappableTasks() throws ManagerException {
        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, null, "position#2", false, true);
        addProductPosition(managers, pro2, pos2, 1);
        Product pro3 = addProduct(managers, "product3");
        Position pos3 = addPosition(managers, null, "position#3", false);
        addProductPosition(managers, pro3, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2, pos3);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1, pos2, pos3);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos1, pos2, pos3);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos1, pos2, pos3);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2009-01-07"));
        addQualification(managers, emp7, pos1, pos2, pos3);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        Employee emp8 = addEmployee(managers, "employee#8");
        setHireDate(managers, emp8, date("2009-01-08"));
        addQualification(managers, emp8, pos1, pos2, pos3);
        setEmployeePreference(managers, emp8, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        // Monday
        ProductionEvent event0 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.monEvening);

        // Tuesday
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event9 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event11 = addProductionEvent(managers, pro3, shifts.tueRep);
        ProductionEvent event12 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event13 = addProductionEvent(managers, pro1, shifts.tueEvening);

        // Wednesday
        ProductionEvent event14 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event15 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event16 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event17 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event18 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event19 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event20 = addProductionEvent(managers, pro1, shifts.wedEvening);

        // Thrusday
        ProductionEvent event21 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event22 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event23 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event24 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event25 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event26 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event27 = addProductionEvent(managers, pro1, shifts.thuEvening);
        ProductionEvent event28 = addProductionEvent(managers, pro1, shifts.thuEvening);

        /*
         * Not optimizied
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 18:00"));

        List<ProductionEvent> weekDay = Arrays.asList(
                event0,
                event1,
                event2,
                event7,
                event8,
                event9,
                event10,
                event14,
                event15,
                event16,
                event17,
                event18,
                event21,
                event22,
                event23,
                event24);
        List<ProductionEvent> weekDayRep = Arrays.asList(event3, event4, event11, event25, event26);
        List<ProductionEvent> weekEvening = Arrays.asList(event5, event6, event12, event13, event19, event20, event27, event28);

        assertEquals("Wrong number of events", 29, events.size());
        // Employee#1
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp1);
        assertAssignment(0, events, weekDayRep, pos3, emp1);

        // Employee#2
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp2);
        assertAssignment(0, events, weekDayRep, pos3, emp1);

        // Employee#3
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp3);
        assertAssignment(0, events, weekDayRep, pos3, emp3);

        // Employee#4
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp4);
        assertAssignment(0, events, weekDayRep, pos3, emp4);

        // Employee#5
        assertAssignment(4, events, weekEvening, pos1, emp5);

        // Employee#6
        assertAssignment(2, 3, events, weekDayRep, pos3, emp6);
        assertAssignment(0, 1, events, weekDay, pos2, emp6);

        // Employee#7
        assertAssignment(4, events, weekEvening, pos1, emp7);

        // Employee#8
        assertAssignment(2, 3, events, weekDayRep, pos3, emp8);
        assertAssignment(0, 1, events, weekDay, pos2, emp8);

    }

    /**
     * <h4>Test Objective</h4>
     * <p>
     * Test how the swappable tasks are assigned according to the employee preferred team and mixed with preferred
     * section.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 not-swappable, section1</li>
     * <li>product#2 require one position#2 swappable, section2</li>
     * <li>product#3 require one position#3 not-swappable, section2</li>
     * <li>employee#1 preferred shift : weekDay, weekEvening, weekDayRep, preferred section1</li>
     * <li>employee#2 preferred shift : weekDay, weekEvening, weekDayRep, preferred section2</li>
     * <li>employee#3 preferred shift : weekEvening, weekDay, weekDayRep, preferred section1</li>
     * <li>employee#4 preferred shift : weekDayRep, weekDay, weekEvening, preferred section2</li>
     * <li>employee#5 preferred shift : weekDay, weekEvening, weekDayRep, preferred section2</li>
     * <li>employee#6 preferred shift : weekDay, weekEvening, weekDayRep, preferred section2</li>
     * <li>employee#7 preferred shift : weekDay, weekEvening, weekDayRep, preferred section1</li>
     * <li>employee#8 preferred shift : weekEvening, weekDay, weekDayRep, preferred section1</li>
     * </ul>
     * 
     * 
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Week Day</th>
     * <th>Week Day Remp.</th>
     * <th>Week Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>2x pos#1, 1x pos#2</td>
     * <td>2x pos#3</td>
     * <td>1x pos#1, 1x pos#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>2x pos#1, 2x pos#2</td>
     * <td>1x pos#3</td>
     * <td>1x pos#1, 1x pos#2</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>2x pos#1, 3x pos#2</td>
     * <td></td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>4x pos#2</td>
     * <td>2x pos#3</td>
     * <td>2x pos#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>Week Day</th>
     * <th colspan=2>Week Day Remp.</th>
     * <th colspan=2>Evening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#5 or #6</td>
     * <td>position#3</td>
     * <td>employee#8</td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#4 or #8</td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#8</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#4</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>employee#8</td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#6</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif613AssignSwappableTasks() throws ManagerException {

        Section seciton1 = addSection(managers, "section1");
        Section seciton2 = addSection(managers, "section2");

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, seciton1, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, seciton2, "position#2", false, true);
        addProductPosition(managers, pro2, pos2, 1);
        Product pro3 = addProduct(managers, "product3");
        Position pos3 = addPosition(managers, seciton2, "position#3", false);
        addProductPosition(managers, pro3, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2, pos3);
        setEmployeePreference(managers, emp1, null, null, seciton1, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos2, pos3);
        setEmployeePreference(managers, emp2, null, null, seciton2, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, seciton1, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1, pos2, pos3);
        setEmployeePreference(managers, emp4, null, null, seciton2, Arrays.asList(shifts.weekDayRep, shifts.weekDay, shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos1, pos2, pos3);
        setEmployeePreference(managers, emp5, null, null, seciton2, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos1, pos2, pos3);
        setEmployeePreference(managers, emp6, null, null, seciton2, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2009-01-07"));
        addQualification(managers, emp7, pos1, pos2, pos3);
        setEmployeePreference(managers, emp7, null, null, seciton1, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp8 = addEmployee(managers, "employee#8");
        setHireDate(managers, emp8, date("2009-01-08"));
        addQualification(managers, emp8, pos1, pos2, pos3);
        setEmployeePreference(managers, emp8, null, null, seciton1, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        // Monday
        ProductionEvent event0 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event6 = addProductionEvent(managers, pro2, shifts.monEvening);

        // Tuesday
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event9 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event11 = addProductionEvent(managers, pro3, shifts.tueRep);
        ProductionEvent event12 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event13 = addProductionEvent(managers, pro2, shifts.tueEvening);

        // Wednesday
        ProductionEvent event14 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event15 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event16 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event17 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event18 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event19 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event20 = addProductionEvent(managers, pro1, shifts.wedEvening);

        // Thrusday
        ProductionEvent event21 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event22 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event23 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event24 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event25 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event26 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event27 = addProductionEvent(managers, pro2, shifts.thuEvening);
        ProductionEvent event28 = addProductionEvent(managers, pro2, shifts.thuEvening);

        /*
         * Not optimizied
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 18:00"));

        List<ProductionEvent> weekDay = Arrays.asList(
                event0,
                event1,
                event2,
                event7,
                event8,
                event9,
                event10,
                event14,
                event15,
                event16,
                event17,
                event18,
                event21,
                event22,
                event23,
                event24);
        List<ProductionEvent> weekDayRep = Arrays.asList(event3, event4, event11, event25, event26);
        List<ProductionEvent> weekEvening = Arrays.asList(event5, event6, event12, event13, event19, event20, event27, event28);

        assertEquals("Wrong number of events", 29, events.size());
        // Employee#1
        assertAssignment(3, events, weekDay, pos1, emp1);
        assertAssignment(1, events, weekDay, pos2, emp1);

        // Employee#2
        assertAssignment(4, events, weekDay, pos2, emp2);

        // Employee#3
        assertAssignment(4, events, weekEvening, Arrays.asList(pos1, pos2), emp3);

        // Employee#4
        assertAssignment(3, events, weekDayRep, pos3, emp4);

        // Employee#5
        assertAssignment(0, 1, events, weekDay, pos1, emp5);
        assertAssignment(3, events, weekDay, pos2, emp5);

        // Employee#6
        assertAssignment(1, events, weekDay, pos2, emp6);
        assertAssignment(2, 3, events, weekDay, pos1, emp6);

        // Employee#7
        assertAssignment(4, events, weekEvening, Arrays.asList(pos1, pos2), emp7);

        // Employee#8
        assertAssignment(2, events, weekDayRep, pos3, emp8);
        assertAssignment(0, 1, events, weekDay, pos2, emp8);

    }

    /**
     * <h4>Test Objective</h4>
     * <p>
     * Test how the swappable tasks are assigned according to the employee preferred team and mixed with employee
     * qualification.
     * <p>
     * Position#1 is NOT known by every employee. Position#2 and position#3 are known by every employee.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 not-swappable, section1</li>
     * <li>product#2 require one position#2 swappable, section2</li>
     * <li>product#3 require one position#3 not-swappable, section2</li>
     * <li>employee#1 preferred shift : weekDay, weekDayRep, weekEvening, preferred section1,</li>
     * <li>employee#2 preferred shift : weekDay, weekDayRep, weekEvening, preferred section2</li>
     * <li>employee#3 preferred shift : weekDay, weekDayRep, weekEvening, preferred section1</li>
     * <li>employee#4 preferred shift : weekEvening, weekDay, weekDayRep, preferred section2, qualify position#1</li>
     * <li>employee#5 preferred shift : weekDay, weekEvening, weekDayRep, preferred section2</li>
     * <li>employee#6 preferred shift : weekDayRep, weekEvening, weekDay, preferred section2, qualify position#1</li>
     * <li>employee#7 preferred shift : weekEvening, weekDayRep, weekDay, preferred section1, qualify position#1</li>
     * <li>employee#8 preferred shift : weekEvening, weekDay, weekDayRep, preferred section1</li>
     * </ul>
     * 
     * 
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Week Day</th>
     * <th>Week Day Remp.</th>
     * <th>Week Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>2x pos#1, 1x pos#2</td>
     * <td>2x pos#3</td>
     * <td>1x pos#1, 1x pos#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>2x pos#1, 2x pos#2</td>
     * <td>1x pos#3</td>
     * <td>1x pos#1, 1x pos#2</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>2x pos#1, 3x pos#2</td>
     * <td></td>
     * <td>1x pos#1, 1x pos#2</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>4x pos#2</td>
     * <td>2x pos#3</td>
     * <td>1x pos#1, 1x pos#2</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>Week Day</th>
     * <th colspan=2>Week Day Remp.</th>
     * <th colspan=2>Evening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * <td>position#3</td>
     * <td>employee#8</td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#6</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * <td></td>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#8</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#2</td>
     * <td>employee#6</td>
     * <td>position#3</td>
     * <td>employee#3</td>
     * <td>position#1</td>
     * <td>employee#4</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#7</td>
     * <td>position#3</td>
     * <td>employee#8</td>
     * <td>position#2</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif614AssignSwappableTasks() throws ManagerException {

        Section seciton1 = addSection(managers, "section1");
        Section seciton2 = addSection(managers, "section2");

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, seciton1, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, seciton2, "position#2", false, true);
        addProductPosition(managers, pro2, pos2, 1);
        Product pro3 = addProduct(managers, "product3");
        Position pos3 = addPosition(managers, seciton2, "position#3", false);
        addProductPosition(managers, pro3, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos2, pos3);
        setEmployeePreference(managers, emp1, null, null, seciton2, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos2, pos3);
        setEmployeePreference(managers, emp2, null, null, seciton2, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, seciton2, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1, pos2, pos3);
        setEmployeePreference(managers, emp4, null, null, seciton1, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos2, pos3);
        setEmployeePreference(managers, emp5, null, null, seciton2, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos1, pos2, pos3);
        setEmployeePreference(managers, emp6, null, null, seciton1, Arrays.asList(shifts.weekDayRep, shifts.weekEvening, shifts.weekDay));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2009-01-07"));
        addQualification(managers, emp7, pos1, pos2, pos3);
        setEmployeePreference(managers, emp7, null, null, seciton1, Arrays.asList(shifts.weekEvening, shifts.weekDayRep, shifts.weekDay));

        Employee emp8 = addEmployee(managers, "employee#8");
        setHireDate(managers, emp8, date("2009-01-08"));
        addQualification(managers, emp8, pos2, pos3);
        setEmployeePreference(managers, emp8, null, null, seciton2, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        // Monday
        ProductionEvent event0 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event6 = addProductionEvent(managers, pro2, shifts.monEvening);

        // Tuesday
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event9 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event11 = addProductionEvent(managers, pro3, shifts.tueRep);
        ProductionEvent event12 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event13 = addProductionEvent(managers, pro2, shifts.tueEvening);

        // Wednesday
        ProductionEvent event14 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event15 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event16 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event17 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event18 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event19 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event20 = addProductionEvent(managers, pro2, shifts.wedEvening);

        // Thrusday
        ProductionEvent event21 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event22 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event23 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event24 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event25 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event26 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event27 = addProductionEvent(managers, pro1, shifts.thuEvening);
        ProductionEvent event28 = addProductionEvent(managers, pro2, shifts.thuEvening);

        /*
         * Not optimizied
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 18:00"));

        List<ProductionEvent> weekDay = Arrays.asList(
                event0,
                event1,
                event2,
                event7,
                event8,
                event9,
                event10,
                event14,
                event15,
                event16,
                event17,
                event18,
                event21,
                event22,
                event23,
                event24);
        List<ProductionEvent> weekDayRep = Arrays.asList(event3, event4, event11, event25, event26);
        List<ProductionEvent> weekEvening = Arrays.asList(event5, event6, event12, event13, event19, event20, event27, event28);

        assertEquals("Wrong number of events", 29, events.size());
        // Employee#1
        assertAssignment(4, events, weekDay, pos2, emp1);

        // Employee#2
        assertAssignment(3, events, weekDay, pos2, emp2);

        // Employee#3
        assertAssignment(3, events, weekDayRep, pos3, emp3);

        // Employee#4
        assertAssignment(4, events, weekEvening, pos1, emp4);

        // Employee#5
        assertAssignment(4, events, weekEvening, pos2, emp5);

        // Employee#6
        assertAssignment(3, events, weekDay, pos1, emp6);
        assertAssignment(1, events, weekDay, pos2, emp6);

        // Employee#7
        assertAssignment(3, events, weekDay, pos1, emp7);
        assertAssignment(1, events, weekDay, pos2, emp7);

        // Employee#8
        assertAssignment(2, events, weekDayRep, pos3, emp8);
        assertAssignment(0, 1, events, weekDay, pos2, emp8);

    }

    /**
     * <h4>Test Objective</h4>
     * <p>
     * Test how the swappable tasks are assigned according to the employee preferred team.
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 not-swappable</li>
     * <li>product#2 require one position#2 swappable</li>
     * <li>product#3 require one position#3 not-swappable</li>
     * <li>employee#1 preferred shift : weekDay, weekDayRep, weekEvening</li>
     * <li>employee#2 preferred shift : weekDay, weekEvening, weekDayRep</li>
     * <li>employee#3 preferred shift : weekDay, weekDayRep, weekEvening</li>
     * <li>employee#4 preferred shift : weekDay, weekEvening, weekDayRep</li>
     * <li>employee#5 preferred shift : weekDay, weekEvening, weekDayRep</li>
     * <li>employee#6 preferred shift : weekDay, weekDayRep, weekEvening</li>
     * <li>employee#7 preferred shift : weekEvening, weekDay, weekDayRep</li>
     * <li>employee#8 preferred shift : weekEvening, weekDay, weekDayRep</li>
     * </ul>
     * 
     * 
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Week Day</th>
     * <th>Week Day Remp.</th>
     * <th>Week Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>2x pos#1, 1x pos#2</td>
     * <td>2x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>2x pos#1, 2x pos#2</td>
     * <td>1x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>2x pos#1, 2x pos#2</td>
     * <td></td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>4x pos#2</td>
     * <td>2x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>Week Day</th>
     * <th colspan=2>Week Day Remp.</th>
     * <th colspan=2>Evening</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#8</td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>employee#6</td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#6 or #8</td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * <td>position#3</td>
     * <td>employee#8</td>
     * <td>position#1</td>
     * <td>employee#7</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * <td>position#3</td>
     * <td>employee#6</td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#3</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#4</td>
     * <td></td>
     * <td></td>
     * <td></td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif615AssignSwappableTasks() throws ManagerException {
        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        Position pos2 = addPosition(managers, null, "position#2", false, true);
        addProductPosition(managers, pro2, pos2, 1);
        Product pro3 = addProduct(managers, "product3");
        Position pos3 = addPosition(managers, null, "position#3", false);
        addProductPosition(managers, pro3, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2, pos3);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos2, pos3);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1, pos2, pos3);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos1, pos2, pos3);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos1, pos2, pos3);
        setEmployeePreference(managers, emp6, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2009-01-07"));
        addQualification(managers, emp7, pos1, pos2, pos3);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        Employee emp8 = addEmployee(managers, "employee#8");
        setHireDate(managers, emp8, date("2009-01-08"));
        addQualification(managers, emp8, pos1, pos2, pos3);
        setEmployeePreference(managers, emp8, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        // Monday
        ProductionEvent event0 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.monEvening);

        // Tuesday
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event9 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event11 = addProductionEvent(managers, pro3, shifts.tueRep);
        ProductionEvent event12 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event13 = addProductionEvent(managers, pro1, shifts.tueEvening);

        // Wednesday
        ProductionEvent event14 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event15 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event16 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event17 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event18 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event19 = addProductionEvent(managers, pro1, shifts.wedEvening);

        // Thrusday
        ProductionEvent event20 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event21 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event22 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event23 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event24 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event25 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event26 = addProductionEvent(managers, pro1, shifts.thuEvening);
        ProductionEvent event27 = addProductionEvent(managers, pro1, shifts.thuEvening);

        /*
         * Not optimizied
         */
        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 18:00"));

        List<ProductionEvent> weekDay = Arrays.asList(
                event0,
                event1,
                event2,
                event7,
                event8,
                event9,
                event10,
                event14,
                event15,
                event16,
                event17,
                event20,
                event21,
                event22,
                event23);
        List<ProductionEvent> weekDayRep = Arrays.asList(event3, event4, event11, event24, event25);
        List<ProductionEvent> weekEvening = Arrays.asList(event5, event6, event12, event13, event18, event19, event26, event27);

        assertEquals("Wrong number of events", 28, events.size());
        // Employee#1
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp1);
        assertAssignment(0, events, weekDayRep, pos3, emp1);

        // Employee#2
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp2);
        assertAssignment(0, events, weekDayRep, pos3, emp1);

        // Employee#3
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp3);
        assertAssignment(0, events, weekDayRep, pos3, emp3);

        // Employee#4
        assertAssignment(3, 4, events, weekDay, Arrays.asList(pos1, pos2), emp4);
        assertAssignment(0, events, weekDayRep, pos3, emp4);

        // Employee#5
        assertAssignment(4, events, weekEvening, pos1, emp5);

        // Employee#6
        assertAssignment(2, 3, events, weekDayRep, pos3, emp6);
        assertAssignment(0, 1, events, weekDay, pos2, emp6);

        // Employee#7
        assertAssignment(4, events, weekEvening, pos1, emp7);

        // Employee#8
        assertAssignment(2, 3, events, weekDayRep, pos3, emp8);

    }

    /**
     * <h4>Test Objective</h4>
     * <p>
     * Check if the employee assigned to swappable task is not assigned according to his preferred section. See bug #68.
     * <p>
     * Every employees atre qualify to work on position#1, #2 and #3.
     * 
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 require one position#1 (section#1) swappable</li>
     * <li>product#2 require one position#2 (section#2) swappable</li>
     * <li>product#3 require one position#3 not-swappable</li>
     * <li>employee#1 preferred shift : weekDayRep, weekDay, weekEvening - preferred Section#1</li>
     * <li>employee#2 preferred shift : weekDayRep, weekDay, weekEvening - preferred Section#1</li>
     * <li>employee#3 preferred shift : weekDay, weekDayRep, weekEvening - preferred Section#1</li>
     * <li>employee#4 preferred shift : weekDay, weekEvening, weekDayRep - preferred Section#2</li>
     * <li>employee#5 preferred shift : weekDay, weekEvening, weekDayRep - preferred Section#2</li>
     * <li>employee#6 preferred shift : weekDay, weekDayRep, weekEvening - preferred Section#1</li>
     * <li>employee#7 preferred shift : weekEvening, weekDay, weekDayRep</li>
     * <li>employee#8 preferred shift : weekEvening, weekDay, weekDayRep</li>
     * </ul>
     * 
     * 
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>Week Day</th>
     * <th>Week Day Remp.</th>
     * <th>Week Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>1x pos#1, 3x pos#2</td>
     * <td>1x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>3x pos#1, 2x pos#2</td>
     * <td>1x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>2x pos#1, 3x pos#2</td>
     * <td></td>
     * <td>2x pos#1</td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>4x pos#2</td>
     * <td>2x pos#3</td>
     * <td>2x pos#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan>Week Day</th>
     * <th colspan>Week Day Remp.</th>
     * <th colspan>Evening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>
     * <ul>
     * <li>position#1 : employee#3</li>
     * <li>position#2 : employee#4</li>
     * <li>position#2 : employee#5</li>
     * <li>position#2 : employee#6</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#3 : employee#1 or #2</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#1 : employee#7</li>
     * <li>position#1 : employee#8</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>
     * <ul>
     * <li>position#1 : employee#1 or #2</li>
     * <li>position#1 : employee#3</li>
     * <li>position#1 : employee#6</li>
     * <li>position#2 : employee#4</li>
     * <li>position#2 : employee#5</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#3 : employee#1 or #2</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#1 : employee#7</li>
     * <li>position#1 : employee#8</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>wed</td>
     * <td>
     * <ul>
     * <li>position#1 : employee#3</li>
     * <li>position#1 : employee#6</li>
     * <li>position#2 : employee#1 or #2</li>
     * <li>position#2 : employee#4</li>
     * <li>position#2 : employee#5</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#3 : employee#1 or #2</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#1 : employee#7</li>
     * <li>position#1 : employee#8</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>thu</td>
     * <td>
     * <ul>
     * <li>position#2 : employee#3</li>
     * <li>position#2 : employee#4</li>
     * <li>position#2 : employee#5</li>
     * <li>position#2 : employee#6</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#3 : employee#1</li>
     * <li>position#3 : employee#2</li>
     * </ul>
     * </td>
     * <td>
     * <ul>
     * <li>position#1 : employee#7</li>
     * <li>position#1 : employee#8</li>
     * </ul>
     * </td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif616AssignSwappableTasks_WithPreferredSection() throws ManagerException {

        Section sec1 = addSection(managers, "section#1");
        Section sec2 = addSection(managers, "section#2");
        Position pos1 = addPosition(managers, sec1, "position#1", false, true);
        Position pos2 = addPosition(managers, sec2, "position#2", false, true);
        Position pos3 = addPosition(managers, null, "position#3", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos2, 1);
        Product pro3 = addProduct(managers, "product3");
        addProductPosition(managers, pro3, pos3, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1, pos2, pos3);
        setEmployeePreference(managers, emp1, null, null, sec1, Arrays.asList(shifts.weekDayRep, shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1, pos2, pos3);
        setEmployeePreference(managers, emp2, null, null, sec1, Arrays.asList(shifts.weekDayRep, shifts.weekEvening, shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1, pos2, pos3);
        setEmployeePreference(managers, emp3, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1, pos2, pos3);
        setEmployeePreference(managers, emp4, null, null, sec2, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos1, pos2, pos3);
        setEmployeePreference(managers, emp5, null, null, sec2, Arrays.asList(shifts.weekDay, shifts.weekEvening, shifts.weekDayRep));

        Employee emp6 = addEmployee(managers, "employee#6");
        setHireDate(managers, emp6, date("2009-01-06"));
        addQualification(managers, emp6, pos1, pos2, pos3);
        setEmployeePreference(managers, emp6, null, null, sec1, Arrays.asList(shifts.weekDay, shifts.weekDayRep, shifts.weekEvening));

        Employee emp7 = addEmployee(managers, "employee#7");
        setHireDate(managers, emp7, date("2009-01-07"));
        addQualification(managers, emp7, pos1, pos2, pos3);
        setEmployeePreference(managers, emp7, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        Employee emp8 = addEmployee(managers, "employee#8");
        setHireDate(managers, emp8, date("2009-01-08"));
        addQualification(managers, emp8, pos1, pos2, pos3);
        setEmployeePreference(managers, emp8, null, null, null, Arrays.asList(shifts.weekEvening, shifts.weekDay, shifts.weekDayRep));

        // Monday
        ProductionEvent event0 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event1 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.monDay);
        ProductionEvent event4 = addProductionEvent(managers, pro3, shifts.monRep);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.monEvening);

        // Tuesday
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event9 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event10 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event11 = addProductionEvent(managers, pro2, shifts.tueDay);
        ProductionEvent event12 = addProductionEvent(managers, pro3, shifts.tueRep);
        ProductionEvent event13 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event14 = addProductionEvent(managers, pro1, shifts.tueEvening);

        // Wednesday
        ProductionEvent event15 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event16 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event17 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event18 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event19 = addProductionEvent(managers, pro2, shifts.wedDay);
        ProductionEvent event20 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event21 = addProductionEvent(managers, pro1, shifts.wedEvening);

        // Thrusday
        ProductionEvent event22 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event23 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event24 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event25 = addProductionEvent(managers, pro2, shifts.thuDay);
        ProductionEvent event26 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event27 = addProductionEvent(managers, pro3, shifts.thuRep);
        ProductionEvent event28 = addProductionEvent(managers, pro1, shifts.thuEvening);
        ProductionEvent event29 = addProductionEvent(managers, pro1, shifts.thuEvening);

        /*
         * Not optimizied
         */
        generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 18:00"));

        assertEquals("Wrong number of events", 30, events.size());

        // Mon
        assertAssignment(1, events, event0, pos1, emp3);
        assertAssignment(3, events, Arrays.asList(event1, event2, event3), pos2, Arrays.asList(emp4, emp5, emp6));
        assertAssignment(1, events, event4, pos3, Arrays.asList(emp1, emp2));
        assertAssignment(2, events, Arrays.asList(event5, event6), pos1, Arrays.asList(emp7, emp8));

        // Tue
        assertAssignment(3, events, Arrays.asList(event7, event8, event9), pos1, Arrays.asList(emp1, emp2, emp3, emp6));
        assertAssignment(2, events, Arrays.asList(event10, event11), pos2, Arrays.asList(emp4, emp5));
        assertAssignment(1, events, event12, pos3, Arrays.asList(emp1, emp2));
        assertAssignment(2, events, Arrays.asList(event13, event14), pos1, Arrays.asList(emp7, emp8));

        // Wed
        assertAssignment(2, events, Arrays.asList(event15, event16), pos1, Arrays.asList(emp3, emp6));
        assertAssignment(3, events, Arrays.asList(event17, event18, event19), pos2, Arrays.asList(emp1, emp2, emp4, emp5));
        assertAssignment(2, events, Arrays.asList(event20, event21), pos1, Arrays.asList(emp7, emp8));

        // Thu
        assertAssignment(4, events, Arrays.asList(event22, event23, event24, event25), pos2, Arrays.asList(emp3, emp4, emp5, emp6));
        assertAssignment(2, events, Arrays.asList(event26, event27), pos3, Arrays.asList(emp1, emp2));
        assertAssignment(2, events, Arrays.asList(event28, event29), pos1, Arrays.asList(emp7, emp8));

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with the non-availability.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 (not available all the week)</li>
     * <li>employee#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td>employee#1 locked</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <p>
     * An error should occured, because employee#1 can't be locked on a position if he's not available.
     * 
     * @throws ManagerException
     * 
     */
    @Test(expected = ManagerException.class)
    public void generatePlanif701LockedConflictingWithNonAvailable() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        addNonAvailability(managers, emp1, time("Sun 00:00"), time("Fri 00:00"));

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Create the locked
        Task lockedEvent = addTask(managers, event2, pos1, null, null);
        setTaskLocked(managers, lockedEvent, emp1);

        generatePlanif(managers, time("Mon 6:00"));
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if an employee can be locked on two (2) event occurring at the same time.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1, one position#2</li>
     * <li>employee#1</li>
     * <li>employee#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td>employee#1 locked</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <p>
     * An error is expected, because an employee can't be assign to two tasks occuring at the same time.
     * </p>
     * 
     * @throws ManagerException
     * 
     */
    @Test(expected = ManagerException.class)
    public void generatePlanif702LockedConflictingWithOneEventPerTime() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Create locked planif event
        Task locked;
        locked = addTask(managers, event2, pos1, event2.getShift().getStartDate(), event2.getShift().getEndDate());
        setTaskLocked(managers, locked, emp1);
        locked = addTask(managers, event2, pos2, event2.getShift().getStartDate(), event2.getShift().getEndDate());
        setTaskLocked(managers, locked, emp1);

        // Generate the planif (with locked)
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));
        context.searchSolution(new MockGeneratePlanifMonitor());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check if an employee can be locked on two (2) different shift.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1 preferred-team #1</li>
     * <li>employee#2 preferred-team #1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#1 locked</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * <td>employee#1 locked</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4> An error is expected.
     * 
     * @throws ManagerException
     * 
     */
    @Test(expected = ManagerException.class)
    public void generatePlanif703LockedConflictingWithOneShiftPerWeek() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        Task lockedEvent = addTask(managers, event1, pos1, shifts.monDay.getStartDate(), shifts.monDay.getEndDate());
        setTaskLocked(managers, lockedEvent, emp1);
        lockedEvent = addTask(managers, event2, pos1, shifts.monEvening.getStartDate(), shifts.monEvening.getEndDate());
        setTaskLocked(managers, lockedEvent, emp1);

        // Generate the planif (with locked)
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));
        context.searchSolution(new MockGeneratePlanifMonitor());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with an employee being locked on it's preferred position.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1(classified), two position#2</li>
     * <li>employee#1 qualification on position#1</li>
     * <li>employee#2 qualification on position#2</li>
     * <li>employee#3 preferred-position position#1, qualification on position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#3 locked on position#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th colspan=2>weekDay</th>
     * </tr>
     * <tr>
     * <th></th>
     * <th>Position</th>
     * <th>Assign To</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>position#1</td>
     * <td>employee#3 (locked)</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif704LockedConflictingWithPreferredPositionNotAssign() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos2);

        Employee emp3 = addEmployee(managers, "employee#3");
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, pos1, shifts.weekDay, null, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        Task lockedEvent = addTask(managers, event1, pos1, shifts.monDay.getStartDate(), shifts.monDay.getEndDate());
        setTaskLocked(managers, lockedEvent, emp3);

        // Generate the planif (with locked)
        generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 6, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos2), emp1);
        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos2), emp2);
        assertAssignment(2, events, Arrays.asList(event1, event2), Arrays.asList(pos1), emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with a preferred-position.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1(classified), one position#2</li>
     * <li>employee#1 preferred-position position#1, qualification on position#2</li>
     * <li>employee#2 preferred-position position#1, qualification on position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#1 locked on position#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif705LockedConflictingWithPreferredPositionSeniorityHigherLocked() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, null, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, pos1, shifts.weekDay, null, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Generate the planif (without locked)
        List<? extends AbstractCalendarEvent> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }

        // Query the planif events object and valid them
        Task pe = (Task) CollectionUtils.find(events, new ManagerTestCase.PlanifEventPredicate(event1, pos2, emp2));
        setTaskLocked(managers, pe, emp1);

        // Generate the planif (with locked)
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
        }

        assertEquals("Wrong number of events", 4, events.size());

        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event1, pos1, emp2)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event1, pos2, emp1)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event2, pos1, emp1)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event2, pos2, emp2)));
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with a preferred-position.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1(classified), one position#2</li>
     * <li>employee#1 preferred-position position#1, qualification on position#2</li>
     * <li>employee#2 preferred-position position#1, qualification on position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#2 locked on position#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif706LockedConflictingWithPreferredPositionSeniorityLowerLocked() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", true);
        Position pos2 = addPosition(managers, null, "position#2", false);
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, pos1, shifts.weekDay, null, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, pos1, shifts.weekDay, null, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Generate the planif (without locked)
        List<? extends AbstractCalendarEvent> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }

        // Query the planif events object and valid them
        Task pe = (Task) CollectionUtils.find(events, new ManagerTestCase.PlanifEventPredicate(event1, pos1, emp1));
        setTaskLocked(managers, pe, emp2);

        // Generate the planif (with locked)
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
        }

        assertEquals("Wrong number of events", 4, events.size());

        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event1, pos1, emp2)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event1, pos2, emp1)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event2, pos1, emp1)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event2, pos2, emp2)));
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with a preferred-section.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (sec#1), one position#2 (sec#2)</li>
     * <li>employee#1 preferred-section sec#1</li>
     * <li>employee#2 preferred-section sec#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#1 locked on sec#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#1 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif707LockedConflictingWithPreferredSectionHigherEmployeeLocked() throws ManagerException {

        Section sec1 = addSection(managers, "sec#1");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Section sec2 = addSection(managers, "sec#2");
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec1, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec1, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Generate the planif (without locked)

        // Query the planif events object and valid them
        Task locked = addTask(managers, event1, pos2, event1.getShift().getStartDate(), event1.getShift().getEndDate());
        setTaskLocked(managers, locked, emp1);

        // Generate the planif (with locked)
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }

        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(events, event1, pos2, emp1);
        assertAssignment(events, event2, pos1, emp1);
        assertAssignment(events, event1, pos1, emp2);
        assertAssignment(events, event2, pos2, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with a preferred-section.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (sec#1), one position#2 (sec#2)</li>
     * <li>employee#1 preferred-section sec#1</li>
     * <li>employee#2 preferred-section sec#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#2 locked on sec#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif708LockedConflictingWithPreferredSectionLowerEmployeeLocked() throws ManagerException {

        Section sec1 = addSection(managers, "sec#1");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Section sec2 = addSection(managers, "sec#2");
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec1, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec1, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Query the planif events object and valid them
        Task locked = addTask(managers, event1, pos1, null, null);
        setTaskLocked(managers, locked, emp2);

        List<Task> events;
        // Generate the planif (with locked)
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }

        assertEquals("Wrong number of events", 4, events.size());

        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event1, pos1, emp2)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event1, pos2, emp1)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event2, pos1, emp1)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event2, pos2, emp2)));
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with a preferred-team.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1 preferred-team shifts.weekDay</li>
     * <li>employee#2 preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * <td>employee#1 locked on shift shifts.weekEvening</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#1 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>null</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif709LockedConflictingWithPreferredShiftHigherEmployeeLocked() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        Task lockedEvent = addTask(managers, event2, pos1, shifts.monEvening.getStartDate(), shifts.monEvening.getEndDate());
        setTaskLocked(managers, lockedEvent, emp1);

        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());

        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp1);

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with a preferred-team.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1</li>
     * <li>employee#1 preferred-team shifts.weekDay</li>
     * <li>employee#2 preferred-team shifts.weekDay</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#2 locked on shift shifts.weekDay</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#2 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif710LockedConflictingWithPreferredShiftLowerEmployeeLocked() throws ManagerException {

        Product pro1 = addProduct(managers, "product1");
        Position pos1 = addPosition(managers, null, "position#1", false);
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        Task lockedEvent = addTask(managers, event1, pos1, shifts.monDay.getStartDate(), shifts.monDay.getEndDate());
        setTaskLocked(managers, lockedEvent, emp2);

        List<Task> events;
        /*
         * Optimizied
         */
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }
        assertEquals("Wrong number of event.", 4, events.size());

        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp1);

        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp2);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with an employee locked on a trask for which his not qualified.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1, one position#2</li>
     * <li>employee#1 qualify position#2</li>
     * <li>employee#2 qualify with position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>product#1</td>
     * <td>employee#1 (locked)</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Day</th>
     * <th>Assignment</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>
     * <ul>
     * <li>position#1: employee#2</li>
     * <li>position#2: null</li>
     * </ul>
     * </td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>
     * <ul>
     * <li>position#1: employee#1</li>
     * <li>position#2: employee#2</li>
     * </ul>
     * </td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     */
    @Test
    public void generatePlanif711LockedConflictingWithQualification() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Position pos2 = addPosition(managers, null, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos2);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Create the locked planif event
        Task locked = addTask(managers, event2, pos1, null, null);
        setTaskLocked(managers, locked, emp1);

        // Generate the planif (with locked)
        generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(1, events, event1, pos2, emp1);
        assertAssignment(1, events, event2, pos1, emp1);

        assertAssignment(1, events, event1, pos1, emp2);
        assertAssignment(1, events, event2, pos2, emp2);
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with the seniority.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1</li>
     * <li>employee#2</li>
     * <li>employee#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#3 locked</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td></td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * </table>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif712LockedConflictingWithSeniority() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        addQualification(managers, emp3, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Query the planif events object and valid them
        Task pe = addTask(managers, event1, pos1, null, null);
        setTaskLocked(managers, pe, emp3);

        generatePlanif(managers, time("Mon 6:00"));
        List<Task> events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));

        assertEquals("Wrong number of events", 4, events.size());

        assertAssignment(2, events, Arrays.asList(event1, event2), pos1, emp1);

        assertAssignment(2, events, Arrays.asList(event1, event2), pos1, emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with the seniority.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1</li>
     * <li>employee#2</li>
     * <li>employee#3</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>employee#3 locked</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td>employee#3 locked</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#3 (locked)</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif713LockedConflictingWithSeniorityEmployeeNotWorking() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);

        Employee emp3 = addEmployee(managers, "employee#3");
        addQualification(managers, emp3, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        // Query the planif events object and valid them
        Task pe1 = addTask(managers, event1, pos1, null, null);
        setTaskLocked(managers, pe1, emp3);
        Task pe2 = addTask(managers, event2, pos1, null, null);
        setTaskLocked(managers, pe2, emp3);

        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }

        assertEquals("Wrong number of events", 4, events.size());

        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event1, pos1, emp1)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event1, pos1, emp3)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event2, pos1, emp1)));
        assertEquals("Wrong planif event assignment", 1, CollectionUtils.countMatches(events, new ManagerTestCase.PlanifEventPredicate(event2, pos1, emp3)));
    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Test with a locked planif-event conflicting with the seniority.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1 qualify position#1</li>
     * <li>employee#2 qualify position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Notice</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>null</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * <td>null locked</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>null (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif714LockedNull() {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        addQualification(managers, emp1, pos1);

        Employee emp2 = addEmployee(managers, "employee#2");
        addQualification(managers, emp2, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.tueDay);

        Task lockedEvent = addTask(managers, event1, pos1, shifts.monDay.getStartDate(), shifts.monDay.getEndDate());
        setTaskLocked(managers, lockedEvent, null);

        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error generating planif", e);
            return;
        }
        assertEquals("Wrong number of event", 4, events.size());
        assertAssignment(3, events, Arrays.asList(event1, event2), pos1, Arrays.asList(emp1, emp2));
        assertAssignment(1, events, event1, pos1, NULL);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Special check with locked. If an employee is schedule to work on the shift (locked on the shift), he must be
     * consider in the seniority list for it's preferred section.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required one position#1 (section1), one position#2 (section2)</li>
     * <li>product#2 required two position#1 (section1), one position#2 (section2)</li>
     * <li>employee#1 with preferred section#2, qualification on position#1, position#2, position#3</li>
     * <li>employee#2 with preferred section#2, qualification on position#1, position#2</li>
     * <li>employee#3 with preferred section#1, qualification on position#1, position#2</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#2</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#3 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#2</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif715LockedOnShiftAssignToPreferredSection() throws ManagerException {

        Section sec1 = addSection(managers, "Section1");
        Section sec2 = addSection(managers, "Section2");
        Position pos1 = addPosition(managers, sec1, "position#1", false);
        Position pos2 = addPosition(managers, sec2, "position#2", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);
        addProductPosition(managers, pro1, pos2, 1);
        Product pro2 = addProduct(managers, "product2");
        addProductPosition(managers, pro2, pos1, 2);
        addProductPosition(managers, pro2, pos2, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        addQualification(managers, emp1, pos2);
        setEmployeePreference(managers, emp1, null, null, sec2, null);

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        addQualification(managers, emp2, pos2);
        setEmployeePreference(managers, emp2, null, null, sec2, null);

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1);
        addQualification(managers, emp3, pos2);
        setEmployeePreference(managers, emp3, null, null, sec1, null);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event3 = addProductionEvent(managers, pro2, shifts.tueDay);

        // Create locked planif event
        Task locked = addTask(managers, event3, pos1, null, null);
        setTaskLocked(managers, locked, emp3);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 5, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos2, emp1);
        assertAssignment(events, event3, pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Special check with locked. If an employee is schedule to work on the shift (locked on the shift), he must be
     * consider a condidate to work on other position during the week to use less employee.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1 qualify position#1</li>
     * <li>employee#2 qualify position#1</li>
     * <li>employee#3 qualify position#1</li>
     * <li>employee#4 qualify position#1</li>
     * <li>employee#5 qualify position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>position#1</td>
     * <td>employee#5 (locked)</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * </tr>
     * <tr>
     * <td>shifts.tueDay</td>
     * <td>position#1</td>
     * <td>employee#5</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * </tr>
     * <tr>
     * <td>shifts.tueEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     */
    @Test
    public void generatePlanif716_EmployeeLockedOnce_OptimizedToUseLessEmployee() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2009-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2009-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp4 = addEmployee(managers, "employee#4");
        setHireDate(managers, emp4, date("2009-01-04"));
        addQualification(managers, emp4, pos1);
        setEmployeePreference(managers, emp4, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp5 = addEmployee(managers, "employee#5");
        setHireDate(managers, emp5, date("2009-01-05"));
        addQualification(managers, emp5, pos1);
        setEmployeePreference(managers, emp5, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);

        // Create locked planif event
        Task locked = addTask(managers, event1, pos1, null, null);
        setTaskLocked(managers, locked, emp5);

        /*
         * Not optimized
         */
        List<Task> events;
        try {
            generatePlanif(managers, time("Mon 6:00"));
            events = managers.getTaskManager().list(time("Mon 00:00"), time("Fri 00:00"));
        } catch (ManagerException e) {
            fail("Error listing planif events", e);
            return;
        }
        assertEquals("Wrong number of events", 8, events.size());
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp1);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp2);
        assertAssignment(2, events, Arrays.asList(event2, event4), pos1, emp3);
        assertAssignment(2, events, Arrays.asList(event1, event3), pos1, emp5);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check with an employee being locked on two different shift.
     * 
     * <p>
     * <h4>Input data</h4>
     * 
     * <ul>
     * <li>product#1 required two position#1</li>
     * <li>employee#1 qualify position#1, preferred shift shifts.weekDay -- locked on two shifts.</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>shifts.monEvening</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <p>
     * An error is expected, because an employee can't work on two different shift.
     * 
     * @throws ManagerException
     */
    @Test(expected = ManagerException.class)
    public void generatePlanif717_WithEmployeeLockedOnTwoShift_EmployeeAssignToOtherPosition() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2009-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);

        // Create locked planif event
        Task locked = addTask(managers, event1, pos1, null, null);
        setTaskLocked(managers, locked, emp1);
        locked = addTask(managers, event2, pos1, null, null);
        setTaskLocked(managers, locked, emp1);

        // Generate the planif
        GeneratePlanifContext context;
        context = managers.getTaskManager().createGeneratePlanifContext();
        context.setWeek(time("Mon 6:00"));

        context.searchSolution(new MockGeneratePlanifMonitor());

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check to assign an employee with a preferred seniority being locked on a different shift. In this scenario,
     * employee#3 has a preferred seniority for the shifts.weekDay, but is locked on the shift shifts.weekEvening.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required two (2) position#1</li>
     * <li>employee#1 qualify on position#1, preferred-team shifts.weekDay</li>
     * <li>employee#2 qualify on position#1, preferred-team shifts.weekDay</li>
     * <li>employee#3 qualify on position#1, with preferred-seniority, preferred-team shifts.weekDay -- locked on
     * weekEvening</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Day / Shift</th>
     * <th>weekDay</th>
     * <th>weekEvening</th>
     * </tr>
     * <tr>
     * <td>mon</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>tue</td>
     * <td>product#1</td>
     * <td>product#1</td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>..</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * <th>Shift</th>
     * <th>Position</th>
     * <th>Assign to</th>
     * </tr>
     * <tr>
     * <td>monDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>monEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td>position#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>tueDay</td>
     * <td>position#1</td>
     * <td>employee#1</td>
     * <td>tueEvening</td>
     * <td>position#1</td>
     * <td>employee#3</td>
     * </tr>
     * <tr>
     * <td></td>
     * <td>position#1</td>
     * <td>employee#2</td>
     * <td></td>
     * <td>position#1</td>
     * <td></td>
     * </tr>
     * <tr>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * <td>...</td>
     * </tr>
     * </table>
     */
    @Test
    public void generatePlanif718_WithEmployeePreferredSeniorityLockedOnDifferentShift_EmployeeAssignToLockedShift() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", false);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 2);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);
        setEmployeePreference(managers, emp2, null, null, null, Arrays.asList(shifts.weekDay));

        Employee emp3 = addEmployee(managers, "employee#3");
        setHireDate(managers, emp3, date("2011-01-03"));
        addQualification(managers, emp3, pos1);
        setEmployeePreferredSeniority(managers, emp3, true);
        setEmployeePreference(managers, emp3, null, null, null, Arrays.asList(shifts.weekDay));

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);
        ProductionEvent event3 = addProductionEvent(managers, pro1, shifts.tueDay);
        ProductionEvent event4 = addProductionEvent(managers, pro1, shifts.tueEvening);
        ProductionEvent event5 = addProductionEvent(managers, pro1, shifts.wedDay);
        ProductionEvent event6 = addProductionEvent(managers, pro1, shifts.wedEvening);
        ProductionEvent event7 = addProductionEvent(managers, pro1, shifts.thuDay);
        ProductionEvent event8 = addProductionEvent(managers, pro1, shifts.thuEvening);

        Task locked = addTask(managers, event2, pos1, null, null);
        setTaskLocked(managers, locked, emp3);

        List<Task> events;
        generatePlanif(managers, time("Mon 6:00"));
        events = managers.getTaskManager().list(time("Sun 00:00"), time("Sat 00:00"));

        assertAssignment(8, events, Arrays.asList(event1, event3, event5, event7), pos1, Arrays.asList(emp1, emp2));
        assertAssignment(4, events, Arrays.asList(event2, event4, event6, event8), pos1, emp3);

    }

    /**
     * 
     * <h4>Test Objective</h4>
     * <p>
     * Check that no warning is displayed when locking an employee on a shift preferred by an other more senior employee
     * who ends up on a classified task.
     * <p>
     * <h4>Input data</h4>
     * <ul>
     * <li>product#1 required one (1) position#1(classified)</li>
     * <li>employee#1 qualify on position#1</li>
     * <li>employee#2 qualify on position#1</li>
     * </ul>
     * <h4>Production Events</h4>
     * <table border=1>
     * <tr>
     * <th>Shift</th>
     * <th>Product</th>
     * <th>Shift</th>
     * <th>Product</th>
     * </tr>
     * <tr>
     * <td>shifts.monDay</td>
     * <td>product#1</td>
     * <td>shifts.MonEvening</td>
     * <td>product#1</td>
     * </tr>
     * </table>
     * 
     * <h4>Expected results</h4>
     * <p>
     * No warning displayed
     * <p>
     * 
     * @throws ManagerException
     * 
     */
    @Test
    public void generatePlanif719_LockedConflictingWithPreferredShiftLowerEmployeeLockedClassifiedPositionNoWarning() throws ManagerException {

        Position pos1 = addPosition(managers, null, "position#1", true);
        Product pro1 = addProduct(managers, "product1");
        addProductPosition(managers, pro1, pos1, 1);

        Employee emp1 = addEmployee(managers, "employee#1");
        setHireDate(managers, emp1, date("2011-01-01"));
        addQualification(managers, emp1, pos1);
        setEmployeePreference(managers, emp1, null, null, null, Arrays.asList(shifts.weekDay, shifts.weekEvening));

        Employee emp2 = addEmployee(managers, "employee#2");
        setHireDate(managers, emp2, date("2011-01-02"));
        addQualification(managers, emp2, pos1);

        // Create the planif.

        ProductionEvent event1 = addProductionEvent(managers, pro1, shifts.monDay);
        ProductionEvent event2 = addProductionEvent(managers, pro1, shifts.monEvening);

        Task lockedEvent = addTask(managers, event1, pos1, shifts.monDay.getStartDate(), shifts.monDay.getEndDate());
        setTaskLocked(managers, lockedEvent, emp2);

        /*
         * Not optimized
         */
        List<Task> events;
        GeneratePlanifContext context = generatePlanif(managers, shifts.start);
        events = managers.getTaskManager().list(shifts.start, shifts.end);

        assertEquals(0, context.getProposedTasks().warnings().size());
    }

    /**
     * Sets the first day of week reference.
     */
    @Before
    public void setsFirstDayOfWeek() {

    }

}
