0001: /*
0002: * <copyright>
0003: *
0004: * Copyright 1997-2004 BBNT Solutions, LLC
0005: * under sponsorship of the Defense Advanced Research Projects
0006: * Agency (DARPA).
0007: *
0008: * You can redistribute this software and/or modify it under the
0009: * terms of the Cougaar Open Source License as published on the
0010: * Cougaar Open Source Website (www.cougaar.org).
0011: *
0012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023: *
0024: * </copyright>
0025: */
0026:
0027: package org.cougaar.logistics.plugin.inventory;
0028:
0029: import java.util.*;
0030:
0031: import org.cougaar.logistics.ldm.Constants;
0032: import org.cougaar.glm.ldm.asset.Inventory;
0033: import org.cougaar.glm.ldm.plan.AlpineAspectType;
0034: import org.cougaar.glm.ldm.plan.ObjectScheduleElement;
0035:
0036: import org.cougaar.planning.plugin.util.PluginHelper;
0037:
0038: import org.cougaar.planning.ldm.plan.*;
0039: import org.cougaar.planning.ldm.asset.TypeIdentificationPG;
0040:
0041: import org.cougaar.planning.ldm.measure.*;
0042:
0043: /** AllocationAssessor module is a module of the InventoryPlugin looks at
0044: * Refill results and Inventory levels to allocate Withdraws
0045: * against the Inventories.
0046: * Right now this is implemented with first come first serve, but it
0047: * should be changed to allocate withdraws that have the highest score
0048: * first where the score is something like quantity * time late or
0049: * scoring function scores.
0050: * Note that this allocator does NOT allocate split shipments.
0051: **/
0052:
0053: public class AllocationAssessor extends InventoryLevelGenerator {
0054: public class AllocPhase {
0055: public int startBucket; // first bucket where allocation occurs
0056: public int endBucket; // bucket beyond where allocation occurs
0057: public double amount; //amount allocated (per bucket) in the phase
0058:
0059: public AllocPhase(int startBucket, double amount) {
0060: this .startBucket = startBucket;
0061: this .endBucket = startBucket + 1;
0062: this .amount = amount;
0063: }
0064:
0065: public String toString(LogisticsInventoryPG thePG) {
0066: return ("AllocPhase of amount: "
0067: + amount
0068: + " from "
0069: + getTimeUtils().dateString(
0070: thePG.convertBucketToTime(startBucket))
0071: + " to " + getTimeUtils().dateString(
0072: thePG.convertBucketToTime(endBucket)));
0073: }
0074: }
0075:
0076: public class TaskDeficit {
0077:
0078: public Task task;
0079:
0080: public Task getTask() {
0081: return task;
0082: }
0083:
0084: LogisticsInventoryPG thePG;
0085:
0086: public ArrayList rateBlocks = new ArrayList();
0087:
0088: public double getRemainingQty(int currentBucket) {
0089: ConstantRateBlock block = getRateBlock(currentBucket);
0090: if (block != null) {
0091: return block.getRemainingQty();
0092: }
0093: return 0.0d;
0094: }
0095:
0096: public void setRemainingQty(int currentBucket, double rq) {
0097: ConstantRateBlock block = getRateBlock(currentBucket);
0098: if (block != null) {
0099: block.setRemainingQty(rq);
0100: }
0101: }
0102:
0103: public void incrementBacklog(int currentBucket, double bl) {
0104: ConstantRateBlock block = getRateBlock(currentBucket);
0105: if (block != null) {
0106: block.incrementBacklog(bl);
0107: }
0108: }
0109:
0110: public Collection getDeficitAllocationPhases() {
0111: ArrayList defPhases = new ArrayList();
0112: Iterator rateBlocksIt = rateBlocks.iterator();
0113:
0114: while (rateBlocksIt.hasNext()) {
0115: ConstantRateBlock currentBlock = (ConstantRateBlock) rateBlocksIt
0116: .next();
0117: defPhases.addAll(currentBlock
0118: .getDeficitAllocationPhases());
0119: }
0120: return defPhases;
0121: }
0122:
0123: public void initializeRateBlocks() {
0124: long taskStartTime = getTaskUtils().getStartTime(task);
0125: long taskEndTime = getTaskUtils().getEndTime(task);
0126: PrepositionalPhrase pp_rate = task
0127: .getPrepositionalPhrase(Constants.Preposition.DEMANDRATE);
0128: if (pp_rate != null) {
0129: Object indObj = pp_rate.getIndirectObject();
0130: if (indObj instanceof Schedule) {
0131: Schedule sched = (Schedule) indObj;
0132: Collection rate_elems = sched
0133: .getOverlappingScheduleElements(
0134: taskStartTime, taskEndTime);
0135: int n = (rate_elems == null ? 0 : rate_elems.size());
0136: if (n == 1) {
0137: rateBlocks.add(new ConstantRateBlock(
0138: taskStartTime, taskEndTime, 0.0d));
0139: } else if (n > 1) {
0140: // return a schedule of daily rates
0141: rateBlocks = new ArrayList(n);
0142: for (Iterator iter = rate_elems.iterator(); iter
0143: .hasNext();) {
0144: ObjectScheduleElement ose = (ObjectScheduleElement) iter
0145: .next();
0146: rateBlocks.add(new ConstantRateBlock(ose
0147: .getStartTime(), ose.getEndTime(),
0148: 0.0d));
0149: }
0150: }
0151: }
0152: } else {
0153: rateBlocks.add(new ConstantRateBlock(taskStartTime,
0154: taskEndTime, 0.0d));
0155: }
0156: }
0157:
0158: //Fill in the gaps in the deficit buckets with successful buckets
0159: public Collection generateAllAllocationPhases() {
0160: Iterator rateBlocksIt = rateBlocks.iterator();
0161:
0162: ArrayList allPhases = new ArrayList();
0163:
0164: while (rateBlocksIt.hasNext()) {
0165: ConstantRateBlock currentBlock = (ConstantRateBlock) rateBlocksIt
0166: .next();
0167: allPhases.addAll(currentBlock
0168: .generateAllAllocationPhases(task, thePG));
0169: }
0170: return allPhases;
0171: }
0172:
0173: public TaskDeficit(Task withdraw, int currentBucket,
0174: double qty, LogisticsInventoryPG thePG) {
0175: task = withdraw;
0176: this .thePG = thePG;
0177: initializeRateBlocks();
0178: setRemainingQty(currentBucket, qty);
0179: }
0180:
0181: public ConstantRateBlock getRateBlock(int bucket) {
0182: long time = thePG.convertBucketToTime(bucket);
0183: return getRateBlock(time);
0184: }
0185:
0186: public ConstantRateBlock getRateBlock(long time) {
0187: Iterator rateBlocksIt = rateBlocks.iterator();
0188:
0189: while (rateBlocksIt.hasNext()) {
0190: ConstantRateBlock currentBlock = (ConstantRateBlock) rateBlocksIt
0191: .next();
0192: if ((currentBlock.startTime <= time)
0193: && (currentBlock.endTime > time)) {
0194: return currentBlock;
0195: }
0196: }
0197: return null;
0198: }
0199:
0200: public void addPhase(double amount, int currentBucket) {
0201: ConstantRateBlock block = getRateBlock(currentBucket);
0202: if (block != null) {
0203: block.addPhase(task, thePG, amount, currentBucket);
0204: }
0205: }
0206: }
0207:
0208: public class ConstantRateBlock {
0209: public long startTime;
0210: public long endTime;
0211: public ArrayList allocated = new ArrayList();
0212: public AllocPhase lastPhase;
0213:
0214: public double remainingQty;
0215:
0216: public double getRemainingQty() {
0217: return remainingQty;
0218: }
0219:
0220: public void setRemainingQty(double rq) {
0221: remainingQty = rq;
0222: }
0223:
0224: public double backlog = 0.0;
0225:
0226: public void incrementBacklog(double bl) {
0227: backlog = bl + backlog;
0228: }
0229:
0230: public Collection getDeficitAllocationPhases() {
0231: return allocated;
0232: }
0233:
0234: //Fill in the gaps in the deficit buckets with successful buckets
0235: public Collection generateAllAllocationPhases(Task task,
0236: LogisticsInventoryPG thePG) {
0237: Iterator defPhasesIt = allocated.iterator();
0238:
0239: int rateBlockStartBucket = thePG.convertTimeToBucket(
0240: startTime, false);
0241:
0242: int rateBlockEndBucket = thePG.convertTimeToBucket(endTime,
0243: true);
0244:
0245: int lastBucket = rateBlockStartBucket;
0246:
0247: ArrayList allPhases = new ArrayList();
0248:
0249: while (defPhasesIt.hasNext()) {
0250: AllocPhase currentPhase = (AllocPhase) defPhasesIt
0251: .next();
0252: if (currentPhase.startBucket > lastBucket) {
0253: /*if ((inventoryPlugin.getClusterId().toString().indexOf("2-NLOS-BTY") >= 0) &&
0254: (task.getDirectObject().getTypeIdentificationPG().getTypeIdentification().indexOf("155mm-DPICM") >= 0)) {
0255: System.out.println("Got a Phase after the end time of the task..." +
0256: " qty of phase is " + currentPhase.amount + " " +
0257: task.getUID() + " late phase starts on " +
0258: new Date(thePG.convertBucketToTime(currentPhase.startBucket)));
0259: }*/
0260: //TODO - EPD This best quantity fill in code causes lots of problems!!!!
0261: long lastTime = thePG
0262: .convertBucketToTime(lastBucket);
0263: AllocPhase betweenPhase = new AllocPhase(
0264: lastBucket, getBestBucketQty(task, thePG,
0265: lastTime));
0266: betweenPhase.endBucket = currentPhase.startBucket;
0267: allPhases.add(betweenPhase);
0268: }
0269: allPhases.add(currentPhase);
0270: lastBucket = currentPhase.endBucket;
0271: }
0272:
0273: if (lastBucket < rateBlockEndBucket) {
0274: long lastTime = thePG.convertBucketToTime(lastBucket);
0275: AllocPhase lastPhase = new AllocPhase(lastBucket,
0276: getBestBucketQty(task, thePG, lastTime));
0277: lastPhase.endBucket = rateBlockEndBucket;
0278: allPhases.add(lastPhase);
0279: }
0280: return allPhases;
0281: }
0282:
0283: public ConstantRateBlock(long startTime, long endTime,
0284: double qty) {
0285: //task = withdraw;
0286: lastPhase = null;
0287: remainingQty = qty;
0288: this .startTime = startTime;
0289: this .endTime = endTime;
0290: //this.thePG=thePG;
0291: }
0292:
0293: public void addPhase(Task task, LogisticsInventoryPG thePG,
0294: double amount, int currentBucket) {
0295: if (amount < 0.0) {
0296: if (logger.isInfoEnabled()) {
0297: String itemId = getTaskUtils()
0298: .getTaskItemName(task);
0299: TypeIdentificationPG typeIdPG = thePG.getResource()
0300: .getTypeIdentificationPG();
0301: String nomenclature = null;
0302: String orgId = thePG.getOrg()
0303: .getItemIdentificationPG()
0304: .getItemIdentification();
0305: if (typeIdPG == null) {
0306: logger
0307: .warn("No typeIdentificationPG for asset");
0308: } else {
0309: nomenclature = typeIdPG.getNomenclature();
0310: }
0311: if (nomenclature == null) {
0312: nomenclature = itemId;
0313: }
0314: logger
0315: .info(" Adding a phase of a negative amount=="
0316: + amount
0317: + " at bucket "
0318: + getTimeUtils()
0319: .dateString(
0320: thePG
0321: .convertBucketToTime(currentBucket))
0322: + "for task: "
0323: + task.getUID()
0324: + " org is "
0325: + inventoryPlugin.getOrgName()
0326: + " and the item is : "
0327: + nomenclature);
0328: }
0329: amount = 0.0;
0330: }
0331: if (amount == 0.0) {
0332: if (task.getVerb().equals(Constants.Verb.WITHDRAW)) {
0333: return;
0334: }
0335: }
0336: if (task.getVerb().equals(Constants.Verb.PROJECTWITHDRAW)
0337: && lastPhase != null
0338: && currentBucket == lastPhase.endBucket
0339: && amount == lastPhase.amount) {
0340: // same as last phase so just extend last phase
0341: lastPhase.endBucket = currentBucket + 1;
0342: } else {
0343:
0344: // find existing phase for bucket if exists
0345: Iterator phases = allocated.iterator();
0346: AllocPhase aPhase = null, thePhase = null;
0347: while (phases.hasNext()) {
0348: aPhase = (AllocPhase) phases.next();
0349: if ((aPhase.startBucket <= currentBucket)
0350: && (aPhase.endBucket > currentBucket)) {
0351: thePhase = aPhase;
0352: break;
0353: }
0354: }
0355: if (thePhase == null) {
0356: // if ((inventoryPlugin.getClusterId().toString().indexOf("2-NLOS-BTY") >= 0) &&
0357: // (task.getDirectObject().getTypeIdentificationPG().getTypeIdentification().indexOf("155mm-DPICM") >= 0)) {
0358: // System.out.println("Adding new last phase to fill deficit... task " + task.getUID() + " bucket " +
0359: // new Date (thePG.convertBucketToTime(currentBucket)) + " amount " + amount);
0360: // }
0361: // add new phase
0362: lastPhase = new AllocPhase(currentBucket, amount);
0363: allocated.add(lastPhase);
0364: } else {
0365: thePhase.amount += amount;
0366: }
0367: }
0368: if (remainingQty == amount) {
0369: if (backlog > 0.0) {
0370: remainingQty = taskQtyInBucket(task, currentBucket,
0371: thePG);
0372: backlog = backlog - remainingQty;
0373: } else {
0374: remainingQty = 0.0;
0375: }
0376: } else {
0377: remainingQty = remainingQty - amount;
0378: }
0379: }
0380: }
0381:
0382: private transient HashMap trailingPointersHash = new HashMap();
0383: private transient ArrayList trailingPointers = new ArrayList();
0384: private transient ArrayList trailingPointersRemove = new ArrayList();
0385: private Role myRole;
0386:
0387: /** Constructor for this module
0388: * @param imPlugin The Plugin calling this module.
0389: * @param role The role the Plugin is playing.
0390: **/
0391: public AllocationAssessor(InventoryManager imPlugin, Role role) {
0392: super (imPlugin);
0393: myRole = role;
0394: }
0395:
0396: /** Called by the InventoryPlugin when we are processing in Backwards Flow
0397: * (which is allocation result notifications) to try and allocated
0398: * withdraw tasks. It also updates the BG's Inventory Levels.
0399: * @param inventories The collection of inventories to be processed
0400: **/
0401: public void reconcileInventoryLevels(Collection inventories) {
0402: Iterator inv_list = inventories.iterator();
0403: long currentTime = inventoryPlugin.getCurrentTimeMillis();
0404: int today_bucket;
0405: Inventory inventory;
0406: LogisticsInventoryPG thePG;
0407: long endOfLevel2 = ((LevelOfDetailInventoryManager) inventoryPlugin)
0408: .getEndOfLevelTwo();
0409: while (inv_list.hasNext()) {
0410: inventory = (Inventory) inv_list.next();
0411: resetTrailingPointers();
0412: thePG = (LogisticsInventoryPG) inventory
0413: .searchForPropertyGroup(LogisticsInventoryPG.class);
0414: long inventoryStart = thePG.getStartTime();
0415: long today = Math.max(inventoryStart, currentTime);
0416: today_bucket = thePG.convertTimeToBucket(today, false);
0417: reconcileThePast(today_bucket, thePG);
0418: int end_bucket = thePG.getLastDemandBucket();
0419: int endOfLevel2Bucket = thePG.convertTimeToBucket(
0420: endOfLevel2, false);
0421: if (end_bucket > endOfLevel2Bucket) {
0422: end_bucket = endOfLevel2Bucket;
0423: }
0424: createAllocations(today_bucket, end_bucket, inventory,
0425: thePG);
0426: allocateNotCountedProjections(inventory, thePG);
0427: allocateCountedEarlyProjections(today_bucket, inventory,
0428: thePG);
0429: }
0430: }
0431:
0432: /**
0433: * Reset Pointers Map, list of pointers, and pointer remove list
0434: */
0435: protected void resetTrailingPointers() {
0436: // clear out the trailing pointers every time we get another inventory
0437: trailingPointersHash = new HashMap();
0438: trailingPointers = new ArrayList();
0439: trailingPointersRemove = new ArrayList();
0440: }
0441:
0442: /** Update the inventory levels from time zero to today.
0443: * @param today_bucket Representation of today.
0444: * @param thePG The PG for the Inventory Asset we are working with.
0445: **/
0446: public void reconcileThePast(int today_bucket,
0447: LogisticsInventoryPG thePG) {
0448: calculateInventoryLevels(thePG.getStartBucket(), today_bucket,
0449: thePG);
0450: }
0451:
0452: public double getBestBucketQty(Task task,
0453: LogisticsInventoryPG thePG, long time) {
0454: Rate r = getTaskUtils().getRate(task, time);
0455: return getQuantityForDuration(r, thePG.getBucketMillis());
0456: }
0457:
0458: public double getQuantityForDuration(Rate r, long duration) {
0459: Duration d = Duration.newMilliseconds(duration);
0460: Scalar scalar = (Scalar) r.computeNumerator(d);
0461: return getTaskUtils().getDouble(scalar);
0462: }
0463:
0464: /** Create and update Withdraw and ProjectWithdraw Task Allocations for a particular Inventory
0465: * @param todayBucket This is the starting bucket to process
0466: * @param endBucket Whats the last valid bucket for the inventory
0467: * @param inv The Inventory we are processing
0468: * @param thePG This is the PG for the Inventory we are processing
0469: **/
0470: protected void createAllocations(int todayBucket, int endBucket,
0471: Inventory inv, LogisticsInventoryPG thePG) {
0472:
0473: int currentBucket = todayBucket;
0474: double qty = 0;
0475: double todayLevel, todayRefill;
0476: Task withdraw;
0477:
0478: // DEBUG
0479: String myOrgName = inventoryPlugin.getClusterId().toString();
0480: String myItemId = inv.getItemIdentificationPG()
0481: .getItemIdentification();
0482: LogisticsInventoryPG logInvPG = (LogisticsInventoryPG) inv
0483: .searchForPropertyGroup(LogisticsInventoryPG.class);
0484: String nomenclature = logInvPG.getResource()
0485: .getTypeIdentificationPG().getNomenclature();
0486:
0487: /*if ((myOrgName.indexOf("2-NLOS-BTY") >= 0) && (myItemId.indexOf("155mm-DPICM") >= 0)) {
0488: System.out.println("### createAlloc : Assessing allocations RIGHT ORG NAME COMBO - " + myOrgName + " - " + myItemId);
0489: }*/
0490:
0491: // loop through the buckets in the inventory
0492: while (currentBucket <= endBucket) {
0493:
0494: todayRefill = findCommittedRefill(currentBucket, thePG,
0495: true);
0496: todayLevel = thePG.getLevel(currentBucket - 1)
0497: + todayRefill;
0498:
0499: /***
0500: **
0501:
0502: if((inventoryPlugin.getOrgName().indexOf("47-FSB") != -1) &&
0503: (thePG.getItemName().indexOf("9140002865294") != -1)) {
0504: logger.error("createAllocations - bucket is "+getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket))+
0505: ", committed refill "+todayRefill+" and today's inventory level "+todayLevel);
0506: }
0507:
0508: **/
0509:
0510: // First try to fill any previous deficits
0511: Iterator tpIt = trailingPointers.iterator();
0512: while (tpIt.hasNext()) {
0513: TaskDeficit td = (TaskDeficit) tpIt.next();
0514: withdraw = td.getTask();
0515: //TODO - EPD HACK for LAT 1.0 delivery to stop late fills of projections
0516: // related problem is in the TD code that "fills in" bare spots.
0517: if (withdraw.getVerb().equals(
0518: Constants.Verb.PROJECTWITHDRAW)) {
0519: long taskEndTime = getTaskUtils().getEndTime(
0520: withdraw);
0521: int taskEndBucket = thePG.convertTimeToBucket(
0522: taskEndTime, true);
0523: if (taskEndBucket < currentBucket) {
0524: continue;
0525: }
0526: }
0527: qty = td.getRemainingQty(currentBucket);
0528: // DEBUG Task deficits
0529: //if ((myOrgName.indexOf("592-ORDCO") >= 0) && (myItemId.indexOf("Level2Am") >= 0)) {
0530: //if ((myOrgName.indexOf("2-NLOS-BTY") >= 0) && (myItemId.indexOf("155mm-DPICM") >= 0)) {
0531: //System.out.println("### createAlloc : trying to fill a PREVIOUS deficit for task:|" + withdraw.getUID() + "| : todaylevel|" + todayLevel + "| and qty is |" + qty + "| and the date is " + getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket)));
0532: //}
0533: //}
0534: // check the level
0535: if (todayLevel <= 0.0) {
0536: // if ((myOrgName.indexOf("2-NLOS-BTY") >= 0) && (myItemId.indexOf("155mm-DPICM") >= 0)) {
0537: // System.out.println("TodayLevel is " + todayLevel + " adding 0 phase for bucket " +
0538: // new Date(thePG.convertBucketToTime(currentBucket)) + " task " +
0539: // td.getTask().getUID());
0540: // }
0541: td.addPhase(0.0, currentBucket);
0542: break;
0543: } else if (todayLevel >= qty) {
0544: // Can completely fill known deficit
0545: /***
0546: **
0547: if((inventoryPlugin.getOrgName().indexOf("47-FSB") != -1) &&
0548: (thePG.getItemName().indexOf("9140002865294") != -1)) {
0549: logger.error("calculateAllocations - filling deficit on day "+
0550: getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket))+
0551: " and the remaining qty is "+qty+" and new inventory level is "+todayLevel+" for task "+
0552: withdraw.getUID() + " task request qty " + getTaskUtils().getDailyQuantity(withdraw));
0553: }
0554: **/
0555:
0556: fillDeficit(td, currentBucket, inv, thePG);
0557: todayLevel = todayLevel - qty;
0558: } else {
0559: //this withdraw has previously had a deficit we cannot fill the deficit entirely during this bucket`
0560: // leave the TaskDeficit in the same place on the queue -- it still needs to be filled with its old priority
0561:
0562: /****
0563: ***
0564:
0565: if((inventoryPlugin.getOrgName().indexOf("47-FSB") != -1) &&
0566: (thePG.getItemName().indexOf("9140002865294") != -1)) {
0567: logger.error("calculateAllocations - adding phase on day "+
0568: getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket))+
0569: " and td.remaining qty is " + qty + " today level is " + todayLevel + " setting today level to 0. This is for task " + withdraw.getUID() + " task request daily quantity " + getTaskUtils().getDailyQuantity(withdraw ));
0570: }
0571:
0572: **/
0573:
0574: td.addPhase(todayLevel, currentBucket);
0575: todayLevel = 0.0;
0576: break; // nothing more to allocate
0577: }
0578: }
0579: // remove any trailing pointers we filled
0580: trailingPointers.removeAll(trailingPointersRemove);
0581: trailingPointersRemove.clear();
0582:
0583: // Fill any counted tasks with remaining inventory (if any)
0584:
0585: Collection wdTasks = thePG
0586: .getActualDemandTasks(currentBucket);
0587: Iterator wdIter = wdTasks.iterator();
0588: while (wdIter.hasNext()) {
0589: withdraw = (Task) wdIter.next();
0590: qty = taskQtyInBucket(withdraw, currentBucket, thePG);
0591: // check the level
0592: if ((todayLevel - qty) > -.00000005) {
0593: // enough inventory to fill task completely
0594:
0595: // NOTE: we have had a case where todayLevel= 12.999999999999995
0596: // and quantity = 12.999999999999998
0597:
0598: fulfillTask(withdraw, currentBucket, inv, thePG);
0599: todayLevel = Math.max(0.0, todayLevel - qty);
0600:
0601: // if((inventoryPlugin.getOrgName().indexOf("47-FSB") != -1) &&
0602: // (thePG.getItemName().indexOf("9140002865294") != -1)) {
0603: // logger.error("calculateAllocations - fulfill task on day "+
0604: // getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket))+
0605: // " demand is "+qty+" and new inventory level is "+todayLevel+" for task "+
0606: // withdraw.getUID() + " task qty " + getTaskUtils().getDailyQuantity(withdraw));
0607: // }
0608:
0609: } else {
0610: // can't fill this task totally -- create deficit on this task
0611: // if it already has a pe - rescind it
0612: PlanElement pe = withdraw.getPlanElement();
0613: if (pe != null)
0614: inventoryPlugin.publishRemove(pe);
0615: TaskDeficit td = getTaskDeficit(withdraw,
0616: currentBucket, thePG);
0617: td.addPhase(todayLevel, currentBucket);
0618: // DEBUG Task deficits
0619: //if ((myOrgName.indexOf("592-ORDCO") >= 0) && (myItemId.indexOf("Level2Amm") >= 0)) {
0620: // System.out.println("### createAlloc : adding a phase to a task deficit/deficit added to TRAILING POINTERS for task:|"
0621: //+ td.getTask().getUID() +"| todaylevel|" + todayLevel +
0622: // "| and qty is |" + qty + "| and the date is " +
0623: //getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket)));
0624: //}
0625:
0626: /***
0627: **
0628: if((inventoryPlugin.getOrgName().indexOf("47-FSB") != -1) &&
0629: (thePG.getItemName().indexOf("9140002865294") != -1)) {
0630: logger.error("calculateAllocations - deficit for task on day "+
0631: getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket))+
0632: " demand is "+qty+" and new inventory level is 0.0 and provided "+todayLevel+" to "+
0633: withdraw.getUID()+ " task qty " + getTaskUtils().getDailyQuantity(withdraw) + " TD: remainingQty " + td.getRemainingQty() + " backlog " + td.backlog);
0634: if(td.lastPhase != null) {
0635: logger.error("And Last Phase is = " + td.lastPhase.toString(thePG));
0636: }
0637: }
0638:
0639: ***
0640: **/
0641:
0642: trailingPointers.add(td);
0643: // this task depletes the inventory level
0644: todayLevel = 0.0;
0645: }
0646: }
0647:
0648: //when we are done going through all the tasks for the day set the level
0649: thePG.setLevel(currentBucket, todayLevel);
0650: currentBucket = currentBucket + 1;
0651: }
0652:
0653: // DEBUG inventory levels
0654: //if ((myOrgName.indexOf("592-ORDCO") >= 0) && (myItemId.indexOf("Level2Amm") >= 0)) {
0655: // for(currentBucket = 0; currentBucket<80; currentBucket++){
0656: //if (thePG.convertBucketToTime(currentBucket) >= 1128643200000L) {
0657: //System.out.println("###-" + myOrgName +
0658: //"-createAlloc Inventory Level = "+
0659: //thePG.getLevel(currentBucket)+ " on ("+ currentBucket +") " +
0660: //getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket)));
0661: // }
0662: // }
0663: //}
0664:
0665: //when we are finished, if we have things left in trailingPointers, fail them
0666: Iterator tpIt = trailingPointers.iterator();
0667: while (tpIt.hasNext()) {
0668: TaskDeficit td = (TaskDeficit) tpIt.next();
0669: // if ((myOrgName.indexOf("2-NLOS-BTY") >= 0) && (myItemId.indexOf("155mm-DPICM") >= 0)) {
0670: // System.out.println("Creating failed phased AR. task deficit is " + td.getTask() + " " + td.getRemainingQty());
0671: // }
0672: //createPhasedAllocationResult(td, inv, thePG, false);
0673: createPhasedAllocationResult(td, inv, thePG, true);
0674: }
0675: }
0676:
0677: private TaskDeficit getTaskDeficit(Task task, int currentBucket,
0678: LogisticsInventoryPG thePG) {
0679: double qty = taskQtyInBucket(task, currentBucket, thePG);
0680: TaskDeficit td = ((TaskDeficit) trailingPointersHash.get(task));
0681: if (td == null) {
0682: td = new TaskDeficit(task, currentBucket, qty, thePG);
0683: if (task.getVerb().equals(Constants.Verb.PROJECTWITHDRAW)) {
0684: trailingPointersHash.put(task, td);
0685: }
0686: } else if (td.getRemainingQty(currentBucket) > 0.0) {
0687: // can only happen when we have a projectWithdraw task which has a previous bucket still
0688: // unfilled
0689: td.incrementBacklog(currentBucket, qty);
0690: } else {
0691: // can only happen when we have a projectWithdraw task which has no previous bucket still
0692: // unfilled
0693: td.setRemainingQty(currentBucket, qty);
0694: }
0695: return td;
0696: }
0697:
0698: private void fillDeficit(TaskDeficit td, int currentBucket,
0699: Inventory inv, LogisticsInventoryPG thePG) {
0700: // DEBUG
0701: //String myOrgName = inventoryPlugin.getMyOrganization().getItemIdentificationPG().getItemIdentification();
0702: //String myItemId = inv.getItemIdentificationPG().getItemIdentification();
0703: Task task = td.getTask();
0704: if (task.getVerb().equals(Constants.Verb.WITHDRAW)) {
0705: // task is completed
0706: if (td.getDeficitAllocationPhases().isEmpty()) {
0707: createLateAllocation(task, thePG
0708: .convertBucketToTime(currentBucket), inv, thePG);
0709: } else {
0710: //BD added the td.addPhase line to make a phase to fill the deficit
0711: td.addPhase(td.getRemainingQty(currentBucket),
0712: currentBucket);
0713: createPhasedAllocationResult(td, inv, thePG, true);
0714: }
0715: } else {
0716: td.addPhase(td.getRemainingQty(currentBucket),
0717: currentBucket);
0718: if ((thePG.convertBucketToTime(currentBucket + 1) >= (long) PluginHelper
0719: .getPreferenceBestValue(task, AspectType.END_TIME))) {
0720: //DEBUG
0721: // if ((myOrgName.indexOf("592") >= 0) && (myItemId.indexOf("Level2Amm") >= 0)) {
0722: // logger.debug("### fillDeficit : creating a phased allocation result for task: " + task.getUID() + " on the date of " + getTimeUtils().dateString(thePG.convertBucketToTime(currentBucket)));
0723: //}
0724: createPhasedAllocationResult(td, inv, thePG, true);
0725: }
0726: }
0727: trailingPointersRemove.add(td);
0728: }
0729:
0730: private void fulfillTask(Task task, int currentBucket,
0731: Inventory inv, LogisticsInventoryPG thePG) {
0732: if (task.getVerb().equals(Constants.Verb.WITHDRAW)) {
0733: //Safely check if the pe is null here and if we get one, pass it to the check method
0734: //instead of letting the check method get it since it may have been rescinded in between
0735: // the task.getPlanElement() calls which can cause an NPE in checkPlanElement
0736: PlanElement pe = task.getPlanElement();
0737: if (pe != null) {
0738: // previously allocated WITHDRAW task -- update plan element if needed
0739: checkPlanElement(task, pe);
0740: } else {
0741: // previously un-allocated WITHDRAW task
0742: createBestAllocation(task, inv, thePG);
0743: }
0744: } else {
0745: //projection
0746: TaskDeficit td = (TaskDeficit) trailingPointersHash
0747: .get(task);
0748: if (td != null) {
0749: //this project withdraw has previously had a deficit
0750: td.addPhase(
0751: taskQtyInBucket(task, currentBucket, thePG),
0752: currentBucket);
0753: if ((thePG.convertBucketToTime(currentBucket + 1) >= (long) PluginHelper
0754: .getPreferenceBestValue(task,
0755: AspectType.END_TIME))) {
0756: // the projectWithdraw does end during this bucket
0757: createPhasedAllocationResult(td, inv, thePG, true);
0758: }
0759: } else if (thePG.convertBucketToTime(currentBucket + 1) >= (long) PluginHelper
0760: .getPreferenceBestValue(task, AspectType.END_TIME)) {
0761: //this project withdraw ends during this bucket
0762: // it has not previously had a deficit
0763: createBestAllocation(task, inv, thePG);
0764: } //else {
0765: //this project withdraw has never had a deficit and does not end during this bucket
0766: // do nothing -- hope for createBestAllocation
0767: //}
0768: }
0769: }
0770:
0771: public void createPhasedAllocationResult(TaskDeficit td,
0772: Inventory inv, LogisticsInventoryPG thePG, boolean success) {
0773: //if we are passing in a false - see if we already made a failed AR/PE. If we did just get out.
0774: Task task = td.getTask();
0775: PlanElement prevPE = task.getPlanElement();
0776: /**if (prevPE != null && !success) {
0777: if (!prevPE.getEstimatedResult().isSuccess()) {
0778: return;
0779: }
0780: }*/
0781:
0782: ArrayList phasedResults = new ArrayList();
0783: double rollupQty = 0;
0784: AspectValue avs[];
0785:
0786: if (shouldSkipMakingResult(task)) {
0787: return;
0788: }
0789:
0790: //initialize the rollup array depending on the verb --sigh...
0791: if (task.getVerb().equals(Constants.Verb.WITHDRAW)) {
0792: avs = new AspectValue[2];
0793: } else {
0794: avs = new AspectValue[3];
0795: }
0796:
0797: ArrayList phases = (ArrayList) td.getDeficitAllocationPhases();
0798: if (phases.isEmpty()) {
0799: //if we totally fail
0800: if ((inventoryPlugin.getClusterId().toString().indexOf(
0801: "2-NLOS-BTY") >= 0)
0802: && (task.getDirectObject()
0803: .getTypeIdentificationPG()
0804: .getTypeIdentification().indexOf(
0805: "155mm-DPICM") >= 0)) {
0806: System.out
0807: .println("Totally failing task b/c there are not phases... "
0808: + task.getUID());
0809: }
0810: createFailedAllocation(task, inv, thePG);
0811: return;
0812: }
0813:
0814: if (task.getVerb().equals(Constants.Verb.WITHDRAW)) {
0815: int rollupEnd = ((AllocPhase) phases.get(phases.size() - 1)).endBucket;
0816: int rollupStart = ((AllocPhase) phases.get(0)).startBucket;
0817: avs[0] = AspectValue.newAspectValue(AspectType.END_TIME,
0818: thePG.convertBucketToTime(rollupEnd));
0819: avs[1] = AspectValue.newAspectValue(AspectType.START_TIME,
0820: thePG.convertBucketToTime(rollupStart));
0821:
0822: Iterator phasesIt = phases.iterator();
0823: //use end and qty
0824: while (phasesIt.hasNext()) {
0825: AllocPhase aPhase = (AllocPhase) phasesIt.next();
0826: AspectValue this Phase[] = new AspectValue[2];
0827: rollupQty = rollupQty + aPhase.amount;
0828: this Phase[0] = AspectValue.newAspectValue(
0829: AspectType.END_TIME, thePG
0830: .convertBucketToTime(aPhase.endBucket));
0831: this Phase[1] = AspectValue.newAspectValue(
0832: AspectType.QUANTITY, aPhase.amount);
0833: phasedResults.add(this Phase);
0834: }
0835: avs[1] = AspectValue.newAspectValue(AspectType.QUANTITY,
0836: rollupQty);
0837: } else {
0838:
0839: phases = (ArrayList) td.generateAllAllocationPhases();
0840:
0841: int rollupEnd = ((AllocPhase) phases.get(phases.size() - 1)).endBucket;
0842: int rollupStart = ((AllocPhase) phases.get(0)).startBucket;
0843: avs[0] = AspectValue.newAspectValue(AspectType.END_TIME,
0844: thePG.convertBucketToTime(rollupEnd));
0845: avs[1] = AspectValue.newAspectValue(AspectType.START_TIME,
0846: thePG.convertBucketToTime(rollupStart));
0847:
0848: Iterator phasesIt = phases.iterator();
0849:
0850: phasesIt = phases.iterator();
0851: while (phasesIt.hasNext()) {
0852: AllocPhase aPhase = (AllocPhase) phasesIt.next();
0853: rollupQty = rollupQty
0854: + ((aPhase.endBucket - aPhase.startBucket) * aPhase.amount);
0855: // take the max endBucket for the rollup end time
0856: if (aPhase.endBucket > rollupEnd) {
0857: rollupEnd = aPhase.endBucket;
0858: }
0859: // take the min startBucket for the rollup start time
0860: if (aPhase.startBucket < rollupStart) {
0861: rollupStart = aPhase.startBucket;
0862: }
0863: AspectValue this Phase[] = new AspectValue[3];
0864: this Phase[0] = AspectValue.newAspectValue(
0865: AspectType.END_TIME, thePG
0866: .convertBucketToTime(aPhase.endBucket));
0867: this Phase[1] = AspectValue.newAspectValue(
0868: AspectType.START_TIME,
0869: thePG.convertBucketToTime(aPhase.startBucket));
0870: this Phase[2] = getDemandRateAV(aPhase.amount, thePG
0871: .getBucketMillis());
0872: // add this phase to our phased results list
0873: phasedResults.add(this Phase);
0874: }
0875: avs[2] = getDemandRateAV(rollupQty, thePG
0876: .convertBucketToTime(rollupEnd)
0877: - thePG.convertBucketToTime(rollupStart));
0878: }
0879:
0880: AllocationResult estimatedResult = inventoryPlugin
0881: .getPlanningFactory().newPhasedAllocationResult(
0882: Constants.Confidence.SCHEDULED, success, avs,
0883: (new Vector(phasedResults)).elements());
0884:
0885: compareResults(estimatedResult, task, inv, thePG);
0886: }
0887:
0888: /**
0889: * Do not process tasks whose end times are beyond level 2
0890: * @param task
0891: * @return true if after level 2 horizon
0892: */
0893: protected boolean shouldSkipMakingResult(Task task) {
0894: long endOfLevel2 = ((LevelOfDetailInventoryManager) inventoryPlugin)
0895: .getEndOfLevelTwo();
0896: long endOfTask = (long) PluginHelper.getPreferenceBestValue(
0897: task, AspectType.END_TIME);
0898: // Do not process tasks whose end times are beyond level 2
0899: return (endOfTask > endOfLevel2);
0900: }
0901:
0902: public double taskQtyInBucket(Task task, int currentBucket,
0903: LogisticsInventoryPG thePG) {
0904: if (task.getVerb().equals(Constants.Verb.WITHDRAW)) {
0905: return getTaskUtils().getPreference(task,
0906: AspectType.QUANTITY);
0907: } else {
0908: long start = (long) PluginHelper.getPreferenceBestValue(
0909: task, AspectType.START_TIME);
0910: long end = (long) PluginHelper.getPreferenceBestValue(task,
0911: AspectType.END_TIME);
0912: return thePG.getProjectionTaskDemand(task, currentBucket,
0913: start, end);
0914: }
0915: }
0916:
0917: /** Create best allocations for Projections that are not being counted.
0918: * These are likely early projections that are not counted because
0919: * Supply tasks (actuals) are being counted in their place.
0920: * Allocate these with yes or best.
0921: * Note that projections that span the not counted and counted projection
0922: * windows are not allocated here.
0923: * @param inventory The Inventory we are processing
0924: * @param thePG This is the PG for the Inventory we are processing
0925: **/
0926: protected void allocateNotCountedProjections(Inventory inventory,
0927: LogisticsInventoryPG thePG) {
0928: // String myOrgName = inventoryPlugin.getMyOrganization().getItemIdentificationPG().getItemIdentification();
0929: //String myItemId = thePG.getResource().getTypeIdentificationPG().getTypeIdentification();
0930:
0931: HashMap customerHash = thePG.getCustomerHash();
0932: Set keys = customerHash.keySet();
0933: Iterator keysIt = keys.iterator();
0934: while (keysIt.hasNext()) {
0935: Object org = keysIt.next();
0936: int countedBucket = thePG.convertTimeToBucket(
0937: ((Long) customerHash.get(org)).longValue(), false) + 1;
0938: int currentBucket = 0;
0939: // loop through the buckets in the inventory
0940: while (currentBucket < countedBucket) {
0941: Collection wdprojs = thePG
0942: .getProjectedDemandTasks(currentBucket);
0943: Iterator wdpIter = wdprojs.iterator();
0944: while (wdpIter.hasNext()) {
0945: Task withdrawProj = (Task) wdpIter.next();
0946: Object customerOrg = TaskUtils
0947: .getCustomer(withdrawProj);
0948: if (customerOrg.equals(org)) {
0949: double endTimePref = getTaskUtils()
0950: .getPreference(withdrawProj,
0951: AspectType.END_TIME);
0952: //make sure there is an end time pref AND that the
0953: //bucket of the end time pref is not equal to or past the countedBucket
0954: //Since endTime is not inclusive of the bucket it falls in decrement by 1
0955: // countedBucket is the firstCountedProjection - if the projection spans both
0956: //the uncounted and counted windows - dont blindly allocate it here ... it should
0957: // be picked up by the counted projections allocation method.
0958: if ((endTimePref != Double.NaN)
0959: && ((thePG.convertTimeToBucket(
0960: (long) endTimePref, true) - 1) < countedBucket)) {
0961: if (withdrawProj.getPlanElement() == null) {
0962: createBestAllocation(withdrawProj,
0963: inventory, thePG);
0964: }
0965: // if it already has a pe we could check it - but for now we won't
0966: }
0967: }
0968: }
0969: //bump the bucket
0970: currentBucket = currentBucket + 1;
0971: }
0972: }
0973: }
0974:
0975: /** Create best allocations for Projections that are counted but in the past.
0976: * These may need to be re-allocated in the past if the optempo changes
0977: * and these tasks are still counted.
0978: * @param today_bucket The current day of the society
0979: * @param inventory The Inventory we are processing
0980: * @param thePG This is the PG for the Inventory we are processing
0981: **/
0982: protected void allocateCountedEarlyProjections(int today_bucket,
0983: Inventory inventory, LogisticsInventoryPG thePG) {
0984: int currentBucket = 0;
0985: // loop through the buckets in the inventory
0986: while (currentBucket < today_bucket) {
0987: Collection wdprojs = thePG
0988: .getProjectedDemandTasks(currentBucket);
0989: Iterator wdpIter = wdprojs.iterator();
0990: while (wdpIter.hasNext()) {
0991: Task withdrawProj = (Task) wdpIter.next();
0992: double endTimePref = getTaskUtils().getPreference(
0993: withdrawProj, AspectType.END_TIME);
0994: //make sure there is an end time pref AND that the
0995: //bucket of the end time pref is not equal to or past the today_bucket
0996: //Since endTime is not inclusive of the bucket it falls in decrement by 1
0997: if ((endTimePref != Double.NaN)
0998: && ((thePG.convertTimeToBucket(
0999: (long) endTimePref, true) - 1) < today_bucket)) {
1000: if (withdrawProj.getPlanElement() == null) {
1001: createBestAllocation(withdrawProj, inventory,
1002: thePG);
1003: }
1004: }
1005: }
1006: currentBucket = currentBucket + 1;
1007: }
1008: }
1009:
1010: /** Utility method to create an Allocation that matches the
1011: * best preferences for the withdraw task
1012: * @param withdraw The withdraw task we are allocating
1013: * @param inv The Inventory we are allocating against
1014: * @param thePG The PG of the Inventory we are allocating against
1015: **/
1016: private void createBestAllocation(Task withdraw, Inventory inv,
1017: LogisticsInventoryPG thePG) {
1018: AllocationResult estimatedResult = null;
1019: if (withdraw.getVerb().equals(Constants.Verb.WITHDRAW)) {
1020: estimatedResult = PluginHelper
1021: .createEstimatedAllocationResult(withdraw,
1022: inventoryPlugin.getPlanningFactory(),
1023: Constants.Confidence.SCHEDULED, true);
1024: } else {
1025: long taskStartTime = getTaskUtils().getStartTime(withdraw);
1026: long taskEndTime = getTaskUtils().getEndTime(withdraw);
1027: PrepositionalPhrase pp_rate = withdraw
1028: .getPrepositionalPhrase(Constants.Preposition.DEMANDRATE);
1029: if (pp_rate != null) {
1030: Object indObj = pp_rate.getIndirectObject();
1031: if (indObj instanceof Schedule) {
1032: Schedule sched = (Schedule) indObj;
1033: Collection rate_elems = sched
1034: .getOverlappingScheduleElements(
1035: taskStartTime, taskEndTime);
1036: int n = (rate_elems == null ? 0 : rate_elems.size());
1037: ArrayList phasedResults = new ArrayList(n);
1038: double rollupQty = 0;
1039: AspectValue avs[];
1040:
1041: avs = new AspectValue[3];
1042:
1043: // return a schedule of daily rates
1044: int rollupEnd = thePG.convertTimeToBucket(
1045: taskEndTime, true);
1046: int rollupStart = thePG.convertTimeToBucket(
1047: taskStartTime, false);
1048:
1049: avs[0] = AspectValue.newAspectValue(
1050: AspectType.END_TIME, taskEndTime);
1051: avs[1] = AspectValue.newAspectValue(
1052: AspectType.START_TIME, taskStartTime);
1053:
1054: for (Iterator iter = rate_elems.iterator(); iter
1055: .hasNext();) {
1056: ObjectScheduleElement ose = (ObjectScheduleElement) iter
1057: .next();
1058: int rateStartBucket = thePG
1059: .convertTimeToBucket(
1060: ose.getStartTime(), false);
1061: int rateEndBucket = thePG.convertTimeToBucket(
1062: ose.getEndTime(), true);
1063: Rate currentRate = (Rate) ose.getObject();
1064:
1065: rollupQty = rollupQty
1066: + this
1067: .getQuantityForDuration(
1068: currentRate,
1069: (rateEndBucket - rateStartBucket));
1070: // take the max endBucket for the rollup end time
1071: if (rateEndBucket > rollupEnd) {
1072: rollupEnd = rateEndBucket;
1073: }
1074: // take the min startBucket for the rollup start time
1075: if (rateStartBucket < rollupStart) {
1076: rollupStart = rateStartBucket;
1077: }
1078: AspectValue this Phase[] = new AspectValue[3];
1079: this Phase[0] = AspectValue
1080: .newAspectValue(
1081: AspectType.END_TIME,
1082: thePG
1083: .convertBucketToTime(rateEndBucket));
1084: this Phase[1] = AspectValue
1085: .newAspectValue(
1086: AspectType.START_TIME,
1087: thePG
1088: .convertBucketToTime(rateStartBucket));
1089: this Phase[2] = getDemandRateAV(
1090: getQuantityForDuration(currentRate,
1091: thePG.getBucketMillis()), thePG
1092: .getBucketMillis());
1093: // add this phase to our phased results list
1094: phasedResults.add(this Phase);
1095: }
1096: avs[2] = getDemandRateAV(rollupQty, thePG
1097: .convertBucketToTime(rollupEnd)
1098: - thePG.convertBucketToTime(rollupStart));
1099:
1100: estimatedResult = inventoryPlugin
1101: .getPlanningFactory()
1102: .newPhasedAllocationResult(
1103: Constants.Confidence.SCHEDULED,
1104: true,
1105: avs,
1106: (new Vector(phasedResults))
1107: .elements());
1108:
1109: }
1110: } else {
1111: estimatedResult = PluginHelper
1112: .createEstimatedAllocationResult(withdraw,
1113: inventoryPlugin.getPlanningFactory(),
1114: Constants.Confidence.SCHEDULED, true);
1115: }
1116: }
1117: compareResults(estimatedResult, withdraw, inv, thePG);
1118: }
1119:
1120: /** Utility method to create a late Allocation
1121: * @param withdraw The withdraw task to allocate
1122: * @param end The end time of the window that it will be filled
1123: * @param inv The Inventory we are allocating against
1124: * @param thePG The PG for the Inventory we are allocating against
1125: * Note that we are using a start and end preference because the allocation
1126: * is based on a bucket that may span more than one day. So we want to say it
1127: * will be filled sometime within the bucket start and end time.
1128: **/
1129: private void createLateAllocation(Task withdraw, long end,
1130: Inventory inv, LogisticsInventoryPG thePG) {
1131: AspectValue avs[] = new AspectValue[2];
1132: avs[0] = AspectValue.newAspectValue(AspectType.END_TIME, end);
1133: avs[1] = AspectValue.newAspectValue(AspectType.QUANTITY,
1134: getTaskUtils().getPreference(withdraw,
1135: AspectType.QUANTITY));
1136: AllocationResult estimatedResult = inventoryPlugin
1137: .getPlanningFactory().newAllocationResult(
1138: Constants.Confidence.SCHEDULED, true, avs);
1139: compareResults(estimatedResult, withdraw, inv, thePG);
1140: }
1141:
1142: private void createFailedAllocation(Task task, Inventory inventory,
1143: LogisticsInventoryPG thePG) {
1144: //check if the task already has a failed allocation on it - don't even bother to compare
1145: //failed should equal failed at this point.
1146: PlanElement prevPE = task.getPlanElement();
1147: if (prevPE != null) {
1148: if (!prevPE.getEstimatedResult().isSuccess()) {
1149: return;
1150: }
1151: }
1152: if (logger.isDebugEnabled()) {
1153: logger.debug("Failing task: "
1154: + getTaskUtils().taskDesc(task) + " at agent: "
1155: + inventoryPlugin.getClusterId().toString()
1156: + " Inventory initial level is: "
1157: + thePG.getLevel(0));
1158: }
1159: // make the failed time the day after the end of the oplan
1160: long failed_time = inventoryPlugin.getOPlanEndTime()
1161: + TimeUtils.MSEC_PER_DAY;
1162: AspectValue avs[];
1163:
1164: if (task.getVerb().equals(Constants.Verb.WITHDRAW)) {
1165: avs = new AspectValue[2];
1166: avs[0] = AspectValue.newAspectValue(AspectType.END_TIME,
1167: failed_time);
1168: avs[1] = AspectValue.newAspectValue(AspectType.QUANTITY,
1169: PluginHelper.getPreferenceBestValue(task,
1170: AspectType.QUANTITY));
1171: } else {
1172: // projection... set start and end to failed_time and set the rate to the pref over 1 bucket
1173: avs = new AspectValue[3];
1174: long failed_start = PluginHelper.getStartTime(task);
1175: AspectValue failedAV;
1176: Duration dur = new Duration(failed_time - failed_start,
1177: Duration.MILLISECONDS);
1178: if (getTaskUtils().isFlowRate(task)) {
1179: Volume vol = new Volume(0.0, Volume.GALLONS);
1180: failedAV = AspectValue.newAspectValue(
1181: AlpineAspectType.DEMANDRATE, new FlowRate(vol,
1182: dur));
1183: } else {
1184: Count cnt = new Count(0.0, Count.EACHES);
1185: failedAV = AspectValue.newAspectValue(
1186: AlpineAspectType.DEMANDRATE, new CountRate(cnt,
1187: dur));
1188: }
1189:
1190: avs[0] = AspectValue.newAspectValue(AspectType.START_TIME,
1191: failed_start);
1192: avs[1] = AspectValue.newAspectValue(AspectType.END_TIME,
1193: failed_time);
1194: avs[2] = failedAV;
1195: }
1196: AllocationResult failed = inventoryPlugin.getPlanningFactory()
1197: .newAllocationResult(Constants.Confidence.SCHEDULED,
1198: false, avs);
1199: //PlanElement prevPE = task.getPlanElement();
1200: if (prevPE == null) {
1201: Allocation alloc = inventoryPlugin.getPlanningFactory()
1202: .createAllocation(task.getPlan(), task, inventory,
1203: failed, myRole);
1204: inventoryPlugin.publishAdd(alloc);
1205: } else {
1206: AllocationResult previous = prevPE.getEstimatedResult();
1207: if (!previous.isEqual(failed)) {
1208: prevPE.setEstimatedResult(failed);
1209: inventoryPlugin.publishChange(prevPE);
1210: }
1211: }
1212: }
1213:
1214: /** Method which checks a previously created planelement for the withdraw task
1215: * to make sure its consistent with the result we just calculated.
1216: * This is called if we want to give a best result - so if the previous
1217: * result was not best we will change it.
1218: * @param withdraw The Withdraw Task we are allocating against the Inventory
1219: * @param pe The PlanElement associated with the Task.
1220: **/
1221: private void checkPlanElement(Task withdraw, PlanElement pe) {
1222: //if this task already has a pe - make sure the results are consistent
1223: // with best.
1224: //PlanElement pe = withdraw.getPlanElement();
1225: AllocationResult ar = pe.getEstimatedResult();
1226: AllocationResult estimatedResult = PluginHelper
1227: .createEstimatedAllocationResult(withdraw,
1228: inventoryPlugin.getPlanningFactory(),
1229: Constants.Confidence.SCHEDULED, true);
1230: if (ar == null || !ar.isEqual(estimatedResult)) {
1231: pe.setEstimatedResult(estimatedResult);
1232: inventoryPlugin.publishChange(pe);
1233: // updatePG(withdraw, thePG);
1234: }
1235: }
1236:
1237: public void compareResults(AllocationResult estimatedResult,
1238: Task withdraw, Inventory inv, LogisticsInventoryPG thePG) {
1239: PlanElement prevPE = withdraw.getPlanElement();
1240: if (prevPE == null) {
1241: Allocation alloc = inventoryPlugin.getPlanningFactory()
1242: .createAllocation(withdraw.getPlan(), withdraw,
1243: inv, estimatedResult, myRole);
1244: inventoryPlugin.publishAdd(alloc);
1245: } else {
1246: AllocationResult previous = prevPE.getEstimatedResult();
1247: if (!previous.isEqual(estimatedResult)) {
1248: if (logger.isDebugEnabled()) {
1249: logger
1250: .debug("Inside compareResults... results are !.equals..."
1251: + "\n previous result: "
1252: + previous
1253: + " estimated result: "
1254: + estimatedResult);
1255: }
1256: prevPE.setEstimatedResult(estimatedResult);
1257: inventoryPlugin.publishChange(prevPE);
1258: } else {
1259: // otherwise leave it alone and don't bother to update the PG
1260: return;
1261: }
1262: }
1263:
1264: // updatePG(withdraw, thePG);
1265: }
1266:
1267: public void updatePG(Task withdraw, LogisticsInventoryPG thePG) {
1268: if (withdraw.getVerb().equals(Constants.Verb.WITHDRAW)) {
1269: thePG.updateWithdrawRequisition(withdraw);
1270: } else {
1271: thePG.updateWithdrawProjection(withdraw);
1272: }
1273: }
1274:
1275: public AspectValue getDemandRateAV(double amount, long millis) {
1276: AspectValue demandRateAV = null;
1277: Duration dur = new Duration(millis, Duration.MILLISECONDS);
1278: if (inventoryPlugin.getSupplyType().equals("BulkPOL")) {
1279: Volume vol = new Volume(amount, Volume.GALLONS);
1280: demandRateAV = AspectValue
1281: .newAspectValue(AlpineAspectType.DEMANDRATE,
1282: new FlowRate(vol, dur));
1283:
1284: } else {
1285: Count cnt = new Count(amount, Count.EACHES);
1286: demandRateAV = AspectValue.newAspectValue(
1287: AlpineAspectType.DEMANDRATE,
1288: new CountRate(cnt, dur));
1289: }
1290: return demandRateAV;
1291: }
1292:
1293: }
|