实训评分规则使用逻辑
This commit is contained in:
parent
7669f34480
commit
a94b1ac3b0
@ -14,9 +14,7 @@ import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
|
|||||||
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
|
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
|
||||||
import club.joylink.rtss.simulation.cbtc.member.MemberManager;
|
import club.joylink.rtss.simulation.cbtc.member.MemberManager;
|
||||||
import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
|
import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
|
||||||
import club.joylink.rtss.simulation.cbtc.training2.Operation2;
|
import club.joylink.rtss.simulation.cbtc.training2.*;
|
||||||
import club.joylink.rtss.simulation.cbtc.training2.Step2;
|
|
||||||
import club.joylink.rtss.simulation.cbtc.training2.Training2;
|
|
||||||
import club.joylink.rtss.util.JsonUtils;
|
import club.joylink.rtss.util.JsonUtils;
|
||||||
import club.joylink.rtss.vo.AccountVO;
|
import club.joylink.rtss.vo.AccountVO;
|
||||||
import club.joylink.rtss.vo.LoginUserInfoVO;
|
import club.joylink.rtss.vo.LoginUserInfoVO;
|
||||||
@ -33,12 +31,14 @@ import org.springframework.util.StringUtils;
|
|||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class Training2Service {
|
public class Training2Service {
|
||||||
public static final String JOB_NAME = "Training2";
|
public static final String EXECUTE_JOB_NAME = "Training2";
|
||||||
|
public static final String SCORING_JOB_NAME = "Training2Scoring";
|
||||||
public static final int RATE = 1000;
|
public static final int RATE = 1000;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -134,10 +134,26 @@ public class Training2Service {
|
|||||||
atsOperationDispatcher.execute(simulation, step.getSimulationMember(), simOperation2.getOperationType().name(), simOperation2.getParams());
|
atsOperationDispatcher.execute(simulation, step.getSimulationMember(), simOperation2.getOperationType().name(), simOperation2.getParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadTraining(long id, Simulation simulation) {
|
/**
|
||||||
DraftTraining2WithBLOBs draftTraining2 = new DraftTraining2WithBLOBs();
|
* 评分监视
|
||||||
Training2 training2 = new Training2(draftTraining2, simulation);
|
*/
|
||||||
simulation.addJobIfAbsent(JOB_NAME, () -> this.run(simulation), RATE);
|
public void scoringMonitor(Simulation simulation) {
|
||||||
|
Training2 training2 = simulation.getTraining2();
|
||||||
|
List<ScoringRule2> scoringRules = training2.getScoringRules();
|
||||||
|
if (CollectionUtils.isEmpty(scoringRules))
|
||||||
|
return;
|
||||||
|
for (ScoringRule2 scoringRule : scoringRules) {
|
||||||
|
for (ScoringRule2.Detail durativeDetail : scoringRule.getDurativeDetails()) {
|
||||||
|
if (durativeDetail.getDeduct() != null) //已经被判定的不用再监视
|
||||||
|
continue;
|
||||||
|
Expression condition = durativeDetail.getCondition();
|
||||||
|
if (condition != null) {
|
||||||
|
if (condition.getValue(boolean.class)) {
|
||||||
|
durativeDetail.setDeduct(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -223,10 +239,11 @@ public class Training2Service {
|
|||||||
groupSimulationService.loadScenes(simulation.getId(), training2.getBgSceneJson());
|
groupSimulationService.loadScenes(simulation.getId(), training2.getBgSceneJson());
|
||||||
}
|
}
|
||||||
// 增加任务
|
// 增加任务
|
||||||
if (simulation.getJobMap().containsKey(JOB_NAME)) {
|
if (simulation.getJobMap().containsKey(EXECUTE_JOB_NAME)) {
|
||||||
simulation.removeJob(JOB_NAME);
|
simulation.removeJob(EXECUTE_JOB_NAME);
|
||||||
}
|
}
|
||||||
simulation.addJobIfAbsent(JOB_NAME, () -> this.run(simulation), RATE);
|
simulation.addJobIfAbsent(EXECUTE_JOB_NAME, () -> this.run(simulation), RATE);
|
||||||
|
simulation.addJobIfAbsent(SCORING_JOB_NAME, () -> this.scoringMonitor(simulation), RATE);
|
||||||
training2.start(mode);
|
training2.start(mode);
|
||||||
simulationLifeCycleService.resume(simulation);
|
simulationLifeCycleService.resume(simulation);
|
||||||
}
|
}
|
||||||
@ -246,7 +263,9 @@ public class Training2Service {
|
|||||||
if (training2 == null) {
|
if (training2 == null) {
|
||||||
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "实训数据不存在");
|
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "实训数据不存在");
|
||||||
}
|
}
|
||||||
|
simulation.removeJob(SCORING_JOB_NAME); //移除打分监视任务
|
||||||
training2.finish();
|
training2.finish();
|
||||||
|
training2.mark();
|
||||||
// 暂停仿真
|
// 暂停仿真
|
||||||
simulationLifeCycleService.pause(simulation);
|
simulationLifeCycleService.pause(simulation);
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,17 @@ package club.joylink.rtss.simulation.cbtc.training2;
|
|||||||
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
|
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 评分规则
|
* 评分规则
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
|
||||||
public class ScoringRule2 {
|
public class ScoringRule2 {
|
||||||
/**
|
/**
|
||||||
* 评分规则应用于该成员
|
* 评分规则应用于该成员
|
||||||
@ -27,20 +30,110 @@ public class ScoringRule2 {
|
|||||||
*/
|
*/
|
||||||
private List<Detail> details;
|
private List<Detail> details;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最终得分
|
||||||
|
*/
|
||||||
|
private Float finalScore;
|
||||||
|
|
||||||
|
public ScoringRule2(SimulationMember member, Float fullMarks, List<Detail> details) {
|
||||||
|
this.member = member;
|
||||||
|
this.fullMarks = fullMarks;
|
||||||
|
this.details = details;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Detail> getDurativeDetails() {
|
||||||
|
if (CollectionUtils.isEmpty(details)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
} else {
|
||||||
|
return details.stream()
|
||||||
|
.filter(detail -> Detail.Type.DURATIVE.equals(detail.getType()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float mark(boolean allStepCompletion) {
|
||||||
|
if (finalScore != null)
|
||||||
|
return finalScore;
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(details)) { //没有打分细则,则实训完成给满分,否则0分
|
||||||
|
return allStepCompletion ? fullMarks : 0f;
|
||||||
|
} else {
|
||||||
|
double deductedPoints = details.stream()
|
||||||
|
.peek(detail -> {
|
||||||
|
if (detail.getDeduct() == null) { //未作出判定
|
||||||
|
if (detail.isDurative()) {
|
||||||
|
detail.setDeduct(false);
|
||||||
|
} else {
|
||||||
|
if (detail.getCondition() != null) {
|
||||||
|
detail.setDeduct(detail.getCondition().getValue(boolean.class));
|
||||||
|
} else {
|
||||||
|
detail.setDeduct(!detail.isCompletion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.mapToDouble(detail -> Boolean.TRUE.equals(detail.getDeduct()) ? detail.getScore() : 0)
|
||||||
|
.sum();
|
||||||
|
float finalScore = (float) (fullMarks - deductedPoints);
|
||||||
|
this.finalScore = finalScore < 0 ? 0 : finalScore;
|
||||||
|
return finalScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public static class Detail {
|
public static class Detail {
|
||||||
private Type type;
|
private Type type;
|
||||||
|
|
||||||
|
private ElementType elementType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扣分分值
|
||||||
|
*/
|
||||||
private float score;
|
private float score;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 满足该条件则扣分
|
||||||
|
*/
|
||||||
private Expression condition;
|
private Expression condition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* null 未判定;true 扣分;false 不扣分;
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
private Boolean deduct;
|
||||||
|
|
||||||
|
public Detail(Type type, ElementType elementType, float score, Expression condition) {
|
||||||
|
this.type = type;
|
||||||
|
this.elementType = elementType;
|
||||||
|
this.score = score;
|
||||||
|
this.condition = condition;
|
||||||
|
}
|
||||||
|
|
||||||
public Object getElement() {
|
public Object getElement() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDurative() {
|
||||||
|
return Type.DURATIVE.equals(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompletion() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
/**
|
||||||
|
* 触发式的
|
||||||
|
*/
|
||||||
|
TRIGGERED,
|
||||||
|
/**
|
||||||
|
* 持续性的
|
||||||
|
*/
|
||||||
|
DURATIVE,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ElementType {
|
||||||
/**
|
/**
|
||||||
* 操作
|
* 操作
|
||||||
*/
|
*/
|
||||||
@ -56,11 +149,11 @@ public class ScoringRule2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Operation2Detail extends Detail{
|
public static class Operation2Detail extends Detail {
|
||||||
private Operation2 element;
|
private Operation2 element;
|
||||||
|
|
||||||
public Operation2Detail(Type type, Operation2 element, float score, Expression condition) {
|
public Operation2Detail(Type type, ElementType elementType, Operation2 element, float score, Expression condition) {
|
||||||
super(type, score, condition);
|
super(type, elementType, score, condition);
|
||||||
this.element = element;
|
this.element = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,19 +161,29 @@ public class ScoringRule2 {
|
|||||||
public Object getElement() {
|
public Object getElement() {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCompletion() {
|
||||||
|
return element.isCompletion();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Step2Detail extends Detail{
|
public static class Step2Detail extends Detail {
|
||||||
private Step2 element;
|
private Step2 step;
|
||||||
|
|
||||||
public Step2Detail(Type type, Step2 element, float score, Expression condition) {
|
public Step2Detail(Type type, ElementType elementType, Step2 step, float score, Expression condition) {
|
||||||
super(type, score, condition);
|
super(type, elementType, score, condition);
|
||||||
this.element = element;
|
this.step = step;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getElement() {
|
public Object getElement() {
|
||||||
return element;
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCompletion() {
|
||||||
|
return step.isCompletion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package club.joylink.rtss.simulation.cbtc.training2;
|
|||||||
import club.joylink.rtss.entity.training2.DraftTraining2WithBLOBs;
|
import club.joylink.rtss.entity.training2.DraftTraining2WithBLOBs;
|
||||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||||
|
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
|
||||||
import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
|
import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
|
||||||
import club.joylink.rtss.util.JsonUtils;
|
import club.joylink.rtss.util.JsonUtils;
|
||||||
import club.joylink.rtss.vo.client.training2.ExpressionVO;
|
import club.joylink.rtss.vo.client.training2.ExpressionVO;
|
||||||
@ -11,10 +12,11 @@ import club.joylink.rtss.vo.client.training2.ScoringRuleVO;
|
|||||||
import club.joylink.rtss.vo.client.training2.Step2VO;
|
import club.joylink.rtss.vo.client.training2.Step2VO;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ -151,6 +153,31 @@ public class Training2 {
|
|||||||
return step2;
|
return step2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Step2> getSteps(SimulationMember simulationMember) {
|
||||||
|
if (CollectionUtils.isEmpty(steps)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
} else {
|
||||||
|
return steps.stream()
|
||||||
|
.filter(step2 -> Objects.equals(simulationMember, step2.getSimulationMember()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打分
|
||||||
|
* @return k-memberId v-分数
|
||||||
|
*/
|
||||||
|
public Map<String, Float> mark() {
|
||||||
|
Map<String, Float> map = new HashMap<>();
|
||||||
|
if (!CollectionUtils.isEmpty(scoringRules)) {
|
||||||
|
for (ScoringRule2 scoringRule : scoringRules) {
|
||||||
|
boolean allStepCompletion = getSteps(scoringRule.getMember()).stream().allMatch(Step2::isCompletion);
|
||||||
|
map.put(scoringRule.getMember().getId(), scoringRule.mark(allStepCompletion));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
SINGLE,
|
SINGLE,
|
||||||
SCENE,
|
SCENE,
|
||||||
|
@ -30,4 +30,8 @@ public class ExpressionVO implements ValuableVO {
|
|||||||
}
|
}
|
||||||
return new Expression(operator, vs);
|
return new Expression(operator, vs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Expression convert2BO(ExpressionVO expressionVO, SimulationDataRepository repository) {
|
||||||
|
return expressionVO == null ? null : expressionVO.convert2BO(repository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,8 @@ public class ScoringRuleVO {
|
|||||||
public static class DetailVO {
|
public static class DetailVO {
|
||||||
private ScoringRule2.Detail.Type type;
|
private ScoringRule2.Detail.Type type;
|
||||||
|
|
||||||
|
private ScoringRule2.Detail.ElementType elementType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 被评分的元素的id(操作、步骤、实训)
|
* 被评分的元素的id(操作、步骤、实训)
|
||||||
*/
|
*/
|
||||||
@ -73,17 +75,17 @@ public class ScoringRuleVO {
|
|||||||
private ExpressionVO condition;
|
private ExpressionVO condition;
|
||||||
|
|
||||||
public ScoringRule2.Detail convert2BO(Training2 training2, SimulationDataRepository repository) {
|
public ScoringRule2.Detail convert2BO(Training2 training2, SimulationDataRepository repository) {
|
||||||
switch (type) {
|
switch (elementType) {
|
||||||
case O:
|
case O:
|
||||||
Operation2 operation2 = training2.getOperation(Integer.parseInt(elementId));
|
Operation2 operation2 = training2.getOperation(Integer.parseInt(elementId));
|
||||||
return new ScoringRule2.Operation2Detail(type, operation2, score, condition.convert2BO(repository));
|
return new ScoringRule2.Operation2Detail(type, elementType, operation2, score, ExpressionVO.convert2BO(condition, repository));
|
||||||
case S:
|
case S:
|
||||||
Step2 step2 = training2.getStep(Integer.parseInt(elementId));
|
Step2 step2 = training2.getStep(Integer.parseInt(elementId));
|
||||||
return new ScoringRule2.Step2Detail(type, step2, score, condition.convert2BO(repository));
|
return new ScoringRule2.Step2Detail(type, elementType, step2, score, ExpressionVO.convert2BO(condition, repository));
|
||||||
case T:
|
case T:
|
||||||
return new ScoringRule2.Detail(type, score, condition.convert2BO(repository));
|
return new ScoringRule2.Detail(type, elementType, score, ExpressionVO.convert2BO(condition, repository));
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Unexpected value: " + type);
|
throw new IllegalStateException("Unexpected value: " + elementType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user