From b8a014509761d2593eb92a4838ac430c7b438038 Mon Sep 17 00:00:00 2001 From: xueqingkun Date: Mon, 22 Jul 2024 16:08:41 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E6=95=B0=E6=8D=AE=E5=BA=93=E5=88=86?= =?UTF-8?q?=E6=9E=90=E8=AF=81=E6=8D=AE=E7=BB=93=E6=9E=9C=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/supervision/constants/ScoreEnum.java | 41 +++++ .../police/controller/ModelController.java | 22 ++- .../police/dto/caseScore/AtomicResult.java | 45 +++++ .../dto/caseScore/CaseScoreDetailBuilder.java | 169 ++++++++++++++++++ .../dto/caseScore/CaseScoreDetailDTO.java | 50 ++++++ .../police/dto/caseScore/IndexResult.java | 79 ++++++++ .../police/dto/caseScore/LawParty.java | 20 +++ .../police/service/ModelService.java | 6 + .../police/service/impl/ModelServiceImpl.java | 47 ++++- 9 files changed, 476 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/supervision/constants/ScoreEnum.java create mode 100644 src/main/java/com/supervision/police/dto/caseScore/AtomicResult.java create mode 100644 src/main/java/com/supervision/police/dto/caseScore/CaseScoreDetailBuilder.java create mode 100644 src/main/java/com/supervision/police/dto/caseScore/CaseScoreDetailDTO.java create mode 100644 src/main/java/com/supervision/police/dto/caseScore/IndexResult.java create mode 100644 src/main/java/com/supervision/police/dto/caseScore/LawParty.java diff --git a/src/main/java/com/supervision/constants/ScoreEnum.java b/src/main/java/com/supervision/constants/ScoreEnum.java new file mode 100644 index 0000000..7d4b7c5 --- /dev/null +++ b/src/main/java/com/supervision/constants/ScoreEnum.java @@ -0,0 +1,41 @@ +package com.supervision.constants; + +import java.util.Objects; + +public enum ScoreEnum { + EVIDENCE_FULL("证据充分", "司法机关对案件形成一致认定意见的概率比较大"), + EVIDENCE_LACK("证据不足", "司法籍贯认定意见不一致的概率比较大"), + EVIDENCE_NOT_FULL("证据不充分", "司法籍贯会作出绝对不起诉或存疑不起诉的决定"); + + private final String name; + private final String desc; + + ScoreEnum(String name, String desc) { + this.name = name; + this.desc = desc; + } + + public String getName() { + return name; + } + + public String getDesc() { + return desc; + } + + public static ScoreEnum getScoreEnum(Integer score) { + if (Objects.isNull(score)){ + return null; + } + + if (score < 50){ + return EVIDENCE_NOT_FULL; + } + + if (score <= 70){ + return EVIDENCE_LACK; + } + + return EVIDENCE_FULL; + } +} diff --git a/src/main/java/com/supervision/police/controller/ModelController.java b/src/main/java/com/supervision/police/controller/ModelController.java index 38c85b8..913df94 100644 --- a/src/main/java/com/supervision/police/controller/ModelController.java +++ b/src/main/java/com/supervision/police/controller/ModelController.java @@ -3,15 +3,18 @@ package com.supervision.police.controller; import com.supervision.common.domain.R; import com.supervision.police.dto.AnalyseCaseDTO; import com.supervision.police.service.ModelService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("model") +@RequiredArgsConstructor public class ModelController { - @Autowired - private ModelService modelService; + private final ModelService modelService; /** * 分析指标 @@ -19,8 +22,23 @@ public class ModelController { * @return */ @PostMapping("/analyseCase") + @Operation(summary = "分析指标") public R analyseCase(@RequestBody AnalyseCaseDTO analyseCaseDTO) { return modelService.analyseCase(analyseCaseDTO); } + + /** + * 获取指标详情 + * @param caseId 案件id + * @return + */ + @GetMapping("/caseScoreDetail") + @Operation(summary = "案件得分详情功能") + public R caseScoreDetail( @RequestParam @Parameter(name = "caseId",description = "案件id") String caseId) { + + String detail = modelService.caseScoreDetail(caseId); + return R.ok(detail); + } + } diff --git a/src/main/java/com/supervision/police/dto/caseScore/AtomicResult.java b/src/main/java/com/supervision/police/dto/caseScore/AtomicResult.java new file mode 100644 index 0000000..41958fd --- /dev/null +++ b/src/main/java/com/supervision/police/dto/caseScore/AtomicResult.java @@ -0,0 +1,45 @@ +package com.supervision.police.dto.caseScore; + +import com.supervision.police.domain.ModelAtomicIndex; +import com.supervision.police.domain.ModelAtomicResult; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Objects; + +/** + * 原子指标结果类 + */ +@Data +public class AtomicResult { + + @Schema(description = "原子指标id") + private String atomicId; + + @Schema(description = "原子指标名称") + private String atomicName; + + @Schema(description = "指标id") + private String indexId; + + @Schema(description = "指标来源 1:人工定义 2:数据库查询 3:图谱生成 4:大模型") + private String indexSource; + + @Schema(description = "原子指标结果 1:真实 2:虚构 3:存在 4:不存在 5:未知") + private String judgeResult; + + + public AtomicResult() { + } + + public AtomicResult(String indexId,ModelAtomicIndex modelAtomicIndex, ModelAtomicResult atomicResult) { + if (Objects.isNull(atomicResult) || Objects.isNull(modelAtomicIndex)){ + return; + } + this.atomicId = modelAtomicIndex.getId(); + this.indexId = indexId; + this.atomicName = modelAtomicIndex.getName(); + this.indexSource = modelAtomicIndex.getIndexSource(); + this.judgeResult = atomicResult.getAtomicResult(); + } +} diff --git a/src/main/java/com/supervision/police/dto/caseScore/CaseScoreDetailBuilder.java b/src/main/java/com/supervision/police/dto/caseScore/CaseScoreDetailBuilder.java new file mode 100644 index 0000000..327910d --- /dev/null +++ b/src/main/java/com/supervision/police/dto/caseScore/CaseScoreDetailBuilder.java @@ -0,0 +1,169 @@ +package com.supervision.police.dto.caseScore; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.supervision.constants.ScoreEnum; +import com.supervision.police.domain.*; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.ai.ollama.OllamaChatClient; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 案件得分详情 + */ +@Data +public class CaseScoreDetailBuilder { + + @Schema(description = "案件id") + private String caseId; + + @Schema(description = "案件名称") + private String caseName; + + @Schema(description = "当事人列表") + private List lawPartyList; + + @Schema(description = "指标结果") + private List indexResultList; + + /** + * Ollama 客户端 + */ + private OllamaChatClient chatClient; + + + /** + * 共性指标分数 + * @return + */ + public Integer getCommonScore() { + + return sumIndexGroupScore("1"); + } + + /** + * 入罪指标分数 + * @return + */ + public Integer getCrimeScore() { + + return sumIndexGroupScore("2"); + } + + /** + * 出罪指标分数 + * @return + */ + public Integer getCrimeOutScore() { + return sumIndexGroupScore("3"); + } + + /** + * 获取行为人 + */ + public LawParty getLawActor() { + if (CollUtil.isEmpty(this.lawPartyList)){ + return null; + } + return this.lawPartyList.stream() + .filter(lawParty -> StrUtil.equals("1",lawParty.getUserType())).findFirst().orElse(null); + } + + public void setIndexResultList(List indexList, List indexResultList, + List atomicIndexList, List atomicResultList) { + + if (CollUtil.isEmpty(indexList) || CollUtil.isEmpty(indexResultList)){ + this.indexResultList = new ArrayList<>(); + return; + } + + Map modelIndexResultMap = indexResultList.stream().collect( + Collectors.toMap(ModelIndexResult::getIndexId, modelIndexResult -> modelIndexResult)); + + this.indexResultList = indexList.stream().map(indexInfo -> + new IndexResult(indexInfo,modelIndexResultMap.get(indexInfo.getId()),atomicIndexList,atomicResultList) + ).toList(); + + + } + + /** + * 设置行为人 + * @param casePersonList + */ + public void setLawActor(List casePersonList) { + if (CollUtil.isEmpty(casePersonList)){ + this.lawPartyList = new ArrayList<>(); + return; + } + this.lawPartyList = casePersonList.stream() + .map(casePerson -> { + LawParty lawParty = new LawParty(); + lawParty.setUserId(casePerson.getId()); + lawParty.setUserName(casePerson.getName()); + lawParty.setUserType(casePerson.getRoleCode()); + return lawParty; + }).toList(); + } + + + /** + * 构建CaseScoreDetailDTO + */ + public CaseScoreDetailDTO build(){ + + CaseScoreDetailDTO caseScoreDetailDTO = new CaseScoreDetailDTO(); + caseScoreDetailDTO.setCaseName(this.caseName); + caseScoreDetailDTO.setCommonScore(this.getCommonScore()); + Integer crimeScore = this.getCrimeScore(); + Integer crimeOutScore = this.getCrimeOutScore(); + caseScoreDetailDTO.setCrimeScore(crimeScore < crimeOutScore? crimeOutScore:crimeScore); + + int sumScore = caseScoreDetailDTO.getCommonScore() + caseScoreDetailDTO.getCrimeScore(); + ScoreEnum scoreEnum = ScoreEnum.getScoreEnum(sumScore); + if (scoreEnum != null){ + caseScoreDetailDTO.setScoreDesc(scoreEnum.getDesc()); + caseScoreDetailDTO.setJudicialCharacterization(scoreEnum.getName()); + } + + caseScoreDetailDTO.setCommonIndexCount(this.countIndexGroup("1",res->true).intValue()); + caseScoreDetailDTO.setCommonIndexHitCount(this.countIndexGroup("1",res->res.getActualScore() > 0).intValue()); + + if (crimeScore < crimeOutScore){ + caseScoreDetailDTO.setCrimeIndexCount(this.countIndexGroup("3",res->true).intValue()); + caseScoreDetailDTO.setCrimeIndexHitCount(this.countIndexGroup("3",res->res.getActualScore() > 0).intValue()); + }else { + caseScoreDetailDTO.setCrimeIndexCount(this.countIndexGroup("2",res->true).intValue()); + caseScoreDetailDTO.setCrimeIndexHitCount(this.countIndexGroup("2",res->res.getActualScore() > 0).intValue()); + } + return caseScoreDetailDTO; + } + + private Integer sumIndexGroupScore(String indexGroup) { + if (CollUtil.isEmpty(this.indexResultList)){ + return 0; + } + + return this.indexResultList.stream() + .filter(indexResult -> StrUtil.equals(indexGroup,indexResult.getIndexGroup())) + .mapToInt(IndexResult::getIndexScore).sum(); + + } + + private Long countIndexGroup(String indexGroup, Function function) { + if (CollUtil.isEmpty(this.indexResultList)){ + return 0L; + } + + return this.indexResultList.stream() + .filter(indexResult -> StrUtil.equals(indexGroup,indexResult.getIndexGroup()) + && function.apply(indexResult)).count(); + + } +} diff --git a/src/main/java/com/supervision/police/dto/caseScore/CaseScoreDetailDTO.java b/src/main/java/com/supervision/police/dto/caseScore/CaseScoreDetailDTO.java new file mode 100644 index 0000000..df334d2 --- /dev/null +++ b/src/main/java/com/supervision/police/dto/caseScore/CaseScoreDetailDTO.java @@ -0,0 +1,50 @@ +package com.supervision.police.dto.caseScore; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +@Data +@Slf4j +public class CaseScoreDetailDTO { + + @Schema(description = "案件名称") + private String caseName; + + @Schema(description = "共性指标分数") + private Integer commonScore; + + @Schema(description = "入罪指标分数") + private Integer crimeScore; + + @Schema(description = "分数描述") + private String scoreDesc; + + @Schema(description = "司法定性") + private String judicialCharacterization; + + @Schema(description = "共性指标数量") + private Integer commonIndexCount; + + @Schema(description = "共性指标命中数量") + private Integer commonIndexHitCount; + + @Schema(description = "共性指标命描述") + private List commonIndexDescList; + + @Schema(description = "入罪指标数量") + private Integer crimeIndexCount; + + @Schema(description = "入罪指标命中数量") + private Integer crimeIndexHitCount; + + @Schema(description = "入罪指标命描述") + private List crimeIndexDescList; + + @Schema(description = "缺失的原子指标数量") + private Integer missAtomicIndexCount; + + +} diff --git a/src/main/java/com/supervision/police/dto/caseScore/IndexResult.java b/src/main/java/com/supervision/police/dto/caseScore/IndexResult.java new file mode 100644 index 0000000..15dacb6 --- /dev/null +++ b/src/main/java/com/supervision/police/dto/caseScore/IndexResult.java @@ -0,0 +1,79 @@ +package com.supervision.police.dto.caseScore; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.StrUtil; +import com.supervision.police.domain.ModelAtomicIndex; +import com.supervision.police.domain.ModelAtomicResult; +import com.supervision.police.domain.ModelIndex; +import com.supervision.police.domain.ModelIndexResult; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Description 指标结果 + */ +@Data +@Slf4j +public class IndexResult { + + @Schema(description = "指标id") + private String indexId; + + @Schema(description = "指标名称") + private String indexName; + + @Schema(description = "指标分组 1:共性指标 2:入罪指标 3:出罪指标") + private String indexGroup; + + @Schema(description = "指标分数") + private Integer indexScore; + + @Schema(description = "实际分数") + private int actualScore; + + @Schema(description = "原子指标结果") + private List atomicResults; + + public IndexResult() { + } + + public IndexResult(ModelIndex indexInfo, ModelIndexResult modelIndexResult, + List atomicIndexList, List atomicResultList ) { + if (Objects.isNull(modelIndexResult) || Objects.isNull(indexInfo)){ + return; + } + this.indexId = indexInfo.getId(); + this.indexGroup = indexInfo.getIndexType(); + this.indexName = indexInfo.getName(); + this.indexScore = indexInfo.getIndexScore(); + if (StrUtil.equals("true", modelIndexResult.getIndexResult())){ + // 如果运行结果为真,则实际分数为指标分数 + this.actualScore = indexInfo.getIndexScore(); + } + if (CollUtil.isEmpty(atomicResultList) || StrUtil.isEmpty(modelIndexResult.getAtomicIds())){ + return; + } + + // 填充原子指标结果属性 + List atomicIdList = Arrays.stream(modelIndexResult.getAtomicIds().split(",")).toList(); + atomicResultList = atomicResultList.stream().filter(atomicResult -> atomicIdList.contains(atomicResult.getAtomicId())).distinct().toList(); + if (CollUtil.isEmpty(atomicResultList)){ + log.info("IndexResult:经过过滤后的原子指标结果为空"); + return; + } + if (Objects.isNull(atomicIndexList)){ + atomicIndexList = new ArrayList<>(1); + } + // 注意不要有重复值 + Map atomicIndexMap = atomicIndexList.stream().collect(Collectors.toMap(ModelAtomicIndex::getId, k -> k, (k1, k2) -> k1)); + this.atomicResults = atomicResultList.stream().map(atomicResult -> new AtomicResult(indexId, + atomicIndexMap.get(atomicResult.getAtomicId()), atomicResult)).toList(); + + } + +} diff --git a/src/main/java/com/supervision/police/dto/caseScore/LawParty.java b/src/main/java/com/supervision/police/dto/caseScore/LawParty.java new file mode 100644 index 0000000..f37b29e --- /dev/null +++ b/src/main/java/com/supervision/police/dto/caseScore/LawParty.java @@ -0,0 +1,20 @@ +package com.supervision.police.dto.caseScore; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 当事人 + */ +@Data +public class LawParty { + + @Schema(description = "当事人id") + private String userId; + + @Schema(description = "当事人名称") + private String userName; + + @Schema(description = "当事人类型 1:行为人 2:当事人") + private String userType; +} diff --git a/src/main/java/com/supervision/police/service/ModelService.java b/src/main/java/com/supervision/police/service/ModelService.java index 74d7754..6a05cc3 100644 --- a/src/main/java/com/supervision/police/service/ModelService.java +++ b/src/main/java/com/supervision/police/service/ModelService.java @@ -7,4 +7,10 @@ public interface ModelService { R analyseCase(AnalyseCaseDTO analyseCaseDTO); + /** + * 获取案件详情 + * @param caseId 案件id + * @return + */ + String caseScoreDetail(String caseId); } diff --git a/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java index 0ffb492..9f8ab68 100644 --- a/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java +++ b/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java @@ -1,10 +1,10 @@ package com.supervision.police.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.supervision.common.domain.R; import com.supervision.common.utils.StringUtils; import com.supervision.neo4j.dto.ResultDTO; @@ -13,6 +13,7 @@ import com.supervision.police.domain.*; import com.supervision.police.dto.AnalyseCaseDTO; import com.supervision.police.dto.AtomicData; import com.supervision.police.dto.JudgeLogic; +import com.supervision.police.dto.caseScore.CaseScoreDetailBuilder; import com.supervision.police.mapper.*; import com.supervision.police.service.ModelService; import lombok.RequiredArgsConstructor; @@ -100,6 +101,50 @@ public class ModelServiceImpl implements ModelService { return R.ok(); } + @Override + public String caseScoreDetail(String caseId) { + Assert.notEmpty(caseId, "案件id不能为空"); + + CaseScoreDetailBuilder caseScoreDetailBuilder = loadCaseScoreDetail(caseId); + + + return null; + } + + private CaseScoreDetailBuilder loadCaseScoreDetail(String caseId) { + + CaseScoreDetailBuilder caseScoreDetailBuilder = new CaseScoreDetailBuilder(); + + // 1 设置案件基本信息 + ModelCase modelCase = modelCaseMapper.selectById(caseId); + caseScoreDetailBuilder.setCaseId(modelCase.getId()); + caseScoreDetailBuilder.setCaseName(modelCase.getCaseName()); + + // 2 设置当事人人员信息 + List casePersonList = casePersonMapper.selectList(new LambdaQueryWrapper().eq(CasePerson::getCaseId, caseId)); + caseScoreDetailBuilder.setLawActor(casePersonList); + + // 3 设置指标结果信息 + + // 3.1 获取指标信息 + List modelIndices = modelIndexMapper.selectList(new LambdaQueryWrapper().eq(ModelIndex::getCaseType, modelCase.getCaseType())); + + // 3.2 获取指标结果信息 后面需要根据行人人id进行过滤 + List modelIndexResults = modelIndexResultMapper.selectList( + new LambdaQueryWrapper().eq(ModelIndexResult::getCaseId, caseId)); + + // 3.3 获取原子指标信息 + List modelAtomicIndices = modelAtomicIndexMapper.selectList(new LambdaQueryWrapper().eq(ModelAtomicIndex::getCaseType, modelCase.getCaseType())); + + // 3.4 获取原子指标结果 + List modelAtomicResults = modelAtomicResultMapper.selectList( + new LambdaQueryWrapper().eq(ModelAtomicResult::getCaseId, caseId)); + + caseScoreDetailBuilder.setIndexResultList(modelIndices, modelIndexResults, modelAtomicIndices, modelAtomicResults); + + return caseScoreDetailBuilder; + } + /** * 最终计算得分 */