# PiLotCheckManagerImpl.java

    package com.mycim.server.pilot.manager.impl;

    import com.fa.sesa.exception.Assert;
    import com.fa.sesa.exception.Errors;
    import com.fa.sesa.i18n.I18nUtils;
    import com.fa.sesa.threadlocal.LocalContext;
    import com.mycim.framework.utils.lang.BooleanUtils;
    import com.mycim.framework.utils.lang.ObjectUtils;
    import com.mycim.framework.utils.lang.StringUtils;
    import com.mycim.framework.utils.lang.collections.CollectionUtils;
    import com.mycim.framework.utils.lang.time.DateUtils;
    import com.mycim.server.base.manager.NamedObjectManager;
    import com.mycim.server.ems.manager.EntityManager;
    import com.mycim.server.ems.manager.EquipmentManager;
    import com.mycim.server.pilot.manager.PiLotCheckManager;
    import com.mycim.server.pilot.manager.PiLotReqManager;
    import com.mycim.server.wip.manager.EquipmentQueryManager;
    import com.mycim.server.wip.manager.PiLotInqManager;
    import com.mycim.valueobject.Constants;
    import com.mycim.valueobject.MessageIdList;
    import com.mycim.valueobject.ObjectList;
    import com.mycim.valueobject.consts.EntityEnum;
    import com.mycim.valueobject.consts.PiLotStatusEnum;
    import com.mycim.valueobject.consts.PiLotTypeEnum;
    import com.mycim.valueobject.ems.Entity;
    import com.mycim.valueobject.ems.Equipment;
    import com.mycim.valueobject.ems.Season;
    import com.mycim.valueobject.ems.pilot.IdleType;
    import com.mycim.valueobject.ems.pilot.PiLotSetup;
    import com.mycim.valueobject.ems.pilot.PiLotView;
    import com.mycim.valueobject.ems.pilot.dto.PiLotSetupQueryDTO;
    import com.mycim.valueobject.sys.Message;
    import com.mycim.valueobject.wip.Lot;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.Date;
    import java.util.List;
    import java.util.Objects;

    /**
     * @author songpy
     * @version 1.0.0
     * @date 2021/9/12
     **/
    @Service
    @Transactional
    public class PiLotCheckManagerImpl implements PiLotCheckManager {
        @Autowired
        private PiLotInqManager piLotInqManager;

        @Autowired
        private NamedObjectManager namedObjectManager;

        @Autowired
        private PiLotReqManager piLotReqManager;

        @Autowired
        private EquipmentQueryManager equipmentQueryManager;

        @Autowired
        private EquipmentManager equipmentManager;

        @Autowired
        private EntityManager entityManager;

        @Override
        public String checkEquipmentPiLot(Lot lot, Equipment equipment) {
            StringBuilder msg = new StringBuilder(StringUtils.EMPTY);
            PiLotView view = piLotInqManager.getPiLotViewByLotRrn(lot.getLotRrn());
            if (Objects.isNull(view)) {
                view = piLotInqManager.getPiLotViewByChildLotRrn(lot.getLotRrn());
            }

            // pilot绑定lot
            if (Objects.nonNull(view)) {
                // 绑定lot  不允许进入pilot设置机台外的其他机台
                if (StringUtils.equalsIgnoreCase(lot.getRouteId(), view.getStartRoute()) &&
                        StringUtils.equalsIgnoreCase(lot.getOperationId(), view.getStartStep())) {
                    Equipment viewEquipment = equipmentManager.getEquipment(view.getEqptRrn());
                    if (!StringUtils.equalsIgnoreCase(getParentEquipment(viewEquipment), getParentEquipment(equipment))) {
                        msg.append(I18nUtils.getMessage(MessageIdList.PILOT_CHECK_EQPT_IN_USE, new Object[]{equipment.getInstanceId(),view.getEqptId()}));
                    }
                }
                if (StringUtils.isNotEmpty(msg.toString())) {
                    return msg.toString();
                }

                if (!StringUtils.equalsIgnoreCase(equipment.getObjectSubtype(), "P")) {
                    return msg.toString();
                }

                //子母批模式
                if (StringUtils.equalsIgnoreCase(view.getSingleLot(), PiLotStatusEnum.NO.toString())) {
                    msg.append(checkSplitBefore(equipment, view));
                    if (StringUtils.isNotEmpty(msg.toString())) {
                        return msg.toString();
                    }

                    msg.append(checkSplitAfter(lot, equipment, view));
                    if (StringUtils.isNotEmpty(msg.toString())) {
                        return msg.toString();
                    }
                }

                // 单批模式
                if (StringUtils.equalsIgnoreCase(view.getSingleLot(), PiLotStatusEnum.YES.toString())) {
                    msg.append(checkSingleLot(lot,equipment,view));
                    if (StringUtils.isNotEmpty(msg.toString())) {
                        return msg.toString();
                    }
                }
            } else {
                // 触发pilot
                msg.append(checkIdleTimePiLot(equipment));
                if (StringUtils.isNotEmpty(msg.toString())) {
                    return msg.toString();
                }

                // 校验设置pilot  其他lot卡控进入设备
                msg.append(checkEquipment(equipment));

            }
            return msg.toString();
        }

        @Override
        public void checkEquipmentPiLotByPM(String eqpId) {
            PiLotSetupQueryDTO queryDTO = new PiLotSetupQueryDTO();
            queryDTO.addStatus(PiLotStatusEnum.ON.toString());
            queryDTO.setType(PiLotTypeEnum.PM.toString());
            queryDTO.setEqptRrn(
                    namedObjectManager.getNamedObjectRrn(eqpId, LocalContext.getFacilityRrn(), ObjectList.ENTITY_KEY));

            PiLotSetup setup = piLotInqManager.getPiLotSetup(queryDTO);
            if (Objects.nonNull(setup)) {
                piLotReqManager.createPiLotView(setup);
            }
        }

        @Override
        public void checkPiLotBoundLot(Long lotRrn) {
            PiLotView view = piLotInqManager.getPiLotViewByLotRrn(lotRrn);
            Assert.state(Objects.nonNull(view), Errors.create().key(MessageIdList.PILOT_NOT_USED_SPLIT)
                                                      .content("This lot cannot be used Pilot Split").build());

            Assert.state(view.getCanSplit(),
                         Errors.create().key(MessageIdList.PILOT_NOT_SPLIT).content("This Lot Not Split").build());

            Assert.state(StringUtils.equalsIgnoreCase(view.getSingleLot(), PiLotStatusEnum.NO.toString()),
                         Errors.create().key(MessageIdList.PILOT_SINGLE_LOT_CANNOT_SPLIT)
                               .content("Pilot single lot cannot split!").build());
        }

        @Override
        public void checkPiLotNormalFunction(long lotRrn,long baseLotRrn) {
            PiLotView piLotView = getPiLotView(lotRrn, baseLotRrn);
            Assert.state(ObjectUtils.isEmpty(piLotView), Errors.create().key(MessageIdList.PILOT_NOT_USED_FUNCTION)
                                                                 .content("Pilot This Function cannot be used").build());
        }

        @Override
        public String checkEquipmentPiLot(Lot lot, Long eqptRrn) {
            Equipment equipment = equipmentManager.getEquipment(eqptRrn);
            return checkEquipmentPiLot(lot, equipment);
        }

        @Override
        public PiLotView getPiLotView(Long lotRrn, Long baseLotRrn) {
            PiLotView piLotView = piLotInqManager.getPiLotViewByLotRrn(lotRrn);
            if (ObjectUtils.isNotEmpty(piLotView)) {
                return piLotView;
            }
            if (lotRrn.longValue() == baseLotRrn.longValue()){
                return  piLotInqManager.getPiLotViewByLotRrn(baseLotRrn);
            } else {
                return  piLotInqManager.getPiLotViewByChildLotRrn(lotRrn);
            }
        }

        @Override
        public void checkPilotRepositionStep(Lot lot, Boolean pilotFlag) {
            PiLotView view = getPiLotView(lot.getLotRrn(),lot.getBasedLotRrn());
            if(pilotFlag) {
                if (ObjectUtils.isEmpty(view)){
                    Assert.state(false, Errors.create().key(MessageIdList.PILOT_NOT_USED_SPLIT)
                                              .content("This lot cannot be used Pilot Split").build());
                }else {
                    // 单批模式没有分批可以使用跳步     子母批模式未分批前不能使用跳步
                    if (StringUtils.equalsIgnoreCase(view.getSingleLot(), PiLotStatusEnum.NO.toString())) {
                        Assert.state(StringUtils.isNotEmpty(view.getChildLotId()), Errors.create().key(MessageIdList.PILOT_NOT_SPLIT)
                                                                                         .content("This Lot Not Split").build());
                    }
                }
            } else {
                Assert.state(ObjectUtils.isEmpty(view), Errors.create().key(MessageIdList.PILOT_NOT_USED_FUNCTION)
                                                              .content("Pilot This Function cannot be used").build());
            }
        }

        private String checkSplitAfter(Lot lot, Equipment equipment, PiLotView view) {
            StringBuilder msg = new StringBuilder();
            PiLotView piLotView = piLotInqManager.getSplitAfterPiLotViewByEqpt(equipment.getInstanceId(),
                                                                               equipment.getInstanceRrn());

            // 分批后母批不能进入任何设备  子批只能走pilot chamber     #42103
            // 没有设置pilot其他的chamber #42283
            if(ObjectUtils.isEmpty(piLotView)
                    && StringUtils.equalsIgnoreCase(view.getStatus(), PiLotStatusEnum.WAITMERGE.toString())
                    && StringUtils.isNotEmpty(equipment.getParentEntityId())) {
                Equipment parentEquipment = equipmentManager.getEquipment(equipment.getParentEntityRrn());
                //子批flow未完成
                if (!view.getComplete()) {
                    //母批 需等待
                    if (StringUtils.equalsIgnoreCase(view.getBoundLotId(),lot.getLotId())) {
                        msg.append(I18nUtils.getMessage(MessageIdList.PILOT_CHILDLOT_FLOW_NOCOMPLETE,"{}:Pilot child lot flow not complete!",
                                                        new Object[]{equipment.getInstanceId()}));
                    }
                    //子批
                    if (StringUtils.equalsIgnoreCase(view.getChildLotId(),lot.getLotId())) {
                        checkPilotChamber(equipment, parentEquipment, view.getParallelRunType(), msg);
                    }
                    //子批flow完成 子批hold  母批走flow
                } else {
                    checkPilotChamber(equipment, parentEquipment, view.getParallelRunType(), msg);
                }
            }

            if (Objects.isNull(piLotView)) {
                return msg.toString();
            }

            // 母批
            if (StringUtils.equalsIgnoreCase(lot.getLotId(), piLotView.getBoundLotId())) {
                if (!piLotView.getComplete()) {
                    msg.append(I18nUtils.getMessage(MessageIdList.PILOT_CHILDLOT_FLOW_NOCOMPLETE,"{}:Pilot child lot flow not complete!",
                                                    new Object[]{equipment.getInstanceId()}));
                }
            }

            return msg.toString();
        }

        private String checkSplitBefore(Equipment equipment,PiLotView view) {
            // 先检查是否存在已经触发的
            StringBuilder msg = new StringBuilder();
            List<PiLotView> piLotViewList = piLotInqManager.getSplitBeforePiLotViewByEqpt(equipment.getInstanceId(),
                                                                                          equipment.getInstanceRrn());

            // 分批前母批 不能进入任何设备  chamber
            if(CollectionUtils.isEmpty(piLotViewList)) {
                if((StringUtils.equalsIgnoreCase(view.getStatus(),PiLotStatusEnum.WAITSPLIT.toString()) ||
                        (StringUtils.equalsIgnoreCase(view.getStatus(),PiLotStatusEnum.WAITMERGE.toString()) &&
                                StringUtils.isEmpty(view.getChildLotId()))
                        ) && StringUtils.isNotEmpty(equipment.getParentEntityId())) {
                    msg.append(I18nUtils.getMessage(MessageIdList.PILOT_PARENT_LOT_NOT_SPLIT,"{}:Pilot parent lot not spilt!",
                                                    new Object[]{equipment.getInstanceId()}));
                }
            }

            for (PiLotView piLotView : piLotViewList) {
               if (StringUtils.equalsIgnoreCase(piLotView.getStatus(), PiLotStatusEnum.WAITSPLIT.toString()) ||
                        (StringUtils.equalsIgnoreCase(piLotView.getStatus(),PiLotStatusEnum.WAITMERGE.toString()) &&
                        StringUtils.isEmpty(piLotView.getChildLotId()))) {
                    msg.append(I18nUtils.getMessage(MessageIdList.PILOT_PARENT_LOT_NOT_SPLIT,"{}:Pilot parent lot not spilt!",
                                                    new Object[]{equipment.getInstanceId()}));
               }
            }
            return msg.toString();
        }

        private String checkIdleTimePiLot(Equipment equipment) {
            StringBuilder msg = new StringBuilder();
            Boolean needPiLot = false;
            PiLotSetup piLotSetup = piLotInqManager.getPiLotSetupIdleByEquipment(equipment.getInstanceId(),
                                                                                 equipment.getInstanceRrn());
            if (Objects.nonNull(piLotSetup)) {

                needPiLot = checkNeedPilotByTime(piLotSetup, equipment, needPiLot);

                if (Boolean.TRUE.equals(needPiLot)) {
                    piLotReqManager.createPiLotView(piLotSetup);
                    piLotSetup = piLotInqManager.getPiLotSetupByRrn(piLotSetup.getPiLotRrn());
                    PiLotView view = piLotInqManager.getPiLotViewByRrn(piLotSetup.getBoundViewRrn());
                    // msg.append("Pilot:" + view.getViewId() + ",Please handle(bound Lot)!</br>");
                    msg.append(I18nUtils.getMessage(MessageIdList.PILOT_SETUP_AND_TRIGGER, "{}:setup and trigger pilot!Please assign lot!Pilot numberId:{}!",
                                                    new Object[]{equipment.getInstanceId(), view.getViewId()}));
                }
            }
            return msg.toString();
        }

        private Long getEquipmentMaxRunTime(PiLotSetup piLotSetup, IdleType idleType, Equipment equipment) {
            Long maxRunTime;
            String lastMoveInTimeStr;
            Date sysDate = new Date(System.currentTimeMillis());
            Date lastUpdateTime = Objects.nonNull(
                    piLotSetup.getCloseTime()) ? piLotSetup.getCloseTime() : piLotSetup.getCreateTime();
            Entity entity = entityManager.getEntity(equipment.getInstanceRrn());
            if (StringUtils.endsWithIgnoreCase(Season.SUBTYPE_LOTLEVEL, idleType.getSubType())) {

                lastMoveInTimeStr = equipmentQueryManager.getLastMoveInTimeByEqp(equipment.getInstanceId(),
                                                                                 equipment.getInstanceRrn());
            } else {
                Entity parentEntity = entityManager.getEntity(entity.getParentEntityRrn());
                lastMoveInTimeStr = equipmentQueryManager.getLastProcessStartTime(parentEntity.getInstanceRrn(),
                                                                                  parentEntity.getInstanceId(),
                                                                                  entity.getChamberType());

            }

            Date maxRunTimeStart = getEffectiveTime4PiLot(lastMoveInTimeStr, lastUpdateTime);

            maxRunTime = sysDate.getTime() - maxRunTimeStart.getTime();
            return maxRunTime;
        }

        private Long getEquipmentIdleByWaferLevel(Equipment equipment, PiLotSetup piLotSetup) {
            Long idleTimeSum = 0L;
            Date sysDate = new Date(System.currentTimeMillis());
            Date lastUpdateTime = Objects.nonNull(
                    piLotSetup.getCloseTime()) ? piLotSetup.getCloseTime() : piLotSetup.getCreateTime();
            String equipmentStatus = entityManager.getEntityCurrentStatus(equipment.getInstanceRrn());
            Entity entity = entityManager.getEntity(equipment.getInstanceRrn());
            String mainEquipmentId = namedObjectManager.getNamedObjectId(entity.getParentEntityRrn());

            if (StringUtils.equalsIgnoreCase(EntityEnum.IDLE.getValue(), equipmentStatus)) {
                String lastProcessEndTimeStr = equipmentQueryManager.getLastProcessEndTime(mainEquipmentId,
                                                                                           entity.getChamberType());
                Date lastProcessEndTime = getEffectiveTime4PiLot(lastProcessEndTimeStr, lastUpdateTime);
                idleTimeSum = sysDate.getTime() - lastProcessEndTime.getTime();
            } else if (StringUtils.equalsIgnoreCase(EntityEnum.RUN.getValue(), equipmentStatus)) {
                if (equipmentQueryManager.checkEquipmentHasRunningLot(entity.getParentEntityRrn())) {
                    idleTimeSum = 0L;
                } else {
                    Date idleStartTime;
                    String lastHoldTimeStr = equipmentQueryManager.getLastHoldTimeOnEqp(entity.getParentEntityRrn());
                    String equipmentLastMoveOutTimeStr = equipmentQueryManager.getLastProcessEndTime(mainEquipmentId,
                                                                                                     entity.getChamberType());
                    idleStartTime = getEffectiveTime4PiLot(lastHoldTimeStr, lastUpdateTime);
                    idleStartTime = getEffectiveTime4PiLot(equipmentLastMoveOutTimeStr, idleStartTime);
                    idleTimeSum = sysDate.getTime() - idleStartTime.getTime();
                }
            }
            return idleTimeSum;
        }

        private Long getEquipmentIdleByLotLevel(Equipment equipment, PiLotSetup piLotSetup) {
            Long idleTimeSum = 0L;
            Date sysDate = new Date(System.currentTimeMillis());
            Date lastUpdateTime = Objects.nonNull(
                    piLotSetup.getCloseTime()) ? piLotSetup.getCloseTime() : piLotSetup.getCreateTime();
            String equipmentStatus = entityManager.getEntityCurrentStatus(equipment.getInstanceRrn());
            if (StringUtils.equalsIgnoreCase(EntityEnum.IDLE.getValue(), equipmentStatus)) {

                String equipmentLastMoveOutTimeStr = equipmentQueryManager.getEquipmentLastMoveOutTime(
                        equipment.getInstanceId());
                Date equipmentLastMoveOutTime = getEffectiveTime4PiLot(equipmentLastMoveOutTimeStr, lastUpdateTime);
                idleTimeSum = sysDate.getTime() - equipmentLastMoveOutTime.getTime();

            } else if (StringUtils.equalsIgnoreCase(EntityEnum.RUN.getValue(), equipmentStatus)) {
                if (equipmentQueryManager.checkEquipmentHasRunningLot(equipment.getInstanceRrn())) {
                    idleTimeSum = 0L;
                } else {
                    String lastHoldTimeStr = equipmentQueryManager.getLastHoldTimeOnEqp(equipment.getInstanceRrn());
                    String equipmentLastMoveOutTimeStr = equipmentQueryManager.getEquipmentLastMoveOutTime(
                            equipment.getInstanceId());
                    Date idleStartTime = getEffectiveTime4PiLot(lastHoldTimeStr, lastUpdateTime);
                    idleStartTime = getEffectiveTime4PiLot(equipmentLastMoveOutTimeStr, idleStartTime);
                    idleTimeSum = sysDate.getTime() - idleStartTime.getTime();
                }
            }
            return idleTimeSum;
        }

        private Date getEffectiveTime4PiLot(String timeStr, Date lastUpdateTime) {
            Date effectiveTime;
            if (StringUtils.isNotBlank(timeStr)) {
                effectiveTime = DateUtils.parse(timeStr, DateUtils.DATE_FORMAT);
            } else {
                effectiveTime = lastUpdateTime;
            }
            effectiveTime = effectiveTime.after(lastUpdateTime) ? effectiveTime : lastUpdateTime;
            return effectiveTime;
        }

        private String getParentEquipment(Equipment equipment){
            if(StringUtils.isNotEmpty(equipment.getParentEntityId())){
                return equipment.getParentEntityId();
            }else {
                return equipment.getInstanceId();
            }
        }

        private String checkSingleLot(Lot lot, Equipment equipment,PiLotView view) {
            StringBuilder msg = new StringBuilder();
            PiLotView piLotView = piLotInqManager.getSingleLotPiLotViewByEqpt(equipment.getInstanceId(),
                                                                                          equipment.getInstanceRrn());
            //chamber机台 pilot逻辑
            if (Objects.isNull(piLotView) && StringUtils.isNotEmpty(equipment.getParentEntityId())) {
                Equipment parentEquipment = equipmentManager.getEquipment(equipment.getParentEntityRrn());
                checkPilotChamber(equipment, parentEquipment, view.getParallelRunType(), msg);
            }

            if (Objects.isNull(piLotView)) {
                return msg.toString();
            }

            return msg.toString();
        }

        // 没有绑定pilot的lot
        private String checkEquipment(Equipment equipment) {
            StringBuilder msg = new StringBuilder();
            PiLotView piLotView = piLotInqManager.getPiLotViewByEqpt(equipment.getInstanceId(),
                                                                            equipment.getInstanceRrn());

            if (Objects.isNull(piLotView)) {
                return msg.toString();
            }

            if (StringUtils.equalsIgnoreCase(piLotView.getStatus(), PiLotStatusEnum.ONGOING.toString())
                    && StringUtils.isEmpty(piLotView.getBoundLotId())) {
                msg.append(I18nUtils.getMessage(MessageIdList.PILOT_NOT_ASSIGN_LOT, "{}:setup pilot!Please assign lot!Pilot NumberId:{}!",
                                                new Object[]{equipment.getInstanceId(), piLotView.getViewId()}));
            } else if ( StringUtils.equalsIgnoreCase(piLotView.getStatus(), PiLotStatusEnum.WAITCOMPLETE.toString()) ||
                        StringUtils.equalsIgnoreCase(piLotView.getStatus(), PiLotStatusEnum.WAITMERGE.toString()) ||
                        StringUtils.equalsIgnoreCase(piLotView.getStatus(), PiLotStatusEnum.WAITSPLIT.toString())){
                msg.append(I18nUtils.getMessage(MessageIdList.PILOT_EQPT_SETUP_PILOT, "{}:setup pilot!Pilot NumberId:{}!",
                                                new Object[]{equipment.getInstanceId(),piLotView.getViewId()}));
            }
            return msg.toString();
        }

        /**
         * pilot chamber机台卡控逻辑
         * @param equipment
         * @param parentEquipment
         * @param runType
         * @param msg
         */
        private void checkPilotChamber(Equipment equipment, Equipment parentEquipment, String runType, StringBuilder msg) {
            // 并行chamber single模式卡控
            if (StringUtils.equalsIgnoreCase(parentEquipment.getChamberMode(), PiLotStatusEnum.PARALLEL.toString()) &&
                    StringUtils.equalsIgnoreCase(runType, PiLotStatusEnum.SINGLE.toString())) {
                msg.append(I18nUtils.getMessage(MessageIdList.PILOT_PARALLEL_EQPT_SIGNLE,"{}:Pilot setup parallel run type is single!",
                                                new Object[]{equipment.getInstanceId()}));
            }
            // 并行chamber mulit模式  其他腔设置pilot
            if (StringUtils.equalsIgnoreCase(parentEquipment.getChamberMode(), PiLotStatusEnum.PARALLEL.toString()) &&
                    StringUtils.equalsIgnoreCase(runType, PiLotStatusEnum.MULTI.toString())) {
                PiLotView otherPiLotView = piLotInqManager.getPiLotViewByEqpt(equipment.getInstanceId(),
                                                                                        equipment.getInstanceRrn());
                if (ObjectUtils.isNotEmpty(otherPiLotView)) {
                    msg.append(I18nUtils.getMessage(MessageIdList.PILOT_EQPT_SETUP_PILOT, "{}:setup pilot!Pilot NumberId:{}!",
                                                    new Object[]{equipment.getInstanceId(),otherPiLotView.getViewId()}));
                }
            }
        }

        /**
         * 判断是否满足by idletime的pilot 触发条件
         * @param piLotSetup
         * @param equipment
         * @param needPiLot
         * @return
         */
        @Override
        public Boolean checkNeedPilotByTime(PiLotSetup piLotSetup, Equipment equipment, Boolean needPiLot) {
            IdleType idleType = piLotSetup.getIdle();
            double idleTime = idleType.getIdleTime() * 60 * 60 * 1000;
            double maxRunTime = idleType.getMaxRunTime() * 60 * 60 * 1000;
            Long idleTimeSum = 0L;
            Long realmaxRunTime = 0L;
            if (StringUtils.equalsIgnoreCase(idleType.getSubType(), IdleType.SUBTYPE_LOTLEVEL.toString())) {
                idleTimeSum = getEquipmentIdleByLotLevel(equipment, piLotSetup);
            } else if (StringUtils.equalsIgnoreCase(idleType.getSubType(), IdleType.SUBTYPE_WAFERLEVEL.toString())) {
                idleTimeSum = getEquipmentIdleByWaferLevel(equipment, piLotSetup);
            }

            if (idleTimeSum > 0 && idleTimeSum > idleTime) {
                needPiLot = true;
            } else if (idleTimeSum == 0 && maxRunTime != 0) {
                realmaxRunTime = getEquipmentMaxRunTime(piLotSetup, idleType, equipment);
                if (realmaxRunTime > maxRunTime) {
                    needPiLot = true;
                }
            }
            return needPiLot;
        }

    }