浏览代码

知识点本身、分段、分组分析

ywx
王宁 3 周前
父节点
当前提交
ce85767c3e

+ 7
- 0
smarking/src/main/java/com/xhkjedu/smarking/mapper/report/reportsubject/MsrSubjectPointMapper.java 查看文件

@@ -2,6 +2,10 @@ package com.xhkjedu.smarking.mapper.report.reportsubject;
2 2
 
3 3
 import com.xhkjedu.base.TkMapper;
4 4
 import com.xhkjedu.smarking.model.report.reportsubject.MsrSubjectPoint;
5
+import com.xhkjedu.smarking.vo.report.reportsubject.PointVo;
6
+import org.apache.ibatis.annotations.Param;
7
+
8
+import java.util.List;
5 9
 
6 10
 /**
7 11
  * @Description 阅卷报告-学科知识点表 Mapper 接口
@@ -9,4 +13,7 @@ import com.xhkjedu.smarking.model.report.reportsubject.MsrSubjectPoint;
9 13
  * @Date 2024-12-09
10 14
  */
11 15
 public interface MsrSubjectPointMapper extends TkMapper<MsrSubjectPoint> {
16
+
17
+    //科目知识点
18
+    List<PointVo> listSubjectPoints(@Param("subjectid") String subjectid, @Param("examid") Integer examid);
12 19
 }

+ 201
- 9
smarking/src/main/java/com/xhkjedu/smarking/service/report/generate/ReportGeneratePointService.java 查看文件

@@ -2,6 +2,7 @@ package com.xhkjedu.smarking.service.report.generate;
2 2
 
3 3
 import com.alibaba.fastjson.JSON;
4 4
 import com.xhkjedu.smarking.mapper.paper.MsPaperAnalyzeMapper;
5
+import com.xhkjedu.smarking.mapper.report.reportsubject.MsrSubjectPointMapper;
5 6
 import com.xhkjedu.smarking.model.exam.MsClassStudent;
6 7
 import com.xhkjedu.smarking.model.paper.MsPaperAnalyze;
7 8
 import com.xhkjedu.smarking.model.paper.MsPaperQtypeQuestion;
@@ -16,14 +17,14 @@ import com.xhkjedu.smarking.vo.paper.QuestionPointVo;
16 17
 import com.xhkjedu.smarking.vo.report.reportother.RankGroupVo;
17 18
 import com.xhkjedu.smarking.vo.report.reportstu.PointQuestionVo;
18 19
 import com.xhkjedu.smarking.vo.report.reportstu.PointStudentVo;
20
+import com.xhkjedu.smarking.vo.report.reportsubject.PointLevelVo;
21
+import com.xhkjedu.smarking.vo.report.reportsubject.PointVo;
19 22
 import com.xhkjedu.utils.N_Utils;
20 23
 import org.springframework.stereotype.Service;
21 24
 
22 25
 import javax.annotation.Resource;
23
-import java.util.ArrayList;
24
-import java.util.Arrays;
25
-import java.util.List;
26
-import java.util.Map;
26
+import java.util.*;
27
+import java.util.function.Function;
27 28
 import java.util.stream.Collectors;
28 29
 
29 30
 /**
@@ -35,6 +36,8 @@ import java.util.stream.Collectors;
35 36
 public class ReportGeneratePointService {
36 37
     @Resource
37 38
     private MsPaperAnalyzeMapper msPaperAnalyzeMapper;
39
+    @Resource
40
+    private MsrSubjectPointMapper msrSubjectPointMapper;
38 41
 
39 42
     //知识点分析,题库知识点按母题分析
40 43
     public void generatePoint(List<MsPaperStudentQuestion> stuSubjectQuestions, List<MsPaperQtypeQuestion> qtypeQuestions,List<MsClassStudent> classStus,
@@ -153,7 +156,9 @@ public class ReportGeneratePointService {
153 156
             List<MsrSubjectPointSection> pointSecs = pointSection(pointStuScores, pointSections, pqvo, 3);
154 157
             savePointSections.addAll(pointSecs);
155 158
 
156
-            //知识点机构考生分组分析
159
+            //知识点考生分组分析
160
+            List<MsrSubjectPointRankgroup> pointRankg = pointRankGroup(pointStuScores,sturanks, pqvo, examid, subjectid, 3);
161
+            savePointRankgroups.addAll(pointRankg);
157 162
 
158 163
             double schoolSumScore = pointStuScores.stream().mapToDouble(PointStudentVo::getStuscore).sum();
159 164
             int stunum = pointStuScores.size();
@@ -178,7 +183,6 @@ public class ReportGeneratePointService {
178 183
                 saveStuPoints.add(stuPoint);
179 184
             }
180 185
         }
181
-
182 186
     }
183 187
 
184 188
     // 知识点:设置每个学生每个试题知识点得分
@@ -289,7 +293,7 @@ public class ReportGeneratePointService {
289 293
     }
290 294
 
291 295
     //知识点-考试排名分组分析
292
-    private List<MsrSubjectPointRankgroup> questionScoreRankGroup(List<PointStudentVo> pointStuScores, List<MsrStudent> stuPapers, PointQuestionVo pqvo,Integer examid,String subjectid, Integer pointlevel){
296
+    private List<MsrSubjectPointRankgroup> pointRankGroup(List<PointStudentVo> pointStuScores, List<MsrStudent> stuPapers, PointQuestionVo pqvo,Integer examid,String subjectid, Integer pointlevel){
293 297
         //获取学生排名最大名次的树
294 298
         Integer totalRank = stuPapers.stream().mapToInt(MsrStudent::getSchoolrank).max().orElse(0);
295 299
         //获取排名分组,默认分为7组
@@ -343,8 +347,6 @@ public class ReportGeneratePointService {
343 347
                     }else{
344 348
                         sectionStuQuestions = groupStuPoints.stream().filter(q -> q.getStuscore() >= sectionScore.getMinvalue() && q.getStuscore() < sectionScore.getMaxvalue()).collect(Collectors.toList());
345 349
                     }
346
-                    // double sectionStuSumScore = sectionStuQuestions.stream().mapToDouble(PointStudentVo::getStuscore).sum();
347
-                    // double sectionStuAvgScore = MarkingUtil.div(sectionStuSumScore, sectionStuQuestions.size());
348 350
                     sqrg.setStunum(sectionStuQuestions.size());
349 351
                     sqrg.setStuids(sectionStuQuestions.stream().map(q -> q.getStudentid().toString()).collect(Collectors.joining(",")));
350 352
                 }else{
@@ -358,4 +360,194 @@ public class ReportGeneratePointService {
358 360
         }
359 361
         return rtnList;
360 362
     }
363
+
364
+    //获取处理知识点对应的顶层、上层知识点
365
+    private Map<String,Map<String,List<PointLevelVo>>> listSubjectPoints(String subjectid,Integer examid,List<PointQuestionVo> pointques){
366
+        //获取所有知识点
367
+        List<PointVo> points = msrSubjectPointMapper.listSubjectPoints(subjectid,examid);
368
+        Map<String,PointVo> pointMap = points.stream().collect(Collectors.toMap(PointVo::getPointid, Function.identity()));
369
+
370
+        List<PointLevelVo> upPoints = new ArrayList<>();//知识点的上层(二级)知识点
371
+        List<PointLevelVo> topPoints = new ArrayList<>();//知识点的顶层层(一级)知识点
372
+        for(PointQuestionVo point : pointques){
373
+            PointLevelVo upPoint = new PointLevelVo();
374
+            upPoint.setPointid(point.getPointid());
375
+            upPoint.setPointname(point.getPointname());
376
+
377
+            PointLevelVo topPoint = new PointLevelVo();
378
+            topPoint.setPointid(point.getPointid());
379
+            topPoint.setPointname(point.getPointname());
380
+
381
+            //获取知识点的详细信息
382
+            if(pointMap.containsKey(point.getPointid())){
383
+                PointVo pointVo = pointMap.get(point.getPointid());
384
+                PointVo parentNode =pointVo.getParent(points);//上层知识点
385
+                upPoint.setTopPointid(parentNode.getPointid());
386
+                upPoint.setTopPointname(parentNode.getPointname());
387
+
388
+                //找到顶层知识点
389
+                PointVo rootNode = getRootNode(parentNode, points);
390
+                if(rootNode!= null){
391
+                    topPoint.setTopPointid(rootNode.getPointid());
392
+                    topPoint.setTopPointname(rootNode.getPointname());
393
+                }else{
394
+                    topPoint.setTopPointid(point.getPointid());
395
+                    topPoint.setTopPointname(point.getPointname());
396
+                }
397
+            }else{
398
+                upPoint.setTopPointid(point.getPointid());
399
+                upPoint.setTopPointname(point.getPointname());
400
+
401
+                topPoint.setTopPointid(point.getPointid());
402
+                topPoint.setTopPointname(point.getPointname());
403
+            }
404
+
405
+            upPoints.add(upPoint);
406
+            topPoints.add(topPoint);
407
+        }
408
+
409
+        Map<String,List<PointLevelVo>> upMap = upPoints.stream().collect(Collectors.groupingBy(PointLevelVo::getTopPointid));
410
+        Map<String,List<PointLevelVo>> topMap = topPoints.stream().collect(Collectors.groupingBy(PointLevelVo::getTopPointid));
411
+        Map<String,Map<String,List<PointLevelVo>>> rtnMap = new HashMap<>();
412
+        rtnMap.put("up",upMap);
413
+        rtnMap.put("top",topMap);
414
+        return rtnMap;
415
+    }
416
+    //获取顶层节点
417
+    private PointVo getRootNode(PointVo targetNode, List<PointVo> allNodes) {
418
+        PointVo current = targetNode;
419
+        while (N_Utils.isNotEmpty(current.getPointpid())) {
420
+            current = current.getParent(allNodes);
421
+        }
422
+        return current;
423
+    }
424
+
425
+    //处理顶级、上级知识点
426
+    private void handlePointLevel(Map<String,List<PointLevelVo>> pointMap,List<PointQuestionVo> pointques,List<PointStudentVo> schoolStuPoints,Integer pointlevel,List<MsrSubjectPointSection> pointSections,
427
+                                    List<MsPaperQtypeQuestion> qtypeQuestions,List<MsClassStudent> classStus,Integer examid,String subjectid,List<MsrStudent> sturanks,
428
+                                    List<MsrSubjectPoint> saveSubjectPoints,List<MsrSubjectPointSection> savePointSections,List<MsrSubjectPointRankgroup> savePointRankgroups){
429
+
430
+        //科目班级知识点情况
431
+        Map<String, List<MsrSubjectPoint>> subjectPointMap = saveSubjectPoints.stream().filter(p -> p.getPointlevel()==3).collect(Collectors.groupingBy(MsrSubjectPoint::getPointid));
432
+        //知识点学科总分区间
433
+        Map<String, List<MsrSubjectPointSection>> pointSectionMap = savePointSections.stream().filter(p -> p.getPointlevel()==3).collect(Collectors.groupingBy(MsrSubjectPointSection::getPointid));
434
+        //知识点分组
435
+        Map<String, List<MsrSubjectPointRankgroup>> pointRankgroupMap = savePointRankgroups.stream().filter(p -> p.getPointlevel()==3).collect(Collectors.groupingBy(MsrSubjectPointRankgroup::getPointid));
436
+
437
+        //处理上层知识点
438
+        for(Map.Entry<String,List<PointLevelVo>> entry : pointMap.entrySet()){
439
+            List<PointLevelVo> pointLevels = entry.getValue();
440
+            PointLevelVo firstPoint = pointLevels.get(0);
441
+            if(pointLevels.size() ==1){
442
+                //说明知识的上层知识点是知识点本身或者仅有一个知识点,则上层知识点分析和他本身的分析一致
443
+                //科目知识点
444
+                List<MsrSubjectPoint> subpoints = subjectPointMap.get(firstPoint.getPointid());
445
+                for(MsrSubjectPoint subpoint : subpoints){
446
+                    subpoint.setPointid(firstPoint.getTopPointid());
447
+                    subpoint.setPointname(firstPoint.getPointname());
448
+                    subpoint.setPointlevel(pointlevel);
449
+                    saveSubjectPoints.add(subpoint);
450
+                }
451
+
452
+                //分数分段
453
+                List<MsrSubjectPointSection> sepoints = pointSectionMap.get(firstPoint.getPointid());
454
+                for(MsrSubjectPointSection sepoint : sepoints) {
455
+                    sepoint.setPointid(firstPoint.getTopPointid());
456
+                    sepoint.setPointname(firstPoint.getPointname());
457
+                    sepoint.setPointlevel(pointlevel);
458
+                    savePointSections.add(sepoint);
459
+                }
460
+
461
+                //分组分析
462
+                List<MsrSubjectPointRankgroup> rgpoints = pointRankgroupMap.get(firstPoint.getPointid());
463
+                for(MsrSubjectPointRankgroup rgpoint : rgpoints) {
464
+                    rgpoint.setPointid(firstPoint.getTopPointid());
465
+                    rgpoint.setPointname(firstPoint.getPointname());
466
+                    rgpoint.setPointlevel(pointlevel);
467
+                    savePointRankgroups.add(rgpoint);
468
+                }
469
+            }else{
470
+                //上层知识点所包含的知识点id集合
471
+                List<String> pointids = pointLevels.stream().map(PointLevelVo::getPointid).collect(Collectors.toList());
472
+                //知识点下试题,以及学生得分
473
+                List<PointQuestionVo> levelPointQues = pointques.stream().filter(q -> pointids.contains(q.getPointid())).collect(Collectors.toList());
474
+                List<PointStudentVo> levelStuPoints = schoolStuPoints.stream().filter(q -> pointids.contains(q.getPointid())).collect(Collectors.toList());
475
+                List<QuestionPointVo> ques = new ArrayList<>();//知识点下所有试题
476
+                for(PointQuestionVo point : levelPointQues) {
477
+                    ques.addAll(point.getQues());
478
+                }
479
+
480
+                List<Integer> mptqids = ques.stream().map(QuestionPointVo::getMptqid).distinct().collect(Collectors.toList());
481
+                //获取试题对应的qn
482
+                List<MsPaperQtypeQuestion> qtypeQues =  qtypeQuestions.stream().filter(q -> mptqids.contains(q.getMptqid())).collect(Collectors.toList());
483
+                String qnStr = qtypeQues.stream().map(q -> q.getMptqn()  + "." + q.getQn()).collect(Collectors.joining(","));
484
+                String mptqidStr = mptqids.stream().map(Object::toString).collect(Collectors.joining(","));
485
+                double pointscore = levelPointQues.stream().mapToDouble(PointQuestionVo::getScore).sum();
486
+                pointscore = N_Utils.formatDouble(pointscore, 1);
487
+                //知识点多个试题,处理成单个学生试题总分值
488
+                List<PointStudentVo> pointStuScores = new ArrayList<>();//处理成学生知识点形式,后续计算使用
489
+                Map<Integer, List<PointStudentVo>> pointStuMap = levelStuPoints.stream().collect(Collectors.groupingBy(PointStudentVo::getStudentid));
490
+                for (Map.Entry<Integer, List<PointStudentVo>> psentry : pointStuMap.entrySet()){
491
+                    List<PointStudentVo> pstuScores = psentry.getValue();
492
+                    double stuScore = pstuScores.stream().mapToDouble(PointStudentVo::getStuscore).sum();
493
+                    stuScore = N_Utils.formatDouble(stuScore, 1);
494
+                    PointStudentVo pstuvo = new PointStudentVo();
495
+                    pstuvo.setStudentid(psentry.getKey());
496
+                    pstuvo.setPointid(entry.getKey());
497
+                    pstuvo.setStuscore(stuScore);
498
+                    pstuvo.setScore(pointscore);
499
+                    pointStuScores.add(pstuvo);
500
+                }
501
+
502
+                MsrSubjectPoint subjectPoint = new MsrSubjectPoint();
503
+                subjectPoint.setExamid(examid);
504
+                subjectPoint.setSubjectid(subjectid);
505
+                subjectPoint.setPointid(firstPoint.getTopPointid());
506
+                subjectPoint.setClassid(0);
507
+                subjectPoint.setPointname(firstPoint.getTopPointid());
508
+                subjectPoint.setFullscore(pointscore);
509
+                subjectPoint.setPointlevel(pointlevel);
510
+                subjectPoint.setMptqids(mptqidStr);
511
+                subjectPoint.setQns(qnStr);
512
+
513
+                //校知识点分析
514
+                MsrSubjectPoint schoolPoint = pointLevelClass(pointStuScores, subjectPoint);
515
+                saveSubjectPoints.add(schoolPoint);
516
+
517
+                //班级知识点分析
518
+                List<Integer> classIds = classStus.stream().map(MsClassStudent::getClassid).distinct().collect(Collectors.toList());
519
+                List<MsrSubjectPoint> classPoints = new ArrayList<>();
520
+                for (Integer classid : classIds) {
521
+                    // 获取班级下学生id
522
+                    List<Integer> classStuIds = classStus.stream().filter(c -> c.getClassid().equals(classid)).map(MsClassStudent::getStudentid).collect(Collectors.toList());
523
+                    // 获取班级下学生试题
524
+                    List<PointStudentVo> classStuPoints = pointStuScores.stream().filter(q -> classStuIds.contains(q.getStudentid())).collect(Collectors.toList());
525
+                    subjectPoint.setClassid(classid);
526
+                    MsrSubjectPoint classPoint = pointLevelClass(classStuPoints, subjectPoint);
527
+                    classPoints.add(classPoint);
528
+                }
529
+
530
+                // 班级知识点保存后,要对平均分排序
531
+                List<Double> avgScores = classPoints.stream().map(MsrSubjectPoint::getAvgscore).collect(Collectors.toList());
532
+                Map<Double,Integer> avgScoreRankMap = MarkingUtil.fspm(avgScores);
533
+                for(MsrSubjectPoint sp : classPoints){
534
+                    sp.setAvgrank(avgScoreRankMap.get(sp.getAvgscore()));
535
+                }
536
+                saveSubjectPoints.addAll(classPoints);
537
+
538
+                PointQuestionVo pqvo = new PointQuestionVo();
539
+                pqvo.setPointid(firstPoint.getTopPointid());
540
+                pqvo.setPointname(firstPoint.getPointname());
541
+                pqvo.setScore(pointscore);
542
+
543
+                //知识点结构与总分的相关性(三级知识点)
544
+                List<MsrSubjectPointSection> pointSecs = pointSection(pointStuScores, pointSections, pqvo, pointlevel);
545
+                savePointSections.addAll(pointSecs);
546
+
547
+                //知识点考生分组分析
548
+                List<MsrSubjectPointRankgroup> pointRankg = pointRankGroup(pointStuScores,sturanks, pqvo, examid, subjectid, pointlevel);
549
+                savePointRankgroups.addAll(pointRankg);
550
+            }
551
+        }
552
+    }
361 553
 }

+ 1
- 0
smarking/src/main/java/com/xhkjedu/smarking/vo/report/reportstu/PointQuestionVo.java 查看文件

@@ -22,4 +22,5 @@ public class PointQuestionVo {
22 22
     private Double srate;//知识点试卷占比
23 23
 
24 24
     private List<QuestionPointVo> ques;//知识点包含试题
25
+
25 26
 }

+ 20
- 0
smarking/src/main/java/com/xhkjedu/smarking/vo/report/reportsubject/PointLevelVo.java 查看文件

@@ -0,0 +1,20 @@
1
+package com.xhkjedu.smarking.vo.report.reportsubject;
2
+
3
+import lombok.Data;
4
+
5
+/**
6
+ * @Description:层级知识点
7
+ * @Author: WN
8
+ * @Date: 2024/12/18 15:13:26
9
+ **/
10
+@Data
11
+public class PointLevelVo {
12
+
13
+    private String pointid;//知识点ID
14
+
15
+    private String pointname;//知识点名称
16
+
17
+    private String topPointid;//上层或顶层知识点id
18
+
19
+    private String topPointname;//上层或顶层知识点名称
20
+}

+ 46
- 0
smarking/src/main/java/com/xhkjedu/smarking/vo/report/reportsubject/PointVo.java 查看文件

@@ -0,0 +1,46 @@
1
+package com.xhkjedu.smarking.vo.report.reportsubject;
2
+
3
+import lombok.Data;
4
+
5
+import java.util.ArrayList;
6
+import java.util.List;
7
+
8
+@Data
9
+public class PointVo {
10
+    //知识点表
11
+    private String pointid;
12
+
13
+    //知识点名称
14
+    private String pointname;
15
+
16
+    //知识点排序
17
+    private Integer pointorder;
18
+
19
+    //所属知识点id
20
+    private String pointpid;
21
+
22
+    private List<PointVo> children = new ArrayList<>();
23
+
24
+
25
+    public PointVo() {}
26
+
27
+    public PointVo(String pointid, String pointpid) {
28
+        this.pointid = pointid;
29
+        this.pointpid = pointpid;
30
+        this.children = new ArrayList<>();
31
+    }
32
+
33
+    public void addChild(PointVo child) {
34
+        children.add(child);
35
+    }
36
+
37
+    // 获取父节点的方法
38
+    public PointVo getParent(List<PointVo> allNodes) {
39
+        for (PointVo node : allNodes) {
40
+            if (node.getPointid().equals(this.pointpid)) {
41
+                return node;
42
+            }
43
+        }
44
+        return null;
45
+    }
46
+}

+ 2
- 2
smarking/src/main/resources/mapper/paper/MsPaperBlockMapper.xml 查看文件

@@ -15,7 +15,7 @@
15 15
             <result property="mbqtype" column="mbqtype"/>
16 16
             <result property="mptqid" column="mptqid"/>
17 17
             <result property="bqn" column="bqn"/>
18
-            <result property="bqscore" column="bqscore"/>
18
+            <result property="bqscore" column="qscore"/>
19 19
             <result property="bqorder" column="bqorder"/>
20 20
             <result property="mergeqid" column="mergeqid"/>
21 21
             <result property="mergeqn" column="mergeqn"/>
@@ -28,7 +28,7 @@
28 28
     <!--获取题块及题块下试题-->
29 29
     <select id="listPaperBlockQuestions" resultMap="paperBlockResultMap">
30 30
         select b.mblockid,b.mpid,b.blockname,b.blocktype,b.blockorder,b.bqnum,b.bqscore,
31
-        q.mbqid,q.mbqtype,q.mptqid,q.bqn,q.bqscore,q.bqorder,q.mergeqid,q.mergeqn,q.mergescore,q.scorestepway,q.scorestep
31
+        q.mbqid,q.mbqtype,q.mptqid,q.bqn,q.bqscore as qscore,q.bqorder,q.mergeqid,q.mergeqn,q.mergescore,q.scorestepway,q.scorestep
32 32
         from ms_paper_block b
33 33
         left join ms_paper_block_question q on b.mblockid=q.mblockid
34 34
         left join ms_paper p on b.mpid=p.mpid

+ 8
- 0
smarking/src/main/resources/mapper/report/reportsubject/MsrSubjectPointMapper.xml 查看文件

@@ -1,4 +1,12 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2 2
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3 3
 <mapper namespace="com.xhkjedu.smarking.mapper.report.reportsubject.MsrSubjectPointMapper">
4
+
5
+    <!--获取科目对应知识点-->
6
+    <select id="listSubjectPoints" resultType="com.xhkjedu.smarking.vo.report.reportsubject.PointVo">
7
+        select p.pointid,p.pointname,p.pointorder,p.pointpid
8
+        from t_point p where p.subjectid=#{subjectid} and (p.belong=1 or (p.belong=3
9
+        and p.schoolid=(select schoolid from ms_exam where examid=#{examid} limit 1))) order by p.pointlevel,p.pointorder
10
+    </select>
11
+
4 12
 </mapper>

正在加载...
取消
保存