【修改】C语言本地判分逻辑,测试用例,关键字比对,代码段读取,结果摘要
This commit is contained in:
@@ -10,7 +10,10 @@ import org.springframework.stereotype.Service;
|
||||
import com.example.exam.exam.dal.SourceAndText;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 判分逻辑集合
|
||||
@@ -66,17 +69,12 @@ public class JudgementServiceImpl implements JudgementService
|
||||
double pass_score = score * is_pass_score;
|
||||
|
||||
// 创建log文件txt,用于记录
|
||||
// LogFileUtils.createFile(pathC + "/log.txt");
|
||||
System.out.println(pathC + " --- " + fileName);
|
||||
String code = JudgementCUtils.readFile(pathC, fileName);
|
||||
// LogFileUtils.writeLine("✅ 系统开始读取学生考试文件:" + code);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 系统开始读取学生考试文件:" + code);
|
||||
if (code == "") {
|
||||
// 如果没有读到源码
|
||||
// LogFileUtils.writeLine("❌ 系统没有读取到学生考试文件。");
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "❌ 系统没有读取到学生考试文件。");
|
||||
|
||||
// LogFileUtils.close();
|
||||
// 该题不得分,直接算成0分
|
||||
sourceAndText.setScore(0);
|
||||
sourceAndText.setText(judgementStr);
|
||||
@@ -88,17 +86,27 @@ public class JudgementServiceImpl implements JudgementService
|
||||
// 总权重值
|
||||
int weight = 0;
|
||||
List<Map<String, Object>> key_list = new ArrayList<>();
|
||||
// 进行关键字权重比对进行判断
|
||||
|
||||
// 只获取 /\\*+Program\\*+/(.*?)/\\*+ End \\*+/ 下的代码进行判断
|
||||
String pattern = "/\\*+Program\\*+/(.*?)/\\*+ End \\*+/";
|
||||
Pattern r = Pattern.compile(pattern, Pattern.DOTALL);
|
||||
Matcher m = r.matcher(code);
|
||||
String result;
|
||||
if (m.find()) {
|
||||
result = m.group(1).trim(); // 提取代码段
|
||||
} else {
|
||||
result = code; // 如果没有匹配到标识符,返回全部代码
|
||||
}
|
||||
|
||||
// 进行关键字权重比对进行判断
|
||||
for (ExamQuestionKeyword examQuestionKeyword : examQuestion.getQuestionKeywords()) {
|
||||
String codeSpacking = code.replace(" ","");
|
||||
String codeSpacking = result.replace(" ","");
|
||||
boolean keyword_run = codeSpacking.contains(examQuestionKeyword.getKeyword());
|
||||
// 计算权值
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("success", keyword_run);
|
||||
item.put("score_rate", examQuestionKeyword.getScoreRate());
|
||||
// LogFileUtils.writeLine("✅ 关键字比对:" + examQuestionKeyword.getKeyword() + "--" + (keyword_run ? "正确" : "错误"));
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 关键字比对:" + examQuestionKeyword.getKeyword() + " -- " + (keyword_run ? "正确" : "错误"));
|
||||
item.put("text", examQuestionKeyword.getKeyword());
|
||||
weight += Integer.parseInt(examQuestionKeyword.getScoreRate());
|
||||
key_list.add(item);
|
||||
}
|
||||
@@ -112,8 +120,10 @@ public class JudgementServiceImpl implements JudgementService
|
||||
// 每个选项分值 = 总分 / 总权重
|
||||
true_number += 1;
|
||||
key_score += one_keyword_score * Integer.parseInt((String) item.get("score_rate"));
|
||||
// LogFileUtils.writeLine("✅ 关键字得分:" + key_score);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 关键字得分:" + key_score);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 关键字比对:" + item.get("text") + " -- 正确 -- 得分:" + one_keyword_score * Integer.parseInt((String) item.get("score_rate")));
|
||||
} else {
|
||||
// 关键字不正确
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "❌ 关键字比对:" + item.get("text") + " -- 错误 -- 得分:0");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -126,34 +136,110 @@ public class JudgementServiceImpl implements JudgementService
|
||||
// 测试用例(比编译通过提前)
|
||||
// 判断是否要程序结果 ,需要程序结果的,就需要测试用例
|
||||
if (is_compile) {
|
||||
// 测试用例数组,记录测试用的正确错误情况
|
||||
List<Map<String, Object>> compileList = new ArrayList<>();
|
||||
// 先运行程序,再将测试用例进行比对
|
||||
// 运行完成后在判断是否需要进行关键字比对
|
||||
boolean run_code = false;
|
||||
List<Boolean> runList = new ArrayList<>();
|
||||
// LogFileUtils.writeLine("✅ 使用c99标准进行测试用例编译...");
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 使用c99标准进行测试用例编译...");
|
||||
boolean isPassIndex = false;
|
||||
for (ExamQuestionAnswer examQuestionAnswer : examQuestion.getAnswerList()) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
|
||||
// 使用C99 运行并得出结果
|
||||
String code_return = JudgementCUtils.run_code(pathC,code, examQuestionAnswer.getContentIn(),"-std=c99",null);
|
||||
if (!isPassIndex && !code_return.contains("error")) {
|
||||
// 编译没有报错,加上编译分数
|
||||
totalScore += pass_score;
|
||||
// LogFileUtils.writeLine("✅ 编译通过得分:" + pass_score);
|
||||
isPassIndex = true;
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 编译通过得分:" + pass_score);
|
||||
|
||||
} else if (!isPassIndex) {
|
||||
// LogFileUtils.writeLine("❌ 编译未通过。");
|
||||
isPassIndex = true;
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "❌ 编译未通过。");
|
||||
}
|
||||
|
||||
String actual = extractUnwrappedText(code_return).trim();
|
||||
String expected = examQuestionAnswer.getContent().trim();
|
||||
// 分值权重
|
||||
item.put("scoreRate", examQuestionAnswer.getScoreRate());
|
||||
item.put("inText", examQuestionAnswer.getContentIn());
|
||||
item.put("resultText", actual);
|
||||
item.put("resultTrueText", expected);
|
||||
if (actual.equals(expected)) {
|
||||
item.put("success", true);
|
||||
// 获取测试用例临界值,并进行判断
|
||||
// if (runList.size() >= Integer.parseInt(examQuestion.getQuestionScores().getCompileCutoff()) && !runList.contains(false)) {
|
||||
// // 测试用例得分
|
||||
// compile_score += (double) (score * is_compile_score);
|
||||
// // 结果得分
|
||||
// result_score += (double) (score * is_result_score);
|
||||
// LogFileUtils.writeLine("✅ 测试用例得分:" + compile_score);
|
||||
// break;
|
||||
// }
|
||||
} else {
|
||||
item.put("success", false);
|
||||
}
|
||||
compileList.add(item);
|
||||
}
|
||||
// 记录存在多少个测试用例,并且同时记录正确测试用例个数
|
||||
int test_case_number = compileList.size();
|
||||
// 测试用例进行分开使用
|
||||
// 测试用例分数站总分的值
|
||||
BigDecimal compileScore = new BigDecimal(score * is_compile_score);
|
||||
for (Map<String, Object> item : compileList) {
|
||||
boolean success = (boolean) item.get("success");
|
||||
String scoreRate = (String) item.get("scoreRate");
|
||||
String inText = (String) item.get("inText");
|
||||
String resultText = (String) item.get("resultText");
|
||||
String resultTrueText = (String) item.get("resultTrueText");
|
||||
|
||||
// 单个测试用例的分值权重
|
||||
BigDecimal singleScore = new BigDecimal((double) Integer.parseInt(scoreRate) / 100).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||
// 单个测试用例正确情况下得分
|
||||
BigDecimal oneCompileScore = compileScore.multiply(singleScore).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||
compile_score += Double.parseDouble(oneCompileScore.toString());
|
||||
if (success) {
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 测试用例:输入("+
|
||||
inText + ")" +
|
||||
",正确结果:(" + resultTrueText + ")" +
|
||||
",学生结果:(" + resultText + ")" +
|
||||
",正确,得分:" + Double.parseDouble(oneCompileScore.toString()));
|
||||
} else {
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "❌ 测试用例:输入("+
|
||||
inText + ")" +
|
||||
",正确结果:(" + resultTrueText + ")" +
|
||||
",学生结果:(" + resultText + ")" +
|
||||
",错误,得分:0");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} else if (is_result) {
|
||||
// 编译代码运行,无测试用例,直接代码运行结果比对
|
||||
boolean run_code = false;
|
||||
List<Boolean> runList = new ArrayList<>();
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 使用c99标准进行结果编译...");
|
||||
boolean isPassIndex = false;
|
||||
for (ExamQuestionAnswer examQuestionAnswer : examQuestion.getAnswerList()) {
|
||||
// 使用C99 运行并得出结果
|
||||
String code_return = JudgementCUtils.run_code(pathC,code, null,"-std=c99",null);
|
||||
if (!isPassIndex && !code_return.contains("error")) {
|
||||
// 编译没有报错,加上编译分数
|
||||
totalScore += pass_score;
|
||||
isPassIndex = true;
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 编译通过得分:" + pass_score);
|
||||
|
||||
} else if (!isPassIndex) {
|
||||
isPassIndex = true;
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "❌ 编译未通过。");
|
||||
}
|
||||
String actual = code_return.trim();
|
||||
String expected = examQuestionAnswer.getContent().trim();
|
||||
if (actual.equals(expected)) {
|
||||
// 判断测试用例结果是否正确
|
||||
runList.add(true);
|
||||
// 获取测试用例临界值,并进行判断
|
||||
// 判断结果是否正确
|
||||
runList.add(true);
|
||||
// 获取结果临界值,并进行判断
|
||||
// if (runList.size() >= Integer.parseInt(examQuestion.getQuestionScores().getCompileCutoff()) && !runList.contains(false)) {
|
||||
// // 测试用例得分
|
||||
// compile_score += (double) (score * is_compile_score);
|
||||
@@ -164,32 +250,27 @@ public class JudgementServiceImpl implements JudgementService
|
||||
// }
|
||||
}
|
||||
}
|
||||
// 记录存在多少个测试用例,并且同时记录正确测试用例个数
|
||||
// 记录存在多少个结果,并且同时记录正确结果个数
|
||||
int test_case_number = examQuestion.getAnswerList().size();
|
||||
int true_test_case_number = runList.size();
|
||||
|
||||
// 判断正确关系
|
||||
// 1、如果完全相等,说明完全正确,直接给满分
|
||||
if (test_case_number == true_test_case_number) {
|
||||
// 满分,该题多少分就是多少分
|
||||
// LogFileUtils.writeLine("✅ 测试用例全部正确:"+ score);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 测试用例全部正确:"+ score);
|
||||
// LogFileUtils.close();
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 结果全部正确:"+ score);
|
||||
sourceAndText.setScore(score);
|
||||
sourceAndText.setText(judgementStr);
|
||||
return sourceAndText;
|
||||
} else if (test_case_number > true_test_case_number) {
|
||||
// 2、测试用例没有完全正确,对多少个就是多少分
|
||||
// 公式:测试用例总分数 / 测试用例数量 * 正确测试用例数量
|
||||
// 2、结果没有完全正确,对多少个就是多少分
|
||||
// 公式:结果总分数 / 结果数量 * 正确结果数量
|
||||
compile_score += (double) ((score * is_compile_score) / test_case_number) * true_test_case_number;
|
||||
// LogFileUtils.writeLine("✅ 测试用例数量:"+ test_case_number + ",正确数量:" + true_test_case_number + ",得分:" + compile_score);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 测试用例数量:"+ test_case_number + ",正确数量:" + true_test_case_number + ",得分:" + compile_score);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 结果数量:"+ test_case_number + ",正确数量:" + true_test_case_number + ",得分:" + compile_score);
|
||||
|
||||
}
|
||||
} else if (is_pass) {
|
||||
// 编译代码运行
|
||||
// 如果使用程序编译,进行程序编译
|
||||
// LogFileUtils.writeLine("✅ 使用c99标准进行编译...");
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 使用c99标准进行编译...");
|
||||
|
||||
// 使用C99 运行并得出结果
|
||||
@@ -197,40 +278,54 @@ public class JudgementServiceImpl implements JudgementService
|
||||
if (!code_return.contains("error")) {
|
||||
// 编译没有报错,加上编译分数
|
||||
totalScore += pass_score;
|
||||
// LogFileUtils.writeLine("✅ 编译通过得分:" + pass_score);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 编译通过得分:" + pass_score);
|
||||
|
||||
} else {
|
||||
// LogFileUtils.writeLine("❌ 编译未通过。");
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "❌ 编译未通过。");
|
||||
}
|
||||
}
|
||||
// 总分 = 总分 + 测试用例得分
|
||||
totalScore += compile_score;
|
||||
if (compile_score > 0) {
|
||||
// 如果测试用例正确有得分的
|
||||
// 结果
|
||||
if (is_result) {
|
||||
// 总分 = 总分 + 结果得分
|
||||
totalScore += result_score;
|
||||
// LogFileUtils.writeLine("✅ 结果得分:" + result_score);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 结果得分:" + result_score);
|
||||
}
|
||||
}
|
||||
// if (compile_score > 0) {
|
||||
// // 如果测试用例正确有得分的
|
||||
// // 结果
|
||||
// if (is_result) {
|
||||
// // 总分 = 总分 + 结果得分
|
||||
// totalScore += result_score;
|
||||
//// LogFileUtils.writeLine("✅ 结果得分:" + result_score);
|
||||
// judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "✅ 结果得分:" + result_score);
|
||||
// }
|
||||
// }
|
||||
totalScore += key_score;
|
||||
// LogFileUtils.close();
|
||||
sourceAndText.setScore(totalScore);
|
||||
sourceAndText.setText(judgementStr);
|
||||
return sourceAndText;
|
||||
} else {
|
||||
// 关键字对几个给几分,没有达到临界值的情况下
|
||||
totalScore += key_score;
|
||||
// LogFileUtils.writeLine("❌ 关键字没有达到临界值,正确数量:"+ true_number);
|
||||
judgementStr = HtmlAppender.appendHtmlLine(judgementStr, "❌ 关键字没有达到临界值,正确数量:"+ true_number);
|
||||
// LogFileUtils.close();
|
||||
sourceAndText.setScore(totalScore);
|
||||
sourceAndText.setText(judgementStr);
|
||||
return sourceAndText;
|
||||
}
|
||||
}
|
||||
public static String extractUnwrappedText(String input) {
|
||||
// 检查 【 和 】 是否成对出现
|
||||
int openBrackets = countOccurrences(input, "【");
|
||||
int closeBrackets = countOccurrences(input, "】");
|
||||
|
||||
if (openBrackets != closeBrackets) {
|
||||
return input; // 不成对,直接返回原字符串
|
||||
} else if (openBrackets == 0) {
|
||||
return input; // 没有【】,直接返回原字符串
|
||||
} else {
|
||||
// 成对,移除所有【.*?】
|
||||
return input.replaceAll("【.*?】", "");
|
||||
}
|
||||
}
|
||||
|
||||
// 统计字符串中某个子串的出现次数
|
||||
private static int countOccurrences(String str, String subStr) {
|
||||
return str.split(subStr, -1).length - 1;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user