| Quintiq file version 2.0 | 
| #parent: #root | 
| Method CapacityRounding ( | 
|   MacroPlan macroPlan, | 
|   Real timeDifference, | 
|   UnitPeriodTimeBase uptb, | 
|   UnitPeriodTimeBases uptbs | 
| ) | 
| { | 
|   TextBody: | 
|   [* | 
|     debuginfo( "需要圆整的时间(单位:小时)", timeDifference, "    Free capacity(单位:小时)", uptb.FreeCapacity().HoursAsReal(), "    ChangeoverDuration(单位:小时)", uptb.ChangeoverDuration().HoursAsReal(), "    需要圆整的产能周期的开始时间:", uptb.StartDate().Format( "Y-M2-D2" ) ); | 
|     //timeDifference         := uptb.FreeCapacity().HoursAsReal() - uptb.ChangeoverDuration().HoursAsReal(); | 
|     nextUnitPeriodTimeBase := ifexpr( isnull( uptb.Next().astype( UnitPeriodTimeBase ) ), select( uptbs, Elements, tempUPTB, tempUPTB.Start() = uptb.End() ), uptb.Next().astype( UnitPeriodTimeBase ) ); | 
|     //debuginfo( "考虑库存和lotsize" ); | 
|     //while ( timeDifference > 0 and not isnull( nextUnitPeriodTimeBase ) ) { | 
|     //  debuginfo( "开始向时间为:", nextUnitPeriodTimeBase.StartDate().Format( "Y-M2-D2" ), "的产能周期借" ); | 
|     //       | 
|     //  traverse ( nextUnitPeriodTimeBase, PeriodTaskOperation, pto, guard( pto.Operation().RoutingStep().Routing().Start(), uptb.StartDate() ) <= uptb.StartDate() and | 
|     //                                                               guard( pto.Operation().RoutingStep().Routing().End(), uptb.End().Date() ) >= uptb.End().Date() and | 
|     //                                                               timeDifference > 0 ) {          | 
|     //    minimumQuantityThatCanBeBorrowed := Real::MaxReal(); | 
|     //    minimumCapacityThatCanBeBorrowed := Real::MaxReal(); | 
|     //    traverse ( pto, NewSupply, ns, true ) { | 
|     //      targetBorrowSplitShiftLotsizeLimit := select( scenarioManager, SplitShiftLotsizeLimit, tempSSLL, tempSSLL.unitID() = unitPeriodTimeBase.UnitID() and | 
|     //                                                                                                       tempSSLL.productID() = ns.ProductInStockingPointInPeriodPlanningLeaf().ProductInStockingPoint_MP().ProductID() and | 
|     //                                                                                                       tempSSLL.startTime() <= ns.Start().Date() and | 
|     //                                                                                                       tempSSLL.endTime() >= ns.End().Date() ); | 
|     //      minimumQuantityThatCanBeBorrowed := minvalue(  | 
|     //                                                    minvalue( ifexpr( not isnull( targetBorrowSplitShiftLotsizeLimit ) and targetBorrowSplitShiftLotsizeLimit.lotsize() < ns.Quantity(),  | 
|     //                                                                      ns.Quantity() - targetBorrowSplitShiftLotsizeLimit.lotsize(),  | 
|     //                                                                      Real::MaxReal() ), | 
|     //                                                              minvalue(  | 
|     //                                                                        ifexpr( ( ns.ProductInStockingPointInPeriodPlanningLeaf().InventoryLevelEnd() - ns.ProductInStockingPointInPeriodPlanningLeaf().MinInventoryLevel() ) > 0,  | 
|     //                                                                                  ns.ProductInStockingPointInPeriodPlanningLeaf().InventoryLevelEnd() - ns.ProductInStockingPointInPeriodPlanningLeaf().MinInventoryLevel(),  | 
|     //                                                                                  0.0  | 
|     //                                                                               ),  | 
|     //                                                                        ns.Quantity()     | 
|     //                                                                       )  | 
|     //                                                             ), | 
|     //                                                    minimumCapacityThatCanBeBorrowed  | 
|     //                                                   ); | 
|     //      debuginfo( "nextUnitPeriodTimeBase的当前周期任务供应的产品名:", ns.ProductInStockingPointInPeriodPlanningLeaf().ProductInStockingPoint_MP().ProductID(), String::Tab(), | 
|     //                 "最小库存:", ns.ProductInStockingPointInPeriodPlanningLeaf().MinInventoryLevel(), String::Tab(), | 
|     //                 "现有库存:", ns.ProductInStockingPointInPeriodPlanningLeaf().InventoryLevelEnd(), String::Tab(), | 
|     //                 "供应数量:", ns.Quantity(), String::Tab(), | 
|     //                 "是否存在lotsize:", ifexpr( isnull( targetBorrowSplitShiftLotsizeLimit ), "不存在", "存在" ), String::Tab(), | 
|     //                 "lotsize数量:", ifexpr( isnull( targetBorrowSplitShiftLotsizeLimit ), -1, targetBorrowSplitShiftLotsizeLimit.lotsize() ) | 
|     //                ); | 
|     //                     | 
|     //      sourceProductInStockingPointInPeriodPlanningLeaf := select( ns, ProductInStockingPointInPeriodPlanningLeaf.ProductInStockingPoint_MP.ProductInStockingPointInPeriodPlanning.astype( ProductInStockingPointInPeriodPlanningLeaf ), tempPISPIPPL, tempPISPIPPL.Start() = unitPeriodTimeBase.Start() ); | 
|     //      sourceNewSupply := select( sourceProductInStockingPointInPeriodPlanningLeaf, NewSupply, tempNS, tempNS.Process_MP().AsProcess_MP().ID() = unitPeriodTimeBase.UnitID() ); | 
|     //      targetReturnSplitShiftLotsizeLimit := select( scenarioManager, SplitShiftLotsizeLimit, tempSSLL, tempSSLL.unitID() = unitPeriodTimeBase.UnitID() and | 
|     //                                                                                                       tempSSLL.productID() = sourceProductInStockingPointInPeriodPlanningLeaf.ProductInStockingPoint_MP().ProductID() and | 
|     //                                                                                                       tempSSLL.startTime() <= sourceProductInStockingPointInPeriodPlanningLeaf.Start().Date() and | 
|     //                                                                                                       tempSSLL.endTime() >= sourceProductInStockingPointInPeriodPlanningLeaf.End().Date() ); | 
|     //      minimumAcceptableQuantity := minvalue( ifexpr( not isnull( targetReturnSplitShiftLotsizeLimit ) and not isnull( sourceNewSupply ) and targetReturnSplitShiftLotsizeLimit.lotsize() > sourceNewSupply.Quantity(),  | 
|     //                                                     targetReturnSplitShiftLotsizeLimit.lotsize() - sourceNewSupply.Quantity(),  | 
|     //                                                     Real::MaxReal()  | 
|     //                                                    ), | 
|     //                                             ifexpr( ( sourceProductInStockingPointInPeriodPlanningLeaf.MaxInventoryLevel() - sourceProductInStockingPointInPeriodPlanningLeaf.InventoryLevelEnd() ) > 0,  | 
|     //                                                       sourceProductInStockingPointInPeriodPlanningLeaf.MaxInventoryLevel() - sourceProductInStockingPointInPeriodPlanningLeaf.InventoryLevelEnd(),  | 
|     //                                                       0.0  | 
|     //                                                    ) | 
|     //                                            );                                             | 
|     //      debuginfo( "要圆整的时间:", sourceProductInStockingPointInPeriodPlanningLeaf.Start().Date().Format( "Y-M2-D2" ), String::Tab(), | 
|     //                 "要圆整的最大库存:", sourceProductInStockingPointInPeriodPlanningLeaf.MaxInventoryLevel(), String::Tab(), | 
|     //                 "要圆整的现有库存:", sourceProductInStockingPointInPeriodPlanningLeaf.InventoryLevelEnd(), String::Tab(), | 
|     //                 "要圆整的供应数量:", guard( sourceNewSupply.Quantity(), 0 ), String::Tab(), | 
|     //                 "是否存在lotsize:", ifexpr( isnull( targetReturnSplitShiftLotsizeLimit ), "不存在", "存在" ), String::Tab(), | 
|     //                 "lotsize数量:", ifexpr( isnull( targetReturnSplitShiftLotsizeLimit ), -1, targetReturnSplitShiftLotsizeLimit.lotsize() ), String::Tab(), | 
|     //                 "要圆整的最小接纳数量:", minimumAcceptableQuantity | 
|     //                ); | 
|     //         | 
|     //      minimumQuantityThatCanBeBorrowed := minvalue( minimumQuantityThatCanBeBorrowed, minimumAcceptableQuantity ); | 
|     //    } | 
|     //    debuginfo( "nextUnitPeriodTimeBase的当前周期任务供应数量:", pto.Quantity(), "    周期任务能借的最低数量:", minimumQuantityThatCanBeBorrowed );                                                      | 
|     //       | 
|     //    minimumCapacityThatCanBeBorrowed := minimumQuantityThatCanBeBorrowed / pto.Operation().Throughput(); | 
|     //    unifiedProcessingTimeOfRounding := minvalue( timeDifference, minimumCapacityThatCanBeBorrowed );  | 
|     //    debuginfo( "剩余圆整的产能:", timeDifference, "    nextUnitPeriodTimeBase的当前周期任务供应数量:", pto.Quantity(), "    能借的产能:", minimumCapacityThatCanBeBorrowed, " 统一借的产能:", unifiedProcessingTimeOfRounding );  | 
|     //    this.A_unifiedProcessingOfRoundingLogic( unifiedProcessingTimeOfRounding, unitPeriodTimeBase, pto, macroPlan );   | 
|     //    timeDifference := timeDifference - unifiedProcessingTimeOfRounding;   | 
|     //  } | 
|     //      | 
|     //  if ( isnull( nextUnitPeriodTimeBase.Next() ) ) { | 
|     //    nextUnitPeriodTimeBase := select( unitPeriodTimeBases, Elements, tempUPTB, tempUPTB.Start() = nextUnitPeriodTimeBase.End() ); | 
|     //  } else { | 
|     //    nextUnitPeriodTimeBase := nextUnitPeriodTimeBase.Next().astype( UnitPeriodTimeBase ); | 
|     //  } | 
|     //  debuginfo( "。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。" ); | 
|     //} | 
|      | 
|     sourceChangeover := uptb.ChangeoverDuration(); | 
|     targetChangeover := Duration::Zero(); | 
|      | 
|     debuginfo( "需要圆整的时间(单位:小时)", timeDifference, "    考虑ChangeOver条件圆整使其达到整班" ); | 
|     nextUnitPeriodTimeBase := ifexpr( isnull( uptb.Next().astype( UnitPeriodTimeBase ) ), select( uptbs, Elements, tempUPTB, tempUPTB.Start() = uptb.End() ), uptb.Next().astype( UnitPeriodTimeBase ) ); | 
|     while ( timeDifference > 0 and not isnull( nextUnitPeriodTimeBase ) ) { | 
|       debuginfo( "开始向时间为:", nextUnitPeriodTimeBase.StartDate().Format( "Y-M2-D2" ), "的产能周期借" ); | 
|       traverse ( nextUnitPeriodTimeBase, PeriodTaskOperation, pto, guard( pto.Operation().RoutingStep().Routing().Start(), uptb.StartDate() ) <= uptb.StartDate() and | 
|                                                                    guard( pto.Operation().RoutingStep().Routing().End(), uptb.End().Date() ) >= uptb.End().Date() and | 
|                                                                    exists( uptb, PeriodTaskOperation.Operation, tempO, tempO = pto.Operation() )                  and | 
|                                                                    timeDifference > 0 ) { | 
|         minimumCapacityThatCanBeBorrowed := pto.Quantity() / pto.Operation().Throughput(); | 
|         unifiedProcessingTimeOfRounding := minvalue( timeDifference, minimumCapacityThatCanBeBorrowed );  | 
|         debuginfo( "剩余圆整的产能:", timeDifference, "    nextUnitPeriodTimeBase的当前周期任务供应数量:", pto.Quantity(), "    能借的产能:", minimumCapacityThatCanBeBorrowed, " 统一借的产能:", unifiedProcessingTimeOfRounding, "    借之前changeover时间:", uptb.ChangeoverDuration() );  | 
|         this.UnifiedProcessingOfRoundingLogic( unifiedProcessingTimeOfRounding, uptb, pto, macroPlan );  | 
|         targetChangeover := uptb.ChangeoverDuration(); | 
|         timeDifference   := timeDifference - unifiedProcessingTimeOfRounding;                                                  | 
|       } | 
|           | 
|       if ( isnull( nextUnitPeriodTimeBase.Next() ) ) { | 
|         nextUnitPeriodTimeBase := select( uptbs, Elements, tempUPTB, tempUPTB.Start() = nextUnitPeriodTimeBase.End() ); | 
|       } else { | 
|         nextUnitPeriodTimeBase := nextUnitPeriodTimeBase.Next().astype( UnitPeriodTimeBase ); | 
|       } | 
|     } | 
|          | 
|     debuginfo( "需要圆整的时间(单位:小时)", timeDifference, "    不考虑任何条件圆整使其到达整班" ); | 
|     nextUnitPeriodTimeBase := ifexpr( isnull( uptb.Next().astype( UnitPeriodTimeBase ) ), select( uptbs, Elements, tempUPTB, tempUPTB.Start() = uptb.End() ), uptb.Next().astype( UnitPeriodTimeBase ) ); | 
|     while ( timeDifference > 0 and not isnull( nextUnitPeriodTimeBase ) ) { | 
|       debuginfo( "开始向时间为:", nextUnitPeriodTimeBase.StartDate().Format( "Y-M2-D2" ), "的产能周期借" ); | 
|       traverse ( nextUnitPeriodTimeBase, PeriodTaskOperation, pto, guard( pto.Operation().RoutingStep().Routing().Start(), uptb.StartDate() ) <= uptb.StartDate() and | 
|                                                                    guard( pto.Operation().RoutingStep().Routing().End(), uptb.End().Date() ) >= uptb.End().Date() and | 
|                                                                    timeDifference > 0 ) { | 
|         minimumCapacityThatCanBeBorrowed := pto.Quantity() / pto.Operation().Throughput(); | 
|         unifiedProcessingTimeOfRounding := minvalue( timeDifference, minimumCapacityThatCanBeBorrowed );  | 
|         debuginfo( "剩余圆整的产能:", timeDifference, "    nextUnitPeriodTimeBase的当前周期任务供应数量:", pto.Quantity(), "    能借的产能:", minimumCapacityThatCanBeBorrowed, " 统一借的产能:", unifiedProcessingTimeOfRounding, "    当前changeover时间:", uptb.ChangeoverDuration().HoursAsReal() );  | 
|         this.UnifiedProcessingOfRoundingLogic( unifiedProcessingTimeOfRounding, uptb, pto, macroPlan );   | 
|         timeDifference := timeDifference - unifiedProcessingTimeOfRounding;                                                  | 
|       } | 
|           | 
|       if ( isnull( nextUnitPeriodTimeBase.Next() ) ) { | 
|         nextUnitPeriodTimeBase := select( uptbs, Elements, tempUPTB, tempUPTB.Start() = nextUnitPeriodTimeBase.End() ); | 
|       } else { | 
|         nextUnitPeriodTimeBase := nextUnitPeriodTimeBase.Next().astype( UnitPeriodTimeBase ); | 
|       } | 
|     } | 
|      | 
|     if ( ( targetChangeover - sourceChangeover ).HoursAsReal() > 0.0 ) { | 
|       this.ZeroCapacityReplenishment( macroPlan, ( targetChangeover - sourceChangeover ).HoursAsReal(), uptb, uptbs ); | 
|     } | 
|   *] | 
| } |