diff --git a/src/main/java/org/example/Main.java b/src/main/java/org/example/Main.java index 8e80b573f63cbea9bc1ebe1f55d8025284005dd4..bcef9e0e345c514d73c707dcffa6e41f3ccb7eee 100644 --- a/src/main/java/org/example/Main.java +++ b/src/main/java/org/example/Main.java @@ -1,6 +1,20 @@ package org.example; import com.google.gson.JsonObject; +import org.example.answerSheet.AnswerSheet; +import org.example.answerSheet.answer.Answer; +import org.example.exam.Exam; +import org.example.exam.ExamFactory; +import org.example.grader.Grader; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class Main { public static void main(String[] args) { @@ -11,7 +25,40 @@ public class Main { String answersPath = casePath + System.getProperty("file.separator") + "answers"; // 杈撳嚭鏂囦欢璺緞 String output = args[1]; - // TODO:鍦ㄤ笅闈㈣皟鐢ㄤ綘瀹炵幇鐨勫姛鑳� + List<Exam> exams = new ArrayList<>(); + Map<Integer,Integer> id2Index = new HashMap<>(); + + File examsFolder = new File(examsPath); + if (examsFolder.exists() && examsFolder.isDirectory()) { + File[] files = examsFolder.listFiles(); + if (files != null) { + for (File file : files) { + Exam exam = ExamFactory.createExam(file); + id2Index.put(exam.getId(),exams.size()); + exams.add(exam); + } + } + } + + try (BufferedWriter writer = new BufferedWriter(new FileWriter(output))) { + writer.write("examId,stuId,score"); + writer.newLine(); + File answersFolder = new File(answersPath); + if (answersFolder.exists() && answersFolder.isDirectory()) { + File[] files = answersFolder.listFiles(); + if (files != null) { + for (File file : files) { + AnswerSheet answerSheet = AnswerSheet.createAnswerSheet(file); + int grade = Grader.grade(exams.get(id2Index.get(answerSheet.getExamId())),answerSheet); + writer.write(String.valueOf(answerSheet.getExamId()) + ',' + + String.valueOf(answerSheet.getStuId()) + ',' + String.valueOf(grade)); + writer.newLine(); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } } } \ No newline at end of file diff --git a/src/main/java/org/example/answerSheet/AnswerSheet.java b/src/main/java/org/example/answerSheet/AnswerSheet.java new file mode 100644 index 0000000000000000000000000000000000000000..4f2a1b8e8d9cc5c5109d4e68ede186e3cd026a03 --- /dev/null +++ b/src/main/java/org/example/answerSheet/AnswerSheet.java @@ -0,0 +1,30 @@ +package org.example.answerSheet; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import lombok.Data; +import org.apache.commons.io.FileUtils; +import org.example.answerSheet.answer.Answer; + +import java.io.File; +import java.io.IOException; + +@Data +public class AnswerSheet { + private int examId; + private int stuId; + private long submitTime; + private Answer[] answers; + public static AnswerSheet createAnswerSheet(File file) { + try { + String content = FileUtils.readFileToString(file,"utf-8"); + JsonParser jsonParser = new JsonParser(); + JsonObject jsonAnswerSheet= (JsonObject) jsonParser.parse(content); + return new Gson().fromJson(jsonAnswerSheet,AnswerSheet.class); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/src/main/java/org/example/answerSheet/answer/Answer.java b/src/main/java/org/example/answerSheet/answer/Answer.java new file mode 100644 index 0000000000000000000000000000000000000000..b6adf9f0bcd344720d0cad0fd2947eba8d554d3b --- /dev/null +++ b/src/main/java/org/example/answerSheet/answer/Answer.java @@ -0,0 +1,9 @@ +package org.example.answerSheet.answer; + +import lombok.Data; + +@Data +public class Answer { + private int id; + private String answer; +} diff --git a/src/main/java/org/example/exam/Exam.java b/src/main/java/org/example/exam/Exam.java index 6c1b5f46732766d6b61c35e27b5d85657adb7172..7eb689d8346c03d3d804c4c8fef39f67f1ec4892 100644 --- a/src/main/java/org/example/exam/Exam.java +++ b/src/main/java/org/example/exam/Exam.java @@ -11,5 +11,4 @@ public abstract class Exam { protected Long startTime; protected Long endTime; protected Question[] questions; - public abstract Exam createExam(File file); } diff --git a/src/main/java/org/example/exam/ExamFactory.java b/src/main/java/org/example/exam/ExamFactory.java index 145b01f85f2b190fcf42a6debdddcf0a4a2030dc..c703094aff445b709066e4c195fe4b9ebb5564bb 100644 --- a/src/main/java/org/example/exam/ExamFactory.java +++ b/src/main/java/org/example/exam/ExamFactory.java @@ -4,6 +4,12 @@ import java.io.File; public class ExamFactory { public static Exam createExam(File file) { - + String fileName = file.getName(); + if (fileName.endsWith("json")) { + return JsonExam.createExam(file); + } else if (fileName.endsWith("xml")) { + return XmlExam.createExam(file); + } + return null; } } diff --git a/src/main/java/org/example/exam/JsonExam.java b/src/main/java/org/example/exam/JsonExam.java index 32897c19cc6d5139aebd7d73742847b1eb3aada6..fe66ecea787c416fa51242eb258c48b26832550d 100644 --- a/src/main/java/org/example/exam/JsonExam.java +++ b/src/main/java/org/example/exam/JsonExam.java @@ -23,7 +23,7 @@ public class JsonExam extends Exam{ this.questions = questions; } - public Exam createExam(File file) { + public static Exam createExam(File file) { try { String content = FileUtils.readFileToString(file,"utf-8"); JsonParser jsonParser = new JsonParser(); diff --git a/src/main/java/org/example/exam/XmlExam.java b/src/main/java/org/example/exam/XmlExam.java index a06120695cb52a3722b93e84b1e99f12e3f0230f..e17d13a1d04dfdef18d2d95ec64244569cbce417 100644 --- a/src/main/java/org/example/exam/XmlExam.java +++ b/src/main/java/org/example/exam/XmlExam.java @@ -9,15 +9,21 @@ import org.example.question.MultipleChoiceQuestion; import org.example.question.ProgrammingQuestion; import org.example.question.Question; import org.example.question.SingleChoiceQuestion; +import org.example.question.sample.Sample; import java.io.File; import java.util.List; @Data -public class XmlExam extends Exam{ - - @Override - public Exam createExam(File file) { +public class XmlExam extends Exam { + public XmlExam(int id, String title, long startTime, long endTime, Question[] questions) { + this.id = id; + this.title = title; + this.startTime = startTime; + this.endTime = endTime; + this.questions = questions; + } + public static Exam createExam(File file) { try { SAXReader saxReader = new SAXReader(); Document content = saxReader.read(file); @@ -28,14 +34,58 @@ public class XmlExam extends Exam{ Question[] questions = new Question[n]; for (int i = 0;i < n;i++) { Element xmlQuestion = xmlQuestionsList.get(i); - int type = Integer.parseInt(xmlQuestion.attributeValue("type")); + int type = Integer.parseInt(xmlQuestion.elementText("type")); + int id = Integer.parseInt(xmlQuestion.elementText("id")); + String questionText = xmlQuestion.elementText("question"); + int points = Integer.parseInt(xmlQuestion.elementText("points")); Question question; switch (type) { case 1: + List<Element> optionsElements = xmlQuestion.element("options").elements(); + String[] options = new String[optionsElements.size()]; + for (int j = 0; j < optionsElements.size(); j++) { + options[j] = optionsElements.get(j).getText(); + } + int answer = Integer.parseInt(xmlQuestion.elementText("answer")); + question = new SingleChoiceQuestion(id, type, questionText, points, options, answer); break; case 2: + optionsElements = xmlQuestion.element("options").elements(); + options = new String[optionsElements.size()]; + for (int j = 0; j < optionsElements.size(); j++) { + options[j] = optionsElements.get(j).getText(); + } + List<Element> answerElements = xmlQuestion.element("answers").elements(); + int[] answers = new int[answerElements.size()]; + for (int j = 0; j < answerElements.size(); j++) { + answers[j] = Integer.parseInt(answerElements.get(j).getText()); + } + String scoreMode = xmlQuestion.elementText("scoreMode"); + int fixScore = 0; + if (scoreMode.equals("fix")) { + fixScore = Integer.parseInt(xmlQuestion.elementText("fixScore")); + } + int[] partialScores = null; + if (scoreMode.equals("partial")) { + List<Element> partialScoreElements = xmlQuestion.element("partialScores").elements(); + partialScores = new int[partialScoreElements.size()]; + for (int j = 0; j < partialScoreElements.size(); j++) { + partialScores[j] = Integer.parseInt(partialScoreElements.get(j).getText()); + } + } + question = new MultipleChoiceQuestion(id, type, questionText, points, options, answers, scoreMode, fixScore, partialScores); break; case 3: + int timeLimit = Integer.parseInt(xmlQuestion.elementText("timeLimit")); + List<Element> sampleElements = xmlQuestion.element("samples").elements(); + Sample[] samples = new Sample[sampleElements.size()]; + for (int j = 0; j < sampleElements.size(); j++) { + Element sampleElement = sampleElements.get(j); + String input = sampleElement.elementText("input"); + String output = sampleElement.elementText("output"); + samples[j] = new Sample(input, output); + } + question = new ProgrammingQuestion(id, type, questionText, points, timeLimit, samples); break; default: question = null; @@ -43,10 +93,12 @@ public class XmlExam extends Exam{ } questions[i] = question; } + return new XmlExam(Integer.parseInt(xmlExam.elementText("id")),xmlExam.elementText("title"), + Long.parseLong(xmlExam.elementText("startTime")),Long.parseLong(xmlExam.elementText("endTime")), + questions); } catch (DocumentException e) { e.printStackTrace(); } - return null; } } diff --git a/src/main/java/org/example/grader/Grader.java b/src/main/java/org/example/grader/Grader.java new file mode 100644 index 0000000000000000000000000000000000000000..1fa6b616fadc3a6f38638968e4b524430f11d926 --- /dev/null +++ b/src/main/java/org/example/grader/Grader.java @@ -0,0 +1,128 @@ +package org.example.grader; + +import lombok.Data; +import org.example.answerSheet.AnswerSheet; +import org.example.answerSheet.answer.Answer; +import org.example.exam.Exam; +import org.example.question.MultipleChoiceQuestion; +import org.example.question.Question; +import org.example.question.SingleChoiceQuestion; + +import java.util.HashSet; +import java.util.Set; + +@Data +public class Grader { + public static int grade(Exam exam, AnswerSheet answerSheet) { + if (answerSheet.getSubmitTime() < exam.getStartTime() || answerSheet.getSubmitTime() > exam.getEndTime()){ + return 0; + } + int grade = 0; + Question[] questions = exam.getQuestions(); + Answer[] answers = answerSheet.getAnswers(); + boolean[] answered = new boolean[questions.length]; + for (int i = 0;i < questions.length;i++) { + answered[i] = false; + } + for (int i = 0;i < answers.length;i++) { + Answer answer = answers[i]; + String stuAnswer = answer.getAnswer(); + Question question = questions[answer.getId() - 1]; + answered[answer.getId() - 1] = true; + Set<Integer> correctAnswerSet; + switch (question.getType()) { + case 1: + if (stuAnswer.length() == 1 && stuAnswer.charAt(0) - 'A' == ((SingleChoiceQuestion) + question).getAnswer()) { + grade += question.getPoints(); + } + break; + case 2: + int[] correctAnswer = ((MultipleChoiceQuestion) question).getAnswer(); + boolean judge = true; + switch (((MultipleChoiceQuestion) question).getScoreMode()) { + case "nothing": + if (correctAnswer.length != stuAnswer.length()) { + break; + } + judge = true; + for (int j = 0;j < stuAnswer.length();j++) { + if (stuAnswer.charAt(j) - 'A' != correctAnswer[j]) { + judge = false; + break; + } + } + if (judge) { + grade += question.getPoints(); + } + break; + case "fix": + if (correctAnswer.length < stuAnswer.length()) { + break; + } + correctAnswerSet = new HashSet<>(); + for (int j : correctAnswer) { + correctAnswerSet.add(j); + } + judge = true; + for (int j = 0;j < stuAnswer.length();j++) { + if (!correctAnswerSet.contains(stuAnswer.charAt(j) - 'A')) { + judge = false; + break; + } + } + if (judge) { + if (correctAnswer.length == stuAnswer.length()) { + grade += question.getPoints(); + } else { + grade += ((MultipleChoiceQuestion) question).getFixScore(); + } + } + break; + case "partial": + if (correctAnswer.length < stuAnswer.length()) { + break; + } + correctAnswerSet = new HashSet<>(); + for (int j : correctAnswer) { + correctAnswerSet.add(j); + } + judge = true; + int partScore = 0; + for (int j = 0;j < stuAnswer.length();j++) { + if (!correctAnswerSet.contains(stuAnswer.charAt(j) - 'A')) { + judge = false; + break; + } else { + for (int k = 0;k < correctAnswer.length;k++) { + if (stuAnswer.charAt(j) - 'A' == correctAnswer[k]) { + partScore += ((MultipleChoiceQuestion) question).getPartialScore()[k]; + break; + } + } + } + } + if (judge) { + if (correctAnswer.length == stuAnswer.length()) { + grade += question.getPoints(); + } else { + grade += partScore; + } + } + } + break; + case 3: + grade += question.getPoints(); + break; + default: + break; + } + } + for (int i = 0;i < questions.length;i++) { + if (!answered[i] && questions[i].getType() == 3) { + grade += questions[i].getPoints(); + } + } + return grade; + } +} diff --git a/src/main/java/org/example/question/MultipleChoiceQuestion.java b/src/main/java/org/example/question/MultipleChoiceQuestion.java index 90715d4211cc2dd0c5f8a87550c0c86d685eb2da..0b229298c4c0d9fb8f9b4a6a75760d5d41ffbdf3 100644 --- a/src/main/java/org/example/question/MultipleChoiceQuestion.java +++ b/src/main/java/org/example/question/MultipleChoiceQuestion.java @@ -22,10 +22,5 @@ public class MultipleChoiceQuestion extends Question { this.fixScore = fixScore; this.partialScore = partialScore; } - - public static Question createQuestion(int id, int type, String question, int points, Object... extraParameter) { - return new MultipleChoiceQuestion(id,type,question,points,(String[]) extraParameter[0],(int[]) extraParameter[1], - (String) extraParameter[2],(int) extraParameter[3], (int[]) extraParameter[4]); - } } diff --git a/src/main/java/org/example/question/ProgrammingQuestion.java b/src/main/java/org/example/question/ProgrammingQuestion.java index 8885d30790e1da3385ba2e172a98ffcc2733790d..f4e818bdb7cdcd9ef783c43e18b534d0034a274a 100644 --- a/src/main/java/org/example/question/ProgrammingQuestion.java +++ b/src/main/java/org/example/question/ProgrammingQuestion.java @@ -16,8 +16,4 @@ public class ProgrammingQuestion extends Question { this.timeLimit = timeLimit; this.samples = samples; } - - public static Question createQuestion(int id, int type, String question, int points, Object... extraParameter) { - return new ProgrammingQuestion(id,type,question,points,(int) extraParameter[0],(Sample[]) extraParameter[1]); - } } diff --git a/src/main/java/org/example/question/QuestionFactory.java b/src/main/java/org/example/question/QuestionFactory.java deleted file mode 100644 index c04059b0be2f5350bead233b07db03dbcadf6441..0000000000000000000000000000000000000000 --- a/src/main/java/org/example/question/QuestionFactory.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.example.question; - -public class QuestionFactory { - public static Question createQuestion(int id, int type, String question, int points, Object... extraParameter) { - switch (type) { - case 1: - return SingleChoiceQuestion.createQuestion(id,type,question,points,extraParameter); - case 2: - return MultipleChoiceQuestion.createQuestion(id,type,question,points,extraParameter); - case 3: - return ProgrammingQuestion.createQuestion(id,type,question,points,extraParameter); - default: - return null; - } - } -} diff --git a/src/main/java/org/example/question/SingleChoiceQuestion.java b/src/main/java/org/example/question/SingleChoiceQuestion.java index 358474e1d6eea2e698082309e0423b0ae34f5ab1..eac974330f2c5db03a864d063bfb9f86d96f0ec5 100644 --- a/src/main/java/org/example/question/SingleChoiceQuestion.java +++ b/src/main/java/org/example/question/SingleChoiceQuestion.java @@ -15,8 +15,4 @@ public class SingleChoiceQuestion extends Question { this.options = options; this.answer = answer; } - - public static Question createQuestion(int id, int type, String question, int points, Object... extraParameter) { - return new SingleChoiceQuestion(id,type,question,points,(String[]) extraParameter[0],(int) extraParameter[1]); - } } diff --git a/src/main/java/org/example/question/sample/Sample.java b/src/main/java/org/example/question/sample/Sample.java index b9358fa4c6cc9da461463cdc58cb0289493d1064..64090f089f3a7bf2689d66c99861da4c8403ab0e 100644 --- a/src/main/java/org/example/question/sample/Sample.java +++ b/src/main/java/org/example/question/sample/Sample.java @@ -6,4 +6,8 @@ import lombok.Data; public class Sample { private String input; private String output; + public Sample(String input, String output) { + this.input = input; + this.output = output; + } }