【修改】C语言本地判分逻辑,测试用例,关键字比对,代码段读取,结果摘要

This commit is contained in:
dlaren
2025-07-22 15:01:36 +08:00
parent b841cc3763
commit b7607d3c9c

View File

@@ -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;
}
}