001: /*
002: * <copyright>
003: * Copyright 2002-2003 BBNT Solutions, LLC
004: * under sponsorship of the Defense Advanced Research Projects Agency (DARPA).
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the Cougaar Open Source License as published by
008: * DARPA on the Cougaar Open Source Website (www.cougaar.org).
009: *
010: * THE COUGAAR SOFTWARE AND ANY DERIVATIVE SUPPLIED BY LICENSOR IS
011: * PROVIDED 'AS IS' WITHOUT WARRANTIES OF ANY KIND, WHETHER EXPRESS OR
012: * IMPLIED, INCLUDING (BUT NOT LIMITED TO) ALL IMPLIED WARRANTIES OF
013: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND WITHOUT
014: * ANY WARRANTIES AS TO NON-INFRINGEMENT. IN NO EVENT SHALL COPYRIGHT
015: * HOLDER BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT OR CONSEQUENTIAL
016: * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE OF DATA OR PROFITS,
017: * TORTIOUS CONDUCT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
018: * PERFORMANCE OF THE COUGAAR SOFTWARE.
019: * </copyright>
020: */
021:
022: package org.cougaar.logistics.plugin.inventory;
023:
024: import org.cougaar.core.util.UniqueObject;
025: import org.cougaar.core.blackboard.Publishable;
026: import org.cougaar.core.util.UID;
027: import org.cougaar.planning.servlet.data.xml.XMLWriter;
028: import org.cougaar.planning.servlet.data.xml.XMLable;
029:
030: import java.util.ArrayList;
031: import java.util.HashSet;
032: import java.util.Collection;
033: import java.util.Iterator;
034: import java.util.Date;
035:
036: import java.math.BigDecimal;
037:
038: /**
039: * ShortfallSummary is an object that summarizizes which inventories of
040: * a particular inventory have shortfall.
041: */
042:
043: public class ShortfallPeriod implements java.io.Serializable,
044: Publishable {
045:
046: private long startTime;
047: private long endTime;
048: private double totalShortfallDemand;
049: private double totalFilled;
050:
051: /**
052: * Constructor
053: */
054:
055: public ShortfallPeriod() {
056: }
057:
058: public ShortfallPeriod(long aStartTime, long anEndTime) {
059: this (aStartTime, anEndTime, 0.0d, 0.0d);
060: }
061:
062: public ShortfallPeriod(long aStartTime, long anEndTime,
063: double demand, double filled) {
064: startTime = aStartTime;
065: endTime = anEndTime;
066: totalShortfallDemand = demand;
067: totalFilled = filled;
068:
069: }
070:
071: /**
072: * The start time for the shortfall period
073: *
074: * @return long milliseconds since epoch time represnting date/time of the start of thr shortfall period
075: */
076: public long getStartTime() {
077: return startTime;
078: }
079:
080: /**
081: * The end time for the shortfall period
082: *
083: * @return long milliseconds since epoch time representing date/time of the end of the shortfall period
084: */
085: public long getEndTime() {
086: return endTime;
087: }
088:
089: /**
090: * The number gleaned from the InventoryBG of the total amount of demand during the time period of this ShortfallPeriod
091: *
092: * @return double The total amount of demand being asked of this inventory during this time period
093: */
094: public double getTotalDemand() {
095: return totalShortfallDemand;
096: }
097:
098: /**
099: * The total amount allocated as the filled amount of the asked for demand during this period. Should be less than
100: * the amount of demand, but could be equal due to a late delivery in an allocation result attached to one of the demand
101: * tasks within the shortfall period. Or if quiescence has not taken place yet and there is not allocation results on the
102: * demand.
103: *
104: * @return double The total amount of demand filled at this inventory over the course of the shortfall period.
105: */
106: public double getTotalFilled() {
107: return totalFilled;
108: }
109:
110: /**
111: * Get total demand rounded to integer or to the hundreths place
112: *
113: * @param roundToInt true if you want to round to an integer
114: * @return total demand rounded to the appropriate precision.
115: */
116: public double getRoundedTotalDemand(boolean roundToInt) {
117: return roundAppropriately(totalShortfallDemand, roundToInt);
118: }
119:
120: /**
121: * Get total demand rounded to an integer or to the hundreths place depending on the passed boolean
122: *
123: * @param roundToInt true if you want the filled demand rounded to an integer false if only to the hundreths place
124: * @return the double represent total filled demand.
125: */
126: public double getRoundedTotalFilled(boolean roundToInt) {
127: return roundAppropriately(totalFilled, roundToInt);
128: }
129:
130: /**
131: * Given the Milliseconds per bucket compute the total number of inventory buckets spanned by this ShortfallPeriod.
132: * A Bucket is the granularity at which we calculate the inventory numbers. If the bucket is an hour long then we
133: * add things up that fall within the same hour. If a day long demand coming in just after midnight and demand coming
134: * in before midnight of the next day is counted in the same bucket.
135: *
136: * @param msecPerBucket The number of milliseconds per inventory bucket
137: * @return int The number of buckets spanned.
138: */
139: public int getNumBuckets(long msecPerBucket) {
140: return ((int) (((endTime + 1) - startTime) / msecPerBucket));
141: }
142:
143: /**
144: * The shortfall qty is the total demand over this period minus the total filled by this period. Most times greater than zero
145: *
146: * @param roundToInt booean true if round to an integer otherwise round to hundreths
147: * @return double representing the integer or double rounded to the hundreths place
148: */
149: public double getShortfallQty(boolean roundToInt) {
150: return roundAppropriately(totalShortfallDemand - totalFilled,
151: roundToInt);
152: }
153:
154: /**
155: * The percent shortfall which is totalDemand - totalFilled/totalDemand * 100 (Ie the less that is filled the greater
156: * the qty percent shortfall.
157: *
158: * @return the double representing total percent shortfall for this period
159: */
160: public double getPercentShortfall() {
161: if (getTotalDemand() > 0.0d) {
162: return roundToInt((getShortfallQty(false) / getTotalDemand()) * 100);
163: }
164: return 0.0d;
165: }
166:
167: /**
168: * Setters for the total demand
169: *
170: * @param demand The total demand for this shortfall period
171: */
172: public void setTotalDemand(double demand) {
173: totalShortfallDemand = demand;
174: }
175:
176: /**
177: * Setters for the total filled
178: *
179: * @param filled The total amount of demand filled over this shortfall period.
180: */
181: public void setTotalFilled(double filled) {
182: totalFilled = filled;
183: }
184:
185: /**
186: * The string representation of all the fields in this object
187: *
188: * @return String - The string representation of all the fields in this object
189: */
190: public String toString() {
191: StringBuffer sb = new StringBuffer("");
192: sb
193: .append("\nStartTime="
194: + TimeUtils.dateString(getStartTime()));
195: sb.append(" - EndTime=" + TimeUtils.dateString(getEndTime()));
196: sb.append("\nShortfallQty=" + getShortfallQty(false));
197: sb.append(",PercentShortfall=" + getPercentShortfall());
198: return sb.toString();
199: }
200:
201: /**
202: * The method to compare two shortfall period. If all the slot values are the same then they are equal periods.
203: *
204: * @param sp other shortfall period
205: * @return boolean true if all the slots are equivilent
206: */
207: public boolean equals(ShortfallPeriod sp) {
208: return ((getStartTime() == sp.getStartTime())
209: && (getEndTime() == sp.getEndTime())
210: && (getTotalDemand() == sp.getTotalDemand()) && (getTotalFilled() == sp
211: .getTotalFilled()));
212: }
213:
214: /**
215: * Helper rounding function
216: *
217: * @param aNum Number to round
218: * @param roundToInt true if round to integer false yields something rounded to the hundreths place
219: * @return double integer or double value rounded to hundreths
220: */
221: public static double roundAppropriately(double aNum,
222: boolean roundToInt) {
223: if (roundToInt) {
224: return roundToInt(aNum);
225: } else {
226: return roundToHundreths(aNum);
227: }
228:
229: }
230:
231: /**
232: * Round to the hundreths place the passed in number
233: *
234: * @param aNum - Number to be rounded to hundreths place.
235: * @return The passed in number rounded to the hundreths place.
236: */
237: public static double roundToHundreths(double aNum) {
238: BigDecimal roundedQty = ((new BigDecimal((double) aNum))
239: .setScale(2, BigDecimal.ROUND_HALF_EVEN));
240: return roundedQty.doubleValue();
241: }
242:
243: /**
244: * Round to an integer the passed in number
245: *
246: * @param aNum - Number to be rounded
247: * @return double an integer value.
248: */
249: public static double roundToInt(double aNum) {
250: BigDecimal roundedQty = ((new BigDecimal((double) aNum))
251: .setScale(0, BigDecimal.ROUND_HALF_EVEN));
252: return roundedQty.doubleValue();
253: }
254:
255: /**
256: * Indicates that this is a persistable object
257: *
258: * @return true
259: */
260: public boolean isPersistable() {
261: return true;
262: }
263: }
|