예제 #1
0
        private void App_OnStartup(object sender, StartupEventArgs e)
        {
            _mutex = new Mutex(
                true,
                "hjudge_server",
                out var isSucceed);
            if (!isSucceed)
            {
                MessageBox.Show("本程序已在运行,请勿重复运行", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                Environment.Exit(1);
            }
            foreach (var i in e.Args)
            {
                if (i == "-silent")
                {
                    Configuration.IsHidden = true;
                }
            }

            try
            {
                if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\AppData"))
                {
                    Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\AppData");
                }
                if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Files"))
                {
                    Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\Files");
                }
                if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Data"))
                {
                    Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\Data");
                }
                if (Environment.Is64BitProcess)
                {
                    File.Copy(AppDomain.CurrentDomain.BaseDirectory + "\\x64\\HPSocket4C_U.dll",
                              AppDomain.CurrentDomain.BaseDirectory + "\\HPSocket4C_U.dll", true);
                }
                else
                {
                    File.Copy(AppDomain.CurrentDomain.BaseDirectory + "\\x86\\HPSocket4C_U.dll",
                              AppDomain.CurrentDomain.BaseDirectory + "\\HPSocket4C_U.dll", true);
                }
            }
            catch
            {
                MessageBox.Show("程序初始化失败", "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                Environment.Exit(1);
            }

            JudgeHelper.Init();
        }
예제 #2
0
        private void Judging(UIElement textBlock, string runExec, string runArgs)
        {
            var cur = -1;
            var noRespondingState      = false;
            var noRespondingTime       = new int[_problem.DataSets.Length];
            var failToCatchProcessTime = new int[_problem.DataSets.Length];

            while (cur < _problem.DataSets.Length - 1)
            {
                var failToCatchProcess = false;
                cur++;
                if (cur != 0)
                {
                    Connection.UpdateMainPageState(
                        $"{DateTime.Now:yyyy/MM/dd HH:mm:ss} 评测 #{JudgeResult.JudgeId} 数据点 {cur}/{_problem.DataSets.Length} 完毕,结果:{JudgeResult.Result[cur - 1]}",
                        textBlock);
                }
                if ((!string.IsNullOrWhiteSpace(_problem.DataSets[cur].InputFile) && !File.Exists(_problem.DataSets[cur].InputFile)) || !File.Exists(_problem.DataSets[cur].OutputFile))
                {
                    JudgeResult.Result[cur]     = "Problem Configuration Error";
                    JudgeResult.Exitcode[cur]   = 0;
                    JudgeResult.Score[cur]      = 0;
                    JudgeResult.Timeused[cur]   = 0;
                    JudgeResult.Memoryused[cur] = 0;
                }
                else
                {
                    if (_problem.InputFileName != "stdin")
                    {
                        if (!string.IsNullOrWhiteSpace(_problem.DataSets[cur].InputFile))
                        {
                            try
                            {
                                File.Copy(_problem.DataSets[cur].InputFile, _workingdir + "\\" + _problem.InputFileName,
                                          true);
                            }
                            catch
                            {
                                Thread.Sleep(2000);
                                try
                                {
                                    File.Copy(_problem.DataSets[cur].InputFile, _workingdir + "\\" + _problem.InputFileName,
                                              true);
                                }
                                catch
                                {
                                    Thread.Sleep(3000);
                                    try
                                    {
                                        File.Copy(_problem.DataSets[cur].InputFile,
                                                  _workingdir + "\\" + _problem.InputFileName,
                                                  true);
                                    }
                                    catch (Exception ex)
                                    {
                                        JudgeResult.Result[cur]     = $"Unknown Error: {ex.Message}";
                                        JudgeResult.Exitcode[cur]   = 0;
                                        JudgeResult.Score[cur]      = 0;
                                        JudgeResult.Timeused[cur]   = 0;
                                        JudgeResult.Memoryused[cur] = 0;
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                    if (_problem.InputFileName == "stdin")
                    {
                        try
                        {
                            File.Delete(_workingdir + "\\" + _problem.OutputFileName + ".htmp");
                        }
                        catch
                        {
                            //ignored
                        }
                    }
                    else
                    {
                        try
                        {
                            File.Delete(_workingdir + "\\" + _problem.OutputFileName);
                        }
                        catch
                        {
                            //ignored
                        }
                    }

                    void exit(object sender, EventArgs args)
                    {
                        _isExited = true;
                    }

                    var testId  = $"test_hjudge_{_id}";
                    var execute = new Process
                    {
                        StartInfo =
                        {
                            FileName               = string.IsNullOrEmpty(runExec)
                                ? _workingdir + $"\\test_hjudge_{_id}.exe"
                                : runExec,
                            Arguments              = string.IsNullOrEmpty(runArgs) ? string.Empty : runArgs,
                            WorkingDirectory       = _workingdir,
                            WindowStyle            = ProcessWindowStyle.Hidden,
                            ErrorDialog            = false,
                            CreateNoWindow         = true,
                            UseShellExecute        = false,
                            RedirectStandardInput  = true,
                            RedirectStandardOutput = true
                        },
                        EnableRaisingEvents = true
                    };

                    execute.Exited += exit;
                    Task <string> res = null;
                    _isFault  = false;
                    _isExited = false;
                    var startCatch = DateTime.Now;
                    JudgeHelper.Subscribe(testId);
                    long lastDt = 0;
                    try
                    {
                        execute.Start();
                    }
                    catch (Exception ex)
                    {
                        JudgeResult.Result[cur]     = $"Unknown Error: {ex.Message}";
                        JudgeResult.Exitcode[cur]   = 0;
                        JudgeResult.Score[cur]      = 0;
                        JudgeResult.Timeused[cur]   = 0;
                        JudgeResult.Memoryused[cur] = 0;
                        JudgeHelper.Desubscribe(testId);
                        continue;
                    }
                    var inputStream  = execute.StandardInput;
                    var outputStream = execute.StandardOutput;
                    while (JudgeHelper.Processes[testId] == null)
                    {
                        if (_isExited || (DateTime.Now - startCatch).TotalSeconds > 10)
                        {
                            failToCatchProcess = true;
                            break;
                        }
                        Thread.Sleep(1);
                    }
                    if (failToCatchProcess)
                    {
                        JudgeHelper.Desubscribe(testId);
                        JudgeResult.Result[cur] = "Unknown Error";
                        JudgeResult.Score[cur]  = 0;
                        failToCatchProcessTime[cur]++;
                        try
                        {
                            execute.Kill();
                        }
                        catch
                        {
                            //ignored
                        }
                        execute.Close();
                        if (failToCatchProcessTime[cur] < 3)
                        {
                            cur--;
                        }
                        continue;
                    }

                    var process      = JudgeHelper.Processes[testId];
                    var noChangeTime = DateTime.Now; //Prevent from process suspending / IO block causing no response

                    JudgeHelper.Desubscribe(testId);

                    try
                    {
                        JudgeResult.Timeused[cur]   = Math.Max(JudgeResult.Timeused[cur], Convert.ToInt64(process.UserProcessorTime.TotalMilliseconds));
                        JudgeResult.Memoryused[cur] = Math.Max(JudgeResult.Memoryused[cur], process.PeakWorkingSet64 >> 10);
                    }
                    catch
                    {
                        //ignored
                    }
                    var resume = false;

                    var isNoResponding = false;
                    do
                    {
                        var taskCount = 0;
                        try
                        {
                            while (!_isExited)
                            {
                                taskCount = 0;
                                if (!resume)
                                {
                                    resume = true;

                                    new Thread(() =>
                                    {
                                        if (_problem.InputFileName == "stdin")
                                        {
                                            try
                                            {
                                                res = outputStream.ReadToEndAsync();
                                                inputStream.AutoFlush = true;
                                                if (!string.IsNullOrWhiteSpace(_problem.DataSets[cur].InputFile))
                                                {
                                                    lock (Connection.StdinWriterLock)
                                                        inputStream.WriteAsync(
                                                            File.ReadAllText(_problem.DataSets[cur].InputFile, Encoding.Default) + "\0")
                                                        .ContinueWith(o =>
                                                        {
                                                            inputStream.Close();
                                                        });
                                                }
                                                else
                                                {
                                                    inputStream.WriteAsync("\0")
                                                    .ContinueWith(o =>
                                                    {
                                                        inputStream.Close();
                                                    });
                                                }
                                            }
                                            catch
                                            {
                                                //ignored
                                            }
                                        }
                                        else
                                        {
                                            try
                                            {
                                                inputStream.Write("\0");
                                                inputStream.Close();
                                            }
                                            catch
                                            {
                                                //ignored
                                            }
                                        }
                                    }).Start();

                                    JudgeHelper.ResumeProcess(process.Id);
                                }
                                JudgeResult.Timeused[cur] = Math.Max(JudgeResult.Timeused[cur],
                                                                     Convert.ToInt64(process.UserProcessorTime.TotalMilliseconds));
                                if (JudgeResult.Timeused[cur] > _problem.DataSets[cur].TimeLimit)
                                {
                                    _isFault  = true;
                                    _isExited = true;
                                    JudgeResult.Result[cur]   = "Time Limit Exceeded";
                                    JudgeResult.Score[cur]    = 0;
                                    JudgeResult.Exitcode[cur] = 0;
                                }

                                taskCount++;
                                JudgeResult.Memoryused[cur] = Math.Max(JudgeResult.Memoryused[cur],
                                                                       process.PeakWorkingSet64 >> 10);
                                if (JudgeResult.Memoryused[cur] > _problem.DataSets[cur].MemoryLimit)
                                {
                                    _isFault  = true;
                                    _isExited = true;
                                    JudgeResult.Result[cur]   = "Memory Limit Exceeded";
                                    JudgeResult.Score[cur]    = 0;
                                    JudgeResult.Exitcode[cur] = 0;
                                }

                                taskCount++;

                                if (lastDt == Convert.ToInt64(process.TotalProcessorTime.TotalMilliseconds))
                                {
                                    if ((DateTime.Now - noChangeTime).TotalMilliseconds >
                                        _problem.DataSets[cur].TimeLimit *
                                        (Connection.CurJudgingCnt - Connection.IntelligentAdditionWorkingThread) * 10)
                                    {
                                        _isExited      = true;
                                        isNoResponding = true;
                                        break;
                                    }

                                    try
                                    {
                                        process.CloseMainWindow();
                                    }
                                    catch
                                    {
                                        //ignored
                                    }
                                }
                                else
                                {
                                    noChangeTime = DateTime.Now;
                                    lastDt       = Convert.ToInt64(process.TotalProcessorTime.TotalMilliseconds);
                                }

                                process.Refresh();
                            }
                        }
                        catch
                        {
                            if (!_isExited)
                            {
                                if (taskCount != 2)
                                {
                                    process.Refresh();
                                }
                            }
                        }
                    } while (!_isExited);

                    try
                    {
                        process.Kill();
                    }
                    catch
                    {
                        //ignored
                    }
                    try
                    {
                        execute.Kill();
                    }
                    catch
                    {
                        //ignored
                    }
                    try
                    {
                        JudgeResult.Exitcode[cur] = execute.ExitCode;
                        if (JudgeResult.Exitcode[cur] == 0)
                        {
                            JudgeResult.Exitcode[cur] = process.ExitCode;
                        }
                        if (JudgeResult.Exitcode[cur] != 0 && !_isFault)
                        {
                            JudgeResult.Result[cur] = "Runtime Error";
                            JudgeResult.Score[cur]  = 0;
                            _isFault       = true;
                            isNoResponding = false;
                        }
                    }
                    catch
                    {
                        //ignored
                    }
                    JudgeHelper.TerminateProcess(process.Id);
                    if (isNoResponding)
                    {
                        JudgeResult.Result[cur] = "Time Limit Exceeded";
                        JudgeResult.Score[cur]  = 0;
                        noRespondingTime[cur]++;
                        if (!noRespondingState)
                        {
                            lock (Connection.AdditionWorkingThreadLock)
                            {
                                Connection.IntelligentAdditionWorkingThread++;
                            }
                            noRespondingState = true;
                        }
                        process.Close();
                        execute.Close();
                        if (noRespondingTime[cur] < 3)
                        {
                            cur--;
                        }
                        continue;
                    }
                    if (_isFault)
                    {
                        process.Close();
                        execute.Close();
                        continue;
                    }
                    Thread.Sleep(1);
                    if (_problem.InputFileName != "stdin")
                    {
                        if (!File.Exists(_workingdir + "\\" + _problem.OutputFileName))
                        {
                            JudgeResult.Result[cur] = "Output File Error";
                            JudgeResult.Score[cur]  = 0;
                            continue;
                        }
                    }
                    else
                    {
                        File.WriteAllText(_workingdir + "\\" + _problem.OutputFileName + ".htmp",
                                          res?.Result ?? string.Empty, Encoding.Default);
                    }
                    outputStream.Close();
                    process.Close();
                    execute.Close();
                    Thread.Sleep(1);
                    lock (Connection.ComparingLock)
                    {
                        if (!string.IsNullOrEmpty(_problem.SpecialJudge))
                        {
                            if (File.Exists(_problem.SpecialJudge))
                            {
                                try
                                {
                                    File.Delete(_workingdir + "\\hjudge_spj_result.dat");
                                }
                                catch
                                {
                                    // ignored
                                }
                                try
                                {
                                    var xx = new ProcessStartInfo
                                    {
                                        ErrorDialog     = false,
                                        UseShellExecute = true,
                                        CreateNoWindow  = true,
                                        FileName        = _problem.SpecialJudge,
                                        Arguments       = Dn(_problem.DataSets[cur].InputFile) + " " +
                                                          Dn(_problem.DataSets[cur].OutputFile) + " " +
                                                          (_problem.InputFileName != "stdin"
                                                        ? Dn(_workingdir + "\\" + _problem.OutputFileName)
                                                        : Dn(_workingdir + "\\" + _problem.OutputFileName + ".htmp")
                                                          ) + " " +
                                                          Dn(_workingdir + "\\hjudge_spj_result.dat"),
                                        WindowStyle = ProcessWindowStyle.Hidden
                                    };
                                    var pcs = new Process {
                                        StartInfo = xx
                                    };
                                    pcs.Start();
                                    if (!pcs.WaitForExit(1000 * 60))
                                    {
                                        try
                                        {
                                            pcs.Kill();
                                        }
                                        catch
                                        {
                                            pcs.Close();
                                        }
                                    }
                                    Thread.Sleep(1);
                                    if (!File.Exists(_workingdir + "\\hjudge_spj_result.dat"))
                                    {
                                        JudgeResult.Result[cur] = "Special Judge Error";
                                        JudgeResult.Score[cur]  = 0;
                                    }
                                    else
                                    {
                                        var p = File.ReadAllText(_workingdir + "\\hjudge_spj_result.dat");
                                        p = Regex.Replace(p, @"\s", string.Empty);
                                        var gs = Convert.ToSingle(p);
                                        JudgeResult.Score[cur] = _problem.DataSets[cur].Score * gs;
                                        if (Math.Abs(gs - 1) > 0.00001F)
                                        {
                                            JudgeResult.Result[cur] = "Wrong Answer";
                                        }
                                        else
                                        {
                                            JudgeResult.Result[cur] = "Correct";
                                        }
                                    }
                                }
                                catch
                                {
                                    JudgeResult.Result[cur] = "Special Judge Error";
                                    JudgeResult.Score[cur]  = 0;
                                }
                            }
                            else
                            {
                                JudgeResult.Result[cur] = "Special Judge Error";
                                JudgeResult.Score[cur]  = 0;
                            }
                        }
                        else
                        {
                            try
                            {
                                var fs1 = new FileStream(_problem.DataSets[cur].OutputFile, FileMode.Open,
                                                         FileAccess.Read,
                                                         FileShare.ReadWrite);
                                var fs2 = new FileStream(
                                    _problem.InputFileName != "stdin"
                                        ? _workingdir + "\\" + _problem.OutputFileName
                                        : _workingdir + "\\" + _problem.OutputFileName + ".htmp",
                                    FileMode.OpenOrCreate,
                                    FileAccess.Read,
                                    FileShare.ReadWrite);
                                var sr1     = new StreamReader(fs1);
                                var sr2     = new StreamReader(fs2);
                                var iswrong = false;
                                do
                                {
                                    string s1;
                                    try
                                    {
                                        s1 = sr1.ReadLine();
                                    }
                                    catch
                                    {
                                        s1 = string.Empty;
                                    }
                                    string s2;
                                    try
                                    {
                                        s2 = sr2.ReadLine();
                                    }
                                    catch
                                    {
                                        s2 = string.Empty;
                                    }
                                    if (s1 == null)
                                    {
                                        s1 = string.Empty;
                                    }
                                    if (s2 == null)
                                    {
                                        s2 = string.Empty;
                                    }
                                    s1 = s1.TrimEnd(' ');
                                    s2 = s2.TrimEnd(' ');
                                    if (s1 == s2)
                                    {
                                        continue;
                                    }
                                    iswrong = true;
                                    JudgeResult.Result[cur] = "Wrong Answer";
                                    JudgeResult.Score[cur]  = 0;
                                    if (Regex.Replace(s1, @"\s", string.Empty) ==
                                        Regex.Replace(s2, @"\s", string.Empty))
                                    {
                                        JudgeResult.Result[cur] = "Presentation Error";
                                    }
                                    else
                                    {
                                        break;
                                    }
                                } while (!(sr1.EndOfStream && sr2.EndOfStream));
                                sr1.Close();
                                sr2.Close();
                                fs1.Close();
                                fs2.Close();
                                if (iswrong)
                                {
                                    continue;
                                }
                                JudgeResult.Result[cur] = "Correct";
                                JudgeResult.Score[cur]  = _problem.DataSets[cur].Score;
                            }
                            catch (Exception ex)
                            {
                                JudgeResult.Result[cur] = $"Unknown Error: {ex.Message}";
                                JudgeResult.Score[cur]  = 0;
                            }
                        }
                    }
                }
                Thread.Sleep(1);
            }
            if (noRespondingState)
            {
                lock (Connection.AdditionWorkingThreadLock)
                {
                    Connection.IntelligentAdditionWorkingThread--;
                }
            }
        }