001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.logistics.ui.inventory;
028:
029: import java.util.ArrayList;
030: import java.util.Date;
031:
032: import com.klg.jclass.chart.ChartDataModel;
033: import com.klg.jclass.chart.LabelledChartDataModel;
034: import com.klg.jclass.chart.ChartDataSupport;
035: import com.klg.jclass.chart.ChartDataEvent;
036: import com.klg.jclass.chart.ChartDataManageable;
037: import com.klg.jclass.chart.ChartDataManager;
038:
039: import org.cougaar.util.log.Logging;
040: import org.cougaar.util.log.Logger;
041:
042: import org.cougaar.logistics.plugin.inventory.LogisticsInventoryFormatter;
043:
044: import org.cougaar.logistics.ui.inventory.data.InventoryData;
045: import org.cougaar.logistics.ui.inventory.data.InventoryProjTask;
046: import org.cougaar.logistics.ui.inventory.data.InventoryTask;
047: import org.cougaar.logistics.ui.inventory.data.InventoryProjAR;
048: import org.cougaar.logistics.ui.inventory.data.InventoryScheduleHeader;
049: import org.cougaar.logistics.ui.inventory.data.InventoryScheduleElement;
050:
051: import org.cougaar.util.TimeSpanSet;
052:
053: /**
054: * <pre>
055: *
056: * The ProjectionsChartDataModel is the ChartDataModel for the
057: * all projection tasks. A Schedule of projections and their
058: * corresponding allocation results are given as the
059: * values to compute into the x and y coordinates for the
060: * chart. If the chart is type of resupply then we calculate
061: * the last corresponding actual date of resupply, and only use
062: * projections and allocation results found after that date.
063: * Otherwise it is counted demand schedules where we have to
064: * sum the actual sum in the same bucket. Either way this
065: * chartDataModel depends on either the actual schedule, or
066: * the actual schedules chart data model.
067: *
068: *
069: * @see InventoryBaseChartDataModel
070: *
071: **/
072:
073: public class ProjectionsChartDataModel extends
074: InventoryBaseChartDataModel {
075:
076: protected String projScheduleName;
077: protected String projARScheduleName;
078: protected String reqScheduleName;
079: protected RequisitionsChartDataModel reqDataModel;
080: protected boolean resupply;
081:
082: protected double projYValues[][];
083:
084: public static final String PROJECTION_SERIES_LABEL = "Projection";
085: public static final String PROJECTION_ALLOCATION_SERIES_LABEL = "Projection Response";
086: public static final String PROJECTION_LEGEND = "";
087:
088: public ProjectionsChartDataModel(String aProjScheduleName,
089: String aProjARScheduleName, String aReqScheduleName,
090: RequisitionsChartDataModel aReqDataModel, boolean isResupply) {
091: this (PROJECTION_LEGEND, aProjScheduleName, aProjARScheduleName,
092: aReqScheduleName, aReqDataModel, isResupply);
093: }
094:
095: public ProjectionsChartDataModel(String legendTitle,
096: String projSchedule, String projARSchedule,
097: String aReqScheduleName,
098: RequisitionsChartDataModel aReqDataModel, boolean isResupply) {
099: this (null, projSchedule, projARSchedule, legendTitle,
100: aReqScheduleName, aReqDataModel, isResupply);
101: }
102:
103: public ProjectionsChartDataModel(InventoryData data,
104: String projSchedule, String projARSchedule,
105: String theLegendTitle, String aReqScheduleName,
106: RequisitionsChartDataModel aReqDataModel, boolean isResupply) {
107: inventory = data;
108: legendTitle = theLegendTitle;
109: projScheduleName = projSchedule;
110: projARScheduleName = projARSchedule;
111: reqScheduleName = aReqScheduleName;
112: reqDataModel = aReqDataModel;
113: resupply = isResupply;
114:
115: nSeries = 2;
116: scheduleNames = new String[2];
117: scheduleNames[0] = projScheduleName;
118: scheduleNames[1] = projARScheduleName;
119: seriesLabels = new String[2];
120: seriesLabels[0] = PROJECTION_SERIES_LABEL;
121: seriesLabels[1] = PROJECTION_ALLOCATION_SERIES_LABEL;
122: logger = Logging.getLogger(this );
123: initValues();
124: }
125:
126: public void setValues() {
127: if (valuesSet)
128: return;
129: setProjectionValues();
130: valuesSet = true;
131: }
132:
133: public void setProjectionValues() {
134:
135: if (inventory == null) {
136: xvalues = new double[nSeries][0];
137: yvalues = new double[nSeries][0];
138: projYValues = new double[nSeries][0];
139: return;
140: }
141:
142: InventoryScheduleHeader schedHeader = (InventoryScheduleHeader) inventory
143: .getSchedules().get(projScheduleName);
144: ArrayList projections = schedHeader.getSchedule();
145: schedHeader = (InventoryScheduleHeader) inventory
146: .getSchedules().get(projARScheduleName);
147: ArrayList projARs = schedHeader.getSchedule();
148: schedHeader = (InventoryScheduleHeader) inventory
149: .getSchedules().get(reqScheduleName);
150: ArrayList requisitions = schedHeader.getSchedule();
151: long maxReqEndTime = 0;
152:
153: if (resupply) {
154: for (int i = 0; i < requisitions.size(); i++) {
155: InventoryTask task = (InventoryTask) requisitions
156: .get(i);
157: long endTime = task.getEndTime();
158: maxReqEndTime = Math.max(endTime, maxReqEndTime);
159: }
160: }
161:
162: computeCriticalNValues();
163:
164: xvalues = new double[nSeries][nValues];
165: yvalues = new double[nSeries][nValues];
166: projYValues = new double[nSeries][nValues];
167: //initZeroYVal(nValues);
168:
169: for (int i = 0; i < nSeries; i++) {
170: for (int j = 0; j < nValues; j++) {
171: xvalues[i][j] = minBucket + (j * bucketDays);
172: yvalues[i][j] = 0;
173: projYValues[i][j] = 0;
174: }
175: }
176:
177: //Explode into buckets
178: ArrayList buckets = new ArrayList();
179: ArrayList bucketARs = new ArrayList();
180: for (int i = 0; i < projections.size(); i++) {
181: InventoryProjTask projTask = (InventoryProjTask) projections
182: .get(i);
183: buckets.addAll(projTask.explodeToBuckets(bucketSize));
184: }
185: for (int i = 0; i < projARs.size(); i++) {
186: InventoryProjAR projAR = (InventoryProjAR) projARs.get(i);
187: bucketARs.addAll(projAR.explodeToBuckets(bucketSize));
188: }
189:
190: for (int i = 0; i < buckets.size(); i++) {
191: InventoryProjTask task = (InventoryProjTask) buckets.get(i);
192: long endTime = task.getEndTime();
193: long startTime = task.getStartTime();
194: if (!resupply
195: || (startTime >= (maxReqEndTime + bucketSize))) {
196: int endBucket = (int) computeBucketFromTime(endTime);
197: int graphBucket = (endBucket - minBucket) / bucketDays;
198: if (graphBucket < 0)
199: logger
200: .error("Array out of bounds alright. The Graphday is negative");
201: if (graphBucket < nValues)
202: projYValues[0][graphBucket] += (task.getDailyRate() * unitFactor);
203: else {
204: if (logger.isInfoEnabled()) {
205: logger
206: .info("ProjectionsChartDataModel:Index Out of bounds on the tasks - falling off the end. Length "
207: + nValues
208: + " and graph day is: "
209: + graphBucket);
210: }
211: }
212: }
213: }
214:
215: for (int i = 0; i < bucketARs.size(); i++) {
216: InventoryProjAR ar = (InventoryProjAR) bucketARs.get(i);
217: if (ar.isSuccess()) {
218: long endTime = ar.getEndTime();
219: long startTime = ar.getStartTime();
220: if (!resupply
221: || (startTime >= (maxReqEndTime + bucketSize))) {
222: int endBucket = (int) computeBucketFromTime(endTime);
223: int graphBucket = (endBucket - minBucket)
224: / bucketDays;
225: if (graphBucket < 0)
226: logger
227: .error("Array out of bounds alright. The Graphday is negative");
228: if (graphBucket < nValues)
229: projYValues[1][graphBucket] += (ar
230: .getDailyRate() * unitFactor);
231: else {
232: if (logger.isInfoEnabled()) {
233: logger
234: .info("ProjectionsChartDataModel:Index Out of bounds on the ARs - falling off the end. Length "
235: + nValues
236: + " and graph day is: "
237: + graphBucket);
238: }
239: }
240: }
241: }
242: }
243:
244: reqDataModel.resetInventory(inventory);
245: for (int i = 0; i < nSeries; i++) {
246: for (int j = 0; j < nValues; j++) {
247: if (xvalues[i][j] == reqDataModel.getXSeries(i)[j]) {
248: yvalues[i][j] = projYValues[i][j]
249: + reqDataModel.getYSeries(i)[j];
250: } else {
251: throw new RuntimeException(
252: "ProjectionsChartDataModel:Accccch! Mis-matching dates between two views...");
253: }
254: }
255: }
256:
257: }
258:
259: /**
260: * Retrieves the specified y-value series
261: * The nth asset.
262: * This returns the nominal getYSeries of the super class
263: * @param index data series index
264: * @return array of double values representing y-value data
265: */
266: public synchronized double[] getRealYSeries(int index) {
267: initValues();
268: if (projYValues == null) {
269: logger
270: .error("InventoryChartDataModel ERROR getRealYSeries has no projYValues?");
271: }
272: return projYValues[index];
273:
274: }
275:
276: }
|