private async Task <JudgeResult> AnswerJudgeAsync(BuildOption buildOption, JudgeOption judgeOption) { var result = new JudgeResult { JudgePoints = new List <JudgePoint> { new JudgePoint() } }; if (judgeOption.AnswerPoint == null || !File.Exists(judgeOption.AnswerPoint.AnswerFile ?? string.Empty)) { result.JudgePoints[0].ResultType = ResultCode.Problem_Config_Error; } try { File.Copy(judgeOption.AnswerPoint.AnswerFile, Path.Combine(_workingdir, $"answer_{judgeOption.GuidStr}.txt"), true); var fileName = Path.Combine(_workingdir, buildOption.SubmitFileName); File.WriteAllText(fileName, buildOption.Source, Encoding.UTF8); var(resultType, percentage, extraInfo) = await CompareAsync(fileName, string.Empty, Path.Combine(_workingdir, $"answer_{judgeOption.GuidStr}.txt"), Path.Combine(_workingdir, buildOption.SubmitFileName), judgeOption, true); result.JudgePoints[0].ResultType = resultType; result.JudgePoints[0].Score = percentage * judgeOption.AnswerPoint.Score; result.JudgePoints[0].ExtraInfo = extraInfo; } catch (Exception ex) { result.JudgePoints[0].ResultType = ResultCode.Unknown_Error; result.JudgePoints[0].ExtraInfo = ex.Message; } return(result); }
public async Task <JudgeResult> JudgeAsync(BuildOption buildOption, JudgeOption judgeOption) { _workingdir = Path.Combine(Path.GetTempPath(), "hjudgeTest", judgeOption.GuidStr); Directory.CreateDirectory(_workingdir); var result = new JudgeResult { JudgePoints = new List <JudgePoint>() }; try { if (judgeOption.AnswerPoint != null) { return(await AnswerJudgeAsync(buildOption, judgeOption)); } var fileName = Path.Combine(_workingdir, $"{buildOption.SubmitFileName}{buildOption.ExtensionName}"); File.WriteAllText(fileName, buildOption.Source, Encoding.UTF8); if (buildOption.StaticCheckOption != null) { var logs = await StaticCheck(buildOption.StaticCheckOption); result.StaticCheckLog = logs; } if (buildOption.CompilerOption != null) { var(isSucceeded, logs) = await Compile(buildOption.CompilerOption, judgeOption.ExtraFiles); result.CompileLog = logs; if (!isSucceeded) { result.JudgePoints = Enumerable.Repeat( new JudgePoint { ResultType = ResultCode.Compile_Error }, judgeOption.DataPoints.Count) .ToList(); return(result); } } for (var i = 0; i < judgeOption.DataPoints.Count; i++) { var point = new JudgePoint(); if (!File.Exists(judgeOption.RunOption?.Exec)) { point.ResultType = ResultCode.Compile_Error; point.ExtraInfo = "Cannot find compiled executable file"; result.JudgePoints.Add(point); continue; } try { try { File.Copy(judgeOption.DataPoints[i].StdInFile.Replace("${index}", (i + 1).ToString()).Replace("${index0}", i.ToString()), Path.Combine(_workingdir, judgeOption.InputFileName), true); } catch { throw new InvalidOperationException("Unable to find standard input file"); } var strErrFile = Path.Combine(_workingdir, $"stderr_{judgeOption.GuidStr}.dat"); var inputFile = Path.Combine(_workingdir, judgeOption.InputFileName); var outputFile = Path.Combine(_workingdir, judgeOption.OutputFileName); var param = new { judgeOption.RunOption.Exec, judgeOption.RunOption.Args, WorkingDir = _workingdir, StdErrRedirectFile = strErrFile, InputFile = inputFile, OutputFile = outputFile, judgeOption.DataPoints[i].TimeLimit, judgeOption.DataPoints[i].MemoryLimit, IsStdIO = judgeOption.UseStdIO, judgeOption.ActiveProcessLimit }; var ret = new StringBuilder(256); if (Execute(JsonConvert.SerializeObject(param), ret)) { point = JsonConvert.DeserializeObject <JudgePoint>(ret.ToString()?.Trim() ?? "{}"); } else { throw new Exception("Unable to execute target program"); } try { File.Copy(judgeOption.DataPoints[i].StdOutFile.Replace("${index}", (i + 1).ToString()).Replace("${index0}", i.ToString()), Path.Combine(_workingdir, $"answer_{judgeOption.GuidStr}.dat"), true); } catch { throw new InvalidOperationException("Unable to find standard output file"); } if (point.ResultType == ResultCode.Runtime_Error) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Enum.IsDefined(typeof(WindowsExceptionCode), (uint)point.ExitCode)) { point.ExtraInfo = Enum.GetName(typeof(WindowsExceptionCode), (uint)point.ExitCode); } else if (Enum.IsDefined(typeof(LinuxExceptionCode), point.ExitCode - 128)) { point.ExtraInfo = Enum.GetName(typeof(LinuxExceptionCode), point.ExitCode - 128); } else { point.ExtraInfo = "UNKNOWN_EXCEPTION"; } point.Score = 0; } else { if (judgeOption.StandardErrorBehavior != StdErrBehavior.Ignore) { try { var stderr = File.ReadAllText(strErrFile).Trim() .Replace(_workingdir, "...") .Replace(_workingdir.Replace("/", "\\"), "...");; if (!string.IsNullOrWhiteSpace(stderr.Replace("\n", string.Empty).Replace("\r", string.Empty).Replace("\t", string.Empty).Trim())) { switch (judgeOption.StandardErrorBehavior) { case StdErrBehavior.TreatAsCompileError: point.ResultType = ResultCode.Compile_Error; point.ExtraInfo = stderr; break; case StdErrBehavior.TreatAsRuntimeError: point.ResultType = ResultCode.Runtime_Error; point.ExtraInfo = stderr; break; } point.Score = 0; } } catch { //ignored } } if (point.ResultType == ResultCode.Accepted) { var(resultType, percentage, extraInfo) = point.ResultType == ResultCode.Accepted ? await CompareAsync(fileName, inputFile, Path.Combine(_workingdir, $"answer_{judgeOption.GuidStr}.dat"), outputFile, judgeOption) : (point.ResultType, 0, point.ExtraInfo); point.ExtraInfo = extraInfo; point.ResultType = resultType; point.Score = percentage * judgeOption.DataPoints[i].Score; } } } catch (Exception ex) { point.ExtraInfo = ex.Message; if (ex is InvalidOperationException) { point.ResultType = ResultCode.Problem_Config_Error; } else { point.ResultType = ResultCode.Unknown_Error; } } result.JudgePoints.Add(point); } } finally { try { Directory.Delete(_workingdir, true); } catch { /* ignored */ } } return(result); }