示例#1
0
        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);
        }