| | |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.List; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 货架核心功能 |
| | |
| | | private SlaveProperties slaveProperties; |
| | | @Autowired |
| | | private WrkDetlService wrkDetlService; |
| | | |
| | | // 深库位排 |
| | | private static final List<Integer> deepLocRowList = Arrays.asList(1,4,5,8,9,12,13,16,17,20,21,24,25,28,29,32); |
| | | |
| | | /** |
| | | * 生成工作号 |
| | |
| | | return workNo; |
| | | } |
| | | |
| | | /** |
| | | * 获取库位---山东宜和纺织 |
| | | * |
| | | * @param sourceSiteNo 入库源站点 |
| | | */ |
| | | public StartupDto getLocNoBySdyhfz(Integer sourceSiteNo,int ioType) { |
| | | |
| | | // 获取可用,可入,无报警堆垛机 |
| | | List<BasCrnp> basCrnps = basCrnpService.selectList(new EntityWrapper<BasCrnp>().eq("crn_sts", 3).eq("crn_err", 0).eq("in_enable", "Y")); |
| | | if (basCrnps.size() == 0) { |
| | | log.error(sourceSiteNo + "入库请求库位失败:堆垛机报警/无可用/无可入"); |
| | | throw new CoolException(sourceSiteNo + "入库请求库位失败:堆垛机报警/无可用/无可入"); |
| | | } |
| | | |
| | | // 计算负载均衡 |
| | | List<CraneLoadInfo> craneInfos = new ArrayList<>(); |
| | | // 负载均衡权重(可调整)任务少,库位占用少的先分配 |
| | | double w1 = 0.6; // 任务数权重 |
| | | double w2 = 0.4; // 仓位权重 |
| | | for (BasCrnp basCrnp : basCrnps) { |
| | | // 挂载任务数 |
| | | int taskCount = locMastService.selectCount(new EntityWrapper<LocMast>().eq("crn_no", basCrnp.getCrnNo()).in("loc_sts", "S", "R")); |
| | | // 空库位数量 |
| | | int emptyCount = locMastService.selectCount(new EntityWrapper<LocMast>().eq("crn_no", basCrnp.getCrnNo()).eq("loc_sts", "O")); |
| | | // 库位占用率 |
| | | double emptyLocOccupancy = (double) (800 - emptyCount) / 800; |
| | | CraneLoadInfo craneLoadInfo = new CraneLoadInfo(); |
| | | craneLoadInfo.setCrnNo(basCrnp.getCrnNo()); |
| | | craneLoadInfo.setTaskCount(taskCount); |
| | | craneLoadInfo.setOccupancy(emptyLocOccupancy); |
| | | craneInfos.add(craneLoadInfo); |
| | | } |
| | | // 获取最值 |
| | | int taskMax = craneInfos.stream().mapToInt(CraneLoadInfo::getTaskCount).max().orElse(0); |
| | | int taskMin = craneInfos.stream().mapToInt(CraneLoadInfo::getTaskCount).min().orElse(0); |
| | | double occMax = craneInfos.stream().mapToDouble(CraneLoadInfo::getOccupancy).max().orElse(0); |
| | | double occMin = craneInfos.stream().mapToDouble(CraneLoadInfo::getOccupancy).min().orElse(0); |
| | | |
| | | // 避免分母为0的情况 |
| | | double taskRange = (taskMax - taskMin) == 0 ? 1 : (taskMax - taskMin); |
| | | double occRange = (occMax - occMin) == 0 ? 1 : (occMax - occMin); |
| | | |
| | | // 计算 α |
| | | for (CraneLoadInfo info : craneInfos) { |
| | | double taskNorm = (info.getTaskCount() - taskMin) / taskRange; |
| | | double occNorm = (info.getOccupancy() - occMin) / occRange; |
| | | double alpha = w1 * taskNorm + w2 * occNorm; |
| | | info.setAlpha(alpha); |
| | | } |
| | | |
| | | // 排序:α 越小越空闲 |
| | | craneInfos.sort(Comparator.comparingDouble(CraneLoadInfo::getAlpha)); |
| | | |
| | | // 寻找库位 |
| | | LocMast locMast = null; |
| | | // 根据入库类型和源站点获取工作路径 |
| | | StaDesc staDesc = null; |
| | | |
| | | for (CraneLoadInfo craneLoadInfo : craneInfos) { |
| | | List<LocMast> locMastList = locMastService.selectList(new EntityWrapper<LocMast>().eq("crn_no", craneLoadInfo.getCrnNo()).eq("loc_sts", "O").orderBy("lev1").orderBy("bay1").orderBy("row1")); |
| | | if (locMastList.size() <= 4) { |
| | | continue; |
| | | } |
| | | // 先取深库位 |
| | | Optional<LocMast> first = locMastList.stream().filter(o -> deepLocRowList.contains(o.getRow1())).findFirst(); |
| | | // 深库位里面没有从浅库位里面取 |
| | | locMast = first.orElseGet(() -> locMastList.get(0)); |
| | | |
| | | if (locMast != null) { |
| | | staDesc = staDescService.selectOne(new EntityWrapper<StaDesc>().eq("type_no", ioType).eq("crn_no", locMast.getCrnNo()).eq("stn_no", sourceSiteNo)); |
| | | if (staDesc == null) { |
| | | log.error("获取工作路径异常,类型:{},堆垛机:{},源站:{}", ioType, locMast.getCrnNo(), sourceSiteNo); |
| | | throw new CoolException("获取工作路径异常,类型:" + ioType + ",堆垛机:" + locMast.getCrnNo() + ",源站:" + sourceSiteNo); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (locMast == null) { |
| | | log.error("堆垛机剩余库位不足:{}", craneInfos); |
| | | throw new CoolException("堆垛机不可用/库位不足,请检查"); |
| | | } |
| | | |
| | | // 生成工作号 |
| | | int workNo = getWorkNo(0); |
| | | // 返回dto |
| | | StartupDto startupDto = new StartupDto(); |
| | | startupDto.setWorkNo(workNo); |
| | | startupDto.setCrnNo(locMast.getCrnNo()); |
| | | startupDto.setSourceStaNo(sourceSiteNo); |
| | | startupDto.setStaNo(staDesc.getCrnStn()); |
| | | startupDto.setLocNo(locMast.getLocNo()); |
| | | |
| | | return startupDto; |
| | | } |
| | | |
| | | //拆盘机处空板扫码,驱动托盘向码垛位,不入库 |
| | | @Transactional |
| | | public StartupDto getScanBarcodeEmptyBoard() { |