抽样算法调整

master
Yangwl 6 days ago
parent ae020c6e09
commit d8e0789307

@ -1,186 +1,119 @@
package com.op.quality.config;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
public class GB2828Sampler {
private static final Map<String, String> CODE_MAP = new HashMap<>();
private static final Map<String, int[]> SAMPLE_SIZE_MAP = new HashMap<>();
private static final Map<String, int[]> AQL_TABLE = new HashMap<>();
// 批量范围与字码对照表(简化版)
private static final Map<String, String[]> BATCH_RANGE_TO_LETTER = new HashMap<>();
static {
// 初始化样本量字码表
initCodeMap();
// 初始化样本量表
initSampleSizeMap();
// 初始化AQL表
initAqlTable();
// 一般检查水平I
BATCH_RANGE_TO_LETTER.put("I", new String[]{
"A", "A", "B", "C","C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N"
});
// 一般检查水平II
BATCH_RANGE_TO_LETTER.put("II", new String[]{
"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q"
});
// 一般检查水平III
BATCH_RANGE_TO_LETTER.put("III", new String[]{
"B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R"
});
// 特殊检查水平S-1
BATCH_RANGE_TO_LETTER.put("S1", new String[]{
"A", "A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C", "D", "D", "D"
});
// 特殊检查水平S-2
BATCH_RANGE_TO_LETTER.put("S2", new String[]{
"A", "A", "A" ,"B", "B", "B", "C", "C", "C", "D", "D", "D", "E", "E", "E"
});
// 特殊检查水平S-3
BATCH_RANGE_TO_LETTER.put("S3", new String[]{
"A", "A", "B", "B", "C", "C", "D", "D", "E", "E", "F", "F", "G", "G", "H"
});
// 特殊检查水平S-4
BATCH_RANGE_TO_LETTER.put("S4", new String[]{
"A", "A", "B", "C", "C", "D", "E", "E", "F", "G", "G", "H", "J", "J", "K"
});
}
private static void initCodeMap() {
// 常规检验水平(I/II/III)
CODE_MAP.put("2-8_I", "A"); CODE_MAP.put("2-8_II", "A"); CODE_MAP.put("2-8_III", "B");
CODE_MAP.put("9-15_I", "B"); CODE_MAP.put("9-15_II", "B"); CODE_MAP.put("9-15_III", "C");
CODE_MAP.put("16-25_I", "C"); CODE_MAP.put("16-25_II", "C"); CODE_MAP.put("16-25_III", "D");
CODE_MAP.put("26-50_I", "D"); CODE_MAP.put("26-50_II", "D"); CODE_MAP.put("26-50_III", "E");
CODE_MAP.put("51-90_I", "E"); CODE_MAP.put("51-90_II", "E"); CODE_MAP.put("51-90_III", "F");
CODE_MAP.put("91-150_I", "F"); CODE_MAP.put("91-150_II", "F"); CODE_MAP.put("91-150_III", "G");
CODE_MAP.put("151-280_I", "G"); CODE_MAP.put("151-280_II", "G"); CODE_MAP.put("151-280_III", "H");
CODE_MAP.put("281-500_I", "H"); CODE_MAP.put("281-500_II", "H"); CODE_MAP.put("281-500_III", "J");
CODE_MAP.put("501-1200_I", "J"); CODE_MAP.put("501-1200_II", "J"); CODE_MAP.put("501-1200_III", "K");
CODE_MAP.put("1201-3200_I", "K"); CODE_MAP.put("1201-3200_II", "K"); CODE_MAP.put("1201-3200_III", "L");
CODE_MAP.put("3201-10000_I", "L"); CODE_MAP.put("3201-10000_II", "L"); CODE_MAP.put("3201-10000_III", "M");
CODE_MAP.put("10001-35000_I", "M"); CODE_MAP.put("10001-35000_II", "M"); CODE_MAP.put("10001-35000_III", "N");
CODE_MAP.put("35001-150000_I", "N"); CODE_MAP.put("35001-150000_II", "N"); CODE_MAP.put("35001-150000_III", "P");
CODE_MAP.put("150001-500000_I", "P"); CODE_MAP.put("150001-500000_II", "P"); CODE_MAP.put("150001-500000_III", "Q");
CODE_MAP.put("500001+_I", "Q"); CODE_MAP.put("500001+_II", "Q"); CODE_MAP.put("500001+_III", "R");
// 特殊检验水平(S1-S4)
CODE_MAP.put("2-8_S1", "A"); CODE_MAP.put("2-8_S2", "A"); CODE_MAP.put("2-8_S3", "A"); CODE_MAP.put("2-8_S4", "A");
CODE_MAP.put("9-15_S1", "A"); CODE_MAP.put("9-15_S2", "A"); CODE_MAP.put("9-15_S3", "B"); CODE_MAP.put("9-15_S4", "B");
CODE_MAP.put("16-25_S1", "A"); CODE_MAP.put("16-25_S2", "B"); CODE_MAP.put("16-25_S3", "B"); CODE_MAP.put("16-25_S4", "C");
CODE_MAP.put("26-50_S1", "B"); CODE_MAP.put("26-50_S2", "B"); CODE_MAP.put("26-50_S3", "C"); CODE_MAP.put("26-50_S4", "D");
CODE_MAP.put("51-90_S1", "B"); CODE_MAP.put("51-90_S2", "C"); CODE_MAP.put("51-90_S3", "D"); CODE_MAP.put("51-90_S4", "E");
CODE_MAP.put("91-150_S1", "B"); CODE_MAP.put("91-150_S2", "C"); CODE_MAP.put("91-150_S3", "E"); CODE_MAP.put("91-150_S4", "F");
CODE_MAP.put("151-280_S1", "C"); CODE_MAP.put("151-280_S2", "D"); CODE_MAP.put("151-280_S3", "F"); CODE_MAP.put("151-280_S4", "G");
CODE_MAP.put("281-500_S1", "C"); CODE_MAP.put("281-500_S2", "E"); CODE_MAP.put("281-500_S3", "G"); CODE_MAP.put("281-500_S4", "H");
CODE_MAP.put("501-1200_S1", "D"); CODE_MAP.put("501-1200_S2", "F"); CODE_MAP.put("501-1200_S3", "H"); CODE_MAP.put("501-1200_S4", "J");
CODE_MAP.put("1201-3200_S1", "D"); CODE_MAP.put("1201-3200_S2", "G"); CODE_MAP.put("1201-3200_S3", "J"); CODE_MAP.put("1201-3200_S4", "K");
CODE_MAP.put("3201-10000_S1", "E"); CODE_MAP.put("3201-10000_S2", "H"); CODE_MAP.put("3201-10000_S3", "K"); CODE_MAP.put("3201-10000_S4", "L");
CODE_MAP.put("10001-35000_S1", "E"); CODE_MAP.put("10001-35000_S2", "J"); CODE_MAP.put("10001-35000_S3", "L"); CODE_MAP.put("10001-35000_S4", "M");
CODE_MAP.put("35001-150000_S1", "F"); CODE_MAP.put("35001-150000_S2", "K"); CODE_MAP.put("35001-150000_S3", "M"); CODE_MAP.put("35001-150000_S4", "N");
CODE_MAP.put("150001-500000_S1", "G"); CODE_MAP.put("150001-500000_S2", "L"); CODE_MAP.put("150001-500000_S3", "N"); CODE_MAP.put("150001-500000_S4", "P");
CODE_MAP.put("500001+_S1", "H"); CODE_MAP.put("500001+_S2", "M"); CODE_MAP.put("500001+_S3", "P"); CODE_MAP.put("500001+_S4", "Q");
// 字码与抽样数量对照表
private static final Map<String, Integer> LETTER_TO_SAMPLE_SIZE = new HashMap<>();
static {
LETTER_TO_SAMPLE_SIZE.put("A", 2);
LETTER_TO_SAMPLE_SIZE.put("B", 3);
LETTER_TO_SAMPLE_SIZE.put("C", 5);
LETTER_TO_SAMPLE_SIZE.put("D", 8);
LETTER_TO_SAMPLE_SIZE.put("E", 13);
LETTER_TO_SAMPLE_SIZE.put("F", 20);
LETTER_TO_SAMPLE_SIZE.put("G", 32);
LETTER_TO_SAMPLE_SIZE.put("H", 50);
LETTER_TO_SAMPLE_SIZE.put("J", 80);
LETTER_TO_SAMPLE_SIZE.put("K", 125);
LETTER_TO_SAMPLE_SIZE.put("L", 200);
LETTER_TO_SAMPLE_SIZE.put("M", 315);
LETTER_TO_SAMPLE_SIZE.put("N", 500);
LETTER_TO_SAMPLE_SIZE.put("P", 800);
LETTER_TO_SAMPLE_SIZE.put("Q", 1250);
LETTER_TO_SAMPLE_SIZE.put("R", 2000);
}
private static void initSampleSizeMap() {
SAMPLE_SIZE_MAP.put("A", new int[]{0,0,0,1,1,2,3,5,7,10,14,21});
SAMPLE_SIZE_MAP.put("B", new int[]{0,0,1,2,3,5,7,10,14,21,30,42});
SAMPLE_SIZE_MAP.put("C", new int[]{0,1,2,3,5,7,10,14,21,30,42,60});
SAMPLE_SIZE_MAP.put("D", new int[]{1,1,3,5,7,10,14,21,30,42,60,90});
SAMPLE_SIZE_MAP.put("E", new int[]{2,3,5,7,10,14,21,30,42,60,90,150});
SAMPLE_SIZE_MAP.put("F", new int[]{3,5,7,10,14,21,30,42,60,90,150,240});
SAMPLE_SIZE_MAP.put("G", new int[]{5,7,10,14,21,30,42,60,90,150,240,360});
SAMPLE_SIZE_MAP.put("H", new int[]{7,10,14,21,30,42,60,90,150,240,360,540});
SAMPLE_SIZE_MAP.put("J", new int[]{10,14,21,30,42,60,90,150,240,360,540,800});
SAMPLE_SIZE_MAP.put("K", new int[]{14,21,30,42,60,90,150,240,360,540,800,1200});
SAMPLE_SIZE_MAP.put("L", new int[]{21,30,42,60,90,150,240,360,540,800,1200,1800});
SAMPLE_SIZE_MAP.put("M", new int[]{30,42,60,90,150,240,360,540,800,1200,1800,3000});
SAMPLE_SIZE_MAP.put("N", new int[]{42,60,90,150,240,360,540,800,1200,1800,3000,4500});
SAMPLE_SIZE_MAP.put("P", new int[]{60,90,150,240,360,540,800,1200,1800,3000,4500,7000});
SAMPLE_SIZE_MAP.put("Q", new int[]{90,150,240,360,540,800,1200,1800,3000,4500,7000,10000});
SAMPLE_SIZE_MAP.put("R", new int[]{150,240,360,540,800,1200,1800,3000,4500,7000,10000,15000});
}
private static void initAqlTable() {
// 数组元素对应标准AQL值0.065,0.10,0.15,0.25,0.40,0.65,1.0,1.5,2.5,4.0,6.5
AQL_TABLE.put("A", new int[]{0,0,1,1,2,3,5,7,10,14,21});
AQL_TABLE.put("B", new int[]{0,1,1,2,3,5,7,10,14,21,30});
AQL_TABLE.put("C", new int[]{0,1,2,3,5,7,10,14,21,30,42});
AQL_TABLE.put("D", new int[]{1,1,2,3,5,7,10,14,21,30,42});
AQL_TABLE.put("E", new int[]{1,2,3,5,7,10,14,21,30,42,60});
AQL_TABLE.put("F", new int[]{2,3,5,7,10,14,21,30,42,60,80});
AQL_TABLE.put("G", new int[]{3,5,7,10,14,21,30,42,60,80,120});
AQL_TABLE.put("H", new int[]{5,7,10,14,21,30,42,60,80,120,180});
AQL_TABLE.put("J", new int[]{7,10,14,21,30,42,60,80,120,180,280});
AQL_TABLE.put("K", new int[]{10,14,21,30,42,60,80,120,180,280,400});
AQL_TABLE.put("L", new int[]{14,21,30,42,60,80,120,180,280,400,600});
AQL_TABLE.put("M", new int[]{21,30,42,60,80,120,180,280,400,600,800});
AQL_TABLE.put("N", new int[]{30,42,60,80,120,180,280,400,600,800,1200});
AQL_TABLE.put("P", new int[]{42,60,80,120,180,280,400,600,800,1200,1800});
AQL_TABLE.put("Q", new int[]{60,80,120,180,280,400,600,800,1200,1800,2500});
AQL_TABLE.put("R", new int[]{80,120,180,280,400,600,800,1200,1800,2500,3200});
}
public SamplingResult getSamplingPlan(int lotSize, String level, double aql) {
String code = determineCode(lotSize, level);
int sampleSize = determineSampleSize(code, level);
int[] acRe = determineAcReNumbers(code, aql);
return new SamplingResult(code, sampleSize, acRe[0], acRe[1]);
}
private String determineCode(int lotSize, String level) {
String range = getRange(lotSize);
return CODE_MAP.getOrDefault(range + "_" + level, "K");
}
private String getRange(int size) {
if (size >= 2 && size <= 8) return "2-8";
else if (size >= 9 && size <= 15) return "9-15";
else if (size >= 16 && size <= 25) return "16-25";
else if (size >= 26 && size <= 50) return "26-50";
else if (size >= 51 && size <= 90) return "51-90";
else if (size >= 91 && size <= 150) return "91-150";
else if (size >= 151 && size <= 280) return "151-280";
else if (size >= 281 && size <= 500) return "281-500";
else if (size >= 501 && size <= 1200) return "501-1200";
else if (size >= 1201 && size <= 3200) return "1201-3200";
else if (size >= 3201 && size <= 10000) return "3201-10000";
else if (size >= 10001 && size <= 35000) return "10001-35000";
else if (size >= 35001 && size <= 150000) return "35001-150000";
else if (size >= 150001 && size <= 500000) return "150001-500000";
else return "500001+";
}
private int determineSampleSize(String code, String level) {
int[] sizes = SAMPLE_SIZE_MAP.get(code);
switch(level) {
case "I": case "S1": case "S2": return sizes[0];
case "II": case "S3": return sizes[1];
case "III": case "S4": return sizes[2];
default: return sizes[1];
/**
*
* @param batchSize
* @param inspectionLevel II, III, S-1, S-2
* @return
*/
public static String getSampleSizeLetter(int batchSize, String inspectionLevel) {
int index = calculateBatchRangeIndex(batchSize);
String[] letters = BATCH_RANGE_TO_LETTER.get(inspectionLevel);
if (letters == null || index >= letters.length) {
return "B"; // 默认返回B
}
return letters[index];
}
private int[] determineAcReNumbers(String code, double aql) {
int[] aqlValues = AQL_TABLE.get(code);
if (aql <= 0.065) return new int[]{aqlValues[0], aqlValues[0]+1};
else if (aql <= 0.10) return new int[]{aqlValues[1], aqlValues[1]+1};
else if (aql <= 0.15) return new int[]{aqlValues[2], aqlValues[2]+1};
else if (aql <= 0.25) return new int[]{aqlValues[3], aqlValues[3]+1};
else if (aql <= 0.40) return new int[]{aqlValues[4], aqlValues[4]+1};
else if (aql <= 0.65) return new int[]{aqlValues[5], aqlValues[5]+1};
else if (aql <= 1.0) return new int[]{aqlValues[6], aqlValues[6]+1};
else if (aql <= 1.5) return new int[]{aqlValues[7], aqlValues[7]+1};
else if (aql <= 2.5) return new int[]{aqlValues[8], aqlValues[8]+1};
else if (aql <= 4.0) return new int[]{aqlValues[9], aqlValues[9]+1};
else if (aql <= 6.5) return new int[]{aqlValues[10], aqlValues[10]+1};
else return new int[]{aqlValues[11], aqlValues[11]+1};
/**
*
*/
private static int calculateBatchRangeIndex(int batchSize) {
if (batchSize <= 8) return 0;
if (batchSize <= 15) return 1;
if (batchSize <= 25) return 2;
if (batchSize <= 50) return 3;
if (batchSize <= 90) return 4;
if (batchSize <= 150) return 5;
if (batchSize <= 280) return 6;
if (batchSize <= 500) return 7;
if (batchSize <= 1200) return 8;
if (batchSize <= 3200) return 9;
if (batchSize <= 10000) return 10;
if (batchSize <= 35000) return 11;
if (batchSize <= 150000) return 12;
if (batchSize <= 500000) return 13;
if (batchSize <= 1000000) return 14;
return 15; // 超过100万
}
public static class SamplingResult {
public final String code;
public final int sampleSize;
public final int acceptNumber;
public final int rejectNumber;
public SamplingResult(String code, int sampleSize, int acceptNumber, int rejectNumber) {
this.code = code;
this.sampleSize = sampleSize;
this.acceptNumber = acceptNumber;
this.rejectNumber = rejectNumber;
}
/**
*
* @param sampleLetter
* @return
*/
public static int getSampleSize(String sampleLetter) {
return LETTER_TO_SAMPLE_SIZE.getOrDefault(sampleLetter, 0);
}
public static void main(String[] args) {
GB2828Sampler sampler = new GB2828Sampler();
// 常规检验水平II示例
GB2828Sampler.SamplingResult normalResult =
sampler.getSamplingPlan(5000 ,"III", 0.0);
System.out.println("常规检验: " + normalResult.code + " " +
normalResult.sampleSize + " " + normalResult.acceptNumber);
// 特殊检验水平S2示例
GB2828Sampler.SamplingResult specialResult =
sampler.getSamplingPlan(1500, "S4", 1.0);
System.out.println("特殊检验: " + specialResult.code + " " +
specialResult.sampleSize + " " + specialResult.acceptNumber);
// 示例批量30001一般检查水平Ⅱ
String letter = getSampleSizeLetter(30001, "I");
int sampleSize = getSampleSize(letter);
System.out.println("样品量字码: " + letter);
System.out.println("抽样数量: " + sampleSize);
}
}

@ -245,16 +245,15 @@ public class QcProCheckServiceImpl implements QcProCheckService {
qcd.setDefectQualitys(defectInfo.getDefectQualitys());
qcd.setClassTypeCodes(defectInfo.getClassId());
}
if (StringUtils.isNotBlank(qcd.getSamplingPlan())&&StringUtils.isNotBlank(qcd.getDefectCategory())){
GB2828Sampler sampler = new GB2828Sampler();
// 常规检验水平II示例
GB2828Sampler.SamplingResult normalResult =
sampler.getSamplingPlan(qcd.getQuality().setScale(0, RoundingMode.HALF_UP).intValue(),qcd.getSamplingPlan(), Double.valueOf(qcd.getDefectCategory()));
qcd.setSampleQuality(String.valueOf(normalResult.acceptNumber));
if (StringUtils.isNotBlank(qcd.getSamplingPlan())){
//抽样算法
if (!StringUtils.isNotBlank(qcd.getSampleQuality())){
String letter = GB2828Sampler.getSampleSizeLetter(qcd.getQuality().setScale(0, RoundingMode.HALF_UP).intValue(), qcd.getSamplingPlan());
int sampleSize = GB2828Sampler.getSampleSize(letter);
qcd.setSampleQuality(String.valueOf(sampleSize));
}
}
}
dto.setQcCheckTaskDetails(qcCheckTaskDetails);
List<QcCheckTaskDefect> defects = qcCheckTaskIncomeMapper.getCkeckDefectList(qcCheckTaskDetail);
if (CollectionUtils.isEmpty(defects)) {

Loading…
Cancel
Save