Task subTask = makeTask (parentTask, directObject); long bestTime = early.getTime() + ((long)daysSoFar)*MILLIS_PER_DAY; if (bestTime > best.getTime()) { if (isInfoEnabled()) info (getName () + ".getSubtasks - had to correct bestTime, was " + new Date (bestTime) + " now " + best); bestTime = best.getTime(); }
long bestTime = getBestTime (early, best, daysSoFar);
  public Vector getSubtasks(Task parentTask) {    if (!(parentTask.getVerb ().equals (Constants.Verb.PROJECTSUPPLY)))      error ("Expecting a project supply task, got " + parentTask);    Vector childTasks = new Vector ();    // create the d.o.    Asset supplyAsset = parentTask.getDirectObject();    Preference pref = prefHelper.getPrefWithAspectType (parentTask, AlpineAspectType.DEMANDRATE);    double ratePerSec = prefHelper.getPreferenceBestValue (pref); // base number is in tons per second!    double ratePerDay = ratePerSec*SECS_PER_DAY;    Date readyAt = prefHelper.getReadyAt   (parentTask);    Date early   = getEarlyDate (parentTask);    Date best    = prefHelper.getBestDate  (parentTask);    Date late    = getLateDate  (parentTask);    if (early.getTime () < readyAt.getTime ())      early = readyAt;    if (best.getTime () < readyAt.getTime ())      best = readyAt;    long window = best.getTime () - readyAt.getTime();    long originalWindowInDays = window/MILLIS_PER_DAY;    long numSubtasks = window/(CHUNK_DAYS*MILLIS_PER_DAY);    if (window - (numSubtasks * CHUNK_DAYS*MILLIS_PER_DAY) != 0)      numSubtasks++;    if (numSubtasks < 1) {      error (getName () + ".getSubtasks - task " + parentTask.getUID () +             " will create no subtasks?  Window was " + originalWindowInDays + " days");    }    if (isInfoEnabled ()) {      info (getName () + ".getSubtasks - task " + parentTask.getUID () +            " from " + readyAt +            " to " + best +            " will produce " + numSubtasks + " subtasks.");    }    String unit = (prepHelper.hasPrepNamed (parentTask, Constants.Preposition.FOR)) ?        (String) prepHelper.getIndirectObject (parentTask, Constants.Preposition.FOR) : "null";    // create one subtask for every chunk set of days, with an asset that is the total    // delivered over the period = days*ratePerDay    long daysSoFar = 0;    double totalQuantity = 0;    double targetQuantity = ((double) (window/1000l))*ratePerSec;    Date lastBestDate = readyAt;    if (isInfoEnabled ()) {      info (getName () + ".getSubtasks - task " + parentTask.getUID () + " target quantity " + targetQuantity +            " windowInSec " + window/1000l + " rate/sec " + ratePerSec);    }    for (int i = 0; i < (int) numSubtasks; i++) {      boolean onLastTask = (window/MILLIS_PER_DAY) < CHUNK_DAYS;      long daysToChunk = (onLastTask) ? window/MILLIS_PER_DAY : CHUNK_DAYS;      if (isInfoEnabled () && onLastTask)        info ("on last task - days " + daysToChunk + " since " + window/MILLIS_PER_DAY + " < " + CHUNK_DAYS);      daysSoFar += daysToChunk;      window    -= daysToChunk*MILLIS_PER_DAY;      double quantity = ((double)daysToChunk) * ratePerDay;      if (onLastTask && ((totalQuantity + quantity) != targetQuantity)) {        if (isInfoEnabled ())          info (" task " + parentTask.getUID () +                " adjusting quantity from " +quantity +                " to " + (targetQuantity - totalQuantity) +                " total is " + totalQuantity);        quantity = targetQuantity - totalQuantity;      } else if (isInfoEnabled ()) {        info (".getSubtasks - task " + parentTask.getUID () + " quantity is " + quantity +              " chunk days " + daysToChunk+ " rate " + ratePerDay);      }      if (quantity < 0.00001) {        if (isInfoEnabled()) {          info (".getSubtasks - task " + parentTask.getUID () +                " gets a quantity of zero, ratePerDay was " + ratePerDay +                " chunk days " +daysToChunk);        }      }      //      double massInKGs = ((GLMAsset)supplyAsset).getPhysicalPG().getMass().getKilograms()*quantity;      double massInSTons = quantity;      totalQuantity += quantity;      //  CHANGE to JUST Grab the d.o.?      // set item id pg to show it's a reservation, and not a normal task's asset      ItemIdentificationPG itemIDPG = (ItemIdentificationPG) supplyAsset.getItemIdentificationPG();      String itemID = itemIDPG.getItemIdentification();      String itemNomen = itemIDPG.getNomenclature ();      if (itemID == null) {        TypeIdentificationPG typeID = supplyAsset.getTypeIdentificationPG ();        itemID = typeID.getTypeIdentification();      }      if (itemNomen == null) {        TypeIdentificationPG typeID = supplyAsset.getTypeIdentificationPG ();        itemNomen = typeID.getNomenclature();      }      Asset directObject =          getMilvanDirectObject (itemNomen, itemID, unit, massInSTons);      Task subTask = makeTask (parentTask, directObject);//deliveredAsset);      long bestTime = early.getTime() + ((long)daysSoFar)*MILLIS_PER_DAY;      if (bestTime > best.getTime()) {        if (isInfoEnabled())          info (getName () +                ".getSubtasks - had to correct bestTime, was " + new Date (bestTime) +                " now " + best);        bestTime = best.getTime();      }      Date startDate = new Date(getAlarmService().currentTimeMillis () +                                TASK_TRANSMISSION_DELAY);      if (isInfoEnabled ())        info (getName () + ".getSubtasks - making task " + subTask.getUID() +              " with best arrival " + new Date(bestTime) + " and start " + startDate);      prefHelper.replacePreference((NewTask)subTask,                                   prefHelper.makeEndDatePreference (ldmf,                                                                     early,                                                                     new Date (bestTime),                                                                     late));      prefHelper.replacePreference((NewTask)subTask,                                   prefHelper.makeStartDatePreference (ldmf, startDate));      prefHelper.removePrefWithAspectType (subTask, AlpineAspectType.DEMANDRATE); // we've included it in the d.o.      prepHelper.removePrepNamed (subTask, Constants.Preposition.MAINTAINING);      prepHelper.removePrepNamed (subTask, Constants.Preposition.REFILL);      prepHelper.addPrepToTask (subTask, prepHelper.makePrepositionalPhrase (ldmf, "Start", lastBestDate));      if (isInfoEnabled())        info (getName () + " publishing reservation " + subTask.getUID() +              " for " + itemNomen +              " from " + lastBestDate + " to " + new Date(bestTime) + " weight " +              //massInKGs + " kgs.");              massInSTons + " short tons.");      lastBestDate = new Date (bestTime);      childTasks.addElement (subTask);    }    // post condition    if (totalQuantity != targetQuantity) {      if (isWarnEnabled ())        warn (getName () + " total quantity " + totalQuantity +              " != original total " + targetQuantity +              " = window " + originalWindowInDays +              " * ratePerDay " + ratePerDay);    }    if (isInfoEnabled())      info (getName () + " returning " + childTasks.size() + " subtasks for " + parentTask.getUID());    return childTasks;  }