mirror of
https://codeup.aliyun.com/64f7d6b8ce01efaafef1e678/coal/coal.git
synced 2026-01-25 07:46:40 +08:00
feat(WeightDeviceDataService): enhance anomaly detection with detailed field comparison and numeric tolerance
This commit is contained in:
@@ -54,6 +54,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@@ -267,29 +268,104 @@ where 二次过磅时间>='%s' and 二次过磅时间<='%s'
|
||||
|
||||
private boolean isAnomalousData(Map<String, Object> sysData, Object bfData) {
|
||||
// 检查系统数据和业务数据是否一致
|
||||
// 这里可以根据业务规则来定义什么是异常数据
|
||||
if (sysData == null || bfData == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 示例检查逻辑:检查数量是否匹配
|
||||
try {
|
||||
Object sysCnt = sysData.get("cnt");
|
||||
if (bfData instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> bfMap = (Map<String, Object>) bfData;
|
||||
Object bfCnt = bfMap.get("cnt");
|
||||
if (!(bfData instanceof Map)) {
|
||||
log.warn("业务数据格式不正确,期望Map类型");
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> bfMap = (Map<String, Object>) bfData;
|
||||
|
||||
// 检查所有重要字段:毛重、皮重、净重、扣重、实重、数量
|
||||
String[] checkFields = {"mz", "pz", "jz", "kz", "sz", "cnt"};
|
||||
|
||||
for (String field : checkFields) {
|
||||
Object sysValue = sysData.get(field);
|
||||
Object bfValue = bfMap.get(field);
|
||||
|
||||
if (sysCnt != null && bfCnt != null) {
|
||||
return !sysCnt.toString().equals(bfCnt.toString());
|
||||
// 如果任一值为null,需要两者都为null才算一致
|
||||
if (sysValue == null || bfValue == null) {
|
||||
if (sysValue != bfValue) {
|
||||
log.debug("字段 {} 存在null值不一致: 系统={}, 业务={}", field, sysValue, bfValue);
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 对于数值字段,进行数值比较
|
||||
if (isNumericField(field)) {
|
||||
if (!compareNumericValues(sysValue, bfValue)) {
|
||||
log.debug("数值字段 {} 不匹配: 系统={}, 业务={}", field, sysValue, bfValue);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// 对于非数值字段,进行字符串比较
|
||||
if (!sysValue.toString().equals(bfValue.toString())) {
|
||||
log.debug("字段 {} 不匹配: 系统={}, 业务={}", field, sysValue, bfValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("检查异常数据时发生错误", e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNumericField(String fieldName) {
|
||||
// 重量相关字段都是数值类型
|
||||
return fieldName.equals("mz") || fieldName.equals("pz") || fieldName.equals("jz")
|
||||
|| fieldName.equals("kz") || fieldName.equals("sz") || fieldName.equals("cnt");
|
||||
}
|
||||
|
||||
private boolean compareNumericValues(Object value1, Object value2) {
|
||||
try {
|
||||
// 转换为Double进行比较,容忍小的浮点误差
|
||||
Double num1 = parseToDouble(value1);
|
||||
Double num2 = parseToDouble(value2);
|
||||
|
||||
if (num1 == null || num2 == null) {
|
||||
return Objects.equals(num1, num2);
|
||||
}
|
||||
|
||||
// 对于重量数据,容忍0.01的误差(精确到分)
|
||||
return Math.abs(num1 - num2) < 0.01;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.debug("数值比较失败,回退到字符串比较: {} vs {}", value1, value2);
|
||||
return value1.toString().equals(value2.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private Double parseToDouble(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return false;
|
||||
try {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).doubleValue();
|
||||
}
|
||||
|
||||
String str = value.toString().trim();
|
||||
if (str.isEmpty()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return Double.parseDouble(str);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
log.debug("无法解析数值: {}", value);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<LocalDate> binarySearchAnomalousDates(String deviceId, LocalDate startDate, LocalDate endDate) {
|
||||
|
||||
Reference in New Issue
Block a user