package com.bs.lithoframe.service.reticle.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bs.lithoframe.service.kpimaintaintable.entity.TMainAlignApply;
import com.bs.lithoframe.service.kpimaintaintable.entity.TMainOvlApply;
import com.bs.lithoframe.service.kpimaintaintable.mapper.TMainAlignApplyMapper;
import com.bs.lithoframe.service.kpimaintaintable.mapper.TMainOvlApplyMapper;
import com.bs.lithoframe.service.mark.entity.MarkSizeSpec;
import com.bs.lithoframe.service.mark.mapper.MaskSizeSpecMapper;
import com.bs.lithoframe.service.mark.totalcount.entity.MarkTotalCount;
import com.bs.lithoframe.service.mark.totalcount.mapper.MarkTotalCountMapper;
import com.bs.lithoframe.service.reticle.commom.MarkSizeUtils;
import com.bs.lithoframe.service.reticle.dto.FetchSheetDTO;
import com.bs.lithoframe.service.reticle.dto.MarkAutoGenerateDTO;
import com.bs.lithoframe.service.reticle.dto.MarkAutoGenerateLayerDTO;
import com.bs.lithoframe.service.reticle.entity.*;
import com.bs.lithoframe.service.reticle.mapper.*;
import com.bs.lithoframe.service.reticle.service.ILfmsAsmlAlSizeSummaryService;
import com.bs.lithoframe.service.reticle.strategy.SheetContext;
import com.bs.lithoframe.service.reticle.vo.AsmlQueryMarkCountVO;
import com.bs.platform.core.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author L3150243 PX
* @since 2025-06-24
*/
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class LfmsAsmlAlSizeSummaryServiceImpl extends ServiceImpl<LfmsAsmlAlSizeSummaryMapper, LfmsAsmlAlSizeSummary> implements ILfmsAsmlAlSizeSummaryService {
@Resource
private SheetContext sheetContext;
@Resource
private TMainAlignApplyMapper alignApplyMapper;
@Resource
private TMainOvlApplyMapper ovlApplyMapper;
@Resource
private MarkSizeUtils markSizeUtils;
@Resource
private LfmsAsmlAlSizeSummaryMapper asmlAlSizeSummaryMapper;
@Resource
private LfmsReticleMapper reticleMapper;
@Resource
private LfmsDesignRecordMapper designRecordMapper;
@Resource
private LfmsAsmlAlCellValueMapper asmlAlCellValueMapper;
@Resource
private LfmsAsmlAlDummySummaryMapper asmlAlDummySummaryMapper;
@Resource
private MarkTotalCountMapper totalCountMapper;
@Resource
private MaskSizeSpecMapper markSizeSpecMapper;
/**
* Mark Auto Generate按钮,做两件事
* 1、自动生成mark size summary
* 2、自动生成cover layer
*
* @param dto
* @return highlight信息
*/
@Override
// @Transactional(rollbackFor = Exception.class)
public List<LfmsAsmlAlSizeSummary> markAutoGenerate(MarkAutoGenerateDTO dto) {
log.info("Starting mark auto-generation. Parameters: {}", JsonUtil.toJSONString(dto));
// 1. 快速失败检查:无参考层时直接返回空结果
if (CollectionUtils.isEmpty(dto.getReferenceLayers())) {
log.info("No reference layers selected. Skipping auto-generation.");
return Collections.emptyList();
}
// 2. 获取当前层尺寸摘要数据
List<LfmsAsmlAlSizeSummary> currentSummaries = fetchCurrentSizeSummaries(dto);
if (CollectionUtils.isEmpty(currentSummaries)) {
log.warn("No size summaries found for the specified layers");
return Collections.emptyList();
}
// 3. 执行核心生成逻辑
return processGeneration(dto, currentSummaries);
}
private List<LfmsAsmlAlSizeSummary> processGeneration(MarkAutoGenerateDTO dto,
List<LfmsAsmlAlSizeSummary> currentSummaries) {
List<LfmsAsmlAlSizeSummary> results = new ArrayList<>();
// 3.1 生成KPI数据
List<LfmsAsmlAlSizeSummary> kpiResults = this.sizeSummaryAutoGenerate(dto, currentSummaries);
if (!CollectionUtils.isEmpty(kpiResults)) {
results.addAll(kpiResults);
}
// 3.2 生成覆盖层数据
List<LfmsAsmlAlSizeSummary> coverLayers = this.coverLayerAutoGenerate(dto, currentSummaries);
if (!CollectionUtils.isEmpty(coverLayers)) {
results.addAll(coverLayers);
}
log.info("Auto-generation completed. Generated {} records", results.size());
return results;
}
private List<LfmsAsmlAlSizeSummary> fetchCurrentSizeSummaries(MarkAutoGenerateDTO dto) {
// 获取查询参数
Map<String, String> params = markSizeUtils.getMarkSizeParam(
dto.getCurrentProject(), dto.getCurrentProjectId(),
dto.getCurrentPart(), dto.getTypeName(), dto.getMainVersion()
);
// 提取当前层名称
List<String> layerNames = dto.getReferenceLayers().stream()
.map(MarkAutoGenerateLayerDTO::getCurrentLayer)
.collect(Collectors.toList());
// 构建查询条件
LambdaQueryWrapper<LfmsAsmlAlSizeSummary> query = new LambdaQueryWrapper<>();
query.eq(LfmsAsmlAlSizeSummary::getReticleKey, params.get("rKey"))
.eq(LfmsAsmlAlSizeSummary::getSubVersion, dto.getSubVersion())
.eq(LfmsAsmlAlSizeSummary::getSizeType, "mark")
.in(LfmsAsmlAlSizeSummary::getLayerName, layerNames);
return asmlAlSizeSummaryMapper.selectList(query);
}
public List<LfmsAsmlAlSizeSummary> markAutoGenerate_old(MarkAutoGenerateDTO markAutoGenerateDTO) {
log.info("asml sheet markAutoGenerate 入参:{}", JsonUtil.toJSONString(markAutoGenerateDTO));
List<LfmsAsmlAlSizeSummary> result = new ArrayList<>();
//如果没有选的就没有
if (CollectionUtils.isEmpty(markAutoGenerateDTO.getReferenceLayers())) {
return result;
}
//1.获取本地数据SizeSummaries
List<LfmsAsmlAlSizeSummary> currentSizeSummaries = getAsmlAlSizeSummaryList(markAutoGenerateDTO);
if (CollectionUtils.isEmpty(currentSizeSummaries)) {
log.info("getAsmlAlSizeSummaryList 数据为空");
return result;
}
//2.获取kpi 数据
result = this.sizeSummaryAutoGenerate(markAutoGenerateDTO, currentSizeSummaries);
//3.获取 coverLayer 数据
List<LfmsAsmlAlSizeSummary> coverLayerList = this.coverLayerAutoGenerate(markAutoGenerateDTO, currentSizeSummaries);
//总数据
result.addAll(coverLayerList);
return result;
}
/**
* 获取本地数据SizeSummaries
*
* @param markAutoGenerateDTO
* @return
*/
private List<LfmsAsmlAlSizeSummary> getAsmlAlSizeSummaryList(MarkAutoGenerateDTO markAutoGenerateDTO) {
//获取lfms系统mark size summary 信息
List<String> currentLayerNameList = markAutoGenerateDTO.getReferenceLayers().stream().map(MarkAutoGenerateLayerDTO::getCurrentLayer).collect(Collectors.toList());
//生成查询参数 rKey projectId
Map<String, String> currentMarkSizeParam = markSizeUtils.getMarkSizeParam(markAutoGenerateDTO.getCurrentProject(), markAutoGenerateDTO.getCurrentProjectId(), markAutoGenerateDTO.getCurrentPart(), markAutoGenerateDTO.getTypeName(), markAutoGenerateDTO.getMainVersion());
LambdaQueryWrapper<LfmsAsmlAlSizeSummary> asmlAlSizeSummaryQueryWrapper = new LambdaQueryWrapper<>();
asmlAlSizeSummaryQueryWrapper
.eq(LfmsAsmlAlSizeSummary::getReticleKey, currentMarkSizeParam.get("rKey"))
.eq(LfmsAsmlAlSizeSummary::getSubVersion, markAutoGenerateDTO.getSubVersion())
.eq(LfmsAsmlAlSizeSummary::getSizeType,"mark")
.in(LfmsAsmlAlSizeSummary::getLayerName, currentLayerNameList);
return asmlAlSizeSummaryMapper.selectList(asmlAlSizeSummaryQueryWrapper);
}
private void getMainKpiProjectId(MarkAutoGenerateDTO markAutoGenerateDTO) {
}
private List<TMainAlignApply> getTMainAlignApplyList(MarkAutoGenerateDTO markAutoGenerateDTO) {
//拉取alignment数据
LambdaQueryWrapper<TMainAlignApply> alignQueryWrapper = new LambdaQueryWrapper<>();
String projectIdSql = String.format("PROJECT_ID = " +
"(SELECT ID FROM T_MAIN_TAIN_KPI_APPLY WHERE ARCHIVE = 0 AND PROJECT = '%s' AND lOOP_F = '%s' ORDER BY CREATE_TIME FETCH FIRST 1 ROW ONLY)",
markAutoGenerateDTO.getProject(),
markAutoGenerateDTO.getPart());
List<String> referenceLayerNameList = markAutoGenerateDTO.getReferenceLayers().stream().map(MarkAutoGenerateLayerDTO::getReferenceLayer).collect(Collectors.toList());
/**
* todo
* 且过滤WQ/MCC” X/Y值如果违反“WQ>1%”“MCC>0.97和If need redesign(Y/N)”为Y
*
*/
//先获取maskVersion
alignQueryWrapper
.in(TMainAlignApply::getAlignTo, referenceLayerNameList)
.apply(projectIdSql)
// .ne(TMainAlignApply::getIfNeedRedesign, "Y")
// WQ/MCC” X/Y值如果违反“WQ>1%
.eq(TMainAlignApply::getMarkType,"ASML_AL")
.isNotNull(TMainAlignApply::getMarkSizeMarkType).isNotNull(TMainAlignApply::getMarkSizeCellName)
.isNotNull(TMainAlignApply::getMarkSizeSegType).isNotNull(TMainAlignApply::getMarkSizeCd)
.isNotNull(TMainAlignApply::getMarkSizePitch).isNotNull(TMainAlignApply::getMarkSizeMirror);
return alignApplyMapper.selectList(alignQueryWrapper);
}
private List<TMainOvlApply> getTMainOvlApplyList(MarkAutoGenerateDTO markAutoGenerateDTO) {
String projectIdSql = String.format("PROJECT_ID = " +
"(SELECT ID FROM T_MAIN_TAIN_KPI_APPLY WHERE ARCHIVE = 0 AND PROJECT = '%s' AND lOOP_F = '%s' ORDER BY CREATE_TIME FETCH FIRST 1 ROW ONLY)",
markAutoGenerateDTO.getProject(),
markAutoGenerateDTO.getPart());
List<String> referenceLayerNameList = markAutoGenerateDTO.getReferenceLayers().stream().map(MarkAutoGenerateLayerDTO::getReferenceLayer).collect(Collectors.toList());
//查询KPI系统的ovl数据
LambdaQueryWrapper<TMainOvlApply> ovlQueryWrapper = new LambdaQueryWrapper<>();
ovlQueryWrapper.eq(TMainOvlApply::getArchive, 0).
in(TMainOvlApply::getLayerName, referenceLayerNameList)
.eq(TMainOvlApply::getMarkType, "OVL")
.ne(TMainOvlApply::getIfNeedRedesign, "Y")
.apply(projectIdSql);
// .isNotNull(TMainOvlApply::getMarkSizeMarkType)
// .isNotNull(TMainOvlApply::getMarkSizeSegType).isNotNull(TMainOvlApply::getMarkSizeCd)
// .isNotNull(TMainOvlApply::getMarkSizePitch);
List<TMainOvlApply> ovlApplies = ovlApplyMapper.selectList(ovlQueryWrapper);
return ovlApplies;
}
private Map<String, List<TMainAlignApply>> tMainAlignApplyConvertToMap(List<TMainAlignApply> mainAlignApplies) {
//根据layer name分组,获取组内最新的maskVersion 按理来应该有align to来分组
return mainAlignApplies.stream().collect(Collectors.groupingBy(TMainAlignApply::getAlignTo,
Collectors.collectingAndThen(Collectors.toList(), list -> {
String newMaskVersion = list.stream().map(TMainAlignApply::getMaskVersion).max(String::compareTo).get();
return list.stream().filter(item -> Objects.equals(item.getMaskVersion(), newMaskVersion)).collect(Collectors.toList());
}
)
));
}
private Map<String, List<TMainOvlApply>> tMainOvlApplysConvertToMap(List<TMainOvlApply> mainOvlApplys) {
if(CollectionUtils.isEmpty(mainOvlApplys)){
return new HashMap<>();
}
//根据layer name分组,获取组内最新的maskVersion
return mainOvlApplys.stream().collect(Collectors.groupingBy(TMainOvlApply::getLayerName,
Collectors.collectingAndThen(Collectors.toList(), list -> {
String newMaskVersion = list.stream().map(TMainOvlApply::getMaskVersion).max(String::compareTo).get();
return list.stream().filter(item -> Objects.equals(item.getMaskVersion(), newMaskVersion)).collect(Collectors.toList());
}
)
));
}
private Map<String, List<LfmsAsmlAlSizeSummary>> sizeSummariesConvertToMap(List<LfmsAsmlAlSizeSummary> currentSizeSummaries) {
return currentSizeSummaries.stream().collect(Collectors.groupingBy(LfmsAsmlAlSizeSummary::getLayerName));
}
private final static List<String> markTypeList = Arrays.asList("HOLE_SEG", "LS_SEG_L", "LS_SEG_S", "LS_SEG_HOR", "LS_SEG_VER", "CTB_STD", "CTB_HOLE_SEG", "CTB_LS_SEG_L", "CTB_LS_SEG_S", "CTB_LS_SEG_HOR", "CTB_LS_SEG_VER");
private void fillFmsAsmlAlSizeSummary(LfmsAsmlAlSizeSummary lfmsAsmlAlSizeSummary, TMainAlignApply tMainAlignApply, MarkAutoGenerateDTO markAutoGenerateDTO, Map<String, String> usedMap, List<LfmsAsmlAlSizeSummary> resultList) {
/**
* 如果对于参考的KPI的mark和当前的Mark 的mark type不相等,
* 且 SEG type不等于HOLE_SEG / LS_SEG_L / LS_SEG_S / LS_SEG_HOR / LS_SEG_VER / CTB_STD / CTB_HOLE_SEG / CTB_LS_SEG_L / CTB_LS_SEG_S / CTB_LS_SEG_HOR / CTB_LS_SEG_VER,需要highlight,当前mark背景色标红即可。
*/
if (!lfmsAsmlAlSizeSummary.getMarkType().equals(tMainAlignApply.getMarkType())) {
if (!markTypeList.contains(lfmsAsmlAlSizeSummary.getSegType())) {
//需要highlight,当前mark背景色标红即可
}
}
lfmsAsmlAlSizeSummary.setSegType(tMainAlignApply.getMarkSizeSegType());
lfmsAsmlAlSizeSummary.setCd(tMainAlignApply.getMarkSizeCd());
lfmsAsmlAlSizeSummary.setPitch(tMainAlignApply.getMarkSizePitch());
lfmsAsmlAlSizeSummary.setTone(tMainAlignApply.getMarkSizeTone());
//Mark remark字段默认填写:refer proj+layer+NO.+mark type,同时可以将mark type字段单独存储,因为后续Hightlight规则会匹配当前的mark type和引用的mark type是否一致
lfmsAsmlAlSizeSummary.setAdditionRemark(markAutoGenerateDTO.getProject() + tMainAlignApply.getLayerName() + tMainAlignApply.getOrderNo() + tMainAlignApply.getMarkType());
usedMap.put(lfmsAsmlAlSizeSummary.getMarkType() + lfmsAsmlAlSizeSummary.getMirror(), tMainAlignApply.getCellName());
resultList.add(lfmsAsmlAlSizeSummary);
}
private void fillFmsAsmlAlSizeSummary(LfmsAsmlAlSizeSummary lfmsAsmlAlSizeSummary, TMainOvlApply tMainOvlApply, MarkAutoGenerateDTO markAutoGenerateDTO, Map<String, String> usedMap, List<LfmsAsmlAlSizeSummary> resultList) {
/**
* 如果对于参考的KPI的mark和当前的Mark 的mark type不相等,
* 且 SEG type不等于HOLE_SEG / LS_SEG_L / LS_SEG_S / LS_SEG_HOR / LS_SEG_VER / CTB_STD / CTB_HOLE_SEG / CTB_LS_SEG_L / CTB_LS_SEG_S / CTB_LS_SEG_HOR / CTB_LS_SEG_VER,需要highlight,当前mark背景色标红即可。
*/
if (!lfmsAsmlAlSizeSummary.getMarkType().equals(tMainOvlApply.getMarkType())) {
if (!markTypeList.contains(lfmsAsmlAlSizeSummary.getSegType())) {
//需要highlight,当前mark背景色标红即可
}
}
lfmsAsmlAlSizeSummary.setSegType(tMainOvlApply.getMarkSizeSegType());
lfmsAsmlAlSizeSummary.setCd(tMainOvlApply.getMarkSizeCd());
lfmsAsmlAlSizeSummary.setPitch(tMainOvlApply.getMarkSizePitch());
lfmsAsmlAlSizeSummary.setTone(tMainOvlApply.getMarkSizeTone());
//Mark remark字段默认填写:refer proj+layer+NO.+mark type,同时可以将mark type字段单独存储,因为后续Hightlight规则会匹配当前的mark type和引用的mark type是否一致
lfmsAsmlAlSizeSummary.setAdditionRemark(markAutoGenerateDTO.getProject() + tMainOvlApply.getLayerName() + tMainOvlApply.getSequenceNo() + tMainOvlApply.getMarkType());
usedMap.put(lfmsAsmlAlSizeSummary.getMarkType() + lfmsAsmlAlSizeSummary.getMirror(), tMainOvlApply.getCellName());
resultList.add(lfmsAsmlAlSizeSummary);
}
// 方法:返回两个double类型参数中的最大值
public static double maxOfTwoDoubles(double num1, double num2) {
return (num1 > num2) ? num1 : num2;
}
public static double sumJsonXOrY(String jsonStr) {
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
Double x = jsonObject.getDouble("X");
Double y = jsonObject.getDouble("Y");
return x+y;
}
public static double maxJsonXOrY(String jsonStr) {
JSONObject jsonObject = JSONObject.parseObject(jsonStr);
Double x = jsonObject.getDouble("X");
Double y = jsonObject.getDouble("Y");
return maxOfTwoDoubles(x, y);
}
/**
* 拉取kpi数据,填充相应size summary数据的“Seg Type”“CD” “Pitch”“Tone”字段信息
*
* @param markAutoGenerateDTO
* @param currentSizeSummaries
* @return highlight信息
*/
private List<LfmsAsmlAlSizeSummary> sizeSummaryAutoGenerate(MarkAutoGenerateDTO markAutoGenerateDTO, List<LfmsAsmlAlSizeSummary> currentSizeSummaries) {
List<LfmsAsmlAlSizeSummary> resultList = new ArrayList<>();
//1.获取AlignApply数据
List<TMainAlignApply> mainAlignApplies = getTMainAlignApplyList(markAutoGenerateDTO);
if(CollectionUtils.isEmpty(mainAlignApplies)){
return resultList;
}
//2.将AlignApply 转换map类型 key:LayerName,value:list
Map<String, List<TMainAlignApply>> alignApplyMap = tMainAlignApplyConvertToMap(mainAlignApplies);
//3.获取 sizeSummariesMap
Map<String, List<LfmsAsmlAlSizeSummary>> sizeSummarieMap = sizeSummariesConvertToMap(currentSizeSummaries);
//4.获取OvlApply数据
List<TMainOvlApply> mainOvlApplys = getTMainOvlApplyList(markAutoGenerateDTO);
//5.ovl转换map
Map<String, List<TMainOvlApply>> ovlApplyMap = tMainOvlApplysConvertToMap(mainOvlApplys);
for (int i = 0; i < markAutoGenerateDTO.getReferenceLayers().size(); i++) {
MarkAutoGenerateLayerDTO markAutoGenerateLayer = markAutoGenerateDTO.getReferenceLayers().get(i);
//sizeSummary 数据
List<LfmsAsmlAlSizeSummary> sizeSummarylist = sizeSummarieMap.get(markAutoGenerateLayer.getCurrentLayer());
if (CollectionUtils.isEmpty(sizeSummarylist)) {
continue;
}
//Map key: Mark Type + Mirror value:Alignment Mark Cell name
Map<String, String> usedMap = new HashMap<>();
for (LfmsAsmlAlSizeSummary lfmsAsmlAlSizeSummary : sizeSummarylist) {
//alignApply 数据
List<TMainAlignApply> alignApplyList = alignApplyMap.get(markAutoGenerateLayer.getReferenceLayer());
//优先Alignment mark > mark type > 方向(if mirror) > BSL mark > Backup mark > LM KPI
if (!CollectionUtils.isEmpty(alignApplyList)) {
//校验是否出现相同的 mark type + mirror
if (usedMap.containsKey(lfmsAsmlAlSizeSummary.getMarkType() + lfmsAsmlAlSizeSummary.getMirror())) {
String cellName = usedMap.get(lfmsAsmlAlSizeSummary.getMarkType() + lfmsAsmlAlSizeSummary.getMirror());
//将已使用CellName 移除
alignApplyList = alignApplyList.stream().filter(f -> !f.getCellName().equals(cellName)).collect(Collectors.toList());
}
//规则1.[优先级规则去得到mark 对应的Seg_type”“CD/PITCH”“Tone”]
String markType = lfmsAsmlAlSizeSummary.getMarkType();
List<TMainAlignApply> markTypeAlignApplyList = alignApplyList.stream().filter(f -> f.getMarkType().equals(markType)).collect(Collectors.toList());
//规则1.[mark type]
if (!CollectionUtils.isEmpty(markTypeAlignApplyList) && markTypeAlignApplyList.size() == 1) {
TMainAlignApply tMainAlignApply = markTypeAlignApplyList.get(0);
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, tMainAlignApply, markAutoGenerateDTO, usedMap, resultList);
continue;
}
//规则2.[方向(if mirror)]
markTypeAlignApplyList = alignApplyList.stream().filter(f -> !Objects.isNull(f.getMarkSizeMirror()) && f.getMarkSizeMirror().equals("Y")).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(markTypeAlignApplyList) && markTypeAlignApplyList.size() == 1) {
TMainAlignApply tMainAlignApply = markTypeAlignApplyList.get(0);
//校验当前是否有相同mark type 由于一个layer会有多个相同的mark type+if Mirror信息,获取KPI数据时不可取相同的
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, tMainAlignApply, markAutoGenerateDTO, usedMap, resultList);
continue;
}
//规则3.[BSL mark]
markTypeAlignApplyList = alignApplyList.stream().filter(f -> !Objects.isNull(f.getIfBaselineMark()) && f.getIfBaselineMark().equals("Y")).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(markTypeAlignApplyList) && markTypeAlignApplyList.size() == 1) {
TMainAlignApply tMainAlignApply = markTypeAlignApplyList.get(0);
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, tMainAlignApply, markAutoGenerateDTO, usedMap, resultList);
continue;
}
//规则4.[Backup mark]
markTypeAlignApplyList = alignApplyList.stream().filter(f -> !Objects.isNull(f.getIfBackUp()) && f.getIfBackUp().equals("Y")).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(markTypeAlignApplyList) && markTypeAlignApplyList.size() == 1) {
TMainAlignApply tMainAlignApply = markTypeAlignApplyList.get(0);
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, tMainAlignApply, markAutoGenerateDTO, usedMap, resultList);
continue;
}
//规则5.[LM KPI] 通过对比“ROPI”值, max(X,Y) 越小越好(对于在KPI系统中没有填数值或为NA的,当成KPI最差。) X:5,Y:8 取8 最后min
// maxJsonXOrY(p1.getPerformanceRopi())
Optional<TMainAlignApply> optMarkTypeAlignApply = alignApplyList.stream().filter(f->!Objects.isNull(f.getPerformanceRopi())).min((p1, p2) -> Double.compare(maxJsonXOrY(p1.getPerformanceRopi()), maxJsonXOrY(p2.getPerformanceRopi())));;
if (optMarkTypeAlignApply.isPresent()) {
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, optMarkTypeAlignApply.get(), markAutoGenerateDTO, usedMap, resultList);
continue;
}
}
//ovlApply 数据
List<TMainOvlApply> ovlApplyList = ovlApplyMap.get(markAutoGenerateLayer.getReferenceLayer());
//优先级 OVL mark > BSL mark> backup mark > LM KPI数值
if (!CollectionUtils.isEmpty(ovlApplyList)) {
//校验是否出现相同的 mark type + mirror
if (usedMap.containsKey(lfmsAsmlAlSizeSummary.getMarkType() + lfmsAsmlAlSizeSummary.getMirror())) {
String cellName = usedMap.get(lfmsAsmlAlSizeSummary.getMarkType() + lfmsAsmlAlSizeSummary.getMirror());
//将已使用CellName 移除
ovlApplyList = ovlApplyList.stream().filter(f -> !f.getCellName().equals(cellName)).collect(Collectors.toList());
}
String markType = lfmsAsmlAlSizeSummary.getMarkType();
List<TMainOvlApply> markTypeOvlApplyList = ovlApplyList.stream().filter(f -> f.getMarkType().equals(markType)).collect(Collectors.toList());
//规则1.[mark type]
if (!CollectionUtils.isEmpty(markTypeOvlApplyList) && markTypeOvlApplyList.size() == 1) {
TMainOvlApply mainAlignApply = markTypeOvlApplyList.get(0);
//根据id 查询子表 获取到2条数据 然后根据markType 在子表里面比对 符合的就拿
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, mainAlignApply, markAutoGenerateDTO, usedMap, resultList);
continue;
}
//规则2.[BSL mark]
markTypeOvlApplyList = ovlApplyList.stream().filter(f -> !Objects.isNull(f.getIfBaselineMark()) && f.getIfBaselineMark().equals("Y")).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(markTypeOvlApplyList) && markTypeOvlApplyList.size() == 1) {
TMainOvlApply mainAlignApply = markTypeOvlApplyList.get(0);
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, mainAlignApply, markAutoGenerateDTO, usedMap, resultList);
continue;
}
//规则3.[Backup mark]
markTypeOvlApplyList = ovlApplyList.stream().filter(f -> !Objects.isNull(f.getIfBackUp()) && f.getIfBackUp().equals("Y")).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(markTypeOvlApplyList) && markTypeOvlApplyList.size() == 1) {
TMainOvlApply mainAlignApply = markTypeOvlApplyList.get(0);
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, mainAlignApply, markAutoGenerateDTO, usedMap, resultList);
continue;
}
//规则4.[LM KPI] 从系统对比“Qmerit out/in Mean+3Sigma”值, Qmerit out X + Qmerit out Y + Qmerit in X + Qmerit in Y, 加和越小越好。
Optional<TMainOvlApply> optMarkTypeOvlApply = markTypeOvlApplyList.stream().filter(f->!Objects.isNull(f.getQnerutInMs()) && !Objects.isNull(f.getQnerutOutMs()) ).min((p1, p2) -> Double.compare(sumJsonXOrY(p1.getQnerutOutMs()) + sumJsonXOrY(p1.getQnerutInMs()), sumJsonXOrY(p2.getQnerutOutMs()) + sumJsonXOrY(p2.getQnerutInMs())));
if (optMarkTypeOvlApply.isPresent()) {
fillFmsAsmlAlSizeSummary(lfmsAsmlAlSizeSummary, optMarkTypeOvlApply.get(), markAutoGenerateDTO, usedMap, resultList);
}
}
}
}
return resultList;
// //查询KPI系统的ovl数据
// LambdaQueryWrapper<TMainOvlApply> ovlQueryWrapper = new LambdaQueryWrapper<>();
// ovlQueryWrapper.eq(TMainOvlApply::getArchive, 0).
// in(TMainOvlApply::getLayerName, referenceLayerNameList)
// .eq(TMainOvlApply::getIfBaselineMark, 'Y') //----------------------------- 为什么是 Y
// .apply(projectIdSql)
// .isNotNull(TMainOvlApply::getMarkSizeMarkType)
// .isNotNull(TMainOvlApply::getMarkSizeSegType).isNotNull(TMainOvlApply::getMarkSizeCd)
// .isNotNull(TMainOvlApply::getMarkSizePitch);
// List<TMainOvlApply> ovlApplies = ovlApplyMapper.selectList(ovlQueryWrapper);
// //根据layer name分组,获取组内最新的maskVersion
// Map<String, List<TMainOvlApply>> mainOvlMap = ovlApplies.stream().collect(Collectors.groupingBy(TMainOvlApply::getLayerName,
// Collectors.collectingAndThen(Collectors.toList(), list -> {
// String newMaskVersion = list.stream().map(TMainOvlApply::getMaskVersion).max(String::compareTo).get();
// return list.stream().filter(item -> Objects.equals(item.getMaskVersion(), newMaskVersion)).collect(Collectors.toList());
// }
// )
// ));
//
// //按优先级进行匹配(一、优先Alignment mark > mark type > 方向(if mirror) > BSL mark > Backup mark > LM KPI数值)
// markAutoGenerateDTO.getReferenceLayers().forEach(referenceLayer -> {
// //current Layer的size summary 获取第一个 当前layername 的 数据 本地的
// List<LfmsAsmlAlSizeSummary> sizeSummeryList = currentSizeSummaries.stream().filter(asmlAl -> Objects.equals(asmlAl.getLayerName(), referenceLayer.getCurrentLayer())).collect(Collectors.toList());
// //reference layer 拉取的alignment信息
// List<TMainAlignApply> alignList = mainAlignMap.values().stream().flatMap(Collection::stream)
// .filter(kpiAlign -> Objects.equals(kpiAlign.getAlignTo(), referenceLayer.getReferenceLayer()))
// .collect(Collectors.toList());
// //reference layer 拉取的ovl信息
// List<TMainOvlApply> ovlList = mainOvlMap.values().stream().flatMap(Collection::stream)
// .filter(kpiOvl -> Objects.equals(kpiOvl.getLayerName(), referenceLayer.getReferenceLayer()))
// .collect(Collectors.toList());
//
// for (int i = 0; i < sizeSummeryList.size(); i++) {
// LfmsAsmlAlSizeSummary sizeSummary = sizeSummeryList.get(i);
// /*List<TMainAlignApply> sameTypeAlignList = alignList.stream().filter(kpiAlign -> Objects.equals(kpiAlign.getMarkType(), sizeSummary.getMarkType())).map(kpiAlign -> {
// return alignList.stream().filter(item -> !Objects.equals(kpiAlign.getMarkSizeSegType(), item.getMarkSizeSegType()) && !Objects.equals(kpiAlign.getMarkSizeCd(), item.getMarkSizeCd())
// && !Objects.equals(kpiAlign.getMarkSizePitch(), item.getMarkSizePitch()) && !Objects.equals(kpiAlign.getMarkSizeMirror(), item.getMarkSizeMirror())).collect(Collectors.toList());
// })
// .flatMap(Collection::stream)
//
// .filter(kpiAlign -> Objects.equals(kpiAlign.getMarkSizeMarkType(), sizeSummary.getMarkType()))
// .collect(Collectors.toList());*/
// TMainAlignApply tMainAlignApply = alignList.stream().filter(kpiAlign -> Objects.equals(kpiAlign.getMarkType(), sizeSummary.getMarkType())).findFirst().orElse(null);
// //优先参考与当前layer plan相同的mark type;//优先参考与当前layer plan相同的mark type;
// List<TMainAlignApply> sameTypeAlignList = alignList.stream().filter(kpiAlign -> Objects.equals(kpiAlign.getMarkSizeMarkType(), sizeSummary.getMarkType()))
// //④ 相同type的AL mark size不能重复(Seg type/CD/Pitch/mirror都相同则算重复), 若重复需要继续参考其他mark;
// .filter(kpiAlign -> tMainAlignApply == null || !(Objects.equals(kpiAlign.getMarkType(), sizeSummary.getMarkType()) &&
// Objects.equals(kpiAlign.getMarkSizeSegType(), kpiAlign.getMarkSizeSegType()) && Objects.equals(kpiAlign.getMarkSizeCd(), kpiAlign.getMarkSizeCd())
// && Objects.equals(kpiAlign.getMarkSizePitch(), kpiAlign.getMarkSizePitch()) && Objects.equals(kpiAlign.getMarkSizeMirror(), kpiAlign.getMarkSizeMirror())))
// .collect(Collectors.toList());
// List<TMainOvlApply> sameTypeOvlList = ovlList.stream().filter(kpiOvl -> Objects.equals(kpiOvl.getMarkSizeMarkType(), sizeSummary.getMarkType()))
// //④ 相同type的AL mark size不能重复(Seg type/CD/Pitch/mirror都相同则算重复), 若重复需要继续参考其他mark;
// .filter(kpiOvl -> tMainAlignApply == null || !(Objects.equals(kpiOvl.getMarkType(), sizeSummary.getMarkType()) &&
// Objects.equals(kpiOvl.getMarkSizeSegType(), kpiOvl.getMarkSizeSegType()) && Objects.equals(kpiOvl.getMarkSizeCd(), kpiOvl.getMarkSizeCd())
// && Objects.equals(kpiOvl.getMarkSizePitch(), kpiOvl.getMarkSizePitch())))
// .collect(Collectors.toList());
//
//
// //定义一个匹配的kpi数据对象
// TMainAlignApply alignApply;
// //不同type
// /* collect1、collect2表示不同type AL mark情况下过滤掉不符合“SEG TYPE”后的alignment集合、ovl集合 */
// if (CollectionUtils.isEmpty(sameTypeAlignList)) {
// List<TMainAlignApply> collect1 = alignList.stream().filter(kpiAlign -> Objects.equals(kpiAlign.getMarkSizeSummary(), sizeSummary.getMarkType()))
// .filter(kpiAlign -> {
// String segType = kpiAlign.getMarkSizeSegType();
// //② 当不同type AL mark “SEG TYPE”为"STD_Shrink"“SP_*”"_MCD/_Mpitch"时不能被reference,跳过
// return !"STD_Shrink".equals(segType) && !segType.startsWith("SP_") && !segType.endsWith("_MCD") && !segType.endsWith("_Mpitch");
// }).collect(Collectors.toList());
//
// if (CollectionUtils.isEmpty(collect1)) {
// //alignment查不到,就查询ovl
// TMainOvlApply ovlApply;
// if (CollectionUtils.isEmpty(sameTypeOvlList)) {
// List<TMainOvlApply> collect2 = ovlList.stream().filter(kpiAlign -> Objects.equals(kpiAlign.getMarkSizeSummary(), sizeSummary.getMarkType()))
// .filter(kpiAlign -> {
// String segType = kpiAlign.getMarkSizeSegType();
// //② 当不同type AL mark “SEG TYPE”为"STD_Shrink"“SP_*”"_MCD/_Mpitch"时不能被reference,跳过
// return !"STD_Shrink".equals(segType) && !segType.startsWith("SP_") && !segType.endsWith("_MCD") && !segType.endsWith("_Mpitch");
// }).collect(Collectors.toList());
// if (CollectionUtils.isEmpty(collect2)) {
// continue;
// }
// ovlApply = ovlBSLMark(collect2);
// } else if (sameTypeOvlList.size() == 1) {
// ovlApply = sameTypeOvlList.get(0);
// } else {
// ovlApply = ovlBSLMark(sameTypeOvlList);
// }
//
// sizeSummary.setSegType(ovlApply.getMarkSizeSegType());
// sizeSummary.setCd(ovlApply.getMarkSizeCd());
// sizeSummary.setPitch(ovlApply.getMarkSizePitch());
// sizeSummary.setTone(ovlApply.getMarkSizeTone());
// sizeSummary.setAdditionRemark("'layer':" + ovlApply.getLayerName() + ",'mark':" + ovlApply.getCurrentMarkSize());
// updateSizeSummaries.add(sizeSummary);
// //⑤ 若Reference AL mark 在LM KPI中“If need redesign(Y/N)”为Y需要highlight;
// if (Objects.equals("Y", ovlApply.getIfNeedRedesign())) {
// result.add(String.format("%s:LM KPI system Mark Auto need re-design", sizeSummary.getLayerName()));
// }
// //标记已经引用的mark(相同markType不能引用重复的mark)
// ovlList.stream().filter(item -> Objects.equals(item.getId(), ovlApply.getId())).findFirst().ifPresent(item -> item.setMarkType(sizeSummary.getMarkType()));
// continue;
// }
// alignApply = alignMirror(collect1, sizeSummary);
// }
// //只有一个相同的markType
// else if (sameTypeAlignList.size() == 1) {
// alignApply = sameTypeAlignList.get(0);
// }
// //有多个相同type,继续按规则匹配
// else {
// alignApply = alignMirror(sameTypeAlignList, sizeSummary);
// }
//
// sizeSummary.setSegType(alignApply.getMarkSizeSegType());
// sizeSummary.setCd(alignApply.getMarkSizeCd());
// sizeSummary.setPitch(alignApply.getMarkSizePitch());
// sizeSummary.setTone(alignApply.getMarkSizeTone());
// sizeSummary.setAdditionRemark("'layer':" + alignApply.getLayerName() + ",'mark':" + alignApply.getMarkSize());
// updateSizeSummaries.add(sizeSummary);
// //⑤ 若Reference AL mark 在LM KPI中“If need redesign(Y/N)”为Y需要highlight;
// if (Objects.equals("Y", alignApply.getIfNeedRedesign())) {
// result.add(String.format("%s:LM KPI system Mark Auto need re-design", sizeSummary.getLayerName()));
// }
// //标记已经引用的mark(相同markType不能引用重复的mark)
// alignList.stream().filter(item -> Objects.equals(item.getId(), alignApply.getId())).findFirst().ifPresent(item -> item.setMarkType(sizeSummary.getMarkType()));
// }
// });
//
// if (!CollectionUtils.isEmpty(updateSizeSummaries)) {
// asmlAlSizeSummaryMapper.updateBatch(updateSizeSummaries);
// }
// return result;
}
/**
* 查询出所选的referenceLayer的sizeSummary,过滤出coverLayer,将coverLayer信息新增给对应的currentLayer
* coverLayer定义:LFMS_ASML_AL_SIZE_SUMMARY 表SIZE_TYPE=‘cover’,FEATURE1 = ‘Special’
*
* @return highlight信息
*/
private List<LfmsAsmlAlSizeSummary> coverLayerAutoGenerate(MarkAutoGenerateDTO markAutoGenerateDTO, List<LfmsAsmlAlSizeSummary> currentSizeSummaries) {
List<LfmsAsmlAlSizeSummary> coverLayerList = new ArrayList<>();
List<String> referenceLayerNameList = markAutoGenerateDTO.getReferenceLayers().stream().map(MarkAutoGenerateLayerDTO::getReferenceLayer).collect(Collectors.toList());
//生成cover layer
String projectId = markSizeUtils.getProjectId(markAutoGenerateDTO.getProjectId());
Map<String, String> currentMarkSizeParam = markSizeUtils.getMarkSizeParam(markAutoGenerateDTO.getCurrentProject(), markAutoGenerateDTO.getCurrentProjectId(),
markAutoGenerateDTO.getCurrentPart(), markAutoGenerateDTO.getTypeName(), markAutoGenerateDTO.getMainVersion());
//查询LfmsDesignRecord获取最新mainVersion和subVersion,然后拉取LFMS系统的sizeSummary信息(coverLayer)
LambdaQueryWrapper<LfmsDesignRecord> designRecordQueryWrapper = new LambdaQueryWrapper<>();
designRecordQueryWrapper.eq(LfmsDesignRecord::getProjAbbr, markAutoGenerateDTO.getProject())
.eq(LfmsDesignRecord::getPart, markAutoGenerateDTO.getPart())
.eq(LfmsDesignRecord::getProjId, projectId)
.eq(LfmsDesignRecord::getProjType, markAutoGenerateDTO.getTypeName())
.eq(LfmsDesignRecord::getDesignTable, "RETICLE")
.orderByDesc(LfmsDesignRecord::getMainVersion);
//查询目标数据 design
List<LfmsDesignRecord> designRecords = designRecordMapper.selectList(designRecordQueryWrapper);
String mainVersion = designRecords.get(0).getMainVersion();
String subversion = designRecords.stream().filter(designRecord -> Objects.equals(mainVersion, designRecord.getMainVersion())).map(LfmsDesignRecord::getSubVersion).max(String::compareTo).get();
String rKey = String.join("@", markAutoGenerateDTO.getProject(), markAutoGenerateDTO.getPart(), mainVersion, projectId, markAutoGenerateDTO.getTypeName());
LambdaQueryWrapper<LfmsAsmlAlSizeSummary> asmlAlSizeSummaryQueryWrapper = new LambdaQueryWrapper<>();
asmlAlSizeSummaryQueryWrapper.eq(LfmsAsmlAlSizeSummary::getReticleKey, rKey).eq(LfmsAsmlAlSizeSummary::getSubVersion, subversion)
.eq(LfmsAsmlAlSizeSummary::getSizeType, "cover").eq(LfmsAsmlAlSizeSummary::getFeature1, "Special")
.in(LfmsAsmlAlSizeSummary::getLayerName, referenceLayerNameList);
List<LfmsAsmlAlSizeSummary> asmlAlSizeSummaries = asmlAlSizeSummaryMapper.selectList(asmlAlSizeSummaryQueryWrapper);
if (CollectionUtils.isEmpty(asmlAlSizeSummaries)) {
return coverLayerList;//todo 需要根据规则highlight提醒
}
//匹配到sizeSummary信息,然后新增到数据库,其中四个字段使用当前系统的数据:reticleKey、markCountKey、layerName、subVersion
for (MarkAutoGenerateLayerDTO referenceLayer : markAutoGenerateDTO.getReferenceLayers()) {
boolean match = currentSizeSummaries.stream().anyMatch(sizeSummary -> Objects.equals(sizeSummary.getLayerName(), referenceLayer.getCurrentLayer())
&& Objects.equals(sizeSummary.getSizeType(), "cover"));
if (match) continue;
asmlAlSizeSummaries.stream().filter(sizeSummary -> Objects.equals(sizeSummary.getLayerName(), referenceLayer.getReferenceLayer()))
.forEach(sizeSummary -> {
LfmsAsmlAlSizeSummary addSizeSummary = new LfmsAsmlAlSizeSummary();
BeanUtils.copyProperties(sizeSummary, addSizeSummary);
addSizeSummary.setLayerName(referenceLayer.getCurrentLayer());
addSizeSummary.setReticleKey(currentMarkSizeParam.get("rKey"));
addSizeSummary.setMarkCountKey(String.join("@", markAutoGenerateDTO.getCurrentProjectId(), markAutoGenerateDTO.getMarkCountVersion()));
addSizeSummary.setSubVersion(markAutoGenerateDTO.getSubVersion());
addSizeSummary.setNo(new BigDecimal(1));
coverLayerList.add(addSizeSummary);
});
}
return coverLayerList;
// this.saveBatch(coverLayerList);
// return "";//todo 需要根据规则highlight提醒
}
/**
* 判断页面上的If tape out or not = Y的数据中哪些是Dummy Block,GDS NO 去Reticel table 里查找If Dummy block 是Y,自动创建#_normal
* <p>
* 如何判断If tape out or not = Y?
* 查询LFMS_ASML_AL_CELL_VALUE表里面的if_tape_out值 "IF_TAPE_OUT": "N" if len(df_dummy_value) == 0 else df_dummy_value["IF_TAPE_OUT"].iat[0],
* <p>
* 如何判断Dummy Block?
* 1、查询LFMS_DESIGN_RECORD,找到对应的小版本号或者最新的小版本号subversion
* 2、然后根据subversion匹配LFMS_RETICLE里相应的的数据,找到DUMMY_LAYER==Y的数据,即为Dummy block
*
* @param markAutoGenerateDTO
*/
@Override
public void dummyBlockAutoGenerate(MarkAutoGenerateDTO markAutoGenerateDTO) {
Map<String, String> markSizeParam = markSizeUtils.getMarkSizeParam(markAutoGenerateDTO.getCurrentProject(), markAutoGenerateDTO.getCurrentProjectId(),
markAutoGenerateDTO.getCurrentPart(), markAutoGenerateDTO.getTypeName(), markAutoGenerateDTO.getMainVersion());
//取subversion,根据subversion查询出LfmsReticle的DUMMY_LAYER信息
String subversion = markAutoGenerateDTO.getSubVersion();
LambdaQueryWrapper<LfmsDesignRecord> designRecordQueryWrapper = new LambdaQueryWrapper<>();
designRecordQueryWrapper.eq(LfmsDesignRecord::getProjAbbr, markAutoGenerateDTO.getCurrentProject()).eq(LfmsDesignRecord::getPart, markAutoGenerateDTO.getCurrentPart())
.eq(LfmsDesignRecord::getProjId, markSizeParam.get("projectId")).eq(LfmsDesignRecord::getProjType, markAutoGenerateDTO.getTypeName())
.eq(LfmsDesignRecord::getMainVersion, markAutoGenerateDTO.getMainVersion()).eq(LfmsDesignRecord::getDesignTable, "RETICLE")
.select(LfmsDesignRecord::getSubVersion)
.orderByDesc(LfmsDesignRecord::getSubVersion);
List<LfmsDesignRecord> designRecords = designRecordMapper.selectList(designRecordQueryWrapper);
boolean existSubversion = designRecords.stream().anyMatch(designRecord -> Objects.equals(designRecord.getSubVersion(), markAutoGenerateDTO.getSubVersion()));
if (!existSubversion) {
String reg = "^[1-9][0-9]{7}(_[0-9]{1,2})?$";//原python代码,经了解部分老数据的版本不规范,后期都是采用日期当做版本号,如:“20240621”,不存在此类问题
subversion = designRecords.stream().filter(designRecord -> designRecord.getSubVersion().matches(reg)).map(LfmsDesignRecord::getSubVersion).findFirst().get();
}
LambdaQueryWrapper<LfmsReticle> reticleQueryWrapper = new LambdaQueryWrapper<>();
reticleQueryWrapper.eq(LfmsReticle::getSubVersion, subversion).eq(LfmsReticle::getDummyLayer, "Y").like(LfmsReticle::getIdx, markSizeParam.get("rKey"));
List<LfmsReticle> lfmsReticles = reticleMapper.selectList(reticleQueryWrapper);
if (CollectionUtils.isEmpty(lfmsReticles)) {
return;
}
LambdaQueryWrapper<LfmsAsmlAlCellValue> cellValueQueryWrapper = new LambdaQueryWrapper<>();
cellValueQueryWrapper.eq(LfmsAsmlAlCellValue::getReticleKey, markSizeParam.get("rKey")).eq(LfmsAsmlAlCellValue::getSubVersion, subversion)
.eq(LfmsAsmlAlCellValue::getIfTapeOut, "Y").select(LfmsAsmlAlCellValue::getLayerName);
List<LfmsAsmlAlCellValue> asmlAlCellValues = asmlAlCellValueMapper.selectList(cellValueQueryWrapper);
if (CollectionUtils.isEmpty(asmlAlCellValues)) {
return;
}
//LfmsAsmlAlCellValue里的layerName值示例M2_ARRAY_Dummy
List<String> cellValueLayers = asmlAlCellValues.stream().map(LfmsAsmlAlCellValue::getLayerName).collect(Collectors.toList());
List<String> dummyLayerNames = lfmsReticles.stream().filter(reticle -> cellValueLayers.contains(reticle.getLayerName() + "_Dummy"))
.map(reticle -> reticle.getLayerName() + "_Dummy").collect(Collectors.toList());
if (CollectionUtils.isEmpty(dummyLayerNames)) {
return;
}
LambdaQueryWrapper<LfmsAsmlAlDummySummary> dummySummaryQueryWrapper = new LambdaQueryWrapper<>();
dummySummaryQueryWrapper.eq(LfmsAsmlAlDummySummary::getReticleKey, markSizeParam.get("rKey")).eq(LfmsAsmlAlDummySummary::getSubVersion, subversion)
.in(LfmsAsmlAlDummySummary::getLayerName, dummyLayerNames);
//先删除dummySummary信息,再新增
asmlAlDummySummaryMapper.delete(dummySummaryQueryWrapper);
String finalSubversion = subversion;
List<LfmsAsmlAlDummySummary> addDummySummaries = dummyLayerNames.stream().map(layer -> {
LfmsAsmlAlDummySummary dummySummary = new LfmsAsmlAlDummySummary();
dummySummary.setReticleKey(markSizeParam.get("rKey"));
dummySummary.setMarkCountKey(markSizeParam.get("mKey"));
dummySummary.setLayerName(layer);
dummySummary.setNo(new BigDecimal(1));
dummySummary.setType("NORMAL");
dummySummary.setRefreshed("GREEN");
dummySummary.setSubVersion(finalSubversion);
dummySummary.setCol("");
return dummySummary;
}).collect(Collectors.toList());
addDummySummaries.forEach(dummySummary -> asmlAlDummySummaryMapper.insert(dummySummary));
}
/**
* 根据align sheet 的markSizeMirror判断
*
* @param mainAlignList
* @param asmlAl
* @return
*/
private TMainAlignApply alignMirror(List<TMainAlignApply> mainAlignList, LfmsAsmlAlSizeSummary asmlAl) {
List<TMainAlignApply> mirrorAlignList = mainAlignList.stream().filter(kpiAlign -> Objects.equals(kpiAlign.getMarkSizeMirror(), asmlAl.getMirror())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(mirrorAlignList)) {
return alignBSLMark(mainAlignList);
} else if (mirrorAlignList.size() == 1) {
return mirrorAlignList.get(0);
} else {
return alignBSLMark(mirrorAlignList);
}
}
/**
* 根据align sheet 的ifBaselineMark判断
*
* @param mainAlignList
* @return
*/
private TMainAlignApply alignBSLMark(List<TMainAlignApply> mainAlignList) {
List<TMainAlignApply> baseLineList = mainAlignList.stream().filter(kpiAlign -> Objects.equals("Y", kpiAlign.getIfBaselineMark())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(baseLineList)) {
return alignBackUpMark(mainAlignList);
} else if (baseLineList.size() == 1) {
return baseLineList.get(0);
} else {
return alignBackUpMark(baseLineList);
}
}
/**
* 根据align sheet 的ifBackUp判断
*
* @param mainAlignList
* @return
*/
private TMainAlignApply alignBackUpMark(List<TMainAlignApply> mainAlignList) {
List<TMainAlignApply> backUpList = mainAlignList.stream().filter(kpiAlign -> Objects.equals("Y", kpiAlign.getIfBackUp())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(backUpList)) {
//todo 从系统对比“ROPI”值
return mainAlignList.get(0);
} else if (backUpList.size() == 1) {
return backUpList.get(0);
} else {
//todo 从系统对比“ROPI”值
return backUpList.get(0);
}
}
/**
* 根据ovl sheet 的ifBaselineMark判断
*
* @param mainOvlList
* @return
*/
private TMainOvlApply ovlBSLMark(List<TMainOvlApply> mainOvlList) {
List<TMainOvlApply> baseLineList = mainOvlList.stream().filter(kpiOvl -> Objects.equals("Y", kpiOvl.getIfBaselineMark())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(baseLineList)) {
return ovlBackUpMark(mainOvlList);
} else if (baseLineList.size() == 1) {
return baseLineList.get(0);
} else {
return ovlBackUpMark(baseLineList);
}
}
/**
* 根据ovlsheet的ifBackUp判断
*
* @param mainOvlList
* @return
*/
private TMainOvlApply ovlBackUpMark(List<TMainOvlApply> mainOvlList) {
List<TMainOvlApply> backUpList = mainOvlList.stream().filter(kpiOvl -> Objects.equals("Y", kpiOvl.getIfBackUp())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(backUpList)) {
//todo 从系统对比“ROPI”值
return mainOvlList.get(0);
} else if (backUpList.size() == 1) {
return backUpList.get(0);
} else {
//todo 从系统对比“ROPI”值
return backUpList.get(0);
}
}
/**
* 表头生成重构
* 从markcount拉取数据,并按feature2>mark type>feature1>pepper排序
*
* @param dto
* @return
*/
@Override
public AsmlQueryMarkCountVO fetchSheet(FetchSheetDTO dto) {
//查询sizeMapping信息
List<MarkSizeSpec> sizeMappingList = markSizeSpecMapper.selectList(new LambdaQueryWrapper<MarkSizeSpec>()
.eq(MarkSizeSpec::getTableType, "ASML_AL Mark Type"));
//查询 reticle 的信息, 对应的是表格行信息
//取subversion,根据subversion查询出LfmsReticle
String subversion = dto.getSubVersion();
LambdaQueryWrapper<LfmsDesignRecord> designRecordQueryWrapper = new LambdaQueryWrapper<>();
Map<String, String> markSizeParam = markSizeUtils.getMarkSizeParam(dto.getProject(), dto.getProjectId(),
dto.getPart(), dto.getProjectType(), dto.getMainVersion());
designRecordQueryWrapper.eq(LfmsDesignRecord::getProjAbbr, dto.getProject()).eq(LfmsDesignRecord::getPart, dto.getPart())
.eq(LfmsDesignRecord::getProjId, markSizeParam.get("projectId")).eq(LfmsDesignRecord::getProjType, dto.getProjectType())
.eq(LfmsDesignRecord::getMainVersion, dto.getMainVersion()).eq(LfmsDesignRecord::getDesignTable, "RETICLE")
.select(LfmsDesignRecord::getSubVersion)
.orderByDesc(LfmsDesignRecord::getSubVersion);
List<LfmsDesignRecord> designRecords = designRecordMapper.selectList(designRecordQueryWrapper);
boolean existSubversion = designRecords.stream().anyMatch(designRecord -> Objects.equals(designRecord.getSubVersion(), dto.getSubVersion()));
if (!existSubversion) {
String reg = "^[1-9][0-9]{7}(_[0-9]{1,2})?$";//原python代码,经了解部分老数据的版本不规范,后期都是采用日期当做版本号,如:“20240621”,不存在此类问题
subversion = designRecords.stream().filter(designRecord -> designRecord.getSubVersion().matches(reg)).map(LfmsDesignRecord::getSubVersion).findFirst().get();
}
LambdaQueryWrapper<LfmsReticle> reticleQueryWrapper = new LambdaQueryWrapper<>();
reticleQueryWrapper.eq(LfmsReticle::getSubVersion, subversion).eq(LfmsReticle::getDummyLayer, "Y").like(LfmsReticle::getIdx, markSizeParam.get("rKey"));
List<LfmsReticle> lfmsReticles = reticleMapper.selectList(reticleQueryWrapper);
if (CollectionUtils.isEmpty(lfmsReticles)) {
return null;
}
return null;
}
}帮忙优化下 markAutoGenerate 这个方法关联得代码
最新发布