/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.business.workingday;
import java.math.BigDecimal;
import java.math.RoundingMode;
import org.apache.commons.lang3.Validate;
import org.libreplan.business.common.ProportionalDistributor;
import org.libreplan.business.workingday.EffortDuration.Granularity;
public class ResourcesPerDay {
public static class ResourcesPerDayDistributor {
private final ProportionalDistributor distributor;
private ResourcesPerDayDistributor(ProportionalDistributor distributor) {
this.distributor = distributor;
}
public ResourcesPerDay[] distribute(ResourcesPerDay total) {
int[] shares = distributor.distribute(toIntFormat(total));
ResourcesPerDay[] result = new ResourcesPerDay[shares.length];
for (int i = 0; i < result.length; i++) {
result[i] = backToResourcePerDay(shares[i]);
}
return result;
}
}
public static ResourcesPerDayDistributor distributor(
ResourcesPerDay... resourcesPerDay) {
ProportionalDistributor distributor = ProportionalDistributor
.create(asInts(resourcesPerDay));
return new ResourcesPerDayDistributor(distributor);
}
public static ResourcesPerDayDistributor distributor(
ProportionalDistributor distributor) {
return new ResourcesPerDayDistributor(distributor);
}
private static int[] asInts(ResourcesPerDay[] resourcesPerDay) {
int[] result = new int[resourcesPerDay.length];
for (int i = 0; i < resourcesPerDay.length; i++) {
result[i] = toIntFormat(resourcesPerDay[i]);
}
return result;
}
private static int toIntFormat(ResourcesPerDay each) {
return each.amount.unscaledValue().intValue();
}
private static ResourcesPerDay backToResourcePerDay(int integerFormat) {
return amount(new BigDecimal(integerFormat).movePointLeft(4));
}
public static ResourcesPerDay calculateFrom(EffortDuration durationWorking,
EffortDuration durationWorkable) {
return amount(new BigDecimal(durationWorking.getSeconds()).divide(
new BigDecimal(durationWorkable.getSeconds()), 4,
RoundingMode.HALF_UP));
}
public static ResourcesPerDay amount(int amount) {
return new ResourcesPerDay(new BigDecimal(amount));
}
public static ResourcesPerDay amount(BigDecimal decimal) {
return new ResourcesPerDay(decimal);
}
private final BigDecimal amount;
private ResourcesPerDay(BigDecimal amount) {
Validate.isTrue(amount.intValue() >= 0);
this.amount = amount.setScale(4, RoundingMode.HALF_UP);
}
public BigDecimal getAmount() {
return amount;
}
public EffortDuration asDurationGivenWorkingDayOf(
EffortDuration resourceWorkingDayDuration) {
BigDecimal multiply = getAmount().multiply(
new BigDecimal(resourceWorkingDayDuration.getSeconds()));
if (multiply.compareTo(BigDecimal.ZERO) > 0) {
return EffortDuration.elapsing(Math.max(1,
multiply.setScale(0, RoundingMode.HALF_UP).intValue()),
Granularity.SECONDS);
} else {
return EffortDuration.zero();
}
}
@Override
public int hashCode() {
return amount.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof ResourcesPerDay) {
ResourcesPerDay other = (ResourcesPerDay) obj;
return amount.equals(other.getAmount());
}
return false;
}
public boolean isZero() {
BigDecimal withoutDecimalpart = amount.movePointRight(4);
return withoutDecimalpart.intValue() == 0;
}
@Override
public String toString() {
return amount.toString();
}
}