ItEr49S10CUVisualizacionResponsabilidadesTRaballoNaPlanificacionItEr48S10: Changing the way hours are distributed.
If some row cannot be satisfied the whole hours are distributed among the remaining ones and so on.
This commit is contained in:
parent
dcb1b1aba5
commit
41576f6bb5
1 changed files with 127 additions and 60 deletions
|
|
@ -29,6 +29,7 @@ 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.planner.entities.DayAssignment;
|
||||
import org.navalplanner.business.planner.entities.ResourceAllocation;
|
||||
|
|
@ -57,29 +58,30 @@ public abstract class AllocatorForSpecifiedResourcesPerDayAndHours {
|
|||
}
|
||||
|
||||
public LocalDate untilAllocating(int hoursToAllocate) {
|
||||
LocalDate start = LocalDate.fromDateFields(task.getStartDate());
|
||||
int i = 0;
|
||||
int maxDaysElapsed = 0;
|
||||
for (Integer each : hoursForEachAllocation(hoursToAllocate)) {
|
||||
ResourcesPerDayModification currentAllocation = allocations.get(i);
|
||||
int daysElapsedForCurrent = untilAllocating(currentAllocation, each);
|
||||
for (HoursPerAllocation each : hoursPerAllocation(start,
|
||||
hoursToAllocate)) {
|
||||
int daysElapsedForCurrent = untilAllocating(start, each.allocation,
|
||||
each.hours);
|
||||
maxDaysElapsed = Math.max(maxDaysElapsed, daysElapsedForCurrent);
|
||||
i++;
|
||||
}
|
||||
setAssignmentsForEachAllocation();
|
||||
LocalDate start = LocalDate.fromDateFields(task.getStartDate());
|
||||
return start.plusDays(maxDaysElapsed);
|
||||
}
|
||||
|
||||
private int untilAllocating(
|
||||
private List<HoursPerAllocation> hoursPerAllocation(LocalDate start,
|
||||
int toBeAssigned) {
|
||||
return new HoursPerAllocationCalculator(allocations)
|
||||
.calculateHoursPerAllocation(start, toBeAssigned);
|
||||
}
|
||||
|
||||
private int untilAllocating(LocalDate start,
|
||||
ResourcesPerDayModification resourcesPerDayModification,
|
||||
Integer hoursToAllocate) {
|
||||
int hoursRemaining = hoursToAllocate;
|
||||
LocalDate start = new LocalDate(task.getStartDate().getTime());
|
||||
if (!thereAreAvailableHoursFrom(start, resourcesPerDayModification,
|
||||
hoursToAllocate)) {
|
||||
markUnsatisfied(resourcesPerDayModification.getBeingModified());
|
||||
return 0;
|
||||
}
|
||||
int day = 0;
|
||||
while (hoursRemaining > 0) {
|
||||
LocalDate current = start.plusDays(day);
|
||||
|
|
@ -126,65 +128,130 @@ public abstract class AllocatorForSpecifiedResourcesPerDayAndHours {
|
|||
return DayAssignment.sum(newAssignments);
|
||||
}
|
||||
|
||||
private List<Integer> hoursForEachAllocation(int toBeAssigned) {
|
||||
BigDecimal[] limits = new BigDecimal[allocations.size()];
|
||||
BigDecimal sumAll = sumAll();
|
||||
for (int i = 0; i < limits.length; i++) {
|
||||
BigDecimal amount = allocations.get(i).getGoal()
|
||||
.getAmount();
|
||||
limits[i] = amount.divide(sumAll, RoundingMode.DOWN).multiply(
|
||||
new BigDecimal(toBeAssigned));
|
||||
}
|
||||
final int remainder = toBeAssigned - sumIntegerParts(limits);
|
||||
return distributeRemainder(limits, remainder);
|
||||
}
|
||||
private static class HoursPerAllocation {
|
||||
final int hours;
|
||||
|
||||
private List<Integer> distributeRemainder(BigDecimal[] decimals,
|
||||
final int remainder) {
|
||||
for (int i = 0; i < remainder; i++) {
|
||||
int position = positionOfBiggestDecimalPart(decimals);
|
||||
decimals[position] = new BigDecimal(
|
||||
decimals[position].intValue() + 1);
|
||||
}
|
||||
return asIntegers(decimals);
|
||||
}
|
||||
final ResourcesPerDayModification allocation;
|
||||
|
||||
private List<Integer> asIntegers(BigDecimal[] decimals) {
|
||||
Integer[] result = new Integer[decimals.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = decimals[i].intValue();
|
||||
private HoursPerAllocation(int hours,
|
||||
ResourcesPerDayModification allocation) {
|
||||
this.hours = hours;
|
||||
this.allocation = allocation;
|
||||
}
|
||||
return Arrays.asList(result);
|
||||
}
|
||||
|
||||
private int positionOfBiggestDecimalPart(BigDecimal[] decimals) {
|
||||
int result = 0;
|
||||
BigDecimal currentBiggestDecimalPart = new BigDecimal(0);
|
||||
for (int i = 0; i < decimals.length; i++) {
|
||||
BigDecimal fractionalPart = decimals[i].subtract(new BigDecimal(
|
||||
decimals[i].intValue()));
|
||||
if (currentBiggestDecimalPart.compareTo(fractionalPart) < 0) {
|
||||
currentBiggestDecimalPart = fractionalPart;
|
||||
result = i;
|
||||
public static List<HoursPerAllocation> wrap(
|
||||
List<ResourcesPerDayModification> allocations,
|
||||
List<Integer> hours) {
|
||||
Validate.isTrue(hours.size() == allocations.size());
|
||||
int i = 0;
|
||||
List<HoursPerAllocation> result = new ArrayList<HoursPerAllocation>();
|
||||
for(i = 0; i < allocations.size(); i++){
|
||||
result.add(new HoursPerAllocation(hours.get(i), allocations
|
||||
.get(i)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int sumIntegerParts(BigDecimal[] decimals) {
|
||||
int sum = 0;
|
||||
for (BigDecimal decimal : decimals) {
|
||||
sum += decimal.intValue();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
private class HoursPerAllocationCalculator {
|
||||
private List<ResourcesPerDayModification> allocations;
|
||||
|
||||
private BigDecimal sumAll() {
|
||||
BigDecimal result = new BigDecimal(0);
|
||||
for (ResourcesPerDayModification r : allocations) {
|
||||
result = result.add(r.getGoal().getAmount());
|
||||
private HoursPerAllocationCalculator(
|
||||
List<ResourcesPerDayModification> allocations) {
|
||||
this.allocations = new ArrayList<ResourcesPerDayModification>(
|
||||
allocations);
|
||||
}
|
||||
return result;
|
||||
|
||||
public List<HoursPerAllocation> calculateHoursPerAllocation(
|
||||
LocalDate start, int toAssign) {
|
||||
do {
|
||||
List<Integer> hours = calculateHours(toAssign);
|
||||
List<HoursPerAllocation> result = HoursPerAllocation.wrap(
|
||||
allocations, hours);
|
||||
List<ResourcesPerDayModification> unsatisfied = getUnsatisfied(
|
||||
start, result);
|
||||
if (unsatisfied.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
for (ResourcesPerDayModification each : unsatisfied) {
|
||||
markUnsatisfied(each.getBeingModified());
|
||||
}
|
||||
allocations.removeAll(unsatisfied);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
private List<ResourcesPerDayModification> getUnsatisfied(
|
||||
LocalDate start, List<HoursPerAllocation> hoursPerAllocations) {
|
||||
List<ResourcesPerDayModification> cannotSatisfy = new ArrayList<ResourcesPerDayModification>();
|
||||
for (HoursPerAllocation each : hoursPerAllocations) {
|
||||
if (!thereAreAvailableHoursFrom(start, each.allocation,
|
||||
each.hours)) {
|
||||
cannotSatisfy.add(each.allocation);
|
||||
}
|
||||
}
|
||||
return cannotSatisfy;
|
||||
}
|
||||
|
||||
private List<Integer> calculateHours(int toAssign) {
|
||||
BigDecimal[] limits = new BigDecimal[allocations.size()];
|
||||
BigDecimal sumAll = sumAll();
|
||||
for (int i = 0; i < limits.length; i++) {
|
||||
BigDecimal amount = allocations.get(i).getGoal().getAmount();
|
||||
limits[i] = amount.divide(sumAll, RoundingMode.DOWN).multiply(
|
||||
new BigDecimal(toAssign));
|
||||
}
|
||||
final int remainder = toAssign - sumIntegerParts(limits);
|
||||
return distributeRemainder(limits, remainder);
|
||||
}
|
||||
|
||||
private List<Integer> distributeRemainder(BigDecimal[] decimals,
|
||||
final int remainder) {
|
||||
for (int i = 0; i < remainder; i++) {
|
||||
int position = positionOfBiggestDecimalPart(decimals);
|
||||
decimals[position] = new BigDecimal(decimals[position]
|
||||
.intValue() + 1);
|
||||
}
|
||||
return asIntegers(decimals);
|
||||
}
|
||||
|
||||
private List<Integer> asIntegers(BigDecimal[] decimals) {
|
||||
Integer[] result = new Integer[decimals.length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = decimals[i].intValue();
|
||||
}
|
||||
return Arrays.asList(result);
|
||||
}
|
||||
|
||||
private int positionOfBiggestDecimalPart(BigDecimal[] decimals) {
|
||||
int result = 0;
|
||||
BigDecimal currentBiggestDecimalPart = new BigDecimal(0);
|
||||
for (int i = 0; i < decimals.length; i++) {
|
||||
BigDecimal fractionalPart = decimals[i]
|
||||
.subtract(new BigDecimal(decimals[i].intValue()));
|
||||
if (currentBiggestDecimalPart.compareTo(fractionalPart) < 0) {
|
||||
currentBiggestDecimalPart = fractionalPart;
|
||||
result = i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int sumIntegerParts(BigDecimal[] decimals) {
|
||||
int sum = 0;
|
||||
for (BigDecimal decimal : decimals) {
|
||||
sum += decimal.intValue();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private BigDecimal sumAll() {
|
||||
BigDecimal result = new BigDecimal(0);
|
||||
for (ResourcesPerDayModification r : allocations) {
|
||||
result = result.add(r.getGoal().getAmount());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue