9 changed files with 181 additions and 44 deletions
@ -0,0 +1,109 @@
|
||||
package com.biutag.supervision.service; |
||||
|
||||
import cn.hutool.core.util.NumberUtil; |
||||
import com.biutag.supervision.constants.enums.BusinessTypeEnum; |
||||
import com.biutag.supervision.pojo.entity.NegativeScorePolice; |
||||
import lombok.RequiredArgsConstructor; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.time.LocalDateTime; |
||||
import java.util.Arrays; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* |
||||
* @author wxc |
||||
* @date 2024/11/11 |
||||
*/ |
||||
// 平均问题数 = 总问题数 / 业务涉及人数
|
||||
// 业务标准差 = sum((个人问题数 - 平均问题数)²) / 业务涉及人数
|
||||
// 业务差异值1 = (问题发生率 - 平均问题发生率) / 业务标准差
|
||||
// 业务差异值2 = (问题数 - 平均问题数) / 业务标准差
|
||||
// 业务风险指数 = 50 + (业务差异值 * 15)
|
||||
// 业务权重 = 单个业务风险指数 / 总业务风险指数之和
|
||||
// 个人风险指数 = sum(业务风险指数 * 业务权重)
|
||||
@RequiredArgsConstructor |
||||
@Service |
||||
public class ProfilePoliceService { |
||||
|
||||
private final NegativeScorePoliceService negativeScorePoliceService; |
||||
|
||||
// 业务权重 = 单个业务风险指数 / 总业务风险指数之和
|
||||
public double getBusinessWeight(Double totalScore, List<NegativeScorePolice> businessScorePolice) { |
||||
if (totalScore == 0) { |
||||
return 0.0; |
||||
} |
||||
Double score = businessScorePolice.stream().mapToDouble(NegativeScorePolice::getScore).sum(); |
||||
return NumberUtil.div(score, totalScore); |
||||
} |
||||
|
||||
// 平均问题数 = 单个业务问题数 / 业务涉及人数
|
||||
public double getAvgNumber(int size, int policeSize) { |
||||
if (policeSize == 0) { |
||||
return 0; |
||||
} |
||||
return NumberUtil.div(size, policeSize); |
||||
} |
||||
|
||||
// 业务标准差 = 根号(sum((个人问题数 - 平均问题数)²) / 业务涉及人数)
|
||||
public double getSd(List<NegativeScorePolice> businessScorePolice, double avgNumber, int policeSize) { |
||||
if (policeSize == 0) { |
||||
return 0; |
||||
} |
||||
Map<String, List<NegativeScorePolice>> group = businessScorePolice.stream().collect(Collectors.groupingBy(NegativeScorePolice::getIdCode)); |
||||
return Math.sqrt(group.values().stream().mapToDouble(val -> Math.pow(val.size() - avgNumber, 2)).sum() / policeSize); |
||||
} |
||||
|
||||
// 业务差异值2 = (问题数 - 平均问题数) / 业务标准差
|
||||
public double getDiff(List<NegativeScorePolice> businessScorePolice, String idCode, double avgNumber, double sd) { |
||||
if (sd == 0) { |
||||
return 0; |
||||
} |
||||
long size = businessScorePolice.stream().filter(item -> idCode.equals(item.getIdCode())).count(); |
||||
return NumberUtil.div(size - avgNumber, sd); |
||||
} |
||||
|
||||
public double getBusinessScore(double diff) { |
||||
return 50 + (diff * 15); |
||||
} |
||||
|
||||
|
||||
// 平均问题数 = 单个业务问题数 / 业务涉及人数
|
||||
// 业务标准差 = sum((个人问题数 - 平均问题数)²) / 业务涉及人数
|
||||
// 业务差异值1 = (问题发生率 - 平均问题发生率) / 业务标准差
|
||||
// 业务差异值2 = (问题数 - 平均问题数) / 业务标准差
|
||||
// 业务风险指数 = 50 + (业务差异值 * 15)
|
||||
// 业务权重 = 单个业务风险指数 / 总业务风险指数之和
|
||||
// 个人风险指数 = sum(业务风险指数 * 业务权重)
|
||||
public BigDecimal getPoliceScore(Date beginTime, Date endTime, String idCode) { |
||||
List<NegativeScorePolice> scorePolices = negativeScorePoliceService.list(beginTime, endTime); |
||||
Double totalScore = scorePolices.stream().mapToDouble(NegativeScorePolice::getScore).sum(); |
||||
double policeScore = Arrays.stream(BusinessTypeEnum.values()).mapToDouble(businessTypeEnum -> { |
||||
List<NegativeScorePolice> businessScorePolice = scorePolices.stream().filter(item -> item.getBusinessTypeCode().equals(businessTypeEnum.getValue())).toList(); |
||||
// 业务涉及人数
|
||||
int policeSize = businessScorePolice.stream().map(NegativeScorePolice::getIdCode).collect(Collectors.toSet()).size(); |
||||
// 平均问题数
|
||||
double avgNumber = getAvgNumber(businessScorePolice.size(), policeSize); |
||||
// 业务标准差
|
||||
double sd = getSd(businessScorePolice, avgNumber, policeSize); |
||||
// 业务差异值
|
||||
double diff = 0; |
||||
if (businessTypeEnum.getBusinessVolume()) { |
||||
|
||||
} else { |
||||
diff = getDiff(businessScorePolice, idCode, avgNumber, sd); |
||||
} |
||||
// 业务风险指数
|
||||
double businessScore = getBusinessScore(diff); |
||||
// 业务权重
|
||||
double businessWeight = getBusinessWeight(totalScore, businessScorePolice); |
||||
return NumberUtil.mul(businessScore, businessWeight); |
||||
}).sum(); |
||||
return NumberUtil.roundHalfEven(policeScore, 2); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue