private double GradeOneSubmission(string problemName, string userName, out JudgeUpdateScoreType status) { status = JudgeUpdateScoreType.OK; int total = problemModel[problemName].Testcases.Count; //Remove old submission judgeModel.RemoveSubmission(problemName, userName); OnUpdateScore?.Invoke(this, new JudgeUpdateScoreSubmissionEvent() { ProblemName = problemName, UserName = userName, Status = JudgeUpdateScoreType.RemoveSubmission, Points = 0, }); OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.BeginGradingSubmission, ProblemName = problemName, UserName = userName }); //--------------- check submission existed & get user, problem object User user = userModel[userName]; Problem problem = problemModel[problemName]; List <UserSubmission> submissions = user.GetSubmission(problemName); if (submissions.Count == 0) { //Submission not found OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.SubmissionNotFound, UserName = userName, ProblemName = problemName }); TestcasesGraded += total; judgeModel.CreateNewSubmission(problemName, userName, "Not found submission!", "MS", "(null)"); status = JudgeUpdateScoreType.SubmissionNotFound; return(0); } //--------------- make directory string currentDir = FS.Combine(workSpace, DateTime.Now.Ticks.ToString()); string currentUserDir = FS.Combine(currentDir, user.UserName); string currentProblemDir = FS.Combine(currentDir, problem.ProblemName); string inputRun = FS.Combine(currentProblemDir, "input.txt"); FS.CreateDirectory(currentDir); FS.CreateDirectory(currentUserDir); FS.CreateDirectory(currentProblemDir); FS.CreateEmptyFile(inputRun); Compiler compiler = null; UserSubmission submission = null; CompileStatus compileResult = null; //--------------- compile foreach (UserSubmission sub in submissions) { submission = sub; string userSourceCode = FS.Combine(userModel.UserDirectory, userName, sub.ToString()); string newSource = FS.Combine(currentUserDir, sub.ToString()); FS.CopyFile(userSourceCode, newSource); if (!compilerManager.Contains(sub.Extension)) { continue; } List <Compiler> compilers = compilerManager[sub.Extension]; bool found = false; foreach (Compiler com in compilers) { compiler = com; OnGradeStatusChanged.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.Compiling, Status = com.Name, UserName = userName, ProblemName = problemName }); compileResult = com.Compile(sandbox, sub.ToString(), currentUserDir); if (!IsGrading) //cancel { FS.DeleteDirectory(currentDir); TestcasesGraded += total; return(0); } if (compileResult.Success) { found = true; break; } } if (found) { break; } } if (compiler == null) { //Submission not found OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.CompilerNotFound, UserName = userName, ProblemName = problemName }); TestcasesGraded += total; judgeModel.CreateNewSubmission(problemName, userName, "Not found submission!", "MS", "(null)"); status = JudgeUpdateScoreType.CompilerNotFound; return(0); } if (!compileResult.Success) { //Compile error OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Status = compileResult.Message, UserName = userName, ProblemName = problemName, Event = JudgeGradingEventType.CompileError }); TestcasesGraded += total; FS.DeleteDirectory(currentDir); judgeModel.CreateNewSubmission(problemName, userName, compileResult.Message, "CE", compiler.Name); status = JudgeUpdateScoreType.CompileError; return(0); } //OK OnGradeStatusChanged.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.CompileSuccessfully, UserName = userName, ProblemName = problemName, Status = compiler.Name }); //Check execute exist if (!FS.FileExist(FS.Combine(currentUserDir, compileResult.OutputFileName))) { OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { ProblemName = problemName, UserName = userName, Event = JudgeGradingEventType.SubmissionNotFound }); OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { ProblemName = problemName, UserName = userName, Event = JudgeGradingEventType.NotFoundExecute }); judgeModel.CreateNewSubmission(problemName, userName, "Not found execute", "NFE", compiler.Name); status = JudgeUpdateScoreType.ExecuteNotFound; return(0); } //3. Run testcase List <SubmissionTestcaseResult> gradingTestcaseResult = new List <SubmissionTestcaseResult>(); foreach (Testcase test in problem.Testcases) { OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.BeginRunTest }); string currentTestDir = FS.Combine(currentProblemDir, test.TestcaseName); string sourceInput = FS.Combine(problem.ParentDirectory, problem.ProblemName, test.TestcaseName, problem.Input); string sourceOutput = FS.Combine(problem.ParentDirectory, problem.ProblemName, test.TestcaseName, problem.Output); string destOutput = FS.Combine(currentTestDir, problem.Output); //create testcase directory FS.CreateDirectory(currentTestDir); //copy execute FS.CopyFile(FS.Combine(currentUserDir, compileResult.OutputFileName), FS.Combine(currentTestDir, compileResult.OutputFileName)); //copy input if (!problem.UseStdin) { string destInput = FS.Combine(currentTestDir, problem.Input); FS.CopyFile(sourceInput, destInput); } //run var running_status = sandbox.StartRun(-1, ('"' + compiler.RunProgram + '"' + " " + compiler.RunArgs).Replace("$NAME$", submission.Name), currentTestDir, problem.Timelimit, problem.Memorylimit * 1024, problem.UseStdin ? sourceInput : inputRun, problem.UseStdout ? destOutput : null, TreatExitCodeNonZeroAsRTE ); if (!IsGrading) //cancel { TestcasesGraded += total; FS.DeleteDirectory(currentDir); return(0); } TestcasesGraded++; total--; string grading_status = running_status.Status.ToString(); double points = 0.0; int timeExecute = running_status.TimeExecuted; int memUsed = running_status.MemoryUsed; //check if (running_status.ExitCode != 0) { if (running_status.Status == SandBoxStatusType.TLE) { OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.EndRunTest, ProblemName = problemName, UserName = userName, TestCaseName = test.TestcaseName, TimeExecuted = timeExecute, Status = "TLE" }); } else if (running_status.Status == SandBoxStatusType.MLE) { OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.EndRunTest, ProblemName = problemName, UserName = userName, TestCaseName = test.TestcaseName, Status = "MLE" }); } else if (running_status.Status == SandBoxStatusType.RTE) { OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.EndRunTest, ProblemName = problemName, UserName = userName, TestCaseName = test.TestcaseName, Status = "RTE" }); } else if (running_status.Status == SandBoxStatusType.UnknownError) { OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.EndRunTest, ProblemName = problemName, UserName = userName, TestCaseName = test.TestcaseName, Status = "Unknown" }); } else { throw new Exception("JUDGER ERROR"); } } else { //if run ok -> copy output & rename FS.CopyFile(sourceOutput, destOutput + "$"); //check result bool checker_result = checker.Compare(problem.Checker, problem.Output, problem.Output + "$", currentTestDir); if (checker_result) { grading_status = "AC"; points = test.Point; } else { grading_status = "WA"; } OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.EndRunTest, MemoryUsed = memUsed, TimeExecuted = timeExecute, Status = grading_status, Points = points, TestCaseName = test.TestcaseName, ProblemName = problemName, UserName = userName, }); } gradingTestcaseResult.Add(new SubmissionTestcaseResult() { ProblemName = problemName, UserName = userName, TestcaseName = test.TestcaseName, Points = points, MemoryUsed = memUsed, TimeExecuted = timeExecute, Status = grading_status }); } //update status to database & calc score double totalScore = 0; int submission_id = judgeModel.CreateNewSubmission(problemName, userName, compileResult.Message, "OK", compiler.Name); foreach (SubmissionTestcaseResult r in gradingTestcaseResult) { if (r.Status == "AC") { judgeModel.UpdateLanguageTimeGrading(compiler.Name, r.TimeExecuted); } judgeModel.UpdateStatus(submission_id, r.TestcaseName, r.Points, r.Status, r.TimeExecuted, r.MemoryUsed); totalScore += r.Points; } //4. Clean FS.DeleteDirectory(currentDir); OnGradeStatusChanged?.Invoke(this, new JudgeGradingEvent() { Event = JudgeGradingEventType.EndGradingSubmission }); status = JudgeUpdateScoreType.OK; return(totalScore); }