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