com.softicar.platform.common.container.schedule.coverage.ScheduleCoverageComputer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of platform-common Show documentation
Show all versions of platform-common Show documentation
The SoftiCAR Platform is a lightweight, Java-based library to create interactive business web applications.
package com.softicar.platform.common.container.schedule.coverage;
import com.softicar.platform.common.container.matrix.IImmutableMatrix;
import com.softicar.platform.common.math.arithmetic.IArithmetic;
import java.util.Set;
import java.util.TreeSet;
/**
* Computes the coverage of a work schedule over a to-do schedule.
*
* @author Oliver Richers
*/
public class ScheduleCoverageComputer> {
protected final IImmutableMatrix todoSchedule;
protected final IImmutableMatrix workSchedule;
protected final IArithmetic arithmetic;
protected final ScheduleCoverage todoCoverage;
protected final ScheduleCoverage workCoverage;
public ScheduleCoverageComputer(IImmutableMatrix todoSchedule, IImmutableMatrix workSchedule,
IArithmetic arithmetic) {
this.todoSchedule = todoSchedule;
this.workSchedule = workSchedule;
this.arithmetic = arithmetic;
this.todoCoverage = new ScheduleCoverage<>(arithmetic);
this.workCoverage = new ScheduleCoverage<>(arithmetic);
}
public Set getAllRows() {
Set rows = new TreeSet<>();
rows.addAll(todoSchedule.getRows());
rows.addAll(workSchedule.getRows());
return rows;
}
public ScheduleCoverageComputer compute() {
for (Row row: getAllRows()) {
new RowCoverageComputer(row).compute();
}
return this;
}
public void computeRow(Row row) {
this.todoCoverage.resetRow(row);
this.workCoverage.resetRow(row);
new RowCoverageComputer(row).compute();
}
public ScheduleCoverage getTodoCoverage() {
return todoCoverage;
}
public ScheduleCoverage getWorkCoverage() {
return workCoverage;
}
private class RowCoverageComputer {
private final ScheduleCellIterator todoIterator;
private final ScheduleCellIterator workIterator;
private Quantity backlog;
public RowCoverageComputer(Row row) {
this.todoIterator = new ScheduleCellIterator<>(todoSchedule, arithmetic, row);
this.workIterator = new ScheduleCellIterator<>(workSchedule, arithmetic, row);
this.backlog = arithmetic.getZero();
}
public void compute() {
while (todoIterator.gatherQuantity() && workIterator.gatherQuantity()) {
Quantity todoQuantity = todoIterator.getQuantity();
Quantity workQuantity = workIterator.getQuantity();
if (isNegative(todoQuantity)) {
handleNegativeTodoQuantity();
} else if (isNegative(workQuantity)) {
handleNegativeWorkQuantity(workQuantity);
} else if (isPositive(backlog)) {
handleBacklog();
} else {
Quantity minimum = getMinimum(todoQuantity, workQuantity);
todoIterator.transferToCoverage(todoCoverage, workIterator.getColumn(), minimum);
workIterator.transferToCoverage(workCoverage, todoIterator.getColumn(), minimum);
}
}
// gather remaining to-do and work quantities
gatherRemainingQuantities(todoIterator, todoCoverage);
gatherRemainingQuantities(workIterator, workCoverage);
}
private void handleNegativeTodoQuantity() {
throw new IllegalArgumentException(
String
.format(
"Got negative to-do quantity '%s' for row '%s' and column '%s'. Quantities of the to-do schedule may not be negative.",
todoIterator.getQuantity(),
todoIterator.getRow(),
todoIterator.getColumn()));
}
private void handleNegativeWorkQuantity(Quantity workQuantity) {
backlog = arithmetic.plus(backlog, arithmetic.negate(workQuantity));
workIterator.transferToCoverage(workCoverage, workQuantity);
}
private void handleBacklog() {
Quantity minimum = getMinimum(backlog, workIterator.getQuantity());
backlog = arithmetic.minus(backlog, minimum);
workIterator.transferToCoverage(workCoverage, minimum);
}
private void gatherRemainingQuantities(ScheduleCellIterator iterator, ScheduleCoverage coverage) {
while (iterator.gatherQuantity()) {
iterator.transferToCoverage(coverage, iterator.getQuantity());
}
}
private boolean isPositive(Quantity quantity) {
return arithmetic.isLess(arithmetic.getZero(), quantity);
}
private boolean isNegative(Quantity quantity) {
return arithmetic.isLess(quantity, arithmetic.getZero());
}
private Quantity getMinimum(Quantity a, Quantity b) {
return arithmetic.isLess(a, b)? a : b;
}
}
}