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