First tries to assign all possible hours without using overtime
If overtime must be used it's distributed evenly among all users using previous algorithm. FEA: ItEr71S07FragmentationDeletionItEr70S09
This commit is contained in:
parent
5e24f6b5b0
commit
4dd213706d
4 changed files with 378 additions and 25 deletions
|
|
@ -29,6 +29,7 @@ import org.apache.commons.lang.builder.HashCodeBuilder;
|
|||
import org.navalplanner.business.workingday.EffortDuration;
|
||||
import org.navalplanner.business.workingday.EffortDuration.Granularity;
|
||||
|
||||
|
||||
/**
|
||||
* This class is intended as a Hibernate component. It's formed by two
|
||||
* components, the standard effort and the allowed extra effort. It represents
|
||||
|
|
@ -180,6 +181,28 @@ public class Capacity {
|
|||
duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Is the provided duration below the allowed duration? In that case there
|
||||
* is still spare space for more allocations.
|
||||
* </p>
|
||||
* <p>
|
||||
* The allowed duration is infinite if this {@link Capacity} is
|
||||
* {@link #overAssignableWithoutLimit(boolean)} or the duration provided is
|
||||
* less than the sum of the standard plus allowed extra effort.
|
||||
* </p>
|
||||
*
|
||||
* @param assignedDuration
|
||||
* @return
|
||||
*/
|
||||
public boolean hasSpareSpaceForMoreAllocations(
|
||||
EffortDuration assignedDuration) {
|
||||
Validate.notNull(assignedDuration);
|
||||
return isOverAssignableWithoutLimit()
|
||||
|| assignedDuration.compareTo(standardEffort
|
||||
.plus(allowedExtraEffort)) < 0;
|
||||
}
|
||||
|
||||
public boolean allowsWorking() {
|
||||
return !getStandardEffort().isZero() || isOverAssignableWithoutLimit()
|
||||
|| !getAllowedExtraEffort().isZero();
|
||||
|
|
@ -192,4 +215,4 @@ public class Capacity {
|
|||
: allowedExtraEffort.multiplyBy(capacity));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -25,10 +25,15 @@ import static org.navalplanner.business.workingday.EffortDuration.seconds;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.navalplanner.business.calendars.entities.Capacity;
|
||||
import org.navalplanner.business.calendars.entities.ICalendar;
|
||||
import org.navalplanner.business.calendars.entities.ResourceCalendar;
|
||||
import org.navalplanner.business.calendars.entities.SameWorkHoursEveryDay;
|
||||
|
|
@ -88,6 +93,68 @@ public class EffortDistributor {
|
|||
this.duration = duration;
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public static EffortDuration sumDurations(
|
||||
List<ResourceWithAssignedDuration> withoutOvertime) {
|
||||
EffortDuration result = EffortDuration.zero();
|
||||
for (ResourceWithAssignedDuration each : withoutOvertime) {
|
||||
result = result.plus(each.duration);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static Map<Resource, ResourceWithAssignedDuration> byResource(
|
||||
Collection<? extends ResourceWithAssignedDuration> durations) {
|
||||
Map<Resource, ResourceWithAssignedDuration> result = new HashMap<Resource, ResourceWithAssignedDuration>();
|
||||
for (ResourceWithAssignedDuration each : durations) {
|
||||
result.put(each.resource, each);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IAssignedEffortForResource sumAssignedEffort(
|
||||
List<ResourceWithAssignedDuration> durations,
|
||||
final IAssignedEffortForResource assignedEffortForResource) {
|
||||
final Map<Resource, ResourceWithAssignedDuration> byResource = byResource(durations);
|
||||
return new IAssignedEffortForResource() {
|
||||
|
||||
@Override
|
||||
public EffortDuration getAssignedDurationAt(Resource resource,
|
||||
LocalDate day) {
|
||||
EffortDuration previouslyAssigned = assignedEffortForResource
|
||||
.getAssignedDurationAt(resource, day);
|
||||
ResourceWithAssignedDuration withDuration = byResource
|
||||
.get(resource);
|
||||
if (withDuration != null) {
|
||||
return previouslyAssigned.plus(withDuration.duration);
|
||||
}
|
||||
return previouslyAssigned;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static List<ResourceWithAssignedDuration> join(
|
||||
Collection<? extends ResourceWithAssignedDuration> a,
|
||||
Collection<ResourceWithAssignedDuration> b) {
|
||||
Map<Resource, ResourceWithAssignedDuration> result = byResource(a);
|
||||
Map<Resource, ResourceWithAssignedDuration> byResource = byResource(b);
|
||||
for (Entry<Resource, ResourceWithAssignedDuration> each : byResource
|
||||
.entrySet()) {
|
||||
Resource key = each.getKey();
|
||||
ResourceWithAssignedDuration value = each.getValue();
|
||||
if (result.containsKey(key)) {
|
||||
result.put(key, result.get(key).plus(value));
|
||||
} else {
|
||||
result.put(key, value);
|
||||
}
|
||||
}
|
||||
return new ArrayList<ResourceWithAssignedDuration>(result.values());
|
||||
}
|
||||
|
||||
ResourceWithAssignedDuration plus(ResourceWithAssignedDuration value) {
|
||||
return new ResourceWithAssignedDuration(
|
||||
this.duration.plus(value.duration), resource);
|
||||
}
|
||||
}
|
||||
|
||||
private static final ICalendar generateCalendarFor(Resource resource) {
|
||||
|
|
@ -138,6 +205,45 @@ public class EffortDistributor {
|
|||
this.calendar = generateCalendarFor(resource);
|
||||
}
|
||||
|
||||
ResourceWithAvailableCapacity withAvailableCapacityOn(LocalDate date,
|
||||
IAssignedEffortForResource assignedEffort) {
|
||||
EffortDuration capacity = calendar.getCapacityOn(PartialDay
|
||||
.wholeDay(date));
|
||||
EffortDuration assigned = assignedEffort.getAssignedDurationAt(
|
||||
resource, date);
|
||||
EffortDuration available = capacity.compareTo(assigned) > 0 ? capacity
|
||||
.minus(assigned)
|
||||
: EffortDuration.zero();
|
||||
return new ResourceWithAvailableCapacity(resource, available);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ResourceWithAvailableCapacity implements
|
||||
Comparable<ResourceWithAvailableCapacity> {
|
||||
|
||||
private final Resource resource;
|
||||
|
||||
private final EffortDuration available;
|
||||
|
||||
public ResourceWithAvailableCapacity(Resource resource,
|
||||
EffortDuration available) {
|
||||
Validate.notNull(resource);
|
||||
Validate.notNull(available);
|
||||
this.resource = resource;
|
||||
this.available = available;
|
||||
}
|
||||
|
||||
public ResourceWithAssignedDuration doBiggestAssignationPossible(
|
||||
EffortDuration remaining) {
|
||||
return new ResourceWithAssignedDuration(EffortDuration.min(
|
||||
remaining, available), resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ResourceWithAvailableCapacity o) {
|
||||
return available.compareTo(o.available);
|
||||
}
|
||||
}
|
||||
|
||||
private final List<ResourceWithDerivedData> resources;
|
||||
|
|
@ -161,25 +267,176 @@ public class EffortDistributor {
|
|||
}
|
||||
|
||||
|
||||
public List<ResourceWithAssignedDuration> distributeForDay(LocalDate day,
|
||||
public List<ResourceWithAssignedDuration> distributeForDay(LocalDate date,
|
||||
EffortDuration totalDuration) {
|
||||
List<ResourceWithDerivedData> resourcesAssignable = resourcesAssignableAt(day);
|
||||
List<ShareSource> shares = divisionAt(resourcesAssignable, day);
|
||||
List<ResourceWithDerivedData> resourcesAssignable = resourcesAssignableAt(date);
|
||||
List<ResourceWithAssignedDuration> withoutOvertime = assignAllPossibleWithoutOvertime(
|
||||
date, totalDuration, resourcesAssignable);
|
||||
EffortDuration remaining = totalDuration
|
||||
.minus(ResourceWithAssignedDuration
|
||||
.sumDurations(withoutOvertime));
|
||||
if (remaining.isZero()) {
|
||||
return withoutOvertime;
|
||||
}
|
||||
List<ResourceWithAssignedDuration> withOvertime = distributeInOvertimeForDayRemainingEffort(
|
||||
date, remaining,
|
||||
ResourceWithAssignedDuration.sumAssignedEffort(withoutOvertime,
|
||||
assignedEffortForResource), resourcesAssignable);
|
||||
return ResourceWithAssignedDuration.join(withoutOvertime, withOvertime);
|
||||
}
|
||||
|
||||
private List<ResourceWithDerivedData> resourcesAssignableAt(LocalDate day) {
|
||||
List<ResourceWithDerivedData> result = new ArrayList<ResourceWithDerivedData>();
|
||||
for (ResourceWithDerivedData each : resources) {
|
||||
if (resourceSelector.isSelectable(each.resource, day)) {
|
||||
result.add(each);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<ResourceWithAssignedDuration> assignAllPossibleWithoutOvertime(
|
||||
LocalDate date, EffortDuration totalDuration,
|
||||
List<ResourceWithDerivedData> resourcesAssignable) {
|
||||
List<ResourceWithAvailableCapacity> fromMoreToLessCapacity = resourcesFromMoreToLessCapacityAvailable(
|
||||
resourcesAssignable, date);
|
||||
EffortDuration remaining = totalDuration;
|
||||
List<ResourceWithAssignedDuration> result = new ArrayList<ResourceWithAssignedDuration>();
|
||||
for (ResourceWithAvailableCapacity each : fromMoreToLessCapacity) {
|
||||
if (!each.available.isZero()) {
|
||||
ResourceWithAssignedDuration r = each
|
||||
.doBiggestAssignationPossible(remaining);
|
||||
remaining = remaining.minus(r.duration);
|
||||
if (!r.duration.isZero()) {
|
||||
result.add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<ResourceWithAvailableCapacity> resourcesFromMoreToLessCapacityAvailable(
|
||||
List<ResourceWithDerivedData> resourcesAssignable, LocalDate date) {
|
||||
List<ResourceWithAvailableCapacity> result = new ArrayList<ResourceWithAvailableCapacity>();
|
||||
for (ResourceWithDerivedData each : resourcesAssignable) {
|
||||
result.add(each.withAvailableCapacityOn(date,
|
||||
assignedEffortForResource));
|
||||
}
|
||||
Collections.sort(result, Collections.reverseOrder());
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<ResourceWithAssignedDuration> distributeInOvertimeForDayRemainingEffort(
|
||||
LocalDate day, EffortDuration remainingDuration,
|
||||
IAssignedEffortForResource assignedEffortForEachResource,
|
||||
List<ResourceWithDerivedData> assignableResources) {
|
||||
List<ResourceWithAssignedDuration> remainingDistribution = suppressOverAssignationBeyondAvailableCapacity(
|
||||
day,
|
||||
assignedEffortForEachResource,
|
||||
distributeRemaining(day, remainingDuration,
|
||||
assignedEffortForEachResource, assignableResources));
|
||||
|
||||
EffortDuration durationDistributed = ResourceWithAssignedDuration
|
||||
.sumDurations(remainingDistribution);
|
||||
EffortDuration newRemaining = remainingDuration
|
||||
.minus(durationDistributed);
|
||||
assert newRemaining.compareTo(EffortDuration.zero()) >= 0;
|
||||
if (newRemaining.isZero()) {
|
||||
return remainingDistribution;
|
||||
}
|
||||
IAssignedEffortForResource newEffortForEachResource = ResourceWithAssignedDuration.sumAssignedEffort(
|
||||
remainingDistribution, assignedEffortForEachResource);
|
||||
|
||||
List<ResourceWithDerivedData> resourcesWithAvailableOvertime = withAvailableCapacity(day, newEffortForEachResource, assignableResources);
|
||||
if (resourcesWithAvailableOvertime.isEmpty()) {
|
||||
return remainingDistribution;
|
||||
}
|
||||
return ResourceWithAssignedDuration.join(
|
||||
remainingDistribution,
|
||||
distributeInOvertimeForDayRemainingEffort(day, newRemaining,
|
||||
newEffortForEachResource,
|
||||
resourcesWithAvailableOvertime));
|
||||
}
|
||||
|
||||
private List<ResourceWithAssignedDuration> suppressOverAssignationBeyondAvailableCapacity(
|
||||
LocalDate date,
|
||||
IAssignedEffortForResource assignedEffortForEachResource,
|
||||
List<ResourceWithAssignedDuration> resources) {
|
||||
List<ResourceWithAssignedDuration> result = new ArrayList<ResourceWithAssignedDuration>();
|
||||
for (ResourceWithAssignedDuration each : resources) {
|
||||
Resource resource = each.resource;
|
||||
ICalendar calendar = generateCalendarFor(resource);
|
||||
Capacity capacityWithOvertime = calendar
|
||||
.getCapacityWithOvertime(date);
|
||||
if (capacityWithOvertime.isOverAssignableWithoutLimit()) {
|
||||
result.add(each);
|
||||
} else {
|
||||
EffortDuration durationCanBeAdded = calculateDurationCanBeAdded(
|
||||
assignedEffortForEachResource.getAssignedDurationAt(
|
||||
resource, date), capacityWithOvertime,
|
||||
each.duration);
|
||||
if (!durationCanBeAdded.isZero()) {
|
||||
result.add(new ResourceWithAssignedDuration(
|
||||
durationCanBeAdded, resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private EffortDuration calculateDurationCanBeAdded(
|
||||
EffortDuration alreadyAssigned, Capacity capacityWithOvertime,
|
||||
EffortDuration newAddition) {
|
||||
EffortDuration maximum = capacityWithOvertime.getStandardEffort().plus(
|
||||
capacityWithOvertime.getAllowedExtraEffort());
|
||||
if (alreadyAssigned.compareTo(maximum) >= 0) {
|
||||
return EffortDuration.zero();
|
||||
} else {
|
||||
return EffortDuration.min(newAddition,
|
||||
maximum.minus(alreadyAssigned));
|
||||
}
|
||||
}
|
||||
|
||||
private List<ResourceWithDerivedData> withAvailableCapacity(LocalDate date,
|
||||
IAssignedEffortForResource assignedEffortForEachResource,
|
||||
List<ResourceWithDerivedData> assignableResources) {
|
||||
List<ResourceWithDerivedData> result = new ArrayList<ResourceWithDerivedData>();
|
||||
for (ResourceWithDerivedData each : assignableResources) {
|
||||
Capacity capacity = each.calendar.getCapacityWithOvertime(date);
|
||||
EffortDuration assignedEffort = assignedEffortForEachResource
|
||||
.getAssignedDurationAt(each.resource, date);
|
||||
if (capacity.hasSpareSpaceForMoreAllocations(assignedEffort)) {
|
||||
result.add(each);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<ResourceWithAssignedDuration> distributeRemaining(
|
||||
LocalDate day, EffortDuration remainingDuration,
|
||||
IAssignedEffortForResource assignedEffortForEachResource,
|
||||
List<ResourceWithDerivedData> resourcesWithAvailableOvertime) {
|
||||
List<ShareSource> shares = divisionAt(resourcesWithAvailableOvertime,
|
||||
assignedEffortForEachResource, day);
|
||||
ShareDivision currentDivision = ShareSource.all(shares);
|
||||
ShareDivision newDivison = currentDivision.plus(totalDuration.getSeconds());
|
||||
ShareDivision newDivison = currentDivision.plus(remainingDuration
|
||||
.getSeconds());
|
||||
int[] differences = currentDivision.to(newDivison);
|
||||
return ShareSource.durationsForEachResource(shares, differences,
|
||||
ResourceWithDerivedData.resources(resourcesAssignable));
|
||||
ResourceWithDerivedData
|
||||
.resources(resourcesWithAvailableOvertime));
|
||||
}
|
||||
|
||||
private List<ShareSource> divisionAt(
|
||||
List<ResourceWithDerivedData> resources, LocalDate day) {
|
||||
List<ResourceWithDerivedData> resources,
|
||||
IAssignedEffortForResource assignedEffortForEachResource,
|
||||
LocalDate day) {
|
||||
List<ShareSource> result = new ArrayList<ShareSource>();
|
||||
for (int i = 0; i < resources.size(); i++) {
|
||||
List<Share> shares = new ArrayList<Share>();
|
||||
Resource resource = resources.get(i).resource;
|
||||
ICalendar calendarForResource = resources.get(i).calendar;
|
||||
EffortDuration alreadyAssigned = assignedEffortForResource
|
||||
EffortDuration alreadyAssigned = assignedEffortForEachResource
|
||||
.getAssignedDurationAt(resource, day);
|
||||
final int alreadyAssignedSeconds = alreadyAssigned.getSeconds();
|
||||
Integer capacityEachOneSeconds = calendarForResource.asDurationOn(
|
||||
|
|
@ -197,16 +454,6 @@ public class EffortDistributor {
|
|||
return result;
|
||||
}
|
||||
|
||||
private List<ResourceWithDerivedData> resourcesAssignableAt(LocalDate day) {
|
||||
List<ResourceWithDerivedData> result = new ArrayList<ResourceWithDerivedData>();
|
||||
for (ResourceWithDerivedData each : resources) {
|
||||
if (resourceSelector.isSelectable(each.resource, day)) {
|
||||
result.add(each);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final ResourcesPerDay ONE = ResourcesPerDay.amount(1);
|
||||
|
||||
private static class ShareSource {
|
||||
|
|
@ -231,8 +478,11 @@ public class EffortDistributor {
|
|||
int sum = sumDifferences(differencesInSeconds, differencesIndex,
|
||||
differencesToTake);
|
||||
differencesIndex += differencesToTake;
|
||||
result.add(new ResourceWithAssignedDuration(seconds(sum),
|
||||
resource));
|
||||
ResourceWithAssignedDuration withAssignedDuration = new ResourceWithAssignedDuration(
|
||||
seconds(sum), resource);
|
||||
if (!withAssignedDuration.duration.isZero()) {
|
||||
result.add(withAssignedDuration);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package org.navalplanner.business.test.calendars.entities;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
@ -181,4 +182,30 @@ public class CapacityTest {
|
|||
a.withAllowedExtraEffort(hours(4)))
|
||||
.getAllowedExtraEffort(), equalTo(hours(4)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThereIsCapacityForMoreAllocations() {
|
||||
assertThat(Capacity.create(hours(8)).overAssignableWithoutLimit(true)
|
||||
.hasSpareSpaceForMoreAllocations(hours(10)), is(true));
|
||||
|
||||
Capacity notOverassignable = Capacity.create(hours(8))
|
||||
.overAssignableWithoutLimit(false);
|
||||
|
||||
assertFalse(notOverassignable
|
||||
.hasSpareSpaceForMoreAllocations(hours(10)));
|
||||
assertTrue(notOverassignable
|
||||
.hasSpareSpaceForMoreAllocations(hours(7)));
|
||||
assertFalse(notOverassignable
|
||||
.hasSpareSpaceForMoreAllocations(hours(8)));
|
||||
|
||||
Capacity withSomeExtraHours = notOverassignable
|
||||
.withAllowedExtraEffort(hours(2));
|
||||
|
||||
assertFalse(withSomeExtraHours
|
||||
.hasSpareSpaceForMoreAllocations(hours(10)));
|
||||
assertTrue(withSomeExtraHours
|
||||
.hasSpareSpaceForMoreAllocations(hours(7)));
|
||||
assertTrue(withSomeExtraHours
|
||||
.hasSpareSpaceForMoreAllocations(hours(8)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
package org.navalplanner.business.test.planner.entities;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.getCurrentArguments;
|
||||
import static org.easymock.EasyMock.isA;
|
||||
|
|
@ -512,7 +513,7 @@ public class GenericResourceAllocationTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void moreBusyResourcesAreGivenLessLoad() {
|
||||
public void itGivesAllTheLoadItCanToTheLessLoadedResource() {
|
||||
final int TASK_DURATION_DAYS = 4;
|
||||
givenBaseCalendarWithoutExceptions(8);
|
||||
LocalDate start = new LocalDate(2006, 10, 5);
|
||||
|
|
@ -526,13 +527,65 @@ public class GenericResourceAllocationTest {
|
|||
|
||||
List<GenericDayAssignment> assignmentsWorker1 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker1);
|
||||
assertThat(assignmentsWorker1, haveHours(3, 3, 3, 3));
|
||||
assertThat(assignmentsWorker1, haveHours(1, 1, 1, 1));
|
||||
List<GenericDayAssignment> assignmentsWorker2 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker2);
|
||||
assertThat(assignmentsWorker2, haveHours(0, 0, 0, 0));
|
||||
assertThat(assignmentsWorker2, haveHours());
|
||||
List<GenericDayAssignment> assignmentsWorker3 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker3);
|
||||
assertThat(assignmentsWorker3, haveHours(5, 5, 5, 5));
|
||||
assertThat(assignmentsWorker3, haveHours(7, 7, 7, 7));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesntSurpassTheExtraHours() {
|
||||
final int TASK_DURATION_DAYS = 4;
|
||||
givenBaseCalendarWithoutExceptions(8);
|
||||
LocalDate start = new LocalDate(2006, 10, 5);
|
||||
givenTaskWithStartAndEnd(toInterval(start,
|
||||
Period.days(TASK_DURATION_DAYS)));
|
||||
givenGenericResourceAllocationForTask(task);
|
||||
|
||||
Capacity workingDay = Capacity.create(hours(8));
|
||||
Capacity with2ExtraHours = workingDay
|
||||
.withAllowedExtraEffort(hours(2));
|
||||
givenCalendarsForResources(with2ExtraHours, with2ExtraHours,
|
||||
workingDay.overAssignableWithoutLimit(true));
|
||||
givenWorkersWithLoads(0, 0, 0);
|
||||
|
||||
genericResourceAllocation.forResources(workers).allocate(
|
||||
ResourcesPerDay.amount(4));
|
||||
|
||||
List<GenericDayAssignment> assignmentsWorker1 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker1);
|
||||
assertThat(assignmentsWorker1, haveHours(10, 10, 10, 10));
|
||||
List<GenericDayAssignment> assignmentsWorker2 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker2);
|
||||
assertThat(assignmentsWorker2, haveHours(10, 10, 10, 10));
|
||||
List<GenericDayAssignment> assignmentsWorker3 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker3);
|
||||
assertThat(assignmentsWorker3, haveHours(12, 12, 12, 12));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itGivesAllTheLoadItCanToTheLessLoadedResourceAndThenToTheNextOne() {
|
||||
final int TASK_DURATION_DAYS = 4;
|
||||
givenBaseCalendarWithoutExceptions(8);
|
||||
LocalDate start = new LocalDate(2006, 10, 5);
|
||||
givenTaskWithStartAndEnd(toInterval(start,
|
||||
Period.days(TASK_DURATION_DAYS)));
|
||||
givenGenericResourceAllocationForTask(task);
|
||||
givenWorkersWithLoads(0, 0, 0);
|
||||
|
||||
genericResourceAllocation.forResources(asList(worker1, worker2))
|
||||
.allocate(ResourcesPerDay.amount(2));
|
||||
|
||||
List<GenericDayAssignment> assignmentsWorker1 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker1);
|
||||
assertThat(assignmentsWorker1, haveHours(8, 8, 8, 8));
|
||||
List<GenericDayAssignment> assignmentsWorker2 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker2);
|
||||
assertThat(assignmentsWorker2, haveHours(8, 8, 8, 8));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -588,7 +641,7 @@ public class GenericResourceAllocationTest {
|
|||
assertThat(assignmentsWorker2, haveHours(4, 4, 4, 4));
|
||||
List<GenericDayAssignment> assignmentsWorker3 = genericResourceAllocation
|
||||
.getOrderedAssignmentsFor(worker3);
|
||||
assertThat(assignmentsWorker3, haveHours(0, 0, 0, 0));
|
||||
assertThat(assignmentsWorker3, haveHours());
|
||||
}
|
||||
|
||||
private void givenVirtualWorkerWithCapacityAndLoad(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue