package com.huixinpn.dionysus.domain.psychtest.eval;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.huixinpn.dionysus.domain.psychtest.PsychTestQuestion;
import com.huixinpn.dionysus.domain.psychtest.PsychTestQuestionOption;
import com.huixinpn.dionysus.domain.psychtest.PsychTestResult;
public class PF16EvaluationStrategy implements PsychTestEvaluationStrategy {
// 卡特尔16PF测验计分健
private static final String[] RAW_ANSWERS = new String[] {
"A 3ab,26bc,27bc,51bc,52ab,76bc,101ab,126ab,151bc,176ab",
"B 28b,53b,54b,77c,78b,102c,103b,127c,128b,152b,153c,177a,178a",
"C 4ab,5bc,29bc,30ab,55ab,79bc,80bc,104ab,105ab,129ab,130ab,154bc,179ab",
"E 6bc,7ab,31bc,32bc,56ab,57bc,81bc,106bc,131ab,155ab,156ab,180ab,181ab",
"F 8bc,33ab,58ab,82bc,83bc,107bc,108bc,132ab,133ab,157bc,158bc,182ab,183ab",
"G 9bc,34bc,59ab,84bc,109ab,134ab,159bc,160ab,184ab,185ab",
"H 10ab,35bc,36ab,60bc,61bc,85bc,86bc,110ab,111ab,135bc,136ab,161bc,186ab",
"I 11bc,12bc,37ab,62bc,87bc,112ab,137bc,138ab,162bc,163ab",
"L 13ab,38ab,63bc,64bc,88ab,89bc,113ab,114ab,139bc,164ab",
"M 14bc,15bc,39ab,40ab,65ab,90bc,91ab,115ab,116bc,140ab,141bc,165bc,166bc",
"N 16bc,17ab,41bc,42ab,66bc,67bc,92bc,117ab,142ab,167ab",
"O 18ab,19bc,43ab,44bc,68bc,69ab,93bc,94bc,118ab,119ab,143ab,144bc,168ab",
"Q1 20ab,21ab,45bc,46ab,70ab,95bc,120bc,145ab,169ab,170bc",
"Q2 22bc,47ab,71ab,72ab,96bc,97bc,121bc,122bc,146ab,171ab",
"Q3 23bc,23bc,48ab,73ab,98ab,123bc,147ab,148ab,172bc,173ab",
"Q4 25ab,49ab,50ab,74ab,75bc,99ab,100bc,124ab,125bc,149ab,150ab,174ab,175bc"
};
private Map<Integer, Answer> answers = new HashMap<Integer, Answer>();
public PF16EvaluationStrategy() {
Pattern pattern = Pattern.compile("(\\d+)([abc]+)");
for (String line : RAW_ANSWERS) {
String[] row = line.split("\\s+");
String factor = row[0];
String rawAnswer = row[1];
Matcher matcher = pattern.matcher(rawAnswer);
while(matcher.find()) {
Integer num = Integer.parseInt(matcher.group(1));
String values = matcher.group(2);
answers.put(num, new Answer(factor, values));
}
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
static class Answer {
private String factor;
private String values;
// 不是所有的题目均有计分
public static Answer nullObject = new Answer() {
@Override
public int calculateScore(String rawAnswer) {
return 0;
};
};
public int calculateScore(String rawAnswer) {
// 所有答案均为小写
String answer = rawAnswer.toLowerCase();
// 聪慧性(因素B)量表的题目有正确答案,每题答对1分,不对0分
if ("B".equals(this.factor)) {
return values.equals(answer) ? 1 : 0;
}
// 包含计分项目
if (values.contains(answer)) {
// 除B因素只计1分外,其他因素均为a、c计2分、b计1分
return "b".equals(answer) ? 1 : 2;
}
return 0;
}
}
public Answer requestAnswer(int index) {
Answer answer = answers.get(index);
return answer == null ? Answer.nullObject : answer;
}
class PF16Visitor extends PsychTestValueVisitorAdaptor {
private Map<String, Integer> scores = new HashMap<String, Integer>();
private PF16EvaluationStrategy strategy;
public PF16Visitor(PF16EvaluationStrategy strategy) {
this.strategy = strategy;
}
@Override
public void accept(PsychTestQuestion question, PsychTestQuestionOption option) {
Integer subid = question.getSubId();
Answer answer = strategy.requestAnswer(subid);
String factor = answer.getFactor();
if (factor != null) {
String identity = option.getIdentity();
int score = answer.calculateScore(identity);
if (scores.containsKey(factor)) {
scores.put(factor, scores.get(factor) + score);
} else {
scores.put(factor, score);
}
}
}
public Map<String, Integer> getScore() {
return this.scores;
}
public Map<String, Integer> getNormalizedScore(/*String[] mode*/) {
Map<String, Integer> scores = this.getScore();
// TODO: 判断用户身份,选择对应的常模
return PF16Normalization.normalize(scores, PF16Normalization.ADULT_MALE);
}
}
@Override
public Object evaluate(PsychTestResult result) {
PF16Visitor visitor = new PF16Visitor(this);
result.accept(visitor);
Map<String, Integer> score = visitor.getScore();
//计算常值,append到返回的MAP中
Map<String, Integer> normalized_score = visitor.getNormalizedScore();
for(String key : normalized_score.keySet()){
score.put("normal_"+key, normalized_score.get(key));
}
return score;
}
}