/** * @param availBins the bins to choose from. This method asserts that they are sorted in * descending order. * @param vol * @param weight * @return */ private DefaultMutableTreeNode findBinNode( final List<DefaultMutableTreeNode> availBins, final BigDecimal vol, final BigDecimal weight) { if (availBins.isEmpty()) { throw new NoContainerException(false, false); } // check if everything fits into one bin, starting with the smallest one for (int i = availBins.size() - 1; i >= 0; i--) { final DefaultMutableTreeNode packNode = availBins.get(i); final AvailableBins bin = (AvailableBins) packNode.getUserObject(); final I_M_PackagingContainer pc = bin.getPc(); if (pc.getMaxVolume().compareTo(vol) >= 0 && pc.getMaxWeight().compareTo(weight) >= 0 && bin.getQtyAvail() > 0) { return packNode; } } // no bin is big enough, return the biggest one we got return availBins.get(0); }
/** * Sums up the volume and weight of all items still unpacked, selects a bin from <code>availBins * </code> and updates <code>model</code> accordingly. * * <p>If there is no bin large enough for the summed up weight and volume, the largest bin * available is added. * * @param unallocNodes * @param availBins * @param usedBins * @param model * @param trxName */ private void addBinForUsage( final Properties ctx, final List<DefaultMutableTreeNode> unallocNodes, final List<DefaultMutableTreeNode> availBins, final List<DefaultMutableTreeNode> usedBins, final PackingTreeModel model, final String trxName) { logger.debug("Computing the overall volume and weight we still need to cover"); BigDecimal unallocVolumeSum = BigDecimal.ZERO; BigDecimal unallocWeightSum = BigDecimal.ZERO; BigDecimal unallocVolumeMax = BigDecimal.ZERO; BigDecimal unallocWeightMax = BigDecimal.ZERO; for (final DefaultMutableTreeNode currentNode : unallocNodes) { final LegacyPackingItem pi = getPI(currentNode); final BigDecimal volSingle = pi.retrieveVolumeSingle(trxName); final BigDecimal weightSingle = pi.retrieveWeightSingle(trxName); unallocVolumeSum = unallocVolumeSum.add(pi.getQtySum().multiply(volSingle)); unallocWeightSum = unallocWeightSum.add(pi.getQtySum().multiply(weightSingle)); if (unallocVolumeMax.compareTo(volSingle) < 0) { unallocVolumeMax = volSingle; } if (unallocWeightMax.compareTo(weightSingle) < 0) { unallocWeightMax = weightSingle; } } logger.debug( "Still required: volume-sum=" + unallocVolumeSum + "; volume-max=" + unallocVolumeMax + "; weight-sum:" + unallocWeightSum + "; weight-max=" + unallocWeightMax); removeUnavailableBins(availBins, unallocVolumeMax, unallocWeightMax); final DefaultMutableTreeNode nexBinToUseNode = findBinNode(availBins, unallocVolumeSum, unallocWeightSum); final AvailableBins foundBin = getBin(nexBinToUseNode); foundBin.setQtyAvail(foundBin.getQtyAvail() - 1); final I_M_PackagingContainer foundPC = foundBin.getPc(); final UsedBin newPack = new UsedBin(ctx, foundPC, trxName); logger.info("Adding " + newPack); final DefaultMutableTreeNode newPackNode = new DefaultMutableTreeNode(newPack); usedBins.add(newPackNode); model.insertNodeInto(newPackNode, model.getUsedBins(), model.getUsedBins().getChildCount()); }
private void removeUnavailableBins( final List<DefaultMutableTreeNode> availBins, final BigDecimal requiredVolume, final BigDecimal requiredWeigth) { final Set<DefaultMutableTreeNode> nodesToRemove = new HashSet<DefaultMutableTreeNode>(); boolean insufficientVolume = false; boolean insufficientWeight = false; for (final DefaultMutableTreeNode binNode : availBins) { final AvailableBins bins = getBin(binNode); if (bins.getQtyAvail() <= 0) { logger.info("Bins '" + bins + "' are no longer available"); nodesToRemove.add(binNode); } if (bins.getPc().getMaxVolume().compareTo(requiredVolume) < 0) { logger.info("Payload volume of available bins '" + bins + "' is too small"); nodesToRemove.add(binNode); } if (bins.getPc().getMaxWeight().compareTo(requiredWeigth) < 0) { logger.info("Payload weight of available bins '" + bins + "' is too small"); nodesToRemove.add(binNode); } } availBins.removeAll(nodesToRemove); if (availBins.isEmpty()) { throw new NoContainerException(insufficientVolume, insufficientWeight); } }